mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-06-10 05:03:29 -04:00
Compare commits
96 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0bc6ca08e0 | |||
| 16aaf2f939 | |||
| 3971e3696e | |||
| f11f97e84e | |||
| 7a00658be9 | |||
| 7bc2259c82 | |||
| 3d73faa9a0 | |||
| 134aba4aa0 | |||
| 79a29a62ef | |||
| 3f67fed073 | |||
| cbeec006ec | |||
| fd9cd9c5eb | |||
| 4a576f45ee | |||
| 32bf8cc53c | |||
| 02f7310c16 | |||
| bfe13906e9 | |||
| 32288be744 | |||
| 19be6e9b99 | |||
| 0b8cc71d0d | |||
| ced34ab68a | |||
| e163d5bc3d | |||
| 612da023f0 | |||
| 368a9015ac | |||
| ed9cb1dfd2 | |||
| fb6ea42560 | |||
| b26f2b21da | |||
| 358dd47da7 | |||
| ea1ffdd041 | |||
| ef9fc0a9ec | |||
| 19af4481c0 | |||
| 30a063b75d | |||
| cf6101f4da | |||
| 3d3b8bfc5b | |||
| 0cb4cd158a | |||
| 43fed2d77e | |||
| 11a0a00633 | |||
| 107a365b71 | |||
| bb1078e99c | |||
| 2529dc59bd | |||
| 61cf2bd323 | |||
| 16ee20c2a8 | |||
| 7ef6a434f9 | |||
| e3825ec263 | |||
| cb82e77e40 | |||
| 63cf3610e5 | |||
| dd5d8088f6 | |||
| 1da1b1a2bb | |||
| db02870a05 | |||
| 861bd09848 | |||
| 8426cc93e5 | |||
| 21796367a0 | |||
| 321c258d69 | |||
| 02938cfba2 | |||
| 37b2fc0745 | |||
| 6cb3a830bd | |||
| 96abadd904 | |||
| fa8a0e2a76 | |||
| 60faf3f750 | |||
| ef910a02f7 | |||
| f607afc754 | |||
| 865bcc57a7 | |||
| b5caf33a9b | |||
| f655ab592d | |||
| e6fc34e4c2 | |||
| d370ca93fd | |||
| fcf2141266 | |||
| e2f1cebfb5 | |||
| 907b770676 | |||
| ea49196bae | |||
| f65b711376 | |||
| 269e9faa46 | |||
| 35301556d9 | |||
| fb0f7169d7 | |||
| fbc397a131 | |||
| 818addfdda | |||
| f14c390364 | |||
| dd5e72a023 | |||
| d523b104d8 | |||
| fdcd9a7508 | |||
| c4f34624ba | |||
| 33fe8776bb | |||
| 02256fac66 | |||
| 621afc99f0 | |||
| 9d215b6dce | |||
| 420bdab328 | |||
| 717074ff86 | |||
| 3ab16b70c2 | |||
| 3cf9d655a7 | |||
| 95f27ace2e | |||
| d50ad4779d | |||
| f2df029efa | |||
| bdb201201e | |||
| f4e4545180 | |||
| 0ddb0711ad | |||
| 3234256b03 | |||
| d8a7a6c764 |
@@ -191,7 +191,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: |
|
||||||
@@ -235,7 +235,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
if: ${{ !vars.LINUX_RUNNER }}
|
if: ${{ !vars.LINUX_RUNNER }}
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y ninja-build
|
sudo apt-get install -y ninja-build
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
+3
-3
@@ -5,9 +5,9 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
|||||||
|
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||||
|
|
||||||
project(Ship VERSION 8.0.1 LANGUAGES C CXX)
|
project(Ship VERSION 8.0.6 LANGUAGES C CXX)
|
||||||
set(PROJECT_BUILD_NAME "MacReady Bravo" CACHE STRING "")
|
set(PROJECT_BUILD_NAME "MacReady Golf" CACHE STRING "" FORCE)
|
||||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE)
|
||||||
|
|
||||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
||||||
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
|
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
|
||||||
|
|||||||
+1
-1
Submodule libultraship updated: 9509806ae3...1ca7d0fa78
+1
-1
@@ -328,7 +328,7 @@ endif()
|
|||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
Boost
|
Boost
|
||||||
URL https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/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
|
||||||
|
|||||||
@@ -28,4 +28,10 @@
|
|||||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
</application>
|
</application>
|
||||||
</compatibility>
|
</compatibility>
|
||||||
|
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<asmv3:windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware> <!-- legacy -->
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness> <!-- falls back to pm if pmv2 is not available -->
|
||||||
|
</asmv3:windowsSettings>
|
||||||
|
</asmv3:application>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
<Array Name="gMorphaVtx_007BB8" Count="4" Offset="0x7BB8">
|
<Array Name="gMorphaVtx_006A18" Count="286" Offset="0x006A18">
|
||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1190" RangeStart="0x6238" RangeEnd="0x9238">
|
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1190" RangeStart="0x6238" RangeEnd="0x9238">
|
||||||
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="64" Height="64" Offset="0x6238"/>
|
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="32" Height="64" Offset="0x6238"/>
|
||||||
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x8238"/>
|
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x8238"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
<Array Name="gMorphaVtx_007BB8" Count="4" Offset="0x7BB8">
|
<Array Name="gMorphaVtx_006A18" Count="286" Offset="0x006A18">
|
||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808B7370" RangeStart="0x61E8" RangeEnd="0x9238">
|
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808B7370" RangeStart="0x61E8" RangeEnd="0x91E8">
|
||||||
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="64" Height="64" Offset="0x61E8"/>
|
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="32" Height="64" Offset="0x61E8"/>
|
||||||
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81E8"/>
|
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81E8"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="nes_message_data_static">
|
<File Name="nes_message_data_static">
|
||||||
<Text Name="nes_message_data_static" CodeOffset="0xF6910"/>
|
<Text Name="nes_message_data_static" CodeOffset="0xF68F0"/>
|
||||||
</File>
|
</File>
|
||||||
<File Name="ger_message_data_static">
|
<File Name="ger_message_data_static">
|
||||||
<Text Name="ger_message_data_static" CodeOffset="0xF6910" LangOffset="0xFAB38"/>
|
<Text Name="ger_message_data_static" CodeOffset="0xF68F0" LangOffset="0xFAB18"/>
|
||||||
</File>
|
</File>
|
||||||
<File Name="fra_message_data_static">
|
<File Name="fra_message_data_static">
|
||||||
<Text Name="fra_message_data_static" CodeOffset="0xF6910" LangOffset="0xFCC48"/>
|
<Text Name="fra_message_data_static" CodeOffset="0xF68F0" LangOffset="0xFCC28"/>
|
||||||
</File>
|
</File>
|
||||||
<File Name="staff_message_data_static">
|
<File Name="staff_message_data_static">
|
||||||
<Text Name="staff_message_data_static" CodeOffset="0xFED58"/>
|
<Text Name="staff_message_data_static" CodeOffset="0xFED38"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
<Array Name="gMorphaVtx_007BB8" Count="4" Offset="0x7BB8">
|
<Array Name="gMorphaVtx_006A18" Count="286" Offset="0x006A18">
|
||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1210" RangeStart="0x6238" RangeEnd="0x9238">
|
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1210" RangeStart="0x6238" RangeEnd="0x9238">
|
||||||
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="64" Height="64" Offset="0x6238"/>
|
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="32" Height="64" Offset="0x6238"/>
|
||||||
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x8238"/>
|
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x8238"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
<Array Name="gMorphaVtx_007BB8" Count="4" Offset="0x7BB8">
|
<Array Name="gMorphaVtx_006A18" Count="286" Offset="0x006A18">
|
||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1190" RangeStart="0x6238" RangeEnd="0x9238">
|
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1190" RangeStart="0x61E8" RangeEnd="0x91E8">
|
||||||
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="64" Height="64" Offset="0x6238"/>
|
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="32" Height="64" Offset="0x61E8"/>
|
||||||
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x8238"/>
|
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81E8"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
<Array Name="gMorphaVtx_007BB8" Count="4" Offset="0x7BB8">
|
<Array Name="gMorphaVtx_006A18" Count="286" Offset="0x006A18">
|
||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="ovl_Boss_Dodongo" BaseAddress="0x8089E470" RangeStart="0x61C8" RangeEnd="0x91C8">
|
<File Name="ovl_Boss_Dodongo" BaseAddress="0x8089E470" RangeStart="0x61C8" RangeEnd="0x91C8">
|
||||||
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="64" Height="64" Offset="0x61C8"/>
|
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="32" Height="64" Offset="0x61C8"/>
|
||||||
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81C8"/>
|
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81C8"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
<Array Name="gMorphaVtx_007BB8" Count="4" Offset="0x7BB8">
|
<Array Name="gMorphaVtx_006A18" Count="286" Offset="0x006A18">
|
||||||
<Vtx/>
|
<Vtx/>
|
||||||
</Array>
|
</Array>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Root>
|
<Root>
|
||||||
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1190" RangeStart="0x61C8" RangeEnd="0x91C8">
|
<File Name="ovl_Boss_Dodongo" BaseAddress="0x808C1190" RangeStart="0x61C8" RangeEnd="0x91C8">
|
||||||
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="64" Height="64" Offset="0x61C8"/>
|
<Texture Name="sLavaFloorLavaTex" OutName="lava_floor_lava" Format="rgba16" Width="32" Height="64" Offset="0x61C8"/>
|
||||||
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81C8"/>
|
<Texture Name="sLavaFloorRockTex" OutName="lava_floor_rock" Format="rgba16" Width="32" Height="64" Offset="0x81C8"/>
|
||||||
</File>
|
</File>
|
||||||
</Root>
|
</Root>
|
||||||
|
|||||||
@@ -46,10 +46,18 @@ template<> struct is_char_type<std::byte>: public boost::true_type {};
|
|||||||
|
|
||||||
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
||||||
|
|
||||||
|
#if BOOST_USE_STD_TYPES
|
||||||
|
#define BOOST_ENABLE_IF std::enable_if
|
||||||
|
#define BOOST_IS_SAME std::is_same
|
||||||
|
#else
|
||||||
|
#define BOOST_ENABLE_IF boost::enable_if_
|
||||||
|
#define BOOST_IS_SAME is_same
|
||||||
|
#endif
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline typename boost::enable_if_<
|
inline typename BOOST_ENABLE_IF<
|
||||||
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
||||||
is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
|
BOOST_IS_SAME<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
|
||||||
std::size_t>::type
|
std::size_t>::type
|
||||||
hash_range_32( uint32_t seed, It first, It last )
|
hash_range_32( uint32_t seed, It first, It last )
|
||||||
{
|
{
|
||||||
@@ -114,4 +122,7 @@ std::size_t>::type
|
|||||||
} // namespace hash_detail
|
} // namespace hash_detail
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
|
#undef BOOST_ENABLE_IF
|
||||||
|
#undef BOOST_IS_SAME
|
||||||
|
|
||||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
|
#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
|
||||||
|
|||||||
@@ -23,6 +23,18 @@
|
|||||||
|
|
||||||
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
||||||
|
|
||||||
|
#if BOOST_USE_STD_TYPES
|
||||||
|
#define BOOST_ENABLE_IF std::enable_if
|
||||||
|
#define BOOST_IS_INTEGRAL hash_detail::is_integral
|
||||||
|
#define BOOST_IS_UNSIGNED is_unsigned
|
||||||
|
#define BOOST_MAKE_UNSIGNED make_unsigned
|
||||||
|
#else
|
||||||
|
#define BOOST_ENABLE_IF boost::enable_if_
|
||||||
|
#define BOOST_IS_INTEGRAL boost::is_integral
|
||||||
|
#define BOOST_IS_UNSIGNED boost::is_unsigned
|
||||||
|
#define BOOST_MAKE_UNSIGNED boost::make_unsigned
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -36,7 +48,7 @@ namespace boost
|
|||||||
{
|
{
|
||||||
template<class T,
|
template<class T,
|
||||||
bool bigger_than_size_t = (sizeof(T) > sizeof(uint32_t)),
|
bool bigger_than_size_t = (sizeof(T) > sizeof(uint32_t)),
|
||||||
bool is_unsigned = boost::is_unsigned<T>::value,
|
bool is_unsigned = BOOST_IS_UNSIGNED<T>::value,
|
||||||
std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT,
|
std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT,
|
||||||
std::size_t type_bits = sizeof(T) * CHAR_BIT>
|
std::size_t type_bits = sizeof(T) * CHAR_BIT>
|
||||||
struct hash_integral_impl_32;
|
struct hash_integral_impl_32;
|
||||||
@@ -53,7 +65,7 @@ namespace boost
|
|||||||
{
|
{
|
||||||
static uint32_t fn( T v )
|
static uint32_t fn( T v )
|
||||||
{
|
{
|
||||||
typedef typename boost::make_unsigned<T>::type U;
|
typedef typename BOOST_MAKE_UNSIGNED<T>::type U;
|
||||||
|
|
||||||
if( v >= 0 )
|
if( v >= 0 )
|
||||||
{
|
{
|
||||||
@@ -97,7 +109,7 @@ namespace boost
|
|||||||
} // namespace hash_detail
|
} // namespace hash_detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename boost::enable_if_<boost::is_integral<T>::value, uint32_t>::type
|
typename BOOST_ENABLE_IF<BOOST_IS_INTEGRAL<T>::value, uint32_t>::type
|
||||||
hash_value_32( T v )
|
hash_value_32( T v )
|
||||||
{
|
{
|
||||||
return hash_detail::hash_integral_impl_32<T>::fn( v );
|
return hash_detail::hash_integral_impl_32<T>::fn( v );
|
||||||
@@ -106,7 +118,7 @@ namespace boost
|
|||||||
// contiguous ranges (string, vector, array)
|
// contiguous ranges (string, vector, array)
|
||||||
#if BOOST_VERSION_HAS_HASH_RANGE
|
#if BOOST_VERSION_HAS_HASH_RANGE
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename boost::enable_if_<container_hash::is_contiguous_range<T>::value, uint32_t>::type
|
typename BOOST_ENABLE_IF<container_hash::is_contiguous_range<T>::value, uint32_t>::type
|
||||||
hash_value_32( T const& v )
|
hash_value_32( T const& v )
|
||||||
{
|
{
|
||||||
return boost::hash_range_32( v.data(), v.data() + v.size() );
|
return boost::hash_range_32( v.data(), v.data() + v.size() );
|
||||||
@@ -168,5 +180,9 @@ namespace boost
|
|||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
#undef BOOST_HASH_CHAR_TRAITS
|
#undef BOOST_HASH_CHAR_TRAITS
|
||||||
|
#undef BOOST_ENABLE_IF
|
||||||
|
#undef BOOST_IS_INTEGRAL
|
||||||
|
#undef BOOST_IS_UNSIGNED
|
||||||
|
#undef BOOST_MAKE_UNSIGNED
|
||||||
|
|
||||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
|
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
|
||||||
|
|||||||
@@ -6,4 +6,6 @@
|
|||||||
|
|
||||||
#define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81)
|
#define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81)
|
||||||
|
|
||||||
|
#define BOOST_USE_STD_TYPES ((BOOST_VERSION / 100 % 1000) >= 84)
|
||||||
|
|
||||||
#endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP
|
#endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP
|
||||||
|
|||||||
@@ -1259,6 +1259,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
|||||||
s32 dListIndex);
|
s32 dListIndex);
|
||||||
void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
||||||
PostLimbDrawOpa postLimbDraw, void* arg);
|
PostLimbDrawOpa postLimbDraw, void* arg);
|
||||||
|
Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
||||||
|
PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx);
|
||||||
void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable,
|
void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable,
|
||||||
OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg);
|
OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg);
|
||||||
void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount,
|
void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount,
|
||||||
@@ -2458,6 +2460,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP);
|
|||||||
|
|
||||||
void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH);
|
void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH);
|
||||||
void Interface_RandoRestoreSwordless(void);
|
void Interface_RandoRestoreSwordless(void);
|
||||||
|
s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw,
|
||||||
|
bool* shouldUpdate);
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -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 {
|
||||||
@@ -1402,6 +1405,8 @@ typedef struct PlayState {
|
|||||||
/* 0x1242B */ u8 unk_1242B;
|
/* 0x1242B */ u8 unk_1242B;
|
||||||
/* 0x1242C */ SceneTableEntry* loadedScene;
|
/* 0x1242C */ SceneTableEntry* loadedScene;
|
||||||
/* 0x12430 */ char unk_12430[0xE8];
|
/* 0x12430 */ char unk_12430[0xE8];
|
||||||
|
// SOH [Custom Models] MTX tracker for flex based skeletons
|
||||||
|
Mtx** flexLimbOverrideMTX;
|
||||||
} PlayState; // size = 0x12518
|
} PlayState; // size = 0x12518
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -7,68 +7,6 @@ export RESPATH="${SNAME%/MacOS*}/Resources"
|
|||||||
export LIBPATH="${SNAME%/MacOS*}/Frameworks"
|
export LIBPATH="${SNAME%/MacOS*}/Frameworks"
|
||||||
export DYLD_FALLBACK_LIBRARY_PATH="$LIBPATH"
|
export DYLD_FALLBACK_LIBRARY_PATH="$LIBPATH"
|
||||||
|
|
||||||
remap_hashes ()
|
|
||||||
{
|
|
||||||
# Remap v64 and n64 hashes to their z64 hash equivalent
|
|
||||||
# ZAPD will handle converting the data into z64 format
|
|
||||||
case "$ROMHASH" in
|
|
||||||
a9059b56e761c9034fbe02fe4c24985aaa835dac) # v64
|
|
||||||
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
|
|
||||||
;;
|
|
||||||
24708102dc504d3f375a37f4ae4e149c167dc515) # n64
|
|
||||||
ROMHASH=cee6bc3c2a634b41728f2af8da54d9bf8cc14099
|
|
||||||
;;
|
|
||||||
580dd0bd1b6d2c51cc20a764eece84dba558964c) # v64
|
|
||||||
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
|
|
||||||
;;
|
|
||||||
d6342c59007e57c1194661ec6880b2f078403f4e) # n64
|
|
||||||
ROMHASH=0227d7c0074f2d0ac935631990da8ec5914597b4
|
|
||||||
;;
|
|
||||||
d0bdc2eb320668b4ba6893b9aefe4040a73123ff) # v64
|
|
||||||
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
|
|
||||||
;;
|
|
||||||
4946ab250f6ac9b32d76b21f309ebb8ebc8103d2) # n64
|
|
||||||
ROMHASH=328a1f1beba30ce5e178f031662019eb32c5f3b5
|
|
||||||
;;
|
|
||||||
663c34f1b2c05a09e5beffe4d0dcd440f7d49dc7) # v64
|
|
||||||
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
|
|
||||||
;;
|
|
||||||
24c73d378b0620a380ce5ef9f2b186c6c157a68b) # n64
|
|
||||||
ROMHASH=cfbb98d392e4a9d39da8285d10cbef3974c2f012
|
|
||||||
;;
|
|
||||||
8ebf2e29313f44f2d49e5b4191971d09919e8e48) # v64
|
|
||||||
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
|
|
||||||
;;
|
|
||||||
4264bf7b875737b8fae77d52322a5099d051fc11) # n64
|
|
||||||
ROMHASH=f46239439f59a2a594ef83cf68ef65043b1bffe2
|
|
||||||
;;
|
|
||||||
973bc6fe56010a8d646166a1182a81b4f13b8cf9) # v64
|
|
||||||
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
|
|
||||||
;;
|
|
||||||
d327752c46edc70ff3668b9514083dbbee08927c) # v64
|
|
||||||
ROMHASH=50bebedad9e0f10746a52b07239e47fa6c284d03
|
|
||||||
;;
|
|
||||||
ecdeb1747560834e079c22243febea7f6f26ba3b) # v64
|
|
||||||
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
|
|
||||||
;;
|
|
||||||
f19f8662ec7abee29484a272a6fda53e39efe0f1) # n64
|
|
||||||
ROMHASH=079b855b943d6ad8bd1eb026c0ed169ecbdac7da
|
|
||||||
;;
|
|
||||||
ab519ce04a33818ce2c39b3c514a751d807a494a) # v64
|
|
||||||
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
|
|
||||||
;;
|
|
||||||
c19a34f7646305e1755249fca2071e178bd7cd00) # n64
|
|
||||||
ROMHASH=cfecfdc58d650e71a200c81f033de4e6d617a9f6
|
|
||||||
;;
|
|
||||||
25e8ae79ea0839ca5c984473f7460d8040c36f9c) # v64
|
|
||||||
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
|
|
||||||
;;
|
|
||||||
166c02770d67fcc3954c443eb400a6a3573d3fc0) # n64
|
|
||||||
ROMHASH=517bd9714c73cb96c21e7c2ef640d7b55186102f
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ ! -e "$SHIP_HOME" ]; then mkdir "$SHIP_HOME"; fi
|
if [ ! -e "$SHIP_HOME" ]; then mkdir "$SHIP_HOME"; fi
|
||||||
|
|
||||||
if [ ! -e "$SHIP_HOME"/mods ]; then
|
if [ ! -e "$SHIP_HOME"/mods ]; then
|
||||||
@@ -76,178 +14,6 @@ if [ ! -e "$SHIP_HOME"/mods ]; then
|
|||||||
touch "$SHIP_HOME"/mods/custom_otr_files_go_here.txt
|
touch "$SHIP_HOME"/mods/custom_otr_files_go_here.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If either OTR doesn't exist kick off the OTR gen process
|
|
||||||
if [ ! -e "$SHIP_HOME"/oot.otr ] || [ ! -e "$SHIP_HOME"/oot-mq.otr ]; then
|
|
||||||
|
|
||||||
# If no ROMs exist kick off the file selection prompts
|
|
||||||
while [ ! -e "$SHIP_HOME"/*.*64 ] && [ ! -e "$SHIP_HOME"/oot*.otr ]; do
|
|
||||||
|
|
||||||
SHOULD_PROMPT_FOR_ROM=1
|
|
||||||
while [ $SHOULD_PROMPT_FOR_ROM -eq 1 ]; do
|
|
||||||
SHOULD_PROMPT_FOR_ROM=0
|
|
||||||
# Use osascript to prompt the user to chose a file
|
|
||||||
DROPROM=`osascript <<-EOF
|
|
||||||
set romFile to choose file of type {"b64","n64","v64","z64"} with prompt "Please select your ROM:"
|
|
||||||
return POSIX path of romFile
|
|
||||||
EOF`
|
|
||||||
|
|
||||||
# If no rom was selected, the user cancelled, so exit
|
|
||||||
if [[ -z $DROPROM ]] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
|
||||||
echo "No ROM selected. Exiting..."
|
|
||||||
exit 1
|
|
||||||
elif [[ -z $DROPROM ]]; then
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If an invalid rom was selected, let the user know and ask to try again
|
|
||||||
ROMHASH="$(shasum "$DROPROM" | awk '{ print $1 }')"
|
|
||||||
|
|
||||||
remap_hashes
|
|
||||||
|
|
||||||
case "$ROMHASH" in
|
|
||||||
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
|
|
||||||
ROM_TYPE=0;;
|
|
||||||
0227d7c0074f2d0ac935631990da8ec5914597b4)
|
|
||||||
ROM_TYPE=0;;
|
|
||||||
328a1f1beba30ce5e178f031662019eb32c5f3b5)
|
|
||||||
ROM_TYPE=0;;
|
|
||||||
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
|
|
||||||
ROM_TYPE=0;;
|
|
||||||
f46239439f59a2a594ef83cf68ef65043b1bffe2)
|
|
||||||
ROM_TYPE=1;;
|
|
||||||
50bebedad9e0f10746a52b07239e47fa6c284d03)
|
|
||||||
ROM_TYPE=1;;
|
|
||||||
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
|
|
||||||
ROM_TYPE=1;;
|
|
||||||
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
|
|
||||||
ROM_TYPE=1;;
|
|
||||||
517bd9714c73cb96c21e7c2ef640d7b55186102f)
|
|
||||||
ROM_TYPE=1;;
|
|
||||||
*)
|
|
||||||
TRY_AGAIN_RESULT=`osascript <<-EOF
|
|
||||||
set alertText to "Incompatible ROM hash"
|
|
||||||
set alertMessage to "Incompatible ROM provided, would you like to try again?"
|
|
||||||
return display alert alertText \
|
|
||||||
message alertMessage \
|
|
||||||
as critical \
|
|
||||||
buttons {"Cancel", "Try Again"}
|
|
||||||
EOF`
|
|
||||||
if [[ "$TRY_AGAIN_RESULT" == "button returned:Try Again" ]]; then
|
|
||||||
SHOULD_PROMPT_FOR_ROM=1
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
echo "No ROM selected. Exiting..."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
esac
|
|
||||||
|
|
||||||
cp "$DROPROM" "$SHIP_HOME"
|
|
||||||
|
|
||||||
# Ask user if they would also like to select the other variant (MQ/Vanilla)
|
|
||||||
if [ $ROM_TYPE -eq 0 ] && [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
|
||||||
UPLOAD_ANOTHER_RESULT=`osascript <<-EOF
|
|
||||||
set alertText to "Success"
|
|
||||||
set alertMessage to "Would you also like to provide a Master Quest ROM?"
|
|
||||||
return display alert alertText \
|
|
||||||
message alertMessage \
|
|
||||||
buttons {"No", "Yes"}
|
|
||||||
EOF`
|
|
||||||
elif [[ -z "$UPLOAD_ANOTHER_RESULT" ]]; then
|
|
||||||
UPLOAD_ANOTHER_RESULT=`osascript <<-EOF
|
|
||||||
set alertText to "Success"
|
|
||||||
set alertMessage to "Would you also like to provide a Vanilla (Non Master Quest) ROM?"
|
|
||||||
return display alert alertText \
|
|
||||||
message alertMessage \
|
|
||||||
buttons {"No", "Yes"}
|
|
||||||
EOF`
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$UPLOAD_ANOTHER_RESULT" == "button returned:Yes" ]]; then
|
|
||||||
UPLOAD_ANOTHER_RESULT="button returned:No"
|
|
||||||
SHOULD_PROMPT_FOR_ROM=1
|
|
||||||
continue;
|
|
||||||
fi
|
|
||||||
break
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
# At this point we should now have 1 or more valid roms in $SHIP_HOME directory
|
|
||||||
|
|
||||||
# Prepare tmp dir
|
|
||||||
for ROMPATH in "$SHIP_HOME"/*.*64
|
|
||||||
do
|
|
||||||
ASSETDIR="$(mktemp -d /tmp/assets-XXXXX)"
|
|
||||||
export ASSETDIR
|
|
||||||
cp -r "$RESPATH/assets" "$ASSETDIR"
|
|
||||||
mkdir -p "$ASSETDIR"/tmp
|
|
||||||
cp "$ROMPATH" "$ASSETDIR"/tmp/rom.z64
|
|
||||||
cd "$ASSETDIR" || return
|
|
||||||
|
|
||||||
# If an invalid rom was detected, let the user know
|
|
||||||
ROMHASH="$(shasum "$ASSETDIR"/tmp/rom.z64 | awk '{ print $1 }')"
|
|
||||||
|
|
||||||
remap_hashes
|
|
||||||
|
|
||||||
case "$ROMHASH" in
|
|
||||||
cee6bc3c2a634b41728f2af8da54d9bf8cc14099)
|
|
||||||
ROM=GC_NMQ_D
|
|
||||||
OTRNAME="oot.otr";;
|
|
||||||
0227d7c0074f2d0ac935631990da8ec5914597b4)
|
|
||||||
ROM=GC_NMQ_PAL_F
|
|
||||||
OTRNAME="oot.otr";;
|
|
||||||
328a1f1beba30ce5e178f031662019eb32c5f3b5)
|
|
||||||
ROM=N64_PAL_10
|
|
||||||
OTRNAME="oot.otr";;
|
|
||||||
cfbb98d392e4a9d39da8285d10cbef3974c2f012)
|
|
||||||
ROM=N64_PAL_11
|
|
||||||
OTRNAME="oot.otr";;
|
|
||||||
f46239439f59a2a594ef83cf68ef65043b1bffe2)
|
|
||||||
ROM=GC_MQ_PAL_F
|
|
||||||
OTRNAME="oot-mq.otr";;
|
|
||||||
50bebedad9e0f10746a52b07239e47fa6c284d03)
|
|
||||||
ROM=GC_MQ_D
|
|
||||||
OTRNAME="oot-mq.otr";;
|
|
||||||
079b855b943d6ad8bd1eb026c0ed169ecbdac7da)
|
|
||||||
ROM=GC_MQ_D
|
|
||||||
OTRNAME="oot-mq.otr";;
|
|
||||||
cfecfdc58d650e71a200c81f033de4e6d617a9f6)
|
|
||||||
ROM=GC_MQ_D
|
|
||||||
OTRNAME="oot-mq.otr";;
|
|
||||||
517bd9714c73cb96c21e7c2ef640d7b55186102f)
|
|
||||||
ROM=GC_MQ_D
|
|
||||||
OTRNAME="oot-mq.otr";;
|
|
||||||
*)
|
|
||||||
osascript -e 'display notification "One or more invalid ROM provided" with title "Ship Of Harkinian"'
|
|
||||||
rm -r "$ASSETDIR"
|
|
||||||
cd "$SNAME"
|
|
||||||
continue;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Only generate OTR if we don't have on of this type yet
|
|
||||||
if [ -e "$SHIP_HOME"/"$OTRNAME" ]; then
|
|
||||||
rm -r "$ASSETDIR"
|
|
||||||
cd "$SNAME"
|
|
||||||
continue;
|
|
||||||
fi
|
|
||||||
|
|
||||||
osascript -e 'display notification "Generating OTR..." with title "Ship Of Harkinian"'
|
|
||||||
assets/extractor/ZAPD.out ed -i assets/extractor/xmls/"${ROM}" -b tmp/rom.z64 -fl assets/extractor/filelists -o placeholder -osf placeholder -gsf 1 -rconf assets/extractor/Config_"${ROM}".xml -se OTR --portVer "@CMAKE_PROJECT_VERSION@"
|
|
||||||
if [ -e "$ASSETDIR"/oot.otr ]; then
|
|
||||||
osascript -e 'display notification "OTR successfully generated" with title "Ship Of Harkinian"'
|
|
||||||
cp "$ASSETDIR"/oot.otr "$SHIP_HOME"/"$OTRNAME"
|
|
||||||
rm -r "$ASSETDIR"
|
|
||||||
cd "$SNAME"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ ! -e "$SHIP_HOME"/oot*.otr ]; then
|
|
||||||
osascript -e 'display notification "OTR failed to generate" with title "Ship Of Harkinian"'
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$SNAME"
|
|
||||||
|
|
||||||
arch_name="$(uname -m)"
|
arch_name="$(uname -m)"
|
||||||
launch_arch="arm64"
|
launch_arch="arm64"
|
||||||
if [ "${arch_name}" = "x86_64" ] && [ "$(sysctl -in sysctl.proc_translated)" != "1" ]; then
|
if [ "${arch_name}" = "x86_64" ] && [ "$(sysctl -in sysctl.proc_translated)" != "1" ]; then
|
||||||
|
|||||||
@@ -258,24 +258,28 @@ namespace GameControlEditor {
|
|||||||
window->EndGroupPanelPublic(0);
|
window->EndGroupPanelPublic(0);
|
||||||
|
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
window->BeginGroupPanelPublic("Third-Person Camera", ImGui::GetContentRegionAvail());
|
window->BeginGroupPanelPublic("Free Look/Third-person Camera", ImGui::GetContentRegionAvail());
|
||||||
|
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera");
|
UIWidgets::PaddedEnhancementCheckbox("Enable Free Look", "gFreeCamera");
|
||||||
DrawHelpIcon("Enables free camera control\nNote: You must remap C buttons off of the right stick in the "
|
DrawHelpIcon("Enables free look camera control\nNote: You must remap C buttons off of the right stick in the "
|
||||||
"controller config menu, and map the camera stick to the right stick.");
|
"controller config menu, and map the camera stick to the right stick.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis");
|
UIWidgets::PaddedEnhancementCheckbox("Invert X Axis", "gInvertXAxis");
|
||||||
DrawHelpIcon("Inverts the Camera X Axis in:\n-Free camera");
|
DrawHelpIcon("Inverts the Camera X Axis in:\n-Free Look");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
UIWidgets::PaddedEnhancementCheckbox("Invert Y Axis", "gInvertYAxis", true, true, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
||||||
DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free camera");
|
DrawHelpIcon("Inverts the Camera Y Axis in:\n-Free Look");
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
UIWidgets::PaddedEnhancementSliderFloat("Third-Person Horizontal Sensitivity: %d %%", "##ThirdPersonSensitivity Horizontal",
|
UIWidgets::PaddedEnhancementSliderFloat("Horizontal Sensitivity: %d %%", "##ThirdPersonSensitivity Horizontal",
|
||||||
"gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true);
|
"gThirdPersonCameraSensitivityX", 0.01f, 5.0f, "", 1.0f, true, true, false, true);
|
||||||
UIWidgets::PaddedEnhancementSliderFloat("Third-Person Vertical Sensitivity: %d %%", "##ThirdPersonSensitivity Vertical",
|
DrawHelpIcon("Changes the sensitivity of the X axis control for Free Look");
|
||||||
|
UIWidgets::PaddedEnhancementSliderFloat("Vertical Sensitivity: %d %%", "##ThirdPersonSensitivity Vertical",
|
||||||
"gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true);
|
"gThirdPersonCameraSensitivityY", 0.01f, 5.0f, "", 1.0f, true, true, false, true);
|
||||||
|
DrawHelpIcon("Changes the sensitivity of the Y axis control for Free Look");
|
||||||
UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist",
|
UIWidgets::PaddedEnhancementSliderInt("Camera Distance: %d", "##CamDist",
|
||||||
"gFreeCameraDistMax", 100, 900, "", 185, true, false, true);
|
"gFreeCameraDistMax", 100, 900, "", 185, true, false, true);
|
||||||
UIWidgets::PaddedEnhancementSliderInt("Camera Transition Speed: %d", "##CamTranSpeed",
|
DrawHelpIcon("How far the camera sits from Link while in Free Look mode");
|
||||||
|
UIWidgets::PaddedEnhancementSliderInt("Transition Speed: %d", "##CamTranSpeed",
|
||||||
"gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true);
|
"gFreeCameraTransitionSpeed", 0, 900, "", 25, true, false, true);
|
||||||
|
DrawHelpIcon("How quickly the camera changes to the distance specified above");
|
||||||
window->EndGroupPanelPublic(0);
|
window->EndGroupPanelPublic(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,6 +316,7 @@ namespace GameControlEditor {
|
|||||||
DrawHelpIcon("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select "
|
DrawHelpIcon("Allows the cursor on the pause menu to be over any slot. Sometimes required in rando to select "
|
||||||
"certain items.");
|
"certain items.");
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Enable walk speed modifiers", "gEnableWalkModify", true, false);
|
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");
|
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)) {
|
if (CVarGetInteger("gEnableWalkModify", 0)) {
|
||||||
@@ -323,6 +328,7 @@ namespace GameControlEditor {
|
|||||||
UIWidgets::PaddedEnhancementSliderFloat("Modifier 2: %d %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
|
UIWidgets::PaddedEnhancementSliderFloat("Modifier 2: %d %%", "##WalkMod2", "gWalkModifierTwo", 0.0f, 5.0f, "", 1.0f, true, true, false, true);
|
||||||
window->EndGroupPanelPublic(0);
|
window->EndGroupPanelPublic(0);
|
||||||
}
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL");
|
UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL");
|
||||||
DrawHelpIcon("Speak to Navi with L but enter first-person camera with C-Up");
|
DrawHelpIcon("Speak to Navi with L but enter first-person camera with C-Up");
|
||||||
|
|||||||
@@ -1485,6 +1485,7 @@ void Draw_Placements(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawSillyTab() {
|
void DrawSillyTab() {
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
if (CVarGetInteger("gLetItSnow", 0)) {
|
if (CVarGetInteger("gLetItSnow", 0)) {
|
||||||
if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) {
|
if (UIWidgets::EnhancementCheckbox("Let It Snow", "gLetItSnow")) {
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
@@ -1569,6 +1570,7 @@ void DrawSillyTab() {
|
|||||||
CVarClear("gCosmetics.Kak_Windmill_Speed.Changed");
|
CVarClear("gCosmetics.Kak_Windmill_Speed.Changed");
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
}
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the RGB values from one cosmetic option to another, multiplied by the passed in amount, this
|
// Copies the RGB values from one cosmetic option to another, multiplied by the passed in amount, this
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -380,13 +380,13 @@ CrowdControl::Effect* CrowdControl::ParseMessage(char payload[512]) {
|
|||||||
effect->category = kEffectCatBoots;
|
effect->category = kEffectCatBoots;
|
||||||
effect->timeRemaining = 30000;
|
effect->timeRemaining = 30000;
|
||||||
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
||||||
effect->giEffect->parameters[0] = PLAYER_BOOTS_IRON;
|
effect->giEffect->parameters[0] = EQUIP_VALUE_BOOTS_IRON;
|
||||||
break;
|
break;
|
||||||
case kEffectForceHoverBoots:
|
case kEffectForceHoverBoots:
|
||||||
effect->category = kEffectCatBoots;
|
effect->category = kEffectCatBoots;
|
||||||
effect->timeRemaining = 30000;
|
effect->timeRemaining = 30000;
|
||||||
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
||||||
effect->giEffect->parameters[0] = PLAYER_BOOTS_HOVER;
|
effect->giEffect->parameters[0] = EQUIP_VALUE_BOOTS_HOVER;
|
||||||
break;
|
break;
|
||||||
case kEffectSlipperyFloor:
|
case kEffectSlipperyFloor:
|
||||||
effect->category = kEffectCatSlipperyFloor;
|
effect->category = kEffectCatSlipperyFloor;
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ typedef enum {
|
|||||||
TEXT_WARP_NOCTURNE_OF_SHADOW = 0x891,
|
TEXT_WARP_NOCTURNE_OF_SHADOW = 0x891,
|
||||||
TEXT_WARP_PRELUDE_OF_LIGHT = 0x892,
|
TEXT_WARP_PRELUDE_OF_LIGHT = 0x892,
|
||||||
TEXT_WARP_RANDOM_REPLACED_TEXT = 0x9200,
|
TEXT_WARP_RANDOM_REPLACED_TEXT = 0x9200,
|
||||||
|
TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW = 0x9210,
|
||||||
TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x346, // 0x3yy for cuttable sign range
|
TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN = 0x346, // 0x3yy for cuttable sign range
|
||||||
TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x1B3, // 0x1yy for Navi msg range
|
TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI = 0x1B3, // 0x1yy for Navi msg range
|
||||||
} TextIDs;
|
} TextIDs;
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
if (ImGui::IsItemHovered() && hasDescription) {
|
if (ImGui::IsItemHovered() && hasDescription) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60));
|
ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60).c_str());
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#ifndef _ENHANCEMENT_TYPES_H_
|
||||||
|
#define _ENHANCEMENT_TYPES_H_
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WARP_MODE_OVERRIDE_OFF,
|
WARP_MODE_OVERRIDE_OFF,
|
||||||
WARP_MODE_OVERRIDE_MQ_AS_VANILLA,
|
WARP_MODE_OVERRIDE_MQ_AS_VANILLA,
|
||||||
@@ -74,3 +77,5 @@ typedef enum {
|
|||||||
DEKU_STICK_UNBREAKABLE,
|
DEKU_STICK_UNBREAKABLE,
|
||||||
DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE,
|
DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE,
|
||||||
} DekuStickType;
|
} DekuStickType;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -37,12 +37,19 @@ GameInteractionEffectQueryResult GameInteractor::RemoveEffect(GameInteractionEff
|
|||||||
|
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
bool GameInteractor::IsSaveLoaded() {
|
bool GameInteractor::IsSaveLoaded(bool allowDbgSave) {
|
||||||
Player* player;
|
Player* player;
|
||||||
if (gPlayState != NULL) {
|
if (gPlayState != NULL) {
|
||||||
player = GET_PLAYER(gPlayState);
|
player = GET_PLAYER(gPlayState);
|
||||||
}
|
}
|
||||||
return (gPlayState == NULL || player == NULL || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) ? false : true;
|
|
||||||
|
// Checking for normal game mode prevents debug saves from reporting true on title screen
|
||||||
|
if (gPlayState == NULL || player == NULL || gSaveContext.gameMode != GAMEMODE_NORMAL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid save file or debug save
|
||||||
|
return (gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2) || (allowDbgSave && gSaveContext.fileNum == 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameInteractor::IsGameplayPaused() {
|
bool GameInteractor::IsGameplayPaused() {
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ void GameInteractor_SetTriforceHuntCreditsWarpActive(uint8_t state);
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#define DEFINE_HOOK(name, type) \
|
#define DEFINE_HOOK(name, type) \
|
||||||
struct name { \
|
struct name { \
|
||||||
@@ -193,8 +194,11 @@ public:
|
|||||||
|
|
||||||
DEFINE_HOOK(OnSetGameLanguage, void());
|
DEFINE_HOOK(OnSetGameLanguage, void());
|
||||||
|
|
||||||
|
DEFINE_HOOK(OnFileDropped, void(std::string filePath));
|
||||||
|
DEFINE_HOOK(OnAssetAltChange, void());
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
static bool IsSaveLoaded();
|
static bool IsSaveLoaded(bool allowDbgSave = false);
|
||||||
static bool IsGameplayPaused();
|
static bool IsGameplayPaused();
|
||||||
static bool CanSpawnActor();
|
static bool CanSpawnActor();
|
||||||
static bool CanAddOrTakeAmmo(int16_t amount, int16_t item);
|
static bool CanAddOrTakeAmmo(int16_t amount, int16_t item);
|
||||||
|
|||||||
@@ -181,3 +181,9 @@ void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode) {
|
|||||||
void GameInteractor_ExecuteOnSetGameLanguage() {
|
void GameInteractor_ExecuteOnSetGameLanguage() {
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetGameLanguage>();
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetGameLanguage>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - System
|
||||||
|
|
||||||
|
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) {
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnAssetAltChange>(fn);
|
||||||
|
}
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ void GameInteractor_ExecuteOnUpdateFileNameSelection(int16_t charCode);
|
|||||||
|
|
||||||
// MARK: - Game
|
// MARK: - Game
|
||||||
void GameInteractor_ExecuteOnSetGameLanguage();
|
void GameInteractor_ExecuteOnSetGameLanguage();
|
||||||
|
|
||||||
|
// MARK: - System
|
||||||
|
void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -618,7 +618,7 @@ void DrawGameplayStatsOptionsTab() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameplayStatsWindow::DrawElement() {
|
void GameplayStatsWindow::DrawElement() {
|
||||||
ImGui::SetNextWindowSize(ImVec2(480, 550), ImGuiCond_Appearing);
|
ImGui::SetNextWindowSize(ImVec2(480, 550), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("Gameplay Stats", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
|
if (!ImGui::Begin("Gameplay Stats", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ void ReloadSceneTogglingLinkAge() {
|
|||||||
|
|
||||||
void RegisterInfiniteMoney() {
|
void RegisterInfiniteMoney() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
if (CVarGetInteger("gInfiniteMoney", 0) != 0) {
|
if (CVarGetInteger("gInfiniteMoney", 0) != 0) {
|
||||||
if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) {
|
if (gSaveContext.rupees < CUR_CAPACITY(UPG_WALLET)) {
|
||||||
gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
|
gSaveContext.rupees = CUR_CAPACITY(UPG_WALLET);
|
||||||
@@ -57,6 +58,7 @@ void RegisterInfiniteMoney() {
|
|||||||
|
|
||||||
void RegisterInfiniteHealth() {
|
void RegisterInfiniteHealth() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
if (CVarGetInteger("gInfiniteHealth", 0) != 0) {
|
if (CVarGetInteger("gInfiniteHealth", 0) != 0) {
|
||||||
if (gSaveContext.health < gSaveContext.healthCapacity) {
|
if (gSaveContext.health < gSaveContext.healthCapacity) {
|
||||||
gSaveContext.health = gSaveContext.healthCapacity;
|
gSaveContext.health = gSaveContext.healthCapacity;
|
||||||
@@ -67,6 +69,7 @@ void RegisterInfiniteHealth() {
|
|||||||
|
|
||||||
void RegisterInfiniteAmmo() {
|
void RegisterInfiniteAmmo() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
if (CVarGetInteger("gInfiniteAmmo", 0) != 0) {
|
if (CVarGetInteger("gInfiniteAmmo", 0) != 0) {
|
||||||
// Deku Sticks
|
// Deku Sticks
|
||||||
if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) {
|
if (AMMO(ITEM_STICK) < CUR_CAPACITY(UPG_STICKS)) {
|
||||||
@@ -103,6 +106,7 @@ void RegisterInfiniteAmmo() {
|
|||||||
|
|
||||||
void RegisterInfiniteMagic() {
|
void RegisterInfiniteMagic() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
if (CVarGetInteger("gInfiniteMagic", 0) != 0) {
|
if (CVarGetInteger("gInfiniteMagic", 0) != 0) {
|
||||||
if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) {
|
if (gSaveContext.isMagicAcquired && gSaveContext.magic != (gSaveContext.isDoubleMagicAcquired + 1) * 0x30) {
|
||||||
gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30;
|
gSaveContext.magic = (gSaveContext.isDoubleMagicAcquired + 1) * 0x30;
|
||||||
@@ -113,6 +117,7 @@ void RegisterInfiniteMagic() {
|
|||||||
|
|
||||||
void RegisterInfiniteNayrusLove() {
|
void RegisterInfiniteNayrusLove() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
if (CVarGetInteger("gInfiniteNayru", 0) != 0) {
|
if (CVarGetInteger("gInfiniteNayru", 0) != 0) {
|
||||||
gSaveContext.nayrusLoveTimer = 0x44B;
|
gSaveContext.nayrusLoveTimer = 0x44B;
|
||||||
}
|
}
|
||||||
@@ -121,7 +126,7 @@ void RegisterInfiniteNayrusLove() {
|
|||||||
|
|
||||||
void RegisterMoonJumpOnL() {
|
void RegisterMoonJumpOnL() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
if (!gPlayState) return;
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gMoonJumpOnL", 0) != 0) {
|
if (CVarGetInteger("gMoonJumpOnL", 0) != 0) {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
@@ -136,7 +141,7 @@ void RegisterMoonJumpOnL() {
|
|||||||
|
|
||||||
void RegisterInfiniteISG() {
|
void RegisterInfiniteISG() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
if (!gPlayState) return;
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gEzISG", 0) != 0) {
|
if (CVarGetInteger("gEzISG", 0) != 0) {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
@@ -148,7 +153,7 @@ void RegisterInfiniteISG() {
|
|||||||
//Permanent quick put away (QPA) glitched damage value
|
//Permanent quick put away (QPA) glitched damage value
|
||||||
void RegisterEzQPA() {
|
void RegisterEzQPA() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
if (!gPlayState) return;
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gEzQPA", 0) != 0) {
|
if (CVarGetInteger("gEzQPA", 0) != 0) {
|
||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
@@ -160,7 +165,7 @@ void RegisterEzQPA() {
|
|||||||
|
|
||||||
void RegisterUnrestrictedItems() {
|
void RegisterUnrestrictedItems() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
if (!gPlayState) return;
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
|
|
||||||
if (CVarGetInteger("gNoRestrictItems", 0) != 0) {
|
if (CVarGetInteger("gNoRestrictItems", 0) != 0) {
|
||||||
u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
|
u8 sunsBackup = gPlayState->interfaceCtx.restrictions.sunsSong;
|
||||||
@@ -189,13 +194,18 @@ void RegisterFreezeTime() {
|
|||||||
void RegisterSwitchAge() {
|
void RegisterSwitchAge() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>([]() {
|
||||||
static bool warped = false;
|
static bool warped = false;
|
||||||
|
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true)) {
|
||||||
|
CVarClear("gSwitchAge");
|
||||||
|
warped = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static Vec3f playerPos;
|
static Vec3f playerPos;
|
||||||
static int16_t playerYaw;
|
static int16_t playerYaw;
|
||||||
static RoomContext* roomCtx;
|
static RoomContext* roomCtx;
|
||||||
static s32 roomNum;
|
static s32 roomNum;
|
||||||
|
|
||||||
if (!gPlayState) return;
|
|
||||||
|
|
||||||
if (CVarGetInteger("gSwitchAge", 0) && !warped) {
|
if (CVarGetInteger("gSwitchAge", 0) && !warped) {
|
||||||
playerPos = GET_PLAYER(gPlayState)->actor.world.pos;
|
playerPos = GET_PLAYER(gPlayState)->actor.world.pos;
|
||||||
playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y;
|
playerYaw = GET_PLAYER(gPlayState)->actor.shape.rot.y;
|
||||||
@@ -215,7 +225,7 @@ void RegisterSwitchAge() {
|
|||||||
func_80097534(gPlayState, roomCtx); // load map for new room (unloading the previous room)
|
func_80097534(gPlayState, roomCtx); // load map for new room (unloading the previous room)
|
||||||
}
|
}
|
||||||
warped = false;
|
warped = false;
|
||||||
CVarSetInteger("gSwitchAge", 0);
|
CVarClear("gSwitchAge");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -224,7 +234,8 @@ void RegisterSwitchAge() {
|
|||||||
void RegisterOcarinaTimeTravel() {
|
void RegisterOcarinaTimeTravel() {
|
||||||
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOcarinaSongAction>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnOcarinaSongAction>([]() {
|
||||||
if (!gPlayState) {
|
if (!GameInteractor::IsSaveLoaded(true)) {
|
||||||
|
CVarClear("gTimeTravel");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,8 +1036,16 @@ void RegisterRandomizedEnemySizes() {
|
|||||||
Player* player = GET_PLAYER(gPlayState);
|
Player* player = GET_PLAYER(gPlayState);
|
||||||
Actor* actor = static_cast<Actor*>(refActor);
|
Actor* actor = static_cast<Actor*>(refActor);
|
||||||
|
|
||||||
// Only apply to enemies and bosses. Exclude the wobbly platforms in Jabu because they need to act like platforms.
|
// Exclude wobbly platforms in Jabu because they need to act like platforms.
|
||||||
if (!CVarGetInteger("gRandomizedEnemySizes", 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || actor->id == ACTOR_EN_BROB) {
|
// Exclude Dead Hand hands and Bongo Bongo main body because they make the fights (near) impossible.
|
||||||
|
uint8_t excludedEnemy = actor->id == ACTOR_EN_BROB || actor->id == ACTOR_EN_DHA || (actor->id == ACTOR_BOSS_SST && actor->params == -1);
|
||||||
|
|
||||||
|
// Dodongo, Volvagia and Dead Hand are always smaller because they're impossible when bigger.
|
||||||
|
uint8_t smallOnlyEnemy = actor->id == ACTOR_BOSS_DODONGO || actor->id == ACTOR_BOSS_FD ||
|
||||||
|
actor->id == ACTOR_BOSS_FD2 || actor->id == ACTOR_EN_DH;
|
||||||
|
|
||||||
|
// Only apply to enemies and bosses.
|
||||||
|
if (!CVarGetInteger("gRandomizedEnemySizes", 0) || (actor->category != ACTORCAT_ENEMY && actor->category != ACTORCAT_BOSS) || excludedEnemy) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,9 +1054,8 @@ void RegisterRandomizedEnemySizes() {
|
|||||||
|
|
||||||
uint8_t bigActor = rand() % 2;
|
uint8_t bigActor = rand() % 2;
|
||||||
|
|
||||||
// Big actor. Dodongo and Volvagia are always smaller because they're impossible when bigger.
|
// Big actor
|
||||||
if (bigActor && actor->id != ACTOR_BOSS_DODONGO && actor->id != ACTOR_BOSS_FD &&
|
if (bigActor && !smallOnlyEnemy) {
|
||||||
actor->id != ACTOR_BOSS_FD2) {
|
|
||||||
randomNumber = rand() % 200;
|
randomNumber = rand() % 200;
|
||||||
// Between 100% and 300% size.
|
// Between 100% and 300% size.
|
||||||
randomScale = 1.0f + (randomNumber / 100);
|
randomScale = 1.0f + (randomNumber / 100);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -205,6 +211,8 @@ const std::vector<const char*> enhancementsCvars = {
|
|||||||
"gDisableLOD",
|
"gDisableLOD",
|
||||||
"gDisableDrawDistance",
|
"gDisableDrawDistance",
|
||||||
"gDisableKokiriDrawDistance",
|
"gDisableKokiriDrawDistance",
|
||||||
|
"gEnhancements.WidescreenActorCulling",
|
||||||
|
"gEnhancements.ExtendedCullingExcludeGlitchActors",
|
||||||
"gLowResMode",
|
"gLowResMode",
|
||||||
"gDrawLineupTick",
|
"gDrawLineupTick",
|
||||||
"gQuickBongoKill",
|
"gQuickBongoKill",
|
||||||
@@ -217,6 +225,31 @@ const std::vector<const char*> enhancementsCvars = {
|
|||||||
"gFixTexturesOOB",
|
"gFixTexturesOOB",
|
||||||
"gIvanCoopModeEnabled",
|
"gIvanCoopModeEnabled",
|
||||||
"gEnemySpawnsOverWaterboxes",
|
"gEnemySpawnsOverWaterboxes",
|
||||||
|
"gTreeStickDrops",
|
||||||
|
"gShadowTag",
|
||||||
|
"gRandomizedEnemySizes",
|
||||||
|
"gRandomizedEnemies",
|
||||||
|
"gMirroredWorldMode",
|
||||||
|
"gMirroredWorld",
|
||||||
|
"gHyperEnemies",
|
||||||
|
"gHookshotableReticle",
|
||||||
|
"gHideBunnyHood",
|
||||||
|
"gFixVineFall",
|
||||||
|
"gFileSelectMoreInfo",
|
||||||
|
"gEnemyHealthBar",
|
||||||
|
"gBushDropFix",
|
||||||
|
"gAllDogsRichard",
|
||||||
|
"gAddTraps.enabled",
|
||||||
|
"gAddTraps.Ammo",
|
||||||
|
"gAddTraps.Bomb",
|
||||||
|
"gAddTraps.Burn",
|
||||||
|
"gAddTraps.Ice",
|
||||||
|
"gAddTraps.Kill",
|
||||||
|
"gAddTraps.Knock",
|
||||||
|
"gAddTraps.Shock",
|
||||||
|
"gAddTraps.Speed",
|
||||||
|
"gAddTraps.Tele",
|
||||||
|
"gAddTraps.Void",
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<const char*> cheatCvars = {
|
const std::vector<const char*> cheatCvars = {
|
||||||
@@ -269,7 +302,23 @@ const std::vector<const char*> cheatCvars = {
|
|||||||
"gNoRedeadFreeze",
|
"gNoRedeadFreeze",
|
||||||
"gBombTimerMultiplier",
|
"gBombTimerMultiplier",
|
||||||
"gNoFishDespawn",
|
"gNoFishDespawn",
|
||||||
"gNoBugsDespawn"
|
"gNoBugsDespawn",
|
||||||
|
"gWalkModifierDoesntChangeJump",
|
||||||
|
"gStatsEnabled",
|
||||||
|
"gSaveStatesEnabled",
|
||||||
|
"gSaveStatePromise",
|
||||||
|
"gRegEditEnabled",
|
||||||
|
"gPreset0",
|
||||||
|
"gPreset1",
|
||||||
|
"gDekuStickCheat",
|
||||||
|
"gDebugWarpScreenTranslation",
|
||||||
|
"gDebugSaveFileMode",
|
||||||
|
"gCosmetics.Link_BodyScale.Changed",
|
||||||
|
"gCosmetics.Link_BodyScale.Value",
|
||||||
|
"gCosmetics.Link_HeadScale.Changed",
|
||||||
|
"gCosmetics.Link_HeadScale.Value",
|
||||||
|
"gCosmetics.Link_SwordScale.Changed",
|
||||||
|
"gCosmetics.Link_SwordScale.Value",
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<const char*> randomizerCvars = {
|
const std::vector<const char*> randomizerCvars = {
|
||||||
@@ -399,6 +448,15 @@ const std::vector<const char*> randomizerCvars = {
|
|||||||
"gRandomizeGregHint",
|
"gRandomizeGregHint",
|
||||||
"gRandoManualSeedEntry",
|
"gRandoManualSeedEntry",
|
||||||
"gRandomizerSettingsEnabled",
|
"gRandomizerSettingsEnabled",
|
||||||
|
"gRandomizeTriforceHuntTotalPieces",
|
||||||
|
"gRandomizeTriforceHuntRequiredPieces",
|
||||||
|
"gRandomizeTriforceHunt",
|
||||||
|
"gRandomizeShuffleMasterSword",
|
||||||
|
"gRandomizeSariaHint",
|
||||||
|
"gRandomizeRupeeNames",
|
||||||
|
"gRandomizeFrogsHint",
|
||||||
|
"gRandoRelevantNavi",
|
||||||
|
"gRandoQuestItemFanfares",
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::vector<PresetEntry> vanillaPlusPresetEntries = {
|
const std::vector<PresetEntry> vanillaPlusPresetEntries = {
|
||||||
@@ -816,7 +874,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),
|
||||||
@@ -908,7 +967,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),
|
||||||
@@ -961,7 +1021,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),
|
||||||
|
|||||||
@@ -846,10 +846,10 @@ static void RandomizeDungeonItems() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) {
|
if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) {
|
||||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; });
|
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; });
|
||||||
AddElementsToPool(anyDungeonItems, gerudoKeys);
|
AddElementsToPool(anyDungeonItems, gerudoKeys);
|
||||||
} else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) {
|
} else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) {
|
||||||
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; });
|
auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; });
|
||||||
AddElementsToPool(overworldItems, gerudoKeys);
|
AddElementsToPool(overworldItems, gerudoKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ void LocationTable_Init() {
|
|||||||
|
|
||||||
//Lost Woods
|
//Lost Woods
|
||||||
locationTable[LW_NEAR_SHORTCUTS_GROTTO_CHEST] = ItemLocation::Chest (RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, 0x3E, 0x14, "LW Near Shortcuts Grotto Chest", LW_NEAR_SHORTCUTS_GROTTO_CHEST, BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_NEAR_SHORTCUTS_GROTTO_CHEST] = ItemLocation::Chest (RC_LW_NEAR_SHORTCUTS_GROTTO_CHEST, 0x3E, 0x14, "LW Near Shortcuts Grotto Chest", LW_NEAR_SHORTCUTS_GROTTO_CHEST, BLUE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_SKULL_KID] = ItemLocation::Base (RC_LW_SKULL_KID, 0x5B, "LW Skull Kid", LW_SKULL_KID, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(30), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_SKULL_KID] = ItemLocation::Base (RC_LW_SKULL_KID, 0x5B, "LW Skull Kid", LW_SKULL_KID, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(22), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_TRADE_COJIRO] = ItemLocation::Base (RC_LW_TRADE_COJIRO, 0x5B, "LW Trade Cojiro", LW_TRADE_COJIRO, ODD_MUSHROOM, {Category::cAdultTrade}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_TRADE_COJIRO] = ItemLocation::Base (RC_LW_TRADE_COJIRO, 0x5B, "LW Trade Cojiro", LW_TRADE_COJIRO, ODD_MUSHROOM, {Category::cAdultTrade}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_TRADE_ODD_POTION] = ItemLocation::Base (RC_LW_TRADE_ODD_POTION, 0x5B, "LW Trade Odd Potion", LW_TRADE_ODD_POTION, ODD_POTION, {Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(57), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_TRADE_ODD_POTION] = ItemLocation::Base (RC_LW_TRADE_ODD_POTION, 0x5B, "LW Trade Odd Potion", LW_TRADE_ODD_POTION, ODD_POTION, {Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(49), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_OCARINA_MEMORY_GAME] = ItemLocation::Base (RC_LW_OCARINA_MEMORY_GAME, 0x5B, "LW Ocarina Memory Game", LW_OCARINA_MEMORY_GAME, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(31), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_OCARINA_MEMORY_GAME] = ItemLocation::Base (RC_LW_OCARINA_MEMORY_GAME, 0x5B, "LW Ocarina Memory Game", LW_OCARINA_MEMORY_GAME, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(23), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_TARGET_IN_WOODS] = ItemLocation::Base (RC_LW_TARGET_IN_WOODS, 0x5B, "LW Target in Woods", LW_TARGET_IN_WOODS, PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_TARGET_IN_WOODS] = ItemLocation::Base (RC_LW_TARGET_IN_WOODS, 0x5B, "LW Target in Woods", LW_TARGET_IN_WOODS, PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = ItemLocation::Base (RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, 0x5B, "LW Deku Scrub Near Deku Theater Right",LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, BUY_DEKU_NUT_5, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT] = ItemLocation::Base (RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, 0x5B, "LW Deku Scrub Near Deku Theater Right",LW_DEKU_SCRUB_NEAR_DEKU_THEATER_RIGHT, BUY_DEKU_NUT_5, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = ItemLocation::Base (RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, 0x5B, "LW Deku Scrub Near Deku Theater Left", LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, BUY_DEKU_STICK_1, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT] = ItemLocation::Base (RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, 0x5B, "LW Deku Scrub Near Deku Theater Left", LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, BUY_DEKU_STICK_1, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
locationTable[LW_DEKU_SCRUB_NEAR_BRIDGE] = ItemLocation::Base (RC_LW_DEKU_SCRUB_NEAR_BRIDGE, 0x5B, "LW Deku Scrub Near Bridge", LW_DEKU_SCRUB_NEAR_BRIDGE, PROGRESSIVE_STICK_UPGRADE, {Category::cDekuScrub, Category::cDekuScrubUpgrades}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
locationTable[LW_DEKU_SCRUB_NEAR_BRIDGE] = ItemLocation::Base (RC_LW_DEKU_SCRUB_NEAR_BRIDGE, 0x5B, "LW Deku Scrub Near Bridge", LW_DEKU_SCRUB_NEAR_BRIDGE, PROGRESSIVE_STICK_UPGRADE, {Category::cDekuScrub, Category::cDekuScrubUpgrades}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LOST_WOODS);
|
||||||
@@ -53,7 +53,7 @@ void LocationTable_Init() {
|
|||||||
//Lake Hylia
|
//Lake Hylia
|
||||||
locationTable[LH_CHILD_FISHING] = ItemLocation::Base (RC_LH_CHILD_FISHING, 0x49, "LH Child Fishing", LH_CHILD_FISHING, PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
locationTable[LH_CHILD_FISHING] = ItemLocation::Base (RC_LH_CHILD_FISHING, 0x49, "LH Child Fishing", LH_CHILD_FISHING, PIECE_OF_HEART, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
||||||
locationTable[LH_ADULT_FISHING] = ItemLocation::Base (RC_LH_ADULT_FISHING, 0x49, "LH Adult Fishing", LH_ADULT_FISHING, PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
locationTable[LH_ADULT_FISHING] = ItemLocation::Base (RC_LH_ADULT_FISHING, 0x49, "LH Adult Fishing", LH_ADULT_FISHING, PROGRESSIVE_SCALE, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
||||||
locationTable[LH_LAB_DIVE] = ItemLocation::Base (RC_LH_LAB_DIVE, 0x38, "LH Lab Dive", LH_LAB_DIVE, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(24), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
locationTable[LH_LAB_DIVE] = ItemLocation::Base (RC_LH_LAB_DIVE, 0x38, "LH Lab Dive", LH_LAB_DIVE, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(16), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
||||||
locationTable[LH_TRADE_FROG] = ItemLocation::Base (RC_LH_TRADE_FROG, 0x38, "LH Lab Trade Eyeball Frog", LH_TRADE_FROG, EYEDROPS, {Category::cAdultTrade}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
locationTable[LH_TRADE_FROG] = ItemLocation::Base (RC_LH_TRADE_FROG, 0x38, "LH Lab Trade Eyeball Frog", LH_TRADE_FROG, EYEDROPS, {Category::cAdultTrade}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
||||||
locationTable[LH_UNDERWATER_ITEM] = ItemLocation::Base (RC_LH_UNDERWATER_ITEM, 0x57, "LH Underwater Item", LH_UNDERWATER_ITEM, RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
locationTable[LH_UNDERWATER_ITEM] = ItemLocation::Base (RC_LH_UNDERWATER_ITEM, 0x57, "LH Underwater Item", LH_UNDERWATER_ITEM, RUTOS_LETTER, {}, SpoilerCollectionCheck::EventChkInf(0x31), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
||||||
locationTable[LH_SUN] = ItemLocation::Base (RC_LH_SUN, 0x57, "LH Sun", LH_SUN, FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
locationTable[LH_SUN] = ItemLocation::Base (RC_LH_SUN, 0x57, "LH Sun", LH_SUN, FIRE_ARROWS, {}, SpoilerCollectionCheck::Chest(0x57, 0x1F), SpoilerCollectionCheckGroup::GROUP_LAKE_HYLIA);
|
||||||
@@ -73,7 +73,7 @@ void LocationTable_Init() {
|
|||||||
//Gerudo Fortress
|
//Gerudo Fortress
|
||||||
locationTable[GF_CHEST] = ItemLocation::Chest (RC_GF_CHEST, 0x5D, 0x00, "GF Chest", GF_CHEST, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[GF_CHEST] = ItemLocation::Chest (RC_GF_CHEST, 0x5D, 0x00, "GF Chest", GF_CHEST, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
locationTable[GF_HBA_1000_POINTS] = ItemLocation::Base (RC_GF_HBA_1000_POINTS, 0x5D, "GF HBA 1000 Points", GF_HBA_1000_POINTS, PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[GF_HBA_1000_POINTS] = ItemLocation::Base (RC_GF_HBA_1000_POINTS, 0x5D, "GF HBA 1000 Points", GF_HBA_1000_POINTS, PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x08), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
locationTable[GF_HBA_1500_POINTS] = ItemLocation::Base (RC_GF_HBA_1500_POINTS, 0x5D, "GF HBA 1500 Points", GF_HBA_1500_POINTS, PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(7), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[GF_HBA_1500_POINTS] = ItemLocation::Base (RC_GF_HBA_1500_POINTS, 0x5D, "GF HBA 1500 Points", GF_HBA_1500_POINTS, PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::ItemGetInf(15), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
locationTable[GF_GERUDO_MEMBERSHIP_CARD] = ItemLocation::Base (RC_GF_GERUDO_MEMBERSHIP_CARD, 0x0C, "GF Gerudo Membership Card", GF_GERUDO_MEMBERSHIP_CARD, GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[GF_GERUDO_MEMBERSHIP_CARD] = ItemLocation::Base (RC_GF_GERUDO_MEMBERSHIP_CARD, 0x0C, "GF Gerudo Membership Card", GF_GERUDO_MEMBERSHIP_CARD, GERUDO_MEMBERSHIP_CARD, {}, SpoilerCollectionCheck::GerudoToken(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
locationTable[GF_NORTH_F1_CARPENTER] = ItemLocation::Collectable(RC_GF_NORTH_F1_CARPENTER, 0x0C, 0x0C, "GF North F1 Carpenter", GF_NORTH_F1_CARPENTER, GERUDO_FORTRESS_SMALL_KEY, {Category::cVanillaGFSmallKey}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[GF_NORTH_F1_CARPENTER] = ItemLocation::Collectable(RC_GF_NORTH_F1_CARPENTER, 0x0C, 0x0C, "GF North F1 Carpenter", GF_NORTH_F1_CARPENTER, GERUDO_FORTRESS_SMALL_KEY, {Category::cVanillaGFSmallKey}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
locationTable[GF_NORTH_F2_CARPENTER] = ItemLocation::Collectable(RC_GF_NORTH_F2_CARPENTER, 0x0C, 0x0A, "GF North F2 Carpenter", GF_NORTH_F2_CARPENTER, GERUDO_FORTRESS_SMALL_KEY, {Category::cVanillaGFSmallKey}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[GF_NORTH_F2_CARPENTER] = ItemLocation::Collectable(RC_GF_NORTH_F2_CARPENTER, 0x0C, 0x0A, "GF North F2 Carpenter", GF_NORTH_F2_CARPENTER, GERUDO_FORTRESS_SMALL_KEY, {Category::cVanillaGFSmallKey}, SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
@@ -90,12 +90,12 @@ void LocationTable_Init() {
|
|||||||
locationTable[COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = ItemLocation::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, 0xFD, "Colossus Deku Scrub Grotto Front", COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, BUY_GREEN_POTION, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
locationTable[COLOSSUS_DEKU_SCRUB_GROTTO_FRONT] = ItemLocation::GrottoScrub(RC_COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, 0xFD, "Colossus Deku Scrub Grotto Front", COLOSSUS_DEKU_SCRUB_GROTTO_FRONT, BUY_GREEN_POTION, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_GERUDO_VALLEY);
|
||||||
|
|
||||||
//Market
|
//Market
|
||||||
locationTable[MARKET_TREASURE_CHEST_GAME_REWARD] = ItemLocation::Chest (RC_MARKET_TREASURE_CHEST_GAME_REWARD, 0x10, "MK Treasure Chest Game Reward", MARKET_TREASURE_CHEST_GAME_REWARD, TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(19), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_TREASURE_CHEST_GAME_REWARD] = ItemLocation::Chest (RC_MARKET_TREASURE_CHEST_GAME_REWARD, 0x10, "MK Treasure Chest Game Reward", MARKET_TREASURE_CHEST_GAME_REWARD, TREASURE_GAME_HEART, {}, SpoilerCollectionCheck::ItemGetInf(27), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = ItemLocation::Base (RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, 0x4B, "MK Bombchu Bowling First Prize", MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(25), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_BOMBCHU_BOWLING_FIRST_PRIZE] = ItemLocation::Base (RC_MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, 0x4B, "MK Bombchu Bowling First Prize", MARKET_BOMBCHU_BOWLING_FIRST_PRIZE, PROGRESSIVE_BOMB_BAG, {}, SpoilerCollectionCheck::ItemGetInf(17), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = ItemLocation::Base (RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, 0x4B, "MK Bombchu Bowling Second Prize", MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(26), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_BOMBCHU_BOWLING_SECOND_PRIZE] = ItemLocation::Base (RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, 0x4B, "MK Bombchu Bowling Second Prize", MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(18), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_BOMBCHU_BOWLING_BOMBCHUS] = ItemLocation::Base (RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, 0x4B, "MK Bombchu Bowling Bombchus", NONE, BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_BOMBCHU_BOWLING_BOMBCHUS] = ItemLocation::Base (RC_MARKET_BOMBCHU_BOWLING_BOMBCHUS, 0x4B, "MK Bombchu Bowling Bombchus", NONE, BOMBCHU_DROP, {}, SpoilerCollectionCheck::None(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_LOST_DOG] = ItemLocation::Base (RC_MARKET_LOST_DOG, 0x35, "MK Lost Dog", MARKET_LOST_DOG, PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_LOST_DOG] = ItemLocation::Base (RC_MARKET_LOST_DOG, 0x35, "MK Lost Dog", MARKET_LOST_DOG, PIECE_OF_HEART, {}, SpoilerCollectionCheck::InfTable(0x19, 0x09), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_SHOOTING_GALLERY_REWARD] = ItemLocation::Base (RC_MARKET_SHOOTING_GALLERY_REWARD, 0x42, "MK Shooting Gallery", MARKET_SHOOTING_GALLERY_REWARD, PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(5), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_SHOOTING_GALLERY_REWARD] = ItemLocation::Base (RC_MARKET_SHOOTING_GALLERY_REWARD, 0x42, "MK Shooting Gallery", MARKET_SHOOTING_GALLERY_REWARD, PROGRESSIVE_SLINGSHOT, {}, SpoilerCollectionCheck::ItemGetInf(13), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_10_BIG_POES] = ItemLocation::Base (RC_MARKET_10_BIG_POES, 0x4D, "MK 10 Big Poes", MARKET_10_BIG_POES, EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_10_BIG_POES] = ItemLocation::Base (RC_MARKET_10_BIG_POES, 0x4D, "MK 10 Big Poes", MARKET_10_BIG_POES, EMPTY_BOTTLE, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_TREASURE_CHEST_GAME_ITEM_1] = ItemLocation::Chest (RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, 0x10, 0x01, "MK Chest Game First Room Chest", MARKET_TREASURE_CHEST_GAME_ITEM_1, TREASURE_GAME_SMALL_KEY, {Category::cChestMinigame}, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_TREASURE_CHEST_GAME_ITEM_1] = ItemLocation::Chest (RC_MARKET_TREASURE_CHEST_GAME_ITEM_1, 0x10, 0x01, "MK Chest Game First Room Chest", MARKET_TREASURE_CHEST_GAME_ITEM_1, TREASURE_GAME_SMALL_KEY, {Category::cChestMinigame}, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
locationTable[MARKET_TREASURE_CHEST_GAME_ITEM_2] = ItemLocation::Chest (RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, 0x10, 0x03, "MK Chest Game Second Room Chest", MARKET_TREASURE_CHEST_GAME_ITEM_2, TREASURE_GAME_SMALL_KEY, {Category::cChestMinigame}, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
locationTable[MARKET_TREASURE_CHEST_GAME_ITEM_2] = ItemLocation::Chest (RC_MARKET_TREASURE_CHEST_GAME_ITEM_2, 0x10, 0x03, "MK Chest Game Second Room Chest", MARKET_TREASURE_CHEST_GAME_ITEM_2, TREASURE_GAME_SMALL_KEY, {Category::cChestMinigame}, SpoilerCollectionCheckGroup::GROUP_HYRULE_CASTLE);
|
||||||
@@ -115,14 +115,14 @@ void LocationTable_Init() {
|
|||||||
locationTable[KAK_30_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_30_GOLD_SKULLTULA_REWARD, 0x50, "Kak 30 Gold Skulltula Reward", KAK_30_GOLD_SKULLTULA_REWARD, PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_30_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_30_GOLD_SKULLTULA_REWARD, 0x50, "Kak 30 Gold Skulltula Reward", KAK_30_GOLD_SKULLTULA_REWARD, PROGRESSIVE_WALLET, {}, SpoilerCollectionCheck::EventChkInf(0xDC), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_40_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_40_GOLD_SKULLTULA_REWARD, 0x50, "Kak 40 Gold Skulltula Reward", KAK_40_GOLD_SKULLTULA_REWARD, BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_40_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_40_GOLD_SKULLTULA_REWARD, 0x50, "Kak 40 Gold Skulltula Reward", KAK_40_GOLD_SKULLTULA_REWARD, BOMBCHU_10, {}, SpoilerCollectionCheck::EventChkInf(0xDD), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_50_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_50_GOLD_SKULLTULA_REWARD, 0x50, "Kak 50 Gold Skulltula Reward", KAK_50_GOLD_SKULLTULA_REWARD, PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_50_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_50_GOLD_SKULLTULA_REWARD, 0x50, "Kak 50 Gold Skulltula Reward", KAK_50_GOLD_SKULLTULA_REWARD, PIECE_OF_HEART, {}, SpoilerCollectionCheck::EventChkInf(0xDE), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_100_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_100_GOLD_SKULLTULA_REWARD, 0x50, "Kak 100 Gold Skulltula Reward", KAK_100_GOLD_SKULLTULA_REWARD, HUGE_RUPEE, {}, SpoilerCollectionCheck::EventChkInf(0xDF), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_100_GOLD_SKULLTULA_REWARD] = ItemLocation::Base (RC_KAK_100_GOLD_SKULLTULA_REWARD, 0x50, "Kak 100 Gold Skulltula Reward", KAK_100_GOLD_SKULLTULA_REWARD, HUGE_RUPEE, {}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_MAN_ON_ROOF] = ItemLocation::Base (RC_KAK_MAN_ON_ROOF, 0x52, "Kak Man on Roof", KAK_MAN_ON_ROOF, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(29), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_MAN_ON_ROOF] = ItemLocation::Base (RC_KAK_MAN_ON_ROOF, 0x52, "Kak Man on Roof", KAK_MAN_ON_ROOF, PIECE_OF_HEART, {}, SpoilerCollectionCheck::ItemGetInf(21), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_SHOOTING_GALLERY_REWARD] = ItemLocation::Base (RC_KAK_SHOOTING_GALLERY_REWARD, 0x42, "Kak Shooting Gallery Reward", KAK_SHOOTING_GALLERY_REWARD, PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_SHOOTING_GALLERY_REWARD] = ItemLocation::Base (RC_KAK_SHOOTING_GALLERY_REWARD, 0x42, "Kak Shooting Gallery Reward", KAK_SHOOTING_GALLERY_REWARD, PROGRESSIVE_BOW, {}, SpoilerCollectionCheck::Chest(0x42, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_TRADE_ODD_MUSHROOM] = ItemLocation::Base (RC_KAK_TRADE_ODD_MUSHROOM, 0x4E, "Kak Trade Odd Mushroom", KAK_TRADE_ODD_MUSHROOM, ODD_POTION, {Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(56), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_TRADE_ODD_MUSHROOM] = ItemLocation::Base (RC_KAK_TRADE_ODD_MUSHROOM, 0x4E, "Kak Trade Odd Mushroom", KAK_TRADE_ODD_MUSHROOM, ODD_POTION, {Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(48), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_GRANNYS_SHOP] = ItemLocation::Base (RC_KAK_GRANNYS_SHOP, 0x4E, "Kak Granny's Shop", KAK_GRANNYS_SHOP, BLUE_POTION_REFILL, {Category::cMerchant}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_GRANNYS_SHOP] = ItemLocation::Base (RC_KAK_GRANNYS_SHOP, 0x4E, "Kak Granny's Shop", KAK_GRANNYS_SHOP, BLUE_POTION_REFILL, {Category::cMerchant}, SpoilerCollectionCheck::RandomizerInf(), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_ANJU_AS_ADULT] = ItemLocation::Base (RC_KAK_ANJU_AS_ADULT, 0x52, "Kak Anju as Adult", KAK_ANJU_AS_ADULT, CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(36), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_ANJU_AS_ADULT] = ItemLocation::Base (RC_KAK_ANJU_AS_ADULT, 0x52, "Kak Anju as Adult", KAK_ANJU_AS_ADULT, CLAIM_CHECK, {}, SpoilerCollectionCheck::ItemGetInf(44), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_ANJU_AS_CHILD] = ItemLocation::Base (RC_KAK_ANJU_AS_CHILD, 0x52, "Kak Anju as Child", KAK_ANJU_AS_CHILD, EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(4), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_ANJU_AS_CHILD] = ItemLocation::Base (RC_KAK_ANJU_AS_CHILD, 0x52, "Kak Anju as Child", KAK_ANJU_AS_CHILD, EMPTY_BOTTLE, {}, SpoilerCollectionCheck::ItemGetInf(12), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_TRADE_POCKET_CUCCO] = ItemLocation::Base (RC_KAK_TRADE_POCKET_CUCCO, 0x52, "Kak Trade Pocket Cucco", KAK_TRADE_POCKET_CUCCO, COJIRO, {Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(38), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_TRADE_POCKET_CUCCO] = ItemLocation::Base (RC_KAK_TRADE_POCKET_CUCCO, 0x52, "Kak Trade Pocket Cucco", KAK_TRADE_POCKET_CUCCO, COJIRO, {Category::cAdultTrade}, SpoilerCollectionCheck::ItemGetInf(46), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_IMPAS_HOUSE_FREESTANDING_POH] = ItemLocation::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, 0x37, 0x01, "Kak Impas House Freestanding PoH", KAK_IMPAS_HOUSE_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_IMPAS_HOUSE_FREESTANDING_POH] = ItemLocation::Collectable(RC_KAK_IMPAS_HOUSE_FREESTANDING_POH, 0x37, 0x01, "Kak Impas House Freestanding PoH", KAK_IMPAS_HOUSE_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[KAK_WINDMILL_FREESTANDING_POH] = ItemLocation::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, 0x48, 0x01, "Kak Windmill Freestanding PoH", KAK_WINDMILL_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[KAK_WINDMILL_FREESTANDING_POH] = ItemLocation::Collectable(RC_KAK_WINDMILL_FREESTANDING_POH, 0x48, 0x01, "Kak Windmill Freestanding PoH", KAK_WINDMILL_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ void LocationTable_Init() {
|
|||||||
locationTable[GRAVEYARD_HOOKSHOT_CHEST] = ItemLocation::Chest (RC_GRAVEYARD_HOOKSHOT_CHEST, 0x48, 0x00, "GY Hookshot Chest", GRAVEYARD_HOOKSHOT_CHEST, PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[GRAVEYARD_HOOKSHOT_CHEST] = ItemLocation::Chest (RC_GRAVEYARD_HOOKSHOT_CHEST, 0x48, 0x00, "GY Hookshot Chest", GRAVEYARD_HOOKSHOT_CHEST, PROGRESSIVE_HOOKSHOT, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = ItemLocation::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, 0x48, 0x07, "GY Dampe Race Freestanding PoH", GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[GRAVEYARD_DAMPE_RACE_FREESTANDING_POH] = ItemLocation::Collectable(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, 0x48, 0x07, "GY Dampe Race Freestanding PoH", GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[GRAVEYARD_FREESTANDING_POH] = ItemLocation::Collectable(RC_GRAVEYARD_FREESTANDING_POH, 0x53, 0x04, "GY Freestanding PoH", GRAVEYARD_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[GRAVEYARD_FREESTANDING_POH] = ItemLocation::Collectable(RC_GRAVEYARD_FREESTANDING_POH, 0x53, 0x04, "GY Freestanding PoH", GRAVEYARD_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
locationTable[GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = ItemLocation::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, 0x53, "GY Dampe Gravedigging Tour", GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, PIECE_OF_HEART, {}, SpoilerCollectionCheck::Gravedigger(0x53, 0x1F), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
locationTable[GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR] = ItemLocation::Collectable(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, 0x53, "GY Dampe Gravedigging Tour", GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, PIECE_OF_HEART, {}, SpoilerCollectionCheck::Gravedigger(0x53, 0x19), SpoilerCollectionCheckGroup::GROUP_KAKARIKO);
|
||||||
|
|
||||||
//Death Mountain
|
//Death Mountain
|
||||||
locationTable[DMT_CHEST] = ItemLocation::Chest (RC_DMT_CHEST, 0x60, 0x01, "DMT Chest", DMT_CHEST, PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN);
|
locationTable[DMT_CHEST] = ItemLocation::Chest (RC_DMT_CHEST, 0x60, 0x01, "DMT Chest", DMT_CHEST, PURPLE_RUPEE, {}, SpoilerCollectionCheckGroup::GROUP_DEATH_MOUNTAIN);
|
||||||
@@ -191,7 +191,7 @@ void LocationTable_Init() {
|
|||||||
locationTable[ZF_BOTTOM_FREESTANDING_POH] = ItemLocation::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, 0x59, 0x14, "ZF Bottom Freestanding PoH", ZF_BOTTOM_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
|
locationTable[ZF_BOTTOM_FREESTANDING_POH] = ItemLocation::Collectable(RC_ZF_BOTTOM_FREESTANDING_POH, 0x59, 0x14, "ZF Bottom Freestanding PoH", ZF_BOTTOM_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_ZORAS_DOMAIN);
|
||||||
|
|
||||||
//Lon Lon Ranch
|
//Lon Lon Ranch
|
||||||
locationTable[LLR_TALONS_CHICKENS] = ItemLocation::Base (RC_LLR_TALONS_CHICKENS, 0x4C, "LLR Talons Chickens", LLR_TALONS_CHICKENS, BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(10), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
locationTable[LLR_TALONS_CHICKENS] = ItemLocation::Base (RC_LLR_TALONS_CHICKENS, 0x4C, "LLR Talons Chickens", LLR_TALONS_CHICKENS, BOTTLE_WITH_MILK, {}, SpoilerCollectionCheck::ItemGetInf(2), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
||||||
locationTable[LLR_FREESTANDING_POH] = ItemLocation::Collectable(RC_LLR_FREESTANDING_POH, 0x4C, 0x01, "LLR Freestanding PoH", LLR_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
locationTable[LLR_FREESTANDING_POH] = ItemLocation::Collectable(RC_LLR_FREESTANDING_POH, 0x4C, 0x01, "LLR Freestanding PoH", LLR_FREESTANDING_POH, PIECE_OF_HEART, {}, SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
||||||
locationTable[LLR_DEKU_SCRUB_GROTTO_LEFT] = ItemLocation::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, 0xFC, "LLR Deku Scrub Grotto Left", LLR_DEKU_SCRUB_GROTTO_LEFT, BUY_DEKU_NUT_5, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
locationTable[LLR_DEKU_SCRUB_GROTTO_LEFT] = ItemLocation::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_LEFT, 0xFC, "LLR Deku Scrub Grotto Left", LLR_DEKU_SCRUB_GROTTO_LEFT, BUY_DEKU_NUT_5, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
||||||
locationTable[LLR_DEKU_SCRUB_GROTTO_RIGHT] = ItemLocation::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, 0xFC, "LLR Deku Scrub Grotto Right", LLR_DEKU_SCRUB_GROTTO_RIGHT, BUY_BOMBS_535, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
locationTable[LLR_DEKU_SCRUB_GROTTO_RIGHT] = ItemLocation::GrottoScrub(RC_LLR_DEKU_SCRUB_GROTTO_RIGHT, 0xFC, "LLR Deku Scrub Grotto Right", LLR_DEKU_SCRUB_GROTTO_RIGHT, BUY_BOMBS_535, {Category::cDekuScrub}, SpoilerCollectionCheck::Scrub(), SpoilerCollectionCheckGroup::GROUP_LON_LON_RANCH);
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ void AreaTable_Init_DeathMountain() {
|
|||||||
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
Entrance(DEATH_MOUNTAIN_TRAIL, {[]{return true;}}),
|
||||||
Entrance(GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}),
|
Entrance(GC_WOODS_WARP, {[]{return GCWoodsWarpOpen;}}),
|
||||||
Entrance(GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(BOW)));}}),
|
Entrance(GC_SHOP, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && (CanBlastOrSmash || GoronBracelet || GoronCityChildFire || CanUse(BOW)));}}),
|
||||||
Entrance(GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || GCDaruniasDoorOpenChild;}}),
|
Entrance(GC_DARUNIAS_CHAMBER, {[]{return (IsAdult && StopGCRollingGoronAsAdult) || (IsChild && GCDaruniasDoorOpenChild);}}),
|
||||||
Entrance(GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(GORON_TUNIC) || CanUse(LONGSHOT) || CanUse(NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(GORON_TUNIC) && CanUse(HOOKSHOT)) || (CanUse(NAYRUS_LOVE) && CanUse(HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(HOOKSHOT) && LogicGoronCityGrotto));}}),
|
Entrance(GC_GROTTO_PLATFORM, {[]{return IsAdult && ((CanPlay(SongOfTime) && ((EffectiveHealth > 2) || CanUse(GORON_TUNIC) || CanUse(LONGSHOT) || CanUse(NAYRUS_LOVE))) || (EffectiveHealth > 1 && CanUse(GORON_TUNIC) && CanUse(HOOKSHOT)) || (CanUse(NAYRUS_LOVE) && CanUse(HOOKSHOT)) || (EffectiveHealth > 2 && CanUse(HOOKSHOT) && LogicGoronCityGrotto));}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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, {}, {}, {
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ void AreaTable_Init_ForestTemple() {
|
|||||||
Entrance(FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}),
|
Entrance(FOREST_TEMPLE_WEST_CORRIDOR, {[]{return true;}}),
|
||||||
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}),
|
Entrance(FOREST_TEMPLE_NW_OUTDOORS_UPPER, {[]{return CanUse(HOVER_BOOTS) || (LogicForestOutsideBackdoor && CanJumpslash && GoronBracelet);}}),
|
||||||
Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}),
|
Entrance(FOREST_TEMPLE_NW_CORRIDOR_TWISTED, {[]{return IsAdult && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}),
|
||||||
Entrance(FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return (CanUse(BOW) || CanUse(SLINGSHOT)) && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}),
|
Entrance(FOREST_TEMPLE_NW_CORRIDOR_STRAIGHTENED, {[]{return IsAdult && (CanUse(BOW) || CanUse(SLINGSHOT)) && GoronBracelet && SmallKeys(FOREST_TEMPLE, 2);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
areaTable[FOREST_TEMPLE_NW_CORRIDOR_TWISTED] = Area("Forest Temple NW Corridor Twisted", "Forest Temple", FOREST_TEMPLE, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "playthrough.hpp"
|
#include "playthrough.hpp"
|
||||||
|
|
||||||
|
#include <libultraship/libultraship.h>
|
||||||
#include <boost_custom/container_hash/hash_32.hpp>
|
#include <boost_custom/container_hash/hash_32.hpp>
|
||||||
#include "custom_messages.hpp"
|
#include "custom_messages.hpp"
|
||||||
#include "fill.hpp"
|
#include "fill.hpp"
|
||||||
@@ -8,6 +9,7 @@
|
|||||||
#include "random.hpp"
|
#include "random.hpp"
|
||||||
#include "spoiler_log.hpp"
|
#include "spoiler_log.hpp"
|
||||||
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
#include "soh/Enhancements/randomizer/randomizerTypes.h"
|
||||||
|
#include "variables.h"
|
||||||
|
|
||||||
namespace Playthrough {
|
namespace Playthrough {
|
||||||
|
|
||||||
@@ -39,6 +41,10 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CVarGetInteger("gRandomizerDontGenerateSpoiler", 0)) {
|
||||||
|
settingsStr += (char*)gBuildVersion;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(Settings::seed) + settingsStr);
|
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(Settings::seed) + settingsStr);
|
||||||
Random_Init(finalHash);
|
Random_Init(finalHash);
|
||||||
Settings::hash = std::to_string(finalHash);
|
Settings::hash = std::to_string(finalHash);
|
||||||
|
|||||||
@@ -360,29 +360,12 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
|||||||
{ "Shuffle Dungeon Quest:Ganon's Castle", RSK_MQ_GANONS_CASTLE },
|
{ "Shuffle Dungeon Quest:Ganon's Castle", RSK_MQ_GANONS_CASTLE },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string sanitize(std::string stringValue) {
|
|
||||||
// Add backslashes.
|
|
||||||
for (auto i = stringValue.begin();;) {
|
|
||||||
auto const pos = std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; });
|
|
||||||
if (pos == stringValue.end()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i = std::next(stringValue.insert(pos, '\\'), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes others.
|
|
||||||
stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(), [](char const c) {
|
|
||||||
return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }), stringValue.end());
|
|
||||||
|
|
||||||
return stringValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma optimize("", off)
|
#pragma optimize("", off)
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
#pragma GCC optimize ("O0")
|
#pragma GCC optimize ("O0")
|
||||||
bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
|
bool Randomizer::SpoilerFileExists(const char* spoilerFileName) {
|
||||||
if (strcmp(spoilerFileName, "") != 0) {
|
if (strcmp(spoilerFileName, "") != 0) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream) {
|
if (!spoilerFileStream) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@@ -496,6 +479,13 @@ void Randomizer::LoadHintLocations(const char* spoilerFileName) {
|
|||||||
"Zu {{location}}?\x1B&%gOK&No%w\x02",
|
"Zu {{location}}?\x1B&%gOK&No%w\x02",
|
||||||
"Se téléporter vers&{{location}}?\x1B&%gOK!&Non%w\x02"));
|
"Se téléporter vers&{{location}}?\x1B&%gOK!&Non%w\x02"));
|
||||||
|
|
||||||
|
// Bow Shooting Gallery reminder
|
||||||
|
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW,
|
||||||
|
CustomMessage("Come back when you have your own&bow and you'll get a %rdifferent prize%w!",
|
||||||
|
"Komm wieder sobald du deinen eigenen&Bogen hast, um einen %rspeziellen Preis%w zu&erhalten!",
|
||||||
|
"J'aurai %rune autre récompense%w pour toi&lorsque tu auras ton propre arc."));
|
||||||
|
|
||||||
|
// Lake Hylia water level system
|
||||||
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN,
|
CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN,
|
||||||
CustomMessage("Water level control system.&Keep away!",
|
CustomMessage("Water level control system.&Keep away!",
|
||||||
"Wasserstand Kontrollsystem&Finger weg!",
|
"Wasserstand Kontrollsystem&Finger weg!",
|
||||||
@@ -659,7 +649,7 @@ void Randomizer::LoadMasterQuestDungeons(const char* spoilerFileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream)
|
if (!spoilerFileStream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1293,7 +1283,7 @@ std::string FormatJsonHintText(std::string jsonHint) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
|
void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream)
|
if (!spoilerFileStream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1394,7 +1384,7 @@ void Randomizer::ParseHintLocationsFile(const char* spoilerFileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Randomizer::ParseRequiredTrialsFile(const char* spoilerFileName) {
|
void Randomizer::ParseRequiredTrialsFile(const char* spoilerFileName) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream) {
|
if (!spoilerFileStream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1415,7 +1405,7 @@ void Randomizer::ParseRequiredTrialsFile(const char* spoilerFileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Randomizer::ParseMasterQuestDungeonsFile(const char* spoilerFileName) {
|
void Randomizer::ParseMasterQuestDungeonsFile(const char* spoilerFileName) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream) {
|
if (!spoilerFileStream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1495,7 +1485,7 @@ int16_t Randomizer::GetVanillaMerchantPrice(RandomizerCheck check) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent) {
|
void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream)
|
if (!spoilerFileStream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1558,7 +1548,7 @@ void Randomizer::ParseItemLocationsFile(const char* spoilerFileName, bool silent
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Randomizer::ParseEntranceDataFile(const char* spoilerFileName, bool silent) {
|
void Randomizer::ParseEntranceDataFile(const char* spoilerFileName, bool silent) {
|
||||||
std::ifstream spoilerFileStream(sanitize(spoilerFileName));
|
std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName));
|
||||||
if (!spoilerFileStream) {
|
if (!spoilerFileStream) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2547,6 +2537,7 @@ std::map<RandomizerCheck, RandomizerInf> rcToRandomizerInf = {
|
|||||||
{ RC_LH_CHILD_FISHING, RAND_INF_CHILD_FISHING },
|
{ RC_LH_CHILD_FISHING, RAND_INF_CHILD_FISHING },
|
||||||
{ RC_LH_ADULT_FISHING, RAND_INF_ADULT_FISHING },
|
{ RC_LH_ADULT_FISHING, RAND_INF_ADULT_FISHING },
|
||||||
{ RC_MARKET_10_BIG_POES, RAND_INF_10_BIG_POES },
|
{ RC_MARKET_10_BIG_POES, RAND_INF_10_BIG_POES },
|
||||||
|
{ RC_KAK_100_GOLD_SKULLTULA_REWARD, RAND_INF_KAK_100_GOLD_SKULLTULA_REWARD },
|
||||||
};
|
};
|
||||||
|
|
||||||
RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) {
|
RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) {
|
||||||
@@ -3143,7 +3134,9 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
|
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
|
DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
UIWidgets::EnhancementCheckbox("Manual seed entry", "gRandoManualSeedEntry", false, "");
|
UIWidgets::EnhancementCheckbox("Manual seed entry", "gRandoManualSeedEntry", false, "");
|
||||||
@@ -3166,13 +3159,17 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gRandomizerDontGenerateSpoiler", 0) && gSaveContext.gameMode != GAMEMODE_FILE_SELECT);
|
||||||
if (ImGui::Button("Generate Randomizer")) {
|
if (ImGui::Button("Generate Randomizer")) {
|
||||||
GenerateRandomizer(CVarGetInteger("gRandoManualSeedEntry", 0) ? seedString : "");
|
GenerateRandomizer(CVarGetInteger("gRandoManualSeedEntry", 0) ? seedString : "");
|
||||||
}
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
std::string spoilerfilepath = CVarGetString("gSpoilerLog", "");
|
if (!CVarGetInteger("gRandomizerDontGenerateSpoiler", 0)) {
|
||||||
ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str());
|
std::string spoilerfilepath = CVarGetString("gSpoilerLog", "");
|
||||||
|
ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// RANDOTODO settings presets
|
// RANDOTODO settings presets
|
||||||
// std::string presetfilepath = CVarGetString("gLoadedPreset", "");
|
// std::string presetfilepath = CVarGetString("gLoadedPreset", "");
|
||||||
@@ -3180,6 +3177,8 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
|
|
||||||
UIWidgets::PaddedSeparator();
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
|
|
||||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||||
static ImVec2 cellPadding(8.0f, 8.0f);
|
static ImVec2 cellPadding(8.0f, 8.0f);
|
||||||
|
|
||||||
@@ -4208,7 +4207,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",
|
||||||
@@ -4237,7 +4236,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",
|
||||||
@@ -4266,7 +4265,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",
|
||||||
@@ -4295,7 +4294,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",
|
||||||
@@ -4690,7 +4689,11 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
excludedLocationString += std::to_string(excludedLocationIt);
|
excludedLocationString += std::to_string(excludedLocationIt);
|
||||||
excludedLocationString += ",";
|
excludedLocationString += ",";
|
||||||
}
|
}
|
||||||
CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str());
|
if (excludedLocationString == "") {
|
||||||
|
CVarClear("gRandomizeExcludedLocations");
|
||||||
|
} else {
|
||||||
|
CVarSetString("gRandomizeExcludedLocations", excludedLocationString.c_str());
|
||||||
|
}
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -4867,7 +4870,7 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
enabledTrickString += std::to_string(enabledTrickIt);
|
enabledTrickString += std::to_string(enabledTrickIt);
|
||||||
enabledTrickString += ",";
|
enabledTrickString += ",";
|
||||||
}
|
}
|
||||||
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
|
CVarClear("gRandomizeEnabledTricks");
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -5071,7 +5074,7 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
enabledTrickString += std::to_string(enabledTrickIt);
|
enabledTrickString += std::to_string(enabledTrickIt);
|
||||||
enabledTrickString += ",";
|
enabledTrickString += ",";
|
||||||
}
|
}
|
||||||
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
|
CVarClear("gRandomizeEnabledTricks");
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5109,7 +5112,11 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
enabledTrickString += std::to_string(enabledTrickIt);
|
enabledTrickString += std::to_string(enabledTrickIt);
|
||||||
enabledTrickString += ",";
|
enabledTrickString += ",";
|
||||||
}
|
}
|
||||||
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
|
if (enabledTrickString == "") {
|
||||||
|
CVarClear("gRandomizeEnabledTricks");
|
||||||
|
} else {
|
||||||
|
CVarSetString("gRandomizeEnabledTricks", enabledTrickString.c_str());
|
||||||
|
}
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
||||||
}
|
}
|
||||||
DrawTagChips(*rtObject.rtTags);
|
DrawTagChips(*rtObject.rtTags);
|
||||||
@@ -5225,6 +5232,8 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
ImGui::EndTabBar();
|
ImGui::EndTabBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
if (disableEditingRandoSettings) {
|
if (disableEditingRandoSettings) {
|
||||||
UIWidgets::ReEnableComponent("");
|
UIWidgets::ReEnableComponent("");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
|
|||||||
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, GI_STICKS_1, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", false),
|
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_DEKU_THEATER_LEFT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x01, GI_STICKS_1, "Deku Scrub Near Deku Theater Left", "LW Deku Scrub Near Deku Theater Left", false),
|
||||||
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, GI_STICK_UPGRADE_20, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", true),
|
RC_OBJECT(RC_LW_DEKU_SCRUB_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_LOST_WOODS, 0x09, GI_STICK_UPGRADE_20, "Deku Scrub Near Bridge", "LW Deku Scrub Near Bridge", true),
|
||||||
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03,0xF5), GI_SEEDS_30, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", false),
|
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_REAR, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x03,0xF5), GI_SEEDS_30, "Deku Scrub Grotto Rear", "LW Deku Scrub Grotto Rear", false),
|
||||||
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A,0xF5), GI_NUT_UPGRADE_30, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", false),
|
RC_OBJECT(RC_LW_DEKU_SCRUB_GROTTO_FRONT, RCVORMQ_BOTH, RCTYPE_SCRUB, RCAREA_LOST_WOODS, ACTOR_EN_DNS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x0A,0xF5), GI_NUT_UPGRADE_30, "Deku Scrub Grotto Front", "LW Deku Scrub Grotto Front", true),
|
||||||
RC_OBJECT(RC_DEKU_THEATER_SKULL_MASK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, GI_NONE, "Deku Theater Skull Mask", "Deku Theater Skull Mask", true),
|
RC_OBJECT(RC_DEKU_THEATER_SKULL_MASK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, GI_NONE, "Deku Theater Skull Mask", "Deku Theater Skull Mask", true),
|
||||||
RC_OBJECT(RC_DEKU_THEATER_MASK_OF_TRUTH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, GI_NONE, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", true),
|
RC_OBJECT(RC_DEKU_THEATER_MASK_OF_TRUTH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_LOST_WOODS, ACTOR_ID_MAX, SCENE_GROTTOS, 0x00, GI_NONE, "Deku Theater Mask of Truth", "Deku Theater Mask of Truth", true),
|
||||||
RC_OBJECT(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LOST_WOODS, ACTOR_EN_SI, SCENE_LOST_WOODS, 27905, GI_SKULL_TOKEN, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", true),
|
RC_OBJECT(RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_LOST_WOODS, ACTOR_EN_SI, SCENE_LOST_WOODS, 27905, GI_SKULL_TOKEN, "GS Bean Patch Near Bridge", "LW GS Bean Patch Near Bridge", true),
|
||||||
@@ -238,7 +238,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
|
|||||||
RC_OBJECT(RC_GRAVEYARD_HOOKSHOT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, GI_HOOKSHOT, "Hookshot Chest", "GY Hookshot Chest", true),
|
RC_OBJECT(RC_GRAVEYARD_HOOKSHOT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_BOX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 4352, GI_HOOKSHOT, "Hookshot Chest", "GY Hookshot Chest", true),
|
||||||
RC_OBJECT(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, GI_HEART_PIECE, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", true),
|
RC_OBJECT(RC_GRAVEYARD_DAMPE_RACE_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_WINDMILL_AND_DAMPES_GRAVE, 1798, GI_HEART_PIECE, "Dampe Race Freestanding PoH", "GY Dampe Race Freestanding PoH", true),
|
||||||
RC_OBJECT(RC_GRAVEYARD_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, GI_HEART_PIECE, "Freestanding PoH", "GY Freestanding PoH", true),
|
RC_OBJECT(RC_GRAVEYARD_FREESTANDING_POH, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 1030, GI_HEART_PIECE, "Freestanding PoH", "GY Freestanding PoH", true),
|
||||||
RC_OBJECT(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 7942, GI_HEART_PIECE, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", true),
|
RC_OBJECT(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GRAVEYARD, ACTOR_EN_ITEM00, SCENE_GRAVEYARD, 6406, GI_HEART_PIECE, "Dampe Gravedigging Tour", "GY Dampe Gravedigging Tour", true),
|
||||||
RC_OBJECT(RC_GRAVEYARD_GS_WALL, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GRAVEYARD, ACTOR_EN_SI, SCENE_GRAVEYARD, 20608, GI_SKULL_TOKEN, "GS Wall", "Graveyard GS Wall", true),
|
RC_OBJECT(RC_GRAVEYARD_GS_WALL, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GRAVEYARD, ACTOR_EN_SI, SCENE_GRAVEYARD, 20608, GI_SKULL_TOKEN, "GS Wall", "Graveyard GS Wall", true),
|
||||||
RC_OBJECT(RC_GRAVEYARD_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GRAVEYARD, ACTOR_EN_SI, SCENE_GRAVEYARD, 28673, GI_SKULL_TOKEN, "GS Bean Patch", "Graveyard GS Bean Patch", true),
|
RC_OBJECT(RC_GRAVEYARD_GS_BEAN_PATCH, RCVORMQ_BOTH, RCTYPE_SKULL_TOKEN, RCAREA_GRAVEYARD, ACTOR_EN_SI, SCENE_GRAVEYARD, 28673, GI_SKULL_TOKEN, "GS Bean Patch", "Graveyard GS Bean Patch", true),
|
||||||
RC_OBJECT(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCVORMQ_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, "Song from Composers Grave", "Song from Composers Grave", true),
|
RC_OBJECT(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCVORMQ_BOTH, RCTYPE_SONG_LOCATION, RCAREA_GRAVEYARD, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, "Song from Composers Grave", "Song from Composers Grave", true),
|
||||||
|
|||||||
@@ -73,20 +73,12 @@ bool showLinksPocket;
|
|||||||
bool fortressFast;
|
bool fortressFast;
|
||||||
bool fortressNormal;
|
bool fortressNormal;
|
||||||
|
|
||||||
bool bypassRandoCheck = true;
|
|
||||||
// persistent during gameplay
|
// persistent during gameplay
|
||||||
bool initialized;
|
bool initialized;
|
||||||
bool doAreaScroll;
|
bool doAreaScroll;
|
||||||
bool previousShowHidden = false;
|
bool previousShowHidden = false;
|
||||||
bool hideShopRightChecks = true;
|
bool hideShopRightChecks = true;
|
||||||
|
bool alwaysShowGS = false;
|
||||||
bool checkCollected = false;
|
|
||||||
int checkLoops = 0;
|
|
||||||
int checkCounter = 0;
|
|
||||||
u16 savedFrames = 0;
|
|
||||||
bool messageCloseCheck = false;
|
|
||||||
bool pendingSaleCheck = false;
|
|
||||||
bool transitionCheck = false;
|
|
||||||
|
|
||||||
std::map<uint32_t, RandomizerCheck> startingShopItem = { { SCENE_KOKIRI_SHOP, RC_KF_SHOP_ITEM_1 },
|
std::map<uint32_t, RandomizerCheck> startingShopItem = { { SCENE_KOKIRI_SHOP, RC_KF_SHOP_ITEM_1 },
|
||||||
{ SCENE_BAZAAR, RC_MARKET_BAZAAR_ITEM_1 },
|
{ SCENE_BAZAAR, RC_MARKET_BAZAAR_ITEM_1 },
|
||||||
@@ -111,19 +103,34 @@ std::map<SceneID, RandomizerCheckArea> DungeonRCAreasBySceneID = {
|
|||||||
{SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE},
|
{SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Dungeon entrances with obvious visual differences between MQ and vanilla qualifying as spoiling on sight
|
||||||
|
std::vector<uint32_t> spoilingEntrances = {
|
||||||
|
0x0000, // ENTR_DEKU_TREE_0
|
||||||
|
0x0467, // ENTR_DODONGOS_CAVERN_1
|
||||||
|
0x0028, // ENTR_JABU_JABU_0
|
||||||
|
0x0407, // ENTR_JABU_JABU_1
|
||||||
|
0x0169, // ENTR_FOREST_TEMPLE_0
|
||||||
|
0x0165, // ENTR_FIRE_TEMPLE_0
|
||||||
|
0x0175, // ENTR_FIRE_TEMPLE_1
|
||||||
|
0x0423, // ENTR_WATER_TEMPLE_1
|
||||||
|
0x0082, // ENTR_SPIRIT_TEMPLE_0
|
||||||
|
0x02B2, // ENTR_SHADOW_TEMPLE_1
|
||||||
|
0x0088, // ENTR_ICE_CAVERN_0
|
||||||
|
0x0008, // ENTR_GERUDO_TRAINING_GROUNDS_0
|
||||||
|
0x0467 // ENTR_INSIDE_GANONS_CASTLE_0
|
||||||
|
};
|
||||||
|
|
||||||
std::map<RandomizerCheckArea, std::vector<RandomizerCheckObject>> checksByArea;
|
std::map<RandomizerCheckArea, std::vector<RandomizerCheckObject>> checksByArea;
|
||||||
bool areasFullyChecked[RCAREA_INVALID];
|
bool areasFullyChecked[RCAREA_INVALID];
|
||||||
u32 areasSpoiled = 0;
|
u32 areasSpoiled = 0;
|
||||||
bool showVOrMQ;
|
bool showVOrMQ;
|
||||||
s8 areaChecksGotten[32]; //| "Kokiri Forest (4/9)"
|
s8 areaChecksGotten[RCAREA_INVALID]; //| "Kokiri Forest (4/9)"
|
||||||
bool optCollapseAll; // A bool that will collapse all checks once
|
s8 areaCheckTotals[RCAREA_INVALID];
|
||||||
|
bool optCollapseAll; // A bool that will collapse all checks once
|
||||||
bool optExpandAll; // A bool that will expand all checks once
|
bool optExpandAll; // A bool that will expand all checks once
|
||||||
RandomizerCheck lastItemGetCheck = RC_UNKNOWN_CHECK;
|
|
||||||
RandomizerCheck lastLocationChecked = RC_UNKNOWN_CHECK;
|
RandomizerCheck lastLocationChecked = RC_UNKNOWN_CHECK;
|
||||||
RandomizerCheckArea previousArea = RCAREA_INVALID;
|
RandomizerCheckArea previousArea = RCAREA_INVALID;
|
||||||
RandomizerCheckArea currentArea = RCAREA_INVALID;
|
RandomizerCheckArea currentArea = RCAREA_INVALID;
|
||||||
std::vector<RandomizerCheckArea> checkAreas;
|
|
||||||
std::vector<GetItemEntry> itemsReceived;
|
|
||||||
OSContPad* trackerButtonsPressed;
|
OSContPad* trackerButtonsPressed;
|
||||||
|
|
||||||
void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0);
|
void BeginFloatWindows(std::string UniqueName, bool& open, ImGuiWindowFlags flags = 0);
|
||||||
@@ -194,10 +201,6 @@ Color_RGBA8 Color_Saved_Extra = { 0, 185, 0, 255 }; // Green
|
|||||||
std::vector<uint32_t> buttons = { BTN_A, BTN_B, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT, BTN_L,
|
std::vector<uint32_t> buttons = { BTN_A, BTN_B, BTN_CUP, BTN_CDOWN, BTN_CLEFT, BTN_CRIGHT, BTN_L,
|
||||||
BTN_Z, BTN_R, BTN_START, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
|
BTN_Z, BTN_R, BTN_START, BTN_DUP, BTN_DDOWN, BTN_DLEFT, BTN_DRIGHT };
|
||||||
|
|
||||||
void SetLastItemGetRC(RandomizerCheck rc) {
|
|
||||||
lastItemGetCheck = rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DefaultCheckData(RandomizerCheck rc) {
|
void DefaultCheckData(RandomizerCheck rc) {
|
||||||
gSaveContext.checkTrackerData[rc].status = RCSHOW_UNCHECKED;
|
gSaveContext.checkTrackerData[rc].status = RCSHOW_UNCHECKED;
|
||||||
gSaveContext.checkTrackerData[rc].skipped = 0;
|
gSaveContext.checkTrackerData[rc].skipped = 0;
|
||||||
@@ -240,6 +243,26 @@ void TrySetAreas() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecalculateAreaTotals() {
|
||||||
|
for (auto [rcArea, rcObjects] : checksByArea) {
|
||||||
|
if (rcArea == RCAREA_INVALID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
areaChecksGotten[rcArea] = 0;
|
||||||
|
areaCheckTotals[rcArea] = 0;
|
||||||
|
for (auto rcObj : rcObjects) {
|
||||||
|
if (!IsVisibleInCheckTracker(rcObj)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
areaCheckTotals[rcArea]++;
|
||||||
|
if (gSaveContext.checkTrackerData[rcObj.rc].skipped || gSaveContext.checkTrackerData[rcObj.rc].status == RCSHOW_COLLECTED
|
||||||
|
|| gSaveContext.checkTrackerData[rcObj.rc].status == RCSHOW_SAVED) {
|
||||||
|
areaChecksGotten[rcArea]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetCheckCollected(RandomizerCheck rc) {
|
void SetCheckCollected(RandomizerCheck rc) {
|
||||||
gSaveContext.checkTrackerData[rc].status = RCSHOW_COLLECTED;
|
gSaveContext.checkTrackerData[rc].status = RCSHOW_COLLECTED;
|
||||||
RandomizerCheckObject rcObj;
|
RandomizerCheckObject rcObj;
|
||||||
@@ -248,16 +271,19 @@ void SetCheckCollected(RandomizerCheck rc) {
|
|||||||
} else {
|
} else {
|
||||||
rcObj = RandomizerCheckObjects::GetAllRCObjects().find(rc)->second;
|
rcObj = RandomizerCheckObjects::GetAllRCObjects().find(rc)->second;
|
||||||
}
|
}
|
||||||
if (!gSaveContext.checkTrackerData[rc].skipped) {
|
if (IsVisibleInCheckTracker(rcObj)) {
|
||||||
areaChecksGotten[rcObj.rcArea]++;
|
if (!gSaveContext.checkTrackerData[rc].skipped) {
|
||||||
} else {
|
areaChecksGotten[rcObj.rcArea]++;
|
||||||
gSaveContext.checkTrackerData[rc].skipped = false;
|
} else {
|
||||||
}
|
gSaveContext.checkTrackerData[rc].skipped = false;
|
||||||
if (!checkAreas.empty()) {
|
}
|
||||||
checkAreas.erase(checkAreas.begin());
|
|
||||||
}
|
}
|
||||||
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
|
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
|
||||||
|
|
||||||
|
if (!IsAreaSpoiled(rcObj.rcArea)) {
|
||||||
|
SetAreaSpoiled(rcObj.rcArea);
|
||||||
|
}
|
||||||
|
|
||||||
doAreaScroll = true;
|
doAreaScroll = true;
|
||||||
UpdateOrdering(rcObj.rcArea);
|
UpdateOrdering(rcObj.rcArea);
|
||||||
UpdateInventoryChecks();
|
UpdateInventoryChecks();
|
||||||
@@ -360,32 +386,19 @@ bool vector_contains_scene(std::vector<SceneID> vec, const int16_t scene) {
|
|||||||
|
|
||||||
std::vector<SceneID> skipScenes = {SCENE_GANON_BOSS, SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR, SCENE_GANON_BOSS, SCENE_INSIDE_GANONS_CASTLE_COLLAPSE, SCENE_GANONS_TOWER_COLLAPSE_INTERIOR};
|
std::vector<SceneID> skipScenes = {SCENE_GANON_BOSS, SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR, SCENE_GANON_BOSS, SCENE_INSIDE_GANONS_CASTLE_COLLAPSE, SCENE_GANONS_TOWER_COLLAPSE_INTERIOR};
|
||||||
|
|
||||||
bool EvaluateCheck(RandomizerCheckObject rco) {
|
void ClearAreaChecksAndTotals() {
|
||||||
if (HasItemBeenCollected(rco.rc) && gSaveContext.checkTrackerData[rco.rc].status != RCSHOW_COLLECTED &&
|
for (auto& [rcArea, vec] : checksByArea) {
|
||||||
gSaveContext.checkTrackerData[rco.rc].status != RCSHOW_SAVED) {
|
vec.clear();
|
||||||
SetCheckCollected(rco.rc);
|
areaChecksGotten[rcArea] = 0;
|
||||||
return true;
|
areaCheckTotals[rcArea] = 0;
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckByArea(RandomizerCheckArea area = RCAREA_INVALID) {
|
|
||||||
if (area == RCAREA_INVALID) {
|
|
||||||
area = checkAreas.front();
|
|
||||||
}
|
|
||||||
if (area != RCAREA_INVALID) {
|
|
||||||
auto areaChecks = checksByArea.find(area)->second;
|
|
||||||
if (checkCounter >= areaChecks.size()) {
|
|
||||||
checkCounter = 0;
|
|
||||||
checkLoops++;
|
|
||||||
}
|
|
||||||
auto rco = areaChecks.at(checkCounter);
|
|
||||||
return EvaluateCheck(rco);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetShopSeen(uint32_t sceneNum, bool prices) {
|
void SetShopSeen(uint32_t sceneNum, bool prices) {
|
||||||
RandomizerCheck start = startingShopItem.find(sceneNum)->second;
|
RandomizerCheck start = startingShopItem.find(sceneNum)->second;
|
||||||
|
if (sceneNum == SCENE_POTION_SHOP_KAKARIKO && !LINK_IS_ADULT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (GetCheckArea() == RCAREA_KAKARIKO_VILLAGE && sceneNum == SCENE_BAZAAR) {
|
if (GetCheckArea() == RCAREA_KAKARIKO_VILLAGE && sceneNum == SCENE_BAZAAR) {
|
||||||
start = RC_KAK_BAZAAR_ITEM_1;
|
start = RC_KAK_BAZAAR_ITEM_1;
|
||||||
}
|
}
|
||||||
@@ -457,9 +470,9 @@ void CheckTrackerLoadGame(int32_t fileNum) {
|
|||||||
TrySetAreas();
|
TrySetAreas();
|
||||||
for (auto [rc, rcObj] : RandomizerCheckObjects::GetAllRCObjects()) {
|
for (auto [rc, rcObj] : RandomizerCheckObjects::GetAllRCObjects()) {
|
||||||
RandomizerCheckTrackerData rcTrackerData = gSaveContext.checkTrackerData[rc];
|
RandomizerCheckTrackerData rcTrackerData = gSaveContext.checkTrackerData[rc];
|
||||||
if (rc == RC_UNKNOWN_CHECK || rc == RC_MAX || rc == RC_LINKS_POCKET ||
|
if (rc == RC_UNKNOWN_CHECK || rc == RC_MAX || rc == RC_LINKS_POCKET || !RandomizerCheckObjects::GetAllRCObjects().contains(rc)) {
|
||||||
!RandomizerCheckObjects::GetAllRCObjects().contains(rc))
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
RandomizerCheckObject realRcObj;
|
RandomizerCheckObject realRcObj;
|
||||||
if (rc == RC_GIFT_FROM_SAGES && !IS_RANDO) {
|
if (rc == RC_GIFT_FROM_SAGES && !IS_RANDO) {
|
||||||
@@ -467,15 +480,22 @@ void CheckTrackerLoadGame(int32_t fileNum) {
|
|||||||
} else {
|
} else {
|
||||||
realRcObj = rcObj;
|
realRcObj = rcObj;
|
||||||
}
|
}
|
||||||
if (!IsVisibleInCheckTracker(realRcObj)) continue;
|
|
||||||
|
|
||||||
checksByArea.find(realRcObj.rcArea)->second.push_back(realRcObj);
|
checksByArea.find(realRcObj.rcArea)->second.push_back(realRcObj);
|
||||||
if (rcTrackerData.status == RCSHOW_SAVED || rcTrackerData.skipped) {
|
if (IsVisibleInCheckTracker(realRcObj)) {
|
||||||
areaChecksGotten[realRcObj.rcArea]++;
|
areaCheckTotals[realRcObj.rcArea]++;
|
||||||
|
if (rcTrackerData.status == RCSHOW_COLLECTED || rcTrackerData.status == RCSHOW_SAVED || rcTrackerData.skipped) {
|
||||||
|
areaChecksGotten[realRcObj.rcArea]++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (areaChecksGotten[realRcObj.rcArea] != 0 || RandomizerCheckObjects::AreaIsOverworld(realRcObj.rcArea)) {
|
for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) {
|
||||||
areasSpoiled |= (1 << realRcObj.rcArea);
|
if (!IsAreaSpoiled(static_cast<RandomizerCheckArea>(i)) && (RandomizerCheckObjects::AreaIsOverworld(static_cast<RandomizerCheckArea>(i)) || !IS_RANDO ||
|
||||||
|
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE ||
|
||||||
|
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION ||
|
||||||
|
(OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER &&
|
||||||
|
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12))) {
|
||||||
|
SetAreaSpoiled(static_cast<RandomizerCheckArea>(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
|
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
|
||||||
@@ -496,6 +516,7 @@ void CheckTrackerLoadGame(int32_t fileNum) {
|
|||||||
|
|
||||||
checksByArea.find(startingArea)->second.push_back(linksPocket);
|
checksByArea.find(startingArea)->second.push_back(linksPocket);
|
||||||
areaChecksGotten[startingArea]++;
|
areaChecksGotten[startingArea]++;
|
||||||
|
areaCheckTotals[startingArea]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
showVOrMQ = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_RANDOM_NUMBER ||
|
showVOrMQ = (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_RANDOM_NUMBER ||
|
||||||
@@ -509,12 +530,6 @@ void CheckTrackerLoadGame(int32_t fileNum) {
|
|||||||
UpdateInventoryChecks();
|
UpdateInventoryChecks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckTrackerDialogClosed() {
|
|
||||||
if (messageCloseCheck) {
|
|
||||||
messageCloseCheck = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckTrackerShopSlotChange(uint8_t cursorSlot, int16_t basePrice) {
|
void CheckTrackerShopSlotChange(uint8_t cursorSlot, int16_t basePrice) {
|
||||||
if (gPlayState->sceneNum == SCENE_HAPPY_MASK_SHOP) { // Happy Mask Shop is not used in rando, so is not tracked
|
if (gPlayState->sceneNum == SCENE_HAPPY_MASK_SHOP) { // Happy Mask Shop is not used in rando, so is not tracked
|
||||||
return;
|
return;
|
||||||
@@ -536,10 +551,6 @@ void CheckTrackerTransition(uint32_t sceneNum) {
|
|||||||
if (!GameInteractor::IsSaveLoaded()) {
|
if (!GameInteractor::IsSaveLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gSaveContext;
|
|
||||||
if (transitionCheck) {
|
|
||||||
transitionCheck = false;
|
|
||||||
}
|
|
||||||
doAreaScroll = true;
|
doAreaScroll = true;
|
||||||
previousArea = currentArea;
|
previousArea = currentArea;
|
||||||
currentArea = GetCheckArea();
|
currentArea = GetCheckArea();
|
||||||
@@ -554,34 +565,21 @@ void CheckTrackerTransition(uint32_t sceneNum) {
|
|||||||
SetShopSeen(sceneNum, false);
|
SetShopSeen(sceneNum, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!IsAreaSpoiled(currentArea) && (RandomizerCheckObjects::AreaIsOverworld(currentArea) || std::find(spoilingEntrances.begin(), spoilingEntrances.end(), gPlayState->nextEntranceIndex) != spoilingEntrances.end())) {
|
||||||
|
SetAreaSpoiled(currentArea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckTrackerFrame() {
|
void CheckTrackerFrame() {
|
||||||
if (!GameInteractor::IsSaveLoaded()) {
|
if (!GameInteractor::IsSaveLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!checkAreas.empty() && !transitionCheck && !messageCloseCheck && !pendingSaleCheck) {
|
// TODO: Move to OnAmmoChange hook once it gets added.
|
||||||
for (int i = 0; i < 10; i++) {
|
if (gSaveContext.checkTrackerData[RC_ZR_MAGIC_BEAN_SALESMAN].status != RCSHOW_COLLECTED &&
|
||||||
if (CheckByArea()) {
|
gSaveContext.checkTrackerData[RC_ZR_MAGIC_BEAN_SALESMAN].status != RCSHOW_SAVED) {
|
||||||
checkCounter = 0;
|
if (BEANS_BOUGHT >= 10) {
|
||||||
break;
|
SetCheckCollected(RC_ZR_MAGIC_BEAN_SALESMAN);
|
||||||
} else {
|
|
||||||
checkCounter++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (checkLoops > 15) {
|
|
||||||
checkAreas.erase(checkAreas.begin());
|
|
||||||
checkLoops = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (savedFrames > 0 && !pendingSaleCheck && !messageCloseCheck) {
|
|
||||||
savedFrames--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckTrackerSaleEnd(GetItemEntry giEntry) {
|
|
||||||
if (pendingSaleCheck) {
|
|
||||||
pendingSaleCheck = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,7 +591,7 @@ void CheckTrackerItemReceive(GetItemEntry giEntry) {
|
|||||||
// Vanilla special item checks
|
// Vanilla special item checks
|
||||||
if (!IS_RANDO) {
|
if (!IS_RANDO) {
|
||||||
if (giEntry.itemId == ITEM_SHIELD_DEKU) {
|
if (giEntry.itemId == ITEM_SHIELD_DEKU) {
|
||||||
SetCheckCollected(RC_KF_SHOP_ITEM_3);
|
SetCheckCollected(RC_KF_SHOP_ITEM_1);
|
||||||
return;
|
return;
|
||||||
}else if (giEntry.itemId == ITEM_KOKIRI_EMERALD) {
|
}else if (giEntry.itemId == ITEM_KOKIRI_EMERALD) {
|
||||||
SetCheckCollected(RC_QUEEN_GOHMA);
|
SetCheckCollected(RC_QUEEN_GOHMA);
|
||||||
@@ -622,16 +620,19 @@ void CheckTrackerItemReceive(GetItemEntry giEntry) {
|
|||||||
} else if (giEntry.itemId == ITEM_MEDALLION_LIGHT) {
|
} else if (giEntry.itemId == ITEM_MEDALLION_LIGHT) {
|
||||||
SetCheckCollected(RC_GIFT_FROM_SAGES);
|
SetCheckCollected(RC_GIFT_FROM_SAGES);
|
||||||
return;
|
return;
|
||||||
} else if (giEntry.itemId == ITEM_SONG_LULLABY) {
|
|
||||||
SetCheckCollected(RC_SONG_FROM_IMPA);
|
|
||||||
return;
|
|
||||||
} else if (giEntry.itemId == ITEM_SONG_EPONA) {
|
} else if (giEntry.itemId == ITEM_SONG_EPONA) {
|
||||||
SetCheckCollected(RC_SONG_FROM_MALON);
|
SetCheckCollected(RC_SONG_FROM_MALON);
|
||||||
return;
|
return;
|
||||||
} else if (giEntry.itemId == ITEM_SONG_SARIA) {
|
} else if (giEntry.itemId == ITEM_SONG_SARIA) {
|
||||||
SetCheckCollected(RC_SONG_FROM_SARIA);
|
SetCheckCollected(RC_SONG_FROM_SARIA);
|
||||||
return;
|
return;
|
||||||
} else if (giEntry.itemId == ITEM_SONG_SUN) {
|
} else if (giEntry.itemId == ITEM_BEAN) {
|
||||||
|
SetCheckCollected(RC_ZR_MAGIC_BEAN_SALESMAN);
|
||||||
|
return;
|
||||||
|
} else if (giEntry.itemId == ITEM_BRACELET) {
|
||||||
|
SetCheckCollected(RC_GC_DARUNIAS_JOY);
|
||||||
|
return;
|
||||||
|
}/* else if (giEntry.itemId == ITEM_SONG_SUN) {
|
||||||
SetCheckCollected(RC_SONG_FROM_ROYAL_FAMILYS_TOMB);
|
SetCheckCollected(RC_SONG_FROM_ROYAL_FAMILYS_TOMB);
|
||||||
return;
|
return;
|
||||||
} else if (giEntry.itemId == ITEM_SONG_TIME) {
|
} else if (giEntry.itemId == ITEM_SONG_TIME) {
|
||||||
@@ -658,47 +659,133 @@ void CheckTrackerItemReceive(GetItemEntry giEntry) {
|
|||||||
} else if (giEntry.itemId == ITEM_SONG_PRELUDE) {
|
} else if (giEntry.itemId == ITEM_SONG_PRELUDE) {
|
||||||
SetCheckCollected(RC_SHEIK_AT_TEMPLE);
|
SetCheckCollected(RC_SHEIK_AT_TEMPLE);
|
||||||
return;
|
return;
|
||||||
} else if (giEntry.itemId == ITEM_BRACELET) {
|
}*/
|
||||||
SetCheckCollected(RC_GC_DARUNIAS_JOY);
|
}
|
||||||
return;
|
}
|
||||||
} else if (giEntry.itemId == ITEM_LETTER_ZELDA) {
|
|
||||||
SetCheckCollected(RC_HC_ZELDAS_LETTER);
|
void CheckTrackerSceneFlagSet(int16_t sceneNum, int16_t flagType, int32_t flag) {
|
||||||
return;
|
if (flagType != FLAG_SCENE_TREASURE && flagType != FLAG_SCENE_COLLECTIBLE) {
|
||||||
} else if (giEntry.itemId == ITEM_WEIRD_EGG) {
|
return;
|
||||||
SetCheckCollected(RC_HC_MALON_EGG);
|
}
|
||||||
return;
|
if (sceneNum == SCENE_GRAVEYARD && flag == 0x19 && flagType == FLAG_SCENE_COLLECTIBLE) { // Gravedigging tour special case
|
||||||
} else if (giEntry.itemId == ITEM_BEAN) {
|
SetCheckCollected(RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR);
|
||||||
SetCheckCollected(RC_ZR_MAGIC_BEAN_SALESMAN);
|
return;
|
||||||
|
}
|
||||||
|
for (auto [rc, rcObj] : RandomizerCheckObjects::GetAllRCObjects()) {
|
||||||
|
if (!IsVisibleInCheckTracker(rcObj)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SpoilerCollectionCheckType checkMatchType = flagType == FLAG_SCENE_TREASURE ? SpoilerCollectionCheckType::SPOILER_CHK_CHEST : SpoilerCollectionCheckType::SPOILER_CHK_COLLECTABLE;
|
||||||
|
SpoilerCollectionCheck scCheck = Location(rc)->GetCollectionCheck();
|
||||||
|
if (scCheck.scene == sceneNum && scCheck.flag == flag && scCheck.type == checkMatchType) {
|
||||||
|
SetCheckCollected(rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto checkArea = GetCheckArea();
|
}
|
||||||
if (gSaveContext.pendingSale != ITEM_NONE) {
|
|
||||||
pendingSaleCheck = true;
|
void CheckTrackerFlagSet(int16_t flagType, int32_t flag) {
|
||||||
checkAreas.push_back(checkArea);
|
SpoilerCollectionCheckType checkMatchType = SpoilerCollectionCheckType::SPOILER_CHK_NONE;
|
||||||
|
switch (flagType) {
|
||||||
|
case FLAG_GS_TOKEN:
|
||||||
|
checkMatchType = SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA;
|
||||||
|
break;
|
||||||
|
case FLAG_EVENT_CHECK_INF:
|
||||||
|
if ((flag == EVENTCHKINF_CARPENTERS_FREE(0) || flag == EVENTCHKINF_CARPENTERS_FREE(1) ||
|
||||||
|
flag == EVENTCHKINF_CARPENTERS_FREE(2) || flag == EVENTCHKINF_CARPENTERS_FREE(3))
|
||||||
|
&& GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) {
|
||||||
|
SetCheckCollected(RC_GF_GERUDO_MEMBERSHIP_CARD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkMatchType = SpoilerCollectionCheckType::SPOILER_CHK_EVENT_CHK_INF;
|
||||||
|
break;
|
||||||
|
case FLAG_INF_TABLE:
|
||||||
|
if (flag == INFTABLE_190) {
|
||||||
|
SetCheckCollected(RC_GF_HBA_1000_POINTS);
|
||||||
|
return;
|
||||||
|
} else if (flag == INFTABLE_11E) {
|
||||||
|
SetCheckCollected(RC_GC_ROLLING_GORON_AS_CHILD);
|
||||||
|
return;
|
||||||
|
} else if (flag == INFTABLE_GORON_CITY_DOORS_UNLOCKED) {
|
||||||
|
SetCheckCollected(RC_GC_ROLLING_GORON_AS_ADULT);
|
||||||
|
return;
|
||||||
|
} else if (flag == INFTABLE_139) {
|
||||||
|
SetCheckCollected(RC_ZD_KING_ZORA_THAWED);
|
||||||
|
return;
|
||||||
|
} else if (flag == INFTABLE_191) {
|
||||||
|
SetCheckCollected(RC_MARKET_LOST_DOG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!IS_RANDO) {
|
||||||
|
if (flag == INFTABLE_192) {
|
||||||
|
SetCheckCollected(RC_LW_DEKU_SCRUB_NEAR_BRIDGE);
|
||||||
|
return;
|
||||||
|
} else if (flag == INFTABLE_193) {
|
||||||
|
SetCheckCollected(RC_LW_DEKU_SCRUB_GROTTO_FRONT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLAG_ITEM_GET_INF:
|
||||||
|
if (!IS_RANDO) {
|
||||||
|
if (flag == ITEMGETINF_OBTAINED_STICK_UPGRADE_FROM_STAGE) {
|
||||||
|
SetCheckCollected(RC_DEKU_THEATER_SKULL_MASK);
|
||||||
|
return;
|
||||||
|
} else if (flag == ITEMGETINF_OBTAINED_NUT_UPGRADE_FROM_STAGE) {
|
||||||
|
SetCheckCollected(RC_DEKU_THEATER_MASK_OF_TRUTH);
|
||||||
|
return;
|
||||||
|
} else if (flag == ITEMGETINF_0B) {
|
||||||
|
SetCheckCollected(RC_HF_DEKU_SCRUB_GROTTO);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkMatchType = SpoilerCollectionCheckType::SPOILER_CHK_ITEM_GET_INF;
|
||||||
|
break;
|
||||||
|
case FLAG_RANDOMIZER_INF:
|
||||||
|
checkMatchType = SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scene == SCENE_DESERT_COLOSSUS && (gSaveContext.entranceIndex == 485 || gSaveContext.entranceIndex == 489)) {
|
for (auto [rc, rcObj] : RandomizerCheckObjects::GetAllRCObjects()) {
|
||||||
checkAreas.push_back(RCAREA_SPIRIT_TEMPLE);
|
if ((!IS_RANDO && ((rcObj.vOrMQ == RCVORMQ_MQ && !IS_MASTER_QUEST) ||
|
||||||
return;
|
(rcObj.vOrMQ == RCVORMQ_VANILLA && IS_MASTER_QUEST))) ||
|
||||||
}
|
(IS_RANDO && ((OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) &&
|
||||||
if (GET_PLAYER(gPlayState) == nullptr) {
|
rcObj.vOrMQ == RCVORMQ_VANILLA) ||
|
||||||
transitionCheck = true;
|
!OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) &&
|
||||||
return;
|
rcObj.vOrMQ == RCVORMQ_MQ))) {
|
||||||
}
|
continue;
|
||||||
if (gPlayState->msgCtx.msgMode != MSGMODE_NONE) {
|
}
|
||||||
checkAreas.push_back(checkArea);
|
SpoilerCollectionCheck scCheck = Location(rc)->GetCollectionCheck();
|
||||||
messageCloseCheck = true;
|
SpoilerCollectionCheckType scCheckType = scCheck.type;
|
||||||
return;
|
if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF &&
|
||||||
}
|
(scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MERCHANT ||
|
||||||
if (IS_RANDO || (!IS_RANDO && giEntry.getItemCategory != ITEM_CATEGORY_JUNK)) {
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SHOP_ITEM ||
|
||||||
checkAreas.push_back(checkArea);
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_COW ||
|
||||||
checkCollected = true;
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_SCRUB ||
|
||||||
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_MASTER_SWORD ||
|
||||||
|
scCheckType == SpoilerCollectionCheckType::SPOILER_CHK_RANDOMIZER_INF)) {
|
||||||
|
if (flag == OTRGlobals::Instance->gRandomizer->GetRandomizerInfFromCheck(rc)) {
|
||||||
|
SetCheckCollected(rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int16_t checkFlag = scCheck.flag;
|
||||||
|
if (checkMatchType == SpoilerCollectionCheckType::SPOILER_CHK_GOLD_SKULLTULA) {
|
||||||
|
checkFlag = rcObj.actorParams;
|
||||||
|
}
|
||||||
|
if (checkFlag == flag && scCheck.type == checkMatchType) {
|
||||||
|
SetCheckCollected(rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitTrackerData(bool isDebug) {
|
void InitTrackerData(bool isDebug) {
|
||||||
TrySetAreas();
|
TrySetAreas();
|
||||||
|
areasSpoiled = 0;
|
||||||
for (auto& [rc, rco] : RandomizerCheckObjects::GetAllRCObjects()) {
|
for (auto& [rc, rco] : RandomizerCheckObjects::GetAllRCObjects()) {
|
||||||
if (rc != RC_UNKNOWN_CHECK && rc != RC_MAX) {
|
if (rc != RC_UNKNOWN_CHECK && rc != RC_MAX) {
|
||||||
DefaultCheckData(rc);
|
DefaultCheckData(rc);
|
||||||
@@ -711,7 +798,7 @@ void InitTrackerData(bool isDebug) {
|
|||||||
void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) {
|
void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) {
|
||||||
SaveManager::Instance->SaveArray("checks", ARRAY_COUNT(saveContext->checkTrackerData), [&](size_t i) {
|
SaveManager::Instance->SaveArray("checks", ARRAY_COUNT(saveContext->checkTrackerData), [&](size_t i) {
|
||||||
if (saveContext->checkTrackerData[i].status == RCSHOW_COLLECTED) {
|
if (saveContext->checkTrackerData[i].status == RCSHOW_COLLECTED) {
|
||||||
if (gameSave || savedFrames > 0) {
|
if (gameSave) {
|
||||||
gSaveContext.checkTrackerData[i].status = saveContext->checkTrackerData[i].status = RCSHOW_SAVED;
|
gSaveContext.checkTrackerData[i].status = saveContext->checkTrackerData[i].status = RCSHOW_SAVED;
|
||||||
UpdateAllOrdering();
|
UpdateAllOrdering();
|
||||||
UpdateInventoryChecks();
|
UpdateInventoryChecks();
|
||||||
@@ -726,13 +813,11 @@ void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) {
|
|||||||
SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem);
|
SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
SaveManager::Instance->SaveData("areasSpoiled", areasSpoiled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) {
|
void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) {
|
||||||
SaveTrackerData(saveContext, sectionID, fullSave);
|
SaveTrackerData(saveContext, sectionID, fullSave);
|
||||||
if (fullSave) {
|
|
||||||
savedFrames = 40;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadFile() {
|
void LoadFile() {
|
||||||
@@ -744,27 +829,36 @@ void LoadFile() {
|
|||||||
SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem);
|
SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Teardown() {
|
void Teardown() {
|
||||||
initialized = false;
|
initialized = false;
|
||||||
for (auto& [rcArea, vec] : checksByArea) {
|
ClearAreaChecksAndTotals();
|
||||||
vec.clear();
|
|
||||||
areaChecksGotten[rcArea] = 0;
|
|
||||||
}
|
|
||||||
checksByArea.clear();
|
checksByArea.clear();
|
||||||
areasSpoiled = 0;
|
areasSpoiled = 0;
|
||||||
checkCollected = false;
|
|
||||||
checkLoops = 0;
|
|
||||||
|
|
||||||
lastLocationChecked = RC_UNKNOWN_CHECK;
|
lastLocationChecked = RC_UNKNOWN_CHECK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsAreaSpoiled(RandomizerCheckArea rcArea) {
|
||||||
|
return areasSpoiled & (1 << rcArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAreaSpoiled(RandomizerCheckArea rcArea) {
|
||||||
|
areasSpoiled |= (1 << rcArea);
|
||||||
|
SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true);
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
|
void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
|
||||||
auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast<RandomizerCheck>(check))->second.rcArea;
|
auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast<RandomizerCheck>(check))->second.rcArea;
|
||||||
if (!gSaveContext.checkTrackerData[check].skipped && data.skipped) {
|
if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) ||
|
||||||
|
((gSaveContext.checkTrackerData[check].status != RCSHOW_COLLECTED && gSaveContext.checkTrackerData[check].status != RCSHOW_SAVED) &&
|
||||||
|
(data.status == RCSHOW_COLLECTED || data.status == RCSHOW_SAVED))) {
|
||||||
areaChecksGotten[area]++;
|
areaChecksGotten[area]++;
|
||||||
} else if (gSaveContext.checkTrackerData[check].skipped && !data.skipped) {
|
} else if ((gSaveContext.checkTrackerData[check].skipped && !data.skipped) ||
|
||||||
|
((gSaveContext.checkTrackerData[check].status == RCSHOW_COLLECTED || gSaveContext.checkTrackerData[check].status == RCSHOW_SAVED) &&
|
||||||
|
(data.status != RCSHOW_COLLECTED && data.status != RCSHOW_SAVED))) {
|
||||||
areaChecksGotten[area]--;
|
areaChecksGotten[area]--;
|
||||||
}
|
}
|
||||||
gSaveContext.checkTrackerData[check] = data;
|
gSaveContext.checkTrackerData[check] = data;
|
||||||
@@ -774,10 +868,6 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) {
|
|||||||
void CheckTrackerWindow::DrawElement() {
|
void CheckTrackerWindow::DrawElement() {
|
||||||
ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver);
|
||||||
|
|
||||||
if (!initialized && (gPlayState == nullptr || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) {
|
if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) {
|
||||||
if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) {
|
if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) {
|
||||||
return;
|
return;
|
||||||
@@ -798,7 +888,7 @@ void CheckTrackerWindow::DrawElement() {
|
|||||||
|
|
||||||
BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar);
|
BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar);
|
||||||
|
|
||||||
if (!GameInteractor::IsSaveLoaded()) {
|
if (!GameInteractor::IsSaveLoaded() || !initialized) {
|
||||||
ImGui::Text("Waiting for file load..."); //TODO Language
|
ImGui::Text("Waiting for file load..."); //TODO Language
|
||||||
EndFloatWindows();
|
EndFloatWindows();
|
||||||
return;
|
return;
|
||||||
@@ -809,8 +899,6 @@ void CheckTrackerWindow::DrawElement() {
|
|||||||
sceneId = (SceneID)gPlayState->sceneNum;
|
sceneId = (SceneID)gPlayState->sceneNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
areasSpoiled |= (1 << currentArea);
|
|
||||||
|
|
||||||
//Quick Options
|
//Quick Options
|
||||||
#ifdef __WIIU__
|
#ifdef __WIIU__
|
||||||
float headerHeight = 40.0f;
|
float headerHeight = 40.0f;
|
||||||
@@ -872,13 +960,11 @@ void CheckTrackerWindow::DrawElement() {
|
|||||||
Color_RGBA8 mainColor;
|
Color_RGBA8 mainColor;
|
||||||
Color_RGBA8 extraColor;
|
Color_RGBA8 extraColor;
|
||||||
std::string stemp;
|
std::string stemp;
|
||||||
s32 areaMask = 1;
|
|
||||||
|
|
||||||
for (auto& [rcArea, objs] : checksByArea) {
|
for (auto& [rcArea, objs] : checksByArea) {
|
||||||
RandomizerCheckArea thisArea = currentArea;
|
RandomizerCheckArea thisArea = currentArea;
|
||||||
|
|
||||||
const int areaChecksTotal = static_cast<int>(objs.size());
|
thisAreaFullyChecked = (areaChecksGotten[rcArea] == areaCheckTotals[rcArea]);
|
||||||
thisAreaFullyChecked = (areaChecksGotten[rcArea] == areaChecksTotal);
|
|
||||||
//Last Area needs to be cleaned up
|
//Last Area needs to be cleaned up
|
||||||
if (lastArea != RCAREA_INVALID && doDraw) {
|
if (lastArea != RCAREA_INVALID && doDraw) {
|
||||||
UIWidgets::PaddedSeparator();
|
UIWidgets::PaddedSeparator();
|
||||||
@@ -915,26 +1001,29 @@ void CheckTrackerWindow::DrawElement() {
|
|||||||
stemp = RandomizerCheckObjects::GetRCAreaName(rcArea) + "##TreeNode";
|
stemp = RandomizerCheckObjects::GetRCAreaName(rcArea) + "##TreeNode";
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(mainColor.r / 255.0f, mainColor.g / 255.0f,
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(mainColor.r / 255.0f, mainColor.g / 255.0f,
|
||||||
mainColor.b / 255.0f, mainColor.a / 255.0f));
|
mainColor.b / 255.0f, mainColor.a / 255.0f));
|
||||||
if (doingCollapseOrExpand)
|
if (doingCollapseOrExpand) {
|
||||||
ImGui::SetNextItemOpen(collapseLogic, ImGuiCond_Always);
|
ImGui::SetNextItemOpen(collapseLogic, ImGuiCond_Always);
|
||||||
else
|
} else {
|
||||||
ImGui::SetNextItemOpen(!thisAreaFullyChecked, ImGuiCond_Once);
|
ImGui::SetNextItemOpen(!thisAreaFullyChecked, ImGuiCond_Once);
|
||||||
|
}
|
||||||
doDraw = ImGui::TreeNode(stemp.c_str());
|
doDraw = ImGui::TreeNode(stemp.c_str());
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f,
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f,
|
||||||
extraColor.b / 255.0f, extraColor.a / 255.0f));
|
extraColor.b / 255.0f, extraColor.a / 255.0f));
|
||||||
|
|
||||||
isThisAreaSpoiled = areasSpoiled & areaMask || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0);
|
isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0);
|
||||||
|
|
||||||
if (isThisAreaSpoiled) {
|
if (isThisAreaSpoiled) {
|
||||||
if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) {
|
if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) {
|
||||||
if (OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(DungeonSceneLookupByArea(rcArea)))
|
if (OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(
|
||||||
ImGui::Text("(%d/%d) - MQ", areaChecksGotten[rcArea], areaChecksTotal);
|
DungeonSceneLookupByArea(rcArea))) {
|
||||||
else
|
ImGui::Text("(%d/%d) - MQ", areaChecksGotten[rcArea], areaCheckTotals[rcArea]);
|
||||||
ImGui::Text("(%d/%d) - Vanilla", areaChecksGotten[rcArea], areaChecksTotal);
|
} else {
|
||||||
|
ImGui::Text("(%d/%d) - Vanilla", areaChecksGotten[rcArea], areaCheckTotals[rcArea]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui::Text("(%d/%d)", areaChecksGotten[rcArea], areaChecksTotal);
|
ImGui::Text("(%d/%d)", areaChecksGotten[rcArea], areaCheckTotals[rcArea]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui::Text("???");
|
ImGui::Text("???");
|
||||||
@@ -948,13 +1037,14 @@ void CheckTrackerWindow::DrawElement() {
|
|||||||
doAreaScroll = false;
|
doAreaScroll = false;
|
||||||
}
|
}
|
||||||
for (auto rco : objs) {
|
for (auto rco : objs) {
|
||||||
if (doDraw && isThisAreaSpoiled && IsVisibleInCheckTracker(rco))
|
if (IsVisibleInCheckTracker(rco) && doDraw && isThisAreaSpoiled) {
|
||||||
DrawLocation(rco);
|
DrawLocation(rco);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (doDraw)
|
if (doDraw) {
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
areaMask <<= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndTable(); //Checks Lead-out
|
ImGui::EndTable(); //Checks Lead-out
|
||||||
@@ -1059,7 +1149,6 @@ void LoadSettings() {
|
|||||||
showLinksPocket = IS_RANDO ? // don't show Link's Pocket if not randomizer, or if rando and pocket is disabled
|
showLinksPocket = IS_RANDO ? // don't show Link's Pocket if not randomizer, or if rando and pocket is disabled
|
||||||
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING
|
OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING
|
||||||
:false;
|
:false;
|
||||||
hideShopRightChecks = IS_RANDO ? CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1) : false;
|
|
||||||
|
|
||||||
if (IS_RANDO) {
|
if (IS_RANDO) {
|
||||||
switch (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS)) {
|
switch (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_TOKENS)) {
|
||||||
@@ -1123,7 +1212,7 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) {
|
|||||||
) &&
|
) &&
|
||||||
(rcObj.rcType != RCTYPE_MERCHANT || showMerchants) &&
|
(rcObj.rcType != RCTYPE_MERCHANT || showMerchants) &&
|
||||||
(rcObj.rcType != RCTYPE_OCARINA || showOcarinas) &&
|
(rcObj.rcType != RCTYPE_OCARINA || showOcarinas) &&
|
||||||
(rcObj.rcType != RCTYPE_SKULL_TOKEN ||
|
(rcObj.rcType != RCTYPE_SKULL_TOKEN || alwaysShowGS ||
|
||||||
(showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(rcObj.rcArea)) ||
|
(showOverworldTokens && RandomizerCheckObjects::AreaIsOverworld(rcObj.rcArea)) ||
|
||||||
(showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea))
|
(showDungeonTokens && RandomizerCheckObjects::AreaIsDungeon(rcObj.rcArea))
|
||||||
) &&
|
) &&
|
||||||
@@ -1151,18 +1240,18 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) {
|
|||||||
}
|
}
|
||||||
else if (rcObj.vanillaCompletion) {
|
else if (rcObj.vanillaCompletion) {
|
||||||
return (rcObj.vOrMQ == RCVORMQ_BOTH ||
|
return (rcObj.vOrMQ == RCVORMQ_BOTH ||
|
||||||
rcObj.vOrMQ == RCVORMQ_MQ && OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ||
|
(rcObj.vOrMQ == RCVORMQ_MQ && IS_MASTER_QUEST) ||
|
||||||
rcObj.vOrMQ == RCVORMQ_VANILLA && !OTRGlobals::Instance->gRandomizer->masterQuestDungeons.contains(rcObj.sceneId) ||
|
(rcObj.vOrMQ == RCVORMQ_VANILLA && !IS_MASTER_QUEST) ||
|
||||||
rcObj.rc == RC_GIFT_FROM_SAGES) && rcObj.rc != RC_LINKS_POCKET;
|
rcObj.rc == RC_GIFT_FROM_SAGES) && rcObj.rc != RC_LINKS_POCKET;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInventoryChecks() {
|
void UpdateInventoryChecks() {
|
||||||
//For all the areas with compasses, if you have one, spoil the area
|
//For all the areas with maps, if you have one, spoil the area
|
||||||
for (auto [scene, area] : DungeonRCAreasBySceneID) {
|
for (auto [scene, area] : DungeonRCAreasBySceneID) {
|
||||||
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) {
|
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) {
|
||||||
areasSpoiled |= (1 << area);
|
SetAreaSpoiled(area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1172,8 +1261,6 @@ void UpdateAreaFullyChecked(RandomizerCheckArea area) {
|
|||||||
|
|
||||||
void UpdateAreas(RandomizerCheckArea area) {
|
void UpdateAreas(RandomizerCheckArea area) {
|
||||||
areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size();
|
areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size();
|
||||||
if (areaChecksGotten[area] != 0 || RandomizerCheckObjects::AreaIsOverworld(area))
|
|
||||||
areasSpoiled |= (1 << area);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAllOrdering() {
|
void UpdateAllOrdering() {
|
||||||
@@ -1201,30 +1288,36 @@ bool CompareChecks(RandomizerCheckObject i, RandomizerCheckObject j) {
|
|||||||
bool iSaved = iShow.status == RCSHOW_SAVED;
|
bool iSaved = iShow.status == RCSHOW_SAVED;
|
||||||
bool jCollected = jShow.status == RCSHOW_COLLECTED || jShow.status == RCSHOW_SAVED;
|
bool jCollected = jShow.status == RCSHOW_COLLECTED || jShow.status == RCSHOW_SAVED;
|
||||||
bool jSaved = jShow.status == RCSHOW_SAVED;
|
bool jSaved = jShow.status == RCSHOW_SAVED;
|
||||||
if (!iCollected && jCollected)
|
|
||||||
return true;
|
|
||||||
else if (iCollected && !jCollected)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!iSaved && jSaved)
|
if (!iCollected && jCollected) {
|
||||||
return true;
|
return true;
|
||||||
else if (iSaved && !jSaved)
|
} else if (iCollected && !jCollected) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!iShow.skipped && jShow.skipped)
|
if (!iSaved && jSaved) {
|
||||||
return true;
|
return true;
|
||||||
else if (iShow.skipped && !jShow.skipped)
|
} else if (iSaved && !jSaved) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsEoDCheck(i.rcType) && IsEoDCheck(j.rcType))
|
if (!iShow.skipped && jShow.skipped) {
|
||||||
return true;
|
return true;
|
||||||
else if (IsEoDCheck(i.rcType) && !IsEoDCheck(j.rcType))
|
} else if (iShow.skipped && !jShow.skipped) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (i.rc < j.rc)
|
if (!IsEoDCheck(i.rcType) && IsEoDCheck(j.rcType)) {
|
||||||
return true;
|
return true;
|
||||||
else if (i.rc > j.rc)
|
} else if (IsEoDCheck(i.rcType) && !IsEoDCheck(j.rcType)) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.rc < j.rc) {
|
||||||
|
return true;
|
||||||
|
} else if (i.rc > j.rc) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1242,47 +1335,54 @@ void DrawLocation(RandomizerCheckObject rcObj) {
|
|||||||
RandomizerCheckStatus status = checkData.status;
|
RandomizerCheckStatus status = checkData.status;
|
||||||
bool skipped = checkData.skipped;
|
bool skipped = checkData.skipped;
|
||||||
if (status == RCSHOW_COLLECTED) {
|
if (status == RCSHOW_COLLECTED) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0))
|
if (!showHidden && CVarGetInteger("gCheckTrackerCollectedHide", 0)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default) :
|
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default) :
|
||||||
CVarGetColor("gCheckTrackerCollectedMainColor", Color_Main_Default);
|
CVarGetColor("gCheckTrackerCollectedMainColor", Color_Main_Default);
|
||||||
extraColor = CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default);
|
extraColor = CVarGetColor("gCheckTrackerCollectedExtraColor", Color_Collected_Extra_Default);
|
||||||
} else if (status == RCSHOW_SAVED) {
|
} else if (status == RCSHOW_SAVED) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerSavedHide", 0))
|
if (!showHidden && CVarGetInteger("gCheckTrackerSavedHide", 0)) {
|
||||||
return;
|
return;
|
||||||
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default) :
|
}
|
||||||
CVarGetColor("gCheckTrackerSavedMainColor", Color_Main_Default);
|
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default) :
|
||||||
|
CVarGetColor("gCheckTrackerSavedMainColor", Color_Main_Default);
|
||||||
extraColor = CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default);
|
extraColor = CVarGetColor("gCheckTrackerSavedExtraColor", Color_Saved_Extra_Default);
|
||||||
} else if (skipped) {
|
} else if (skipped) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerSkippedHide", 0))
|
if (!showHidden && CVarGetInteger("gCheckTrackerSkippedHide", 0)) {
|
||||||
return;
|
return;
|
||||||
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default) :
|
}
|
||||||
CVarGetColor("gCheckTrackerSkippedMainColor", Color_Main_Default);
|
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default) :
|
||||||
|
CVarGetColor("gCheckTrackerSkippedMainColor", Color_Main_Default);
|
||||||
extraColor = CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default);
|
extraColor = CVarGetColor("gCheckTrackerSkippedExtraColor", Color_Skipped_Extra_Default);
|
||||||
} else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) {
|
} else if (status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerSeenHide", 0))
|
if (!showHidden && CVarGetInteger("gCheckTrackerSeenHide", 0)) {
|
||||||
return;
|
return;
|
||||||
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default) :
|
}
|
||||||
CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default);
|
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default) :
|
||||||
|
CVarGetColor("gCheckTrackerSeenMainColor", Color_Main_Default);
|
||||||
extraColor = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default);
|
extraColor = CVarGetColor("gCheckTrackerSeenExtraColor", Color_Seen_Extra_Default);
|
||||||
} else if (status == RCSHOW_SCUMMED) {
|
} else if (status == RCSHOW_SCUMMED) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerKnownHide", 0))
|
if (!showHidden && CVarGetInteger("gCheckTrackerScummedHide", 0)) {
|
||||||
return;
|
return;
|
||||||
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default) :
|
}
|
||||||
CVarGetColor("gCheckTrackerScummedMainColor", Color_Main_Default);
|
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default) :
|
||||||
|
CVarGetColor("gCheckTrackerScummedMainColor", Color_Main_Default);
|
||||||
extraColor = CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default);
|
extraColor = CVarGetColor("gCheckTrackerScummedExtraColor", Color_Scummed_Extra_Default);
|
||||||
} else if (status == RCSHOW_UNCHECKED) {
|
} else if (status == RCSHOW_UNCHECKED) {
|
||||||
if (!showHidden && CVarGetInteger("gCheckTrackerUncheckedHide", 0))
|
if (!showHidden && CVarGetInteger("gCheckTrackerUncheckedHide", 0)) {
|
||||||
return;
|
return;
|
||||||
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default) :
|
}
|
||||||
CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default);
|
mainColor = !IsHeartPiece(rcObj.ogItemId) && !IS_RANDO ? CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default) :
|
||||||
|
CVarGetColor("gCheckTrackerUncheckedMainColor", Color_Main_Default);
|
||||||
extraColor = CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default);
|
extraColor = CVarGetColor("gCheckTrackerUncheckedExtraColor", Color_Unchecked_Extra_Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Main Text
|
//Main Text
|
||||||
txt = rcObj.rcShortName;
|
txt = rcObj.rcShortName;
|
||||||
if (lastLocationChecked == rcObj.rc)
|
if (lastLocationChecked == rcObj.rc) {
|
||||||
txt = "* " + txt;
|
txt = "* " + txt;
|
||||||
|
}
|
||||||
|
|
||||||
// Draw button - for Skipped/Seen/Scummed/Unchecked only
|
// Draw button - for Skipped/Seen/Scummed/Unchecked only
|
||||||
if (status == RCSHOW_UNCHECKED || status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED || status == RCSHOW_SCUMMED || skipped) {
|
if (status == RCSHOW_UNCHECKED || status == RCSHOW_SEEN || status == RCSHOW_IDENTIFIED || status == RCSHOW_SCUMMED || skipped) {
|
||||||
@@ -1357,8 +1457,9 @@ void DrawLocation(RandomizerCheckObject rcObj) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (txt == "" && skipped)
|
if (txt == "" && skipped) {
|
||||||
txt = "Skipped"; //TODO language
|
txt = "Skipped"; // TODO language
|
||||||
|
}
|
||||||
|
|
||||||
if (txt != "") {
|
if (txt != "") {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f));
|
||||||
@@ -1384,8 +1485,9 @@ int hue = 0;
|
|||||||
void RainbowTick() {
|
void RainbowTick() {
|
||||||
float freqHue = hue * 2 * M_PI / (360 * CVarGetFloat("gCosmetics.RainbowSpeed", 0.6f));
|
float freqHue = hue * 2 * M_PI / (360 * CVarGetFloat("gCosmetics.RainbowSpeed", 0.6f));
|
||||||
for (auto& cvar : rainbowCVars) {
|
for (auto& cvar : rainbowCVars) {
|
||||||
if (CVarGetInteger((cvar + "RBM").c_str(), 0) == 0)
|
if (CVarGetInteger((cvar + "RBM").c_str(), 0) == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Color_RGBA8 newColor;
|
Color_RGBA8 newColor;
|
||||||
newColor.r = sin(freqHue + 0) * 127 + 128;
|
newColor.r = sin(freqHue + 0) * 127 + 128;
|
||||||
@@ -1492,8 +1594,16 @@ void CheckTrackerSettingsWindow::DrawElement() {
|
|||||||
}
|
}
|
||||||
UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", "gCheckTrackerOptionMQSpoilers");
|
UIWidgets::EnhancementCheckbox("Vanilla/MQ Dungeon Spoilers", "gCheckTrackerOptionMQSpoilers");
|
||||||
UIWidgets::Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. Otherwise, Vanilla/MQ dungeon locations must be unlocked.");
|
UIWidgets::Tooltip("If enabled, Vanilla/MQ dungeons will show on the tracker immediately. Otherwise, Vanilla/MQ dungeon locations must be unlocked.");
|
||||||
UIWidgets::EnhancementCheckbox("Hide right-side shop item checks", "gCheckTrackerOptionHideRightShopChecks", false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
if (UIWidgets::EnhancementCheckbox("Hide right-side shop item checks", "gCheckTrackerOptionHideRightShopChecks", false, "", UIWidgets::CheckboxGraphics::Cross, true)) {
|
||||||
UIWidgets::Tooltip("If enabled, will prevent the tracker from displaying slots 1-4 in all shops. Requires save reload.");
|
hideShopRightChecks = !hideShopRightChecks;
|
||||||
|
RecalculateAreaTotals();
|
||||||
|
}
|
||||||
|
UIWidgets::Tooltip("If enabled, will prevent the tracker from displaying slots 1-4 in all shops.");
|
||||||
|
if (UIWidgets::EnhancementCheckbox("Always show gold skulltulas", "gCheckTrackerOptionAlwaysShowGSLocs", false, "")) {
|
||||||
|
alwaysShowGS = !alwaysShowGS;
|
||||||
|
RecalculateAreaTotals();
|
||||||
|
}
|
||||||
|
UIWidgets::Tooltip("If enabled, will show GS locations in the tracker regardless of tokensanity settings.");
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
@@ -1541,10 +1651,14 @@ void CheckTrackerWindow::InitElement() {
|
|||||||
Teardown();
|
Teardown();
|
||||||
});
|
});
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>(CheckTrackerItemReceive);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSaleEnd>(CheckTrackerSaleEnd);
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(CheckTrackerFrame);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>(CheckTrackerTransition);
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnShopSlotChange>(CheckTrackerShopSlotChange);
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneFlagSet>(CheckTrackerSceneFlagSet);
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFlagSet>(CheckTrackerFlagSet);
|
||||||
|
|
||||||
|
hideShopRightChecks = CVarGetInteger("gCheckTrackerOptionHideRightShopChecks", 1);
|
||||||
|
alwaysShowGS = CVarGetInteger("gCheckTrackerOptionAlwaysShowGSLocs", 0);
|
||||||
|
|
||||||
LocationTable_Init();
|
LocationTable_Init();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,11 +48,10 @@ void Teardown();
|
|||||||
void UpdateAllOrdering();
|
void UpdateAllOrdering();
|
||||||
bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj);
|
bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj);
|
||||||
void InitTrackerData(bool isDebug);
|
void InitTrackerData(bool isDebug);
|
||||||
void SetLastItemGetRC(RandomizerCheck rc);
|
|
||||||
RandomizerCheckArea GetCheckArea();
|
RandomizerCheckArea GetCheckArea();
|
||||||
void CheckTrackerDialogClosed();
|
|
||||||
void ToggleShopRightChecks();
|
|
||||||
void UpdateCheck(uint32_t, RandomizerCheckTrackerData);
|
void UpdateCheck(uint32_t, RandomizerCheckTrackerData);
|
||||||
|
bool IsAreaSpoiled(RandomizerCheckArea rcArea);
|
||||||
|
void SetAreaSpoiled(RandomizerCheckArea rcArea);
|
||||||
} // namespace CheckTracker
|
} // namespace CheckTracker
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ static s16 newIceCavernEntrance = ICE_CAVERN_ENTRANCE;
|
|||||||
static s8 hasCopiedEntranceTable = 0;
|
static s8 hasCopiedEntranceTable = 0;
|
||||||
static s8 hasModifiedEntranceTable = 0;
|
static s8 hasModifiedEntranceTable = 0;
|
||||||
|
|
||||||
void Entrance_SetEntranceDiscovered(u16 entranceIndex);
|
void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance);
|
||||||
|
|
||||||
u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) {
|
u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) {
|
||||||
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->blueWarp == 0
|
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->blueWarp == 0
|
||||||
@@ -276,13 +276,13 @@ s16 Entrance_OverrideNextIndex(s16 nextEntranceIndex) {
|
|||||||
return nextEntranceIndex;
|
return nextEntranceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entrance_SetEntranceDiscovered(nextEntranceIndex);
|
Entrance_SetEntranceDiscovered(nextEntranceIndex, false);
|
||||||
EntranceTracker_SetLastEntranceOverride(nextEntranceIndex);
|
EntranceTracker_SetLastEntranceOverride(nextEntranceIndex);
|
||||||
return Grotto_OverrideSpecialEntrance(Entrance_GetOverride(nextEntranceIndex));
|
return Grotto_OverrideSpecialEntrance(Entrance_GetOverride(nextEntranceIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 Entrance_OverrideDynamicExit(s16 dynamicExitIndex) {
|
s16 Entrance_OverrideDynamicExit(s16 dynamicExitIndex) {
|
||||||
Entrance_SetEntranceDiscovered(dynamicExitList[dynamicExitIndex]);
|
Entrance_SetEntranceDiscovered(dynamicExitList[dynamicExitIndex], false);
|
||||||
EntranceTracker_SetLastEntranceOverride(dynamicExitList[dynamicExitIndex]);
|
EntranceTracker_SetLastEntranceOverride(dynamicExitList[dynamicExitIndex]);
|
||||||
return Grotto_OverrideSpecialEntrance(Entrance_GetOverride(dynamicExitList[dynamicExitIndex]));
|
return Grotto_OverrideSpecialEntrance(Entrance_GetOverride(dynamicExitList[dynamicExitIndex]));
|
||||||
}
|
}
|
||||||
@@ -398,6 +398,11 @@ void Entrance_SetSavewarpEntrance(void) {
|
|||||||
gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
gSaveContext.entranceIndex = 0x0486; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
||||||
} else if (scene == SCENE_LINKS_HOUSE) {
|
} else if (scene == SCENE_LINKS_HOUSE) {
|
||||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE);
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE);
|
||||||
|
} else if (CVarGetInteger("gRememberSaveLocation", 0) && scene != SCENE_FAIRYS_FOUNTAIN && scene != SCENE_GROTTOS &&
|
||||||
|
// Use the saved entrance value with remember save location, except when in grottos/fairy fountains or if
|
||||||
|
// the entrance index is -1 (new save)
|
||||||
|
gSaveContext.entranceIndex != -1) {
|
||||||
|
return;
|
||||||
} else if (LINK_IS_CHILD) {
|
} else if (LINK_IS_CHILD) {
|
||||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
|
||||||
} else {
|
} else {
|
||||||
@@ -784,7 +789,7 @@ u8 Entrance_GetIsEntranceDiscovered(u16 entranceIndex) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entrance_SetEntranceDiscovered(u16 entranceIndex) {
|
void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) {
|
||||||
// Skip if already set to save time from setting the connected entrance or
|
// Skip if already set to save time from setting the connected entrance or
|
||||||
// if this entrance is outside of the randomized entrance range (i.e. is a dynamic entrance)
|
// if this entrance is outside of the randomized entrance range (i.e. is a dynamic entrance)
|
||||||
if (entranceIndex > MAX_ENTRANCE_RANDO_USED_INDEX || Entrance_GetIsEntranceDiscovered(entranceIndex)) {
|
if (entranceIndex > MAX_ENTRANCE_RANDO_USED_INDEX || Entrance_GetIsEntranceDiscovered(entranceIndex)) {
|
||||||
@@ -796,14 +801,20 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex) {
|
|||||||
if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) {
|
if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) {
|
||||||
u32 entranceBit = 1 << (entranceIndex - (idx * bitsPerIndex));
|
u32 entranceBit = 1 << (entranceIndex - (idx * bitsPerIndex));
|
||||||
gSaveContext.sohStats.entrancesDiscovered[idx] |= entranceBit;
|
gSaveContext.sohStats.entrancesDiscovered[idx] |= entranceBit;
|
||||||
// Set connected
|
|
||||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
// Set reverse entrance when not decoupled
|
||||||
if (entranceIndex == gSaveContext.entranceOverrides[i].index) {
|
if (!Randomizer_GetSettingValue(RSK_DECOUPLED_ENTRANCES) && !isReversedEntrance) {
|
||||||
Entrance_SetEntranceDiscovered(gSaveContext.entranceOverrides[i].overrideDestination);
|
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||||
break;
|
if (entranceIndex == gSaveContext.entranceOverrides[i].index) {
|
||||||
|
Entrance_SetEntranceDiscovered(gSaveContext.entranceOverrides[i].overrideDestination, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Save entrancesDiscovered
|
|
||||||
Save_SaveSection(SECTION_ID_ENTRANCES);
|
// Save entrancesDiscovered when it is not the reversed entrance
|
||||||
|
if (!isReversedEntrance) {
|
||||||
|
Save_SaveSection(SECTION_ID_ENTRANCES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ void Entrance_OverrideSpawnScene(int32_t sceneNum, int32_t spawn);
|
|||||||
int32_t Entrance_OverrideSpawnSceneRoom(int32_t sceneNum, int32_t spawn, int32_t room);
|
int32_t Entrance_OverrideSpawnSceneRoom(int32_t sceneNum, int32_t spawn, int32_t room);
|
||||||
void Entrance_EnableFW(void);
|
void Entrance_EnableFW(void);
|
||||||
uint8_t Entrance_GetIsEntranceDiscovered(uint16_t entranceIndex);
|
uint8_t Entrance_GetIsEntranceDiscovered(uint16_t entranceIndex);
|
||||||
void Entrance_SetEntranceDiscovered(uint16_t entranceIndex);
|
void Entrance_SetEntranceDiscovered(uint16_t entranceIndex, uint8_t isReversedEntrance);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
|||||||
// If Link hits a grotto exit, load the entrance index from the grotto exit list
|
// If Link hits a grotto exit, load the entrance index from the grotto exit list
|
||||||
// based on the current grotto ID
|
// based on the current grotto ID
|
||||||
if (nextEntranceIndex == 0x7FFF) {
|
if (nextEntranceIndex == 0x7FFF) {
|
||||||
Entrance_SetEntranceDiscovered(ENTRANCE_RANDO_GROTTO_EXIT_START + grottoId);
|
Entrance_SetEntranceDiscovered(ENTRANCE_RANDO_GROTTO_EXIT_START + grottoId, false);
|
||||||
EntranceTracker_SetLastEntranceOverride(ENTRANCE_RANDO_GROTTO_EXIT_START + grottoId);
|
EntranceTracker_SetLastEntranceOverride(ENTRANCE_RANDO_GROTTO_EXIT_START + grottoId);
|
||||||
nextEntranceIndex = grottoExitList[grottoId];
|
nextEntranceIndex = grottoExitList[grottoId];
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ void Grotto_OverrideActorEntrance(Actor* thisx) {
|
|||||||
|
|
||||||
if (grottoContent == grottoLoadTable[index].content && gPlayState->sceneNum == grottoLoadTable[index].scene) {
|
if (grottoContent == grottoLoadTable[index].content && gPlayState->sceneNum == grottoLoadTable[index].scene) {
|
||||||
// Find the override for the matching index from the grotto Load List
|
// Find the override for the matching index from the grotto Load List
|
||||||
Entrance_SetEntranceDiscovered(ENTRANCE_RANDO_GROTTO_LOAD_START + index);
|
Entrance_SetEntranceDiscovered(ENTRANCE_RANDO_GROTTO_LOAD_START + index, false);
|
||||||
EntranceTracker_SetLastEntranceOverride(ENTRANCE_RANDO_GROTTO_LOAD_START + index);
|
EntranceTracker_SetLastEntranceOverride(ENTRANCE_RANDO_GROTTO_LOAD_START + index);
|
||||||
index = grottoLoadList[index];
|
index = grottoLoadList[index];
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "randomizer_check_tracker.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -30,6 +31,8 @@ void DrawBottle(ItemTrackerItem item);
|
|||||||
void DrawQuest(ItemTrackerItem item);
|
void DrawQuest(ItemTrackerItem item);
|
||||||
void DrawSong(ItemTrackerItem item);
|
void DrawSong(ItemTrackerItem item);
|
||||||
|
|
||||||
|
int itemTrackerSectionId;
|
||||||
|
|
||||||
bool shouldUpdateVectors = true;
|
bool shouldUpdateVectors = true;
|
||||||
|
|
||||||
std::vector<ItemTrackerItem> mainWindowItems = {};
|
std::vector<ItemTrackerItem> mainWindowItems = {};
|
||||||
@@ -282,26 +285,21 @@ void ItemTrackerOnFrame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveNotes(uint32_t fileNum) {
|
|
||||||
CVarSetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str());
|
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidSaveFile() {
|
bool IsValidSaveFile() {
|
||||||
bool validSave = gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2;
|
bool validSave = gSaveContext.fileNum >= 0 && gSaveContext.fileNum <= 2;
|
||||||
return validSave;
|
return validSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasSong(ItemTrackerItem item) {
|
bool HasSong(ItemTrackerItem item) {
|
||||||
return (1 << item.id) & gSaveContext.inventory.questItems;
|
return GameInteractor::IsSaveLoaded() ? ((1 << item.id) & gSaveContext.inventory.questItems) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasQuestItem(ItemTrackerItem item) {
|
bool HasQuestItem(ItemTrackerItem item) {
|
||||||
return (item.data & gSaveContext.inventory.questItems) != 0;
|
return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.questItems) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasEquipment(ItemTrackerItem item) {
|
bool HasEquipment(ItemTrackerItem item) {
|
||||||
return (item.data & gSaveContext.inventory.equipment) != 0;
|
return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.equipment) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
|
ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
|
||||||
@@ -409,8 +407,12 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) {
|
|||||||
#define IM_COL_GREEN IM_COL32(0, 255, 0, 255)
|
#define IM_COL_GREEN IM_COL32(0, 255, 0, 255)
|
||||||
#define IM_COL_GRAY IM_COL32(155, 155, 155, 255)
|
#define IM_COL_GRAY IM_COL32(155, 155, 155, 255)
|
||||||
#define IM_COL_PURPLE IM_COL32(180, 90, 200, 255)
|
#define IM_COL_PURPLE IM_COL32(180, 90, 200, 255)
|
||||||
|
#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255)
|
||||||
|
|
||||||
void DrawItemCount(ItemTrackerItem item) {
|
void DrawItemCount(ItemTrackerItem item, bool hideMax) {
|
||||||
|
if (!GameInteractor::IsSaveLoaded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
||||||
ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item);
|
ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item);
|
||||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
@@ -419,7 +421,7 @@ void DrawItemCount(ItemTrackerItem item) {
|
|||||||
|
|
||||||
if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) {
|
if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) {
|
||||||
std::string currentString = "";
|
std::string currentString = "";
|
||||||
std::string maxString = std::to_string(currentAndMax.maxCapacity);
|
std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity);
|
||||||
ImU32 currentColor = IM_COL_WHITE;
|
ImU32 currentColor = IM_COL_WHITE;
|
||||||
ImU32 maxColor = IM_COL_GREEN;
|
ImU32 maxColor = IM_COL_GREEN;
|
||||||
// "Collected / Max", "Current / Collected / Max", "Current / Max"
|
// "Collected / Max", "Current / Collected / Max", "Current / Max"
|
||||||
@@ -551,7 +553,7 @@ void DrawQuest(ItemTrackerItem item) {
|
|||||||
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
||||||
|
|
||||||
if (item.id == QUEST_SKULL_TOKEN) {
|
if (item.id == QUEST_SKULL_TOKEN) {
|
||||||
DrawItemCount(item);
|
DrawItemCount(item, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
@@ -561,7 +563,7 @@ void DrawQuest(ItemTrackerItem item) {
|
|||||||
|
|
||||||
void DrawItem(ItemTrackerItem item) {
|
void DrawItem(ItemTrackerItem item) {
|
||||||
|
|
||||||
uint32_t actualItemId = INV_CONTENT(item.id);
|
uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE;
|
||||||
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
||||||
bool hasItem = actualItemId != ITEM_NONE;
|
bool hasItem = actualItemId != ITEM_NONE;
|
||||||
std::string itemName = "";
|
std::string itemName = "";
|
||||||
@@ -620,7 +622,7 @@ void DrawItem(ItemTrackerItem item) {
|
|||||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
|
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded),
|
||||||
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
||||||
|
|
||||||
DrawItemCount(item);
|
DrawItemCount(item, false);
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|
||||||
if (itemName == "") {
|
if (itemName == "") {
|
||||||
@@ -631,7 +633,7 @@ void DrawItem(ItemTrackerItem item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DrawBottle(ItemTrackerItem item) {
|
void DrawBottle(ItemTrackerItem item) {
|
||||||
uint32_t actualItemId = gSaveContext.inventory.items[SLOT(item.id) + item.data];
|
uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? (gSaveContext.inventory.items[SLOT(item.id) + item.data]) : false;
|
||||||
bool hasItem = actualItemId != ITEM_NONE;
|
bool hasItem = actualItemId != ITEM_NONE;
|
||||||
|
|
||||||
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
|
if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) {
|
||||||
@@ -650,8 +652,8 @@ void DrawDungeonItem(ItemTrackerItem item) {
|
|||||||
ImU32 dungeonColor = IM_COL_WHITE;
|
ImU32 dungeonColor = IM_COL_WHITE;
|
||||||
uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
|
uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential
|
||||||
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
int iconSize = CVarGetInteger("gItemTrackerIconSize", 36);
|
||||||
bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[item.data]) != 0;
|
bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false;
|
||||||
bool hasSmallKey = (gSaveContext.inventory.dungeonKeys[item.data]) >= 0;
|
bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false;
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
if (itemId == ITEM_KEY_SMALL) {
|
if (itemId == ITEM_KEY_SMALL) {
|
||||||
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded),
|
ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded),
|
||||||
@@ -662,16 +664,18 @@ void DrawDungeonItem(ItemTrackerItem item) {
|
|||||||
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ResourceMgr_IsSceneMasterQuest(item.data) && (CHECK_DUNGEON_ITEM(DUNGEON_MAP, item.data) || item.data == SCENE_GERUDO_TRAINING_GROUND || item.data == SCENE_INSIDE_GANONS_CASTLE)) {
|
if (CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast<SceneID>(item.data))) && GameInteractor::IsSaveLoaded()) {
|
||||||
dungeonColor = IM_COL_PURPLE;
|
dungeonColor = (ResourceMgr_IsSceneMasterQuest(item.data) ? IM_COL_PURPLE : IM_COL_LIGHT_YELLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemId == ITEM_KEY_SMALL) {
|
if (itemId == ITEM_KEY_SMALL) {
|
||||||
DrawItemCount(item);
|
DrawItemCount(item, !CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast<SceneID>(item.data))));
|
||||||
|
|
||||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
|
// offset puts the text at the correct level. for some reason, if the save is loaded, the margin is 3 pixels higher only for small keys, so we use 16 then. Otherwise, 13 is where everything else is
|
||||||
|
int offset = GameInteractor::IsSaveLoaded() ? 16 : 13;
|
||||||
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 + offset)));
|
||||||
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();
|
||||||
@@ -728,13 +732,15 @@ void DrawNotes(bool resizeable = false) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200);
|
ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200);
|
||||||
if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) {
|
if (GameInteractor::IsSaveLoaded()) {
|
||||||
notesNeedSave = true;
|
if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) {
|
||||||
notesIdleFrames = 0;
|
notesNeedSave = true;
|
||||||
}
|
notesIdleFrames = 0;
|
||||||
if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) {
|
}
|
||||||
notesNeedSave = false;
|
if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) {
|
||||||
SaveNotes(gSaveContext.fileNum);
|
notesNeedSave = false;
|
||||||
|
SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
}
|
}
|
||||||
@@ -959,6 +965,26 @@ void UpdateVectors() {
|
|||||||
shouldUpdateVectors = false;
|
shouldUpdateVectors = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemTrackerInitFile(bool isDebug) {
|
||||||
|
itemTrackerNotes.clear();
|
||||||
|
itemTrackerNotes.push_back(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemTrackerSaveFile(SaveContext* saveContext, int sectionID, bool fullSave) {
|
||||||
|
SaveManager::Instance->SaveData("personalNotes", std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemTrackerLoadFile() {
|
||||||
|
std::string initialTrackerNotes = "";
|
||||||
|
SaveManager::Instance->LoadData("personalNotes", initialTrackerNotes);
|
||||||
|
itemTrackerNotes.resize(initialTrackerNotes.length() + 1);
|
||||||
|
if (initialTrackerNotes != "") {
|
||||||
|
SohUtils::CopyStringToCharArray(itemTrackerNotes.Data, initialTrackerNotes.c_str(), itemTrackerNotes.size());
|
||||||
|
} else {
|
||||||
|
itemTrackerNotes.push_back(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ItemTrackerWindow::DrawElement() {
|
void ItemTrackerWindow::DrawElement() {
|
||||||
UpdateVectors();
|
UpdateVectors();
|
||||||
|
|
||||||
@@ -1223,14 +1249,9 @@ void ItemTrackerWindow::InitElement() {
|
|||||||
itemTrackerNotes.push_back(0);
|
itemTrackerNotes.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnLoadFile>([](uint32_t fileNum) {
|
SaveManager::Instance->AddInitFunction(ItemTrackerInitFile);
|
||||||
const char* initialTrackerNotes = CVarGetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), "");
|
itemTrackerSectionId = SaveManager::Instance->AddSaveFunction("itemTrackerData", 1, ItemTrackerSaveFile, true, -1);
|
||||||
itemTrackerNotes.resize(strlen(initialTrackerNotes) + 1);
|
SaveManager::Instance->AddLoadFunction("itemTrackerData", 1, ItemTrackerLoadFile);
|
||||||
strcpy(itemTrackerNotes.Data, initialTrackerNotes);
|
|
||||||
});
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnDeleteFile>([](uint32_t fileNum) {
|
|
||||||
CVarSetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), "");
|
|
||||||
LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
|
|
||||||
});
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(ItemTrackerOnFrame);
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnGameFrameUpdate>(ItemTrackerOnFrame);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ void RegisterOnInterfaceUpdateHook() {
|
|||||||
|
|
||||||
prevTimer = timer;
|
prevTimer = timer;
|
||||||
|
|
||||||
if (!GameInteractor::IsSaveLoaded()) return;
|
if (!GameInteractor::IsSaveLoaded(true)) return;
|
||||||
|
|
||||||
static int16_t lostHealth = 0;
|
static int16_t lostHealth = 0;
|
||||||
static int16_t prevHealth = 0;
|
static int16_t prevHealth = 0;
|
||||||
|
|||||||
+184
-17
@@ -49,6 +49,9 @@
|
|||||||
#include "Fonts.h"
|
#include "Fonts.h"
|
||||||
#include <Utils/StringHelper.h>
|
#include <Utils/StringHelper.h>
|
||||||
#include "Enhancements/custom-message/CustomMessageManager.h"
|
#include "Enhancements/custom-message/CustomMessageManager.h"
|
||||||
|
#include "Enhancements/presets.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <boost_custom/container_hash/hash_32.hpp>
|
||||||
|
|
||||||
#if not defined (__SWITCH__) && not defined(__WIIU__)
|
#if not defined (__SWITCH__) && not defined(__WIIU__)
|
||||||
#include "Extractor/Extract.h"
|
#include "Extractor/Extract.h"
|
||||||
@@ -115,6 +118,8 @@ CrowdControl* CrowdControl::Instance;
|
|||||||
|
|
||||||
#include "soh/config/ConfigUpdaters.h"
|
#include "soh/config/ConfigUpdaters.h"
|
||||||
|
|
||||||
|
void SoH_ProcessDroppedFiles(std::string filePath);
|
||||||
|
|
||||||
OTRGlobals* OTRGlobals::Instance;
|
OTRGlobals* OTRGlobals::Instance;
|
||||||
SaveManager* SaveManager::Instance;
|
SaveManager* SaveManager::Instance;
|
||||||
CustomMessageManager* CustomMessageManager::Instance;
|
CustomMessageManager* CustomMessageManager::Instance;
|
||||||
@@ -132,6 +137,8 @@ Color_RGB8 zoraColor = { 0x00, 0xEC, 0x64 };
|
|||||||
|
|
||||||
float previousImGuiScale;
|
float previousImGuiScale;
|
||||||
|
|
||||||
|
bool prevAltAssets = false;
|
||||||
|
|
||||||
// Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED.
|
// Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Color_RGB8 inner;
|
Color_RGB8 inner;
|
||||||
@@ -253,15 +260,26 @@ OTRGlobals::OTRGlobals() {
|
|||||||
OTRFiles.push_back(sohOtrPath);
|
OTRFiles.push_back(sohOtrPath);
|
||||||
}
|
}
|
||||||
std::string patchesPath = LUS::Context::LocateFileAcrossAppDirs("mods", appShortName);
|
std::string patchesPath = LUS::Context::LocateFileAcrossAppDirs("mods", appShortName);
|
||||||
|
std::vector<std::string> patchOTRs = {};
|
||||||
if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) {
|
if (patchesPath.length() > 0 && std::filesystem::exists(patchesPath)) {
|
||||||
if (std::filesystem::is_directory(patchesPath)) {
|
if (std::filesystem::is_directory(patchesPath)) {
|
||||||
for (const auto& p : std::filesystem::recursive_directory_iterator(patchesPath)) {
|
for (const auto& p : std::filesystem::recursive_directory_iterator(patchesPath, std::filesystem::directory_options::follow_directory_symlink)) {
|
||||||
if (StringHelper::IEquals(p.path().extension().string(), ".otr")) {
|
if (StringHelper::IEquals(p.path().extension().string(), ".otr")) {
|
||||||
OTRFiles.push_back(p.path().generic_string());
|
patchOTRs.push_back(p.path().generic_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::sort(patchOTRs.begin(), patchOTRs.end(), [](const std::string& a, const std::string& b) {
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
a.begin(), a.end(),
|
||||||
|
b.begin(), b.end(),
|
||||||
|
[](char c1, char c2) {
|
||||||
|
return std::tolower(c1) < std::tolower(c2);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
OTRFiles.insert(OTRFiles.end(), patchOTRs.begin(), patchOTRs.end());
|
||||||
std::unordered_set<uint32_t> ValidHashes = {
|
std::unordered_set<uint32_t> ValidHashes = {
|
||||||
OOT_PAL_MQ,
|
OOT_PAL_MQ,
|
||||||
OOT_NTSC_JP_MQ,
|
OOT_NTSC_JP_MQ,
|
||||||
@@ -281,6 +299,9 @@ OTRGlobals::OTRGlobals() {
|
|||||||
};
|
};
|
||||||
// tell LUS to reserve 3 SoH specific threads (Game, Audio, Save)
|
// tell LUS to reserve 3 SoH specific threads (Game, Audio, Save)
|
||||||
context = LUS::Context::CreateInstance("Ship of Harkinian", appShortName, "shipofharkinian.json", OTRFiles, {}, 3);
|
context = LUS::Context::CreateInstance("Ship of Harkinian", appShortName, "shipofharkinian.json", OTRFiles, {}, 3);
|
||||||
|
prevAltAssets = CVarGetInteger("gAltAssets", 0);
|
||||||
|
context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets);
|
||||||
|
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>());
|
||||||
@@ -1021,9 +1042,9 @@ extern "C" void InitOTR() {
|
|||||||
OTRGlobals::Instance = new OTRGlobals();
|
OTRGlobals::Instance = new OTRGlobals();
|
||||||
CustomMessageManager::Instance = new CustomMessageManager();
|
CustomMessageManager::Instance = new CustomMessageManager();
|
||||||
ItemTableManager::Instance = new ItemTableManager();
|
ItemTableManager::Instance = new ItemTableManager();
|
||||||
|
GameInteractor::Instance = new GameInteractor();
|
||||||
SaveManager::Instance = new SaveManager();
|
SaveManager::Instance = new SaveManager();
|
||||||
SohGui::SetupGuiElements();
|
SohGui::SetupGuiElements();
|
||||||
GameInteractor::Instance = new GameInteractor();
|
|
||||||
AudioCollection::Instance = new AudioCollection();
|
AudioCollection::Instance = new AudioCollection();
|
||||||
ActorDB::Instance = new ActorDB();
|
ActorDB::Instance = new ActorDB();
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
@@ -1043,6 +1064,11 @@ extern "C" void InitOTR() {
|
|||||||
|
|
||||||
InitMods();
|
InitMods();
|
||||||
ActorDB::AddBuiltInCustomActors();
|
ActorDB::AddBuiltInCustomActors();
|
||||||
|
// #region SOH [Randomizer] TODO: Remove these and refactor spoiler file handling for randomizer
|
||||||
|
CVarClear("gRandomizerNewFileDropped");
|
||||||
|
CVarClear("gRandomizerDroppedFile");
|
||||||
|
// #endregion
|
||||||
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnFileDropped>(SoH_ProcessDroppedFiles);
|
||||||
|
|
||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
tm *tm_now = localtime(&now);
|
tm *tm_now = localtime(&now);
|
||||||
@@ -1122,8 +1148,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
|
||||||
@@ -1131,7 +1156,7 @@ extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) {
|
|||||||
OTRGlobals::Instance->context->GetWindow()->MainLoop(run_one_game_iter);
|
OTRGlobals::Instance->context->GetWindow()->MainLoop(run_one_game_iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool ShouldClearTextureCacheAtEndOfFrame;
|
extern bool ToggleAltAssetsAtEndOfFrame;
|
||||||
|
|
||||||
extern "C" void Graph_StartFrame() {
|
extern "C" void Graph_StartFrame() {
|
||||||
#ifndef __WIIU__
|
#ifndef __WIIU__
|
||||||
@@ -1214,13 +1239,21 @@ extern "C" void Graph_StartFrame() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case KbScancode::LUS_KB_TAB: {
|
case KbScancode::LUS_KB_TAB: {
|
||||||
// Toggle HD Assets
|
|
||||||
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
CVarSetInteger("gAltAssets", !CVarGetInteger("gAltAssets", 0));
|
||||||
ShouldClearTextureCacheAtEndOfFrame = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (CVarGetInteger("gNewFileDropped", 0)) {
|
||||||
|
std::string filePath = SohUtils::Sanitize(CVarGetString("gDroppedFile", ""));
|
||||||
|
if (!filePath.empty()) {
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnFileDropped>(filePath);
|
||||||
|
}
|
||||||
|
CVarClear("gNewFileDropped");
|
||||||
|
CVarClear("gDroppedFile");
|
||||||
|
}
|
||||||
|
|
||||||
OTRGlobals::Instance->context->GetWindow()->StartFrame();
|
OTRGlobals::Instance->context->GetWindow()->StartFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1286,10 +1319,13 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldClearTextureCacheAtEndOfFrame) {
|
bool curAltAssets = CVarGetInteger("gAltAssets", 0);
|
||||||
|
if (prevAltAssets != curAltAssets) {
|
||||||
|
prevAltAssets = curAltAssets;
|
||||||
|
LUS::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets);
|
||||||
gfx_texture_cache_clear();
|
gfx_texture_cache_clear();
|
||||||
LUS::SkeletonPatcher::UpdateSkeletons();
|
LUS::SkeletonPatcher::UpdateSkeletons();
|
||||||
ShouldClearTextureCacheAtEndOfFrame = false;
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnAssetAltChange>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// OTRTODO: FIGURE OUT END FRAME POINT
|
// OTRTODO: FIGURE OUT END FRAME POINT
|
||||||
@@ -1415,6 +1451,14 @@ extern "C" void ResourceMgr_DirtyDirectory(const char* resName) {
|
|||||||
LUS::Context::GetInstance()->GetResourceManager()->DirtyDirectory(resName);
|
LUS::Context::GetInstance()->GetResourceManager()->DirtyDirectory(resName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void ResourceMgr_UnloadResource(const char* resName) {
|
||||||
|
std::string path = resName;
|
||||||
|
if (path.substr(0, 7) == "__OTR__") {
|
||||||
|
path = path.substr(7);
|
||||||
|
}
|
||||||
|
auto res = LUS::Context::GetInstance()->GetResourceManager()->UnloadResource(path);
|
||||||
|
}
|
||||||
|
|
||||||
// OTRTODO: There is probably a more elegant way to go about this...
|
// OTRTODO: There is probably a more elegant way to go about this...
|
||||||
// Kenix: This is definitely leaking memory when it's called.
|
// Kenix: This is definitely leaking memory when it's called.
|
||||||
extern "C" char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize) {
|
extern "C" char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize) {
|
||||||
@@ -1441,6 +1485,31 @@ extern "C" uint8_t ResourceMgr_FileExists(const char* filePath) {
|
|||||||
return ExtensionCache.contains(path);
|
return ExtensionCache.contains(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" uint8_t ResourceMgr_FileAltExists(const char* filePath) {
|
||||||
|
std::string path = filePath;
|
||||||
|
if (path.substr(0, 7) == "__OTR__") {
|
||||||
|
path = path.substr(7);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.substr(0, 4) != "alt/") {
|
||||||
|
path = "alt/" + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExtensionCache.contains(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" bool ResourceMgr_IsAltAssetsEnabled() {
|
||||||
|
return LUS::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unloads a resource if an alternate version exists when alt assets are enabled
|
||||||
|
// The resource is only removed from the internal cache to prevent it from used in the next resource lookup
|
||||||
|
extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) {
|
||||||
|
if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists((char*) resName)) {
|
||||||
|
ResourceMgr_UnloadResource((char*) resName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void ResourceMgr_LoadFile(const char* resName) {
|
extern "C" void ResourceMgr_LoadFile(const char* resName) {
|
||||||
LUS::Context::GetInstance()->GetResourceManager()->LoadResource(resName);
|
LUS::Context::GetInstance()->GetResourceManager()->LoadResource(resName);
|
||||||
}
|
}
|
||||||
@@ -1480,6 +1549,11 @@ extern "C" char* ResourceMgr_LoadFileFromDisk(const char* filePath) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" uint8_t ResourceMgr_TexIsRaw(const char* texPath) {
|
||||||
|
auto res = std::static_pointer_cast<LUS::Texture>(GetResourceByNameHandlingMQ(texPath));
|
||||||
|
return res->Flags & TEX_FLAG_LOAD_AS_RAW;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" uint8_t ResourceMgr_ResourceIsBackground(char* texPath) {
|
extern "C" uint8_t ResourceMgr_ResourceIsBackground(char* texPath) {
|
||||||
auto res = GetResourceByNameHandlingMQ(texPath);
|
auto res = GetResourceByNameHandlingMQ(texPath);
|
||||||
return res->GetInitData()->Type == LUS::ResourceType::SOH_Background;
|
return res->GetInitData()->Type == LUS::ResourceType::SOH_Background;
|
||||||
@@ -1565,6 +1639,11 @@ extern "C" void ResourceMgr_PushCurrentDirectory(char* path)
|
|||||||
|
|
||||||
extern "C" Gfx* ResourceMgr_LoadGfxByName(const char* path)
|
extern "C" Gfx* ResourceMgr_LoadGfxByName(const char* path)
|
||||||
{
|
{
|
||||||
|
// When an alt resource exists for the DL, we need to unload the original asset
|
||||||
|
// to clear the cache so the alt asset will be loaded instead
|
||||||
|
// OTRTODO: If Alt loading over original cache is fixed, this line can most likely be removed
|
||||||
|
ResourceMgr_UnloadOriginalWhenAltExists(path);
|
||||||
|
|
||||||
auto res = std::static_pointer_cast<LUS::DisplayList>(GetResourceByNameHandlingMQ(path));
|
auto res = std::static_pointer_cast<LUS::DisplayList>(GetResourceByNameHandlingMQ(path));
|
||||||
return (Gfx*)&res->Instructions[0];
|
return (Gfx*)&res->Instructions[0];
|
||||||
}
|
}
|
||||||
@@ -1663,6 +1742,7 @@ extern "C" char* ResourceMgr_LoadArrayByName(const char* path)
|
|||||||
return (char*)res->Scalars.data();
|
return (char*)res->Scalars.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return of LoadArrayByNameAsVec3s must be freed by the caller
|
||||||
extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) {
|
extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) {
|
||||||
auto res = std::static_pointer_cast<LUS::Array>(GetResourceByNameHandlingMQ(path));
|
auto res = std::static_pointer_cast<LUS::Array>(GetResourceByNameHandlingMQ(path));
|
||||||
|
|
||||||
@@ -1795,7 +1875,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel
|
|||||||
pathStr = pathStr.substr(sOtr.length());
|
pathStr = pathStr.substr(sOtr.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAlt = CVarGetInteger("gAltAssets", 0);
|
bool isAlt = ResourceMgr_IsAltAssetsEnabled();
|
||||||
|
|
||||||
if (isAlt) {
|
if (isAlt) {
|
||||||
pathStr = LUS::IResource::gAltAssetPrefix + pathStr;
|
pathStr = LUS::IResource::gAltAssetPrefix + pathStr;
|
||||||
@@ -2045,10 +2125,10 @@ Color_RGB8 GetColorForControllerLED() {
|
|||||||
if (source == LED_SOURCE_CUSTOM) {
|
if (source == LED_SOURCE_CUSTOM) {
|
||||||
color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 });
|
color = CVarGetColor24("gLedPort1Color", { 255, 255, 255 });
|
||||||
}
|
}
|
||||||
if (criticalOverride || source == LED_SOURCE_HEALTH) {
|
if (gPlayState && (criticalOverride || source == LED_SOURCE_HEALTH)) {
|
||||||
if (HealthMeter_IsCritical()) {
|
if (HealthMeter_IsCritical()) {
|
||||||
color = { 0xFF, 0, 0 };
|
color = { 0xFF, 0, 0 };
|
||||||
} else if (source == LED_SOURCE_HEALTH) {
|
} else if (gSaveContext.healthCapacity != 0 && source == LED_SOURCE_HEALTH) {
|
||||||
if (gSaveContext.health / gSaveContext.healthCapacity <= 0.4f) {
|
if (gSaveContext.health / gSaveContext.healthCapacity <= 0.4f) {
|
||||||
color = { 0xFF, 0xFF, 0 };
|
color = { 0xFF, 0xFF, 0 };
|
||||||
} else {
|
} else {
|
||||||
@@ -2414,8 +2494,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;
|
||||||
@@ -2434,6 +2513,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
|||||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, Randomizer_GetSettingValue(RSK_WARP_SONG_HINTS) == RO_GENERIC_OFF);
|
messageEntry = OTRGlobals::Instance->gRandomizer->GetWarpSongMessage(textId, Randomizer_GetSettingValue(RSK_WARP_SONG_HINTS) == RO_GENERIC_OFF);
|
||||||
} else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) {
|
} else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) {
|
||||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId);
|
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId);
|
||||||
|
} else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) {
|
||||||
|
messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW);
|
||||||
} else if (textId == 0x3052 || (textId >= 0x3069 && textId <= 0x3070)) { //Fire Temple gorons
|
} else if (textId == 0x3052 || (textId >= 0x3069 && textId <= 0x3070)) { //Fire Temple gorons
|
||||||
u16 choice = Random(0, NUM_GORON_MESSAGES);
|
u16 choice = Random(0, NUM_GORON_MESSAGES);
|
||||||
messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice);
|
messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice);
|
||||||
@@ -2523,6 +2604,92 @@ 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 CheckTracker_OnMessageClose() {
|
extern "C" void Gfx_UnregisterBlendedTexture(const char* name) {
|
||||||
CheckTracker::CheckTrackerDialogClosed();
|
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) {
|
||||||
|
try {
|
||||||
|
std::ifstream configStream(filePath);
|
||||||
|
if (!configStream) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json configJson;
|
||||||
|
configStream >> configJson;
|
||||||
|
|
||||||
|
// #region SOH [Randomizer] TODO: Refactor spoiler file handling for randomizer
|
||||||
|
if (configJson.contains("version") && configJson.contains("finalSeed")) {
|
||||||
|
CVarSetString("gRandomizerDroppedFile", filePath.c_str());
|
||||||
|
CVarSetInteger("gRandomizerNewFileDropped", 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
if (!configJson.contains("CVars")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCvars(enhancementsCvars);
|
||||||
|
clearCvars(cheatCvars);
|
||||||
|
clearCvars(randomizerCvars);
|
||||||
|
|
||||||
|
// Flatten everything under CVars into a single array
|
||||||
|
auto cvars = configJson["CVars"].flatten();
|
||||||
|
|
||||||
|
for (auto& [key, value] : cvars.items()) {
|
||||||
|
// Replace slashes with dots in key, and remove leading dot
|
||||||
|
std::string path = key;
|
||||||
|
std::replace(path.begin(), path.end(), '/', '.');
|
||||||
|
if (path[0] == '.') {
|
||||||
|
path.erase(0, 1);
|
||||||
|
}
|
||||||
|
if (value.is_string()) {
|
||||||
|
CVarSetString(path.c_str(), value.get<std::string>().c_str());
|
||||||
|
} else if (value.is_number_integer()) {
|
||||||
|
CVarSetInteger(path.c_str(), value.get<int>());
|
||||||
|
} else if (value.is_number_float()) {
|
||||||
|
CVarSetFloat(path.c_str(), value.get<float>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
|
||||||
|
gui->GetGuiWindow("Console")->Hide();
|
||||||
|
gui->GetGuiWindow("Actor Viewer")->Hide();
|
||||||
|
gui->GetGuiWindow("Collision Viewer")->Hide();
|
||||||
|
gui->GetGuiWindow("Save Editor")->Hide();
|
||||||
|
gui->GetGuiWindow("Display List Viewer")->Hide();
|
||||||
|
gui->GetGuiWindow("Stats")->Hide();
|
||||||
|
std::dynamic_pointer_cast<LUS::ConsoleWindow>(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->ClearBindings();
|
||||||
|
|
||||||
|
gui->SaveConsoleVariablesOnNextTick();
|
||||||
|
|
||||||
|
uint32_t finalHash = boost::hash_32<std::string>{}(configJson.dump());
|
||||||
|
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Configuration Loaded. Hash: %d", finalHash);
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
SPDLOG_ERROR("Failed to load config file: {}", e.what());
|
||||||
|
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
|
||||||
|
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file");
|
||||||
|
return;
|
||||||
|
} catch (...) {
|
||||||
|
SPDLOG_ERROR("Failed to load config file");
|
||||||
|
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
|
||||||
|
gui->GetGameOverlay()->TextDrawNotification(30.0f, true, "Failed to load config file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
|||||||
@@ -86,11 +86,15 @@ uint32_t ResourceMgr_GetGameVersion(int index);
|
|||||||
uint32_t ResourceMgr_GetGamePlatform(int index);
|
uint32_t ResourceMgr_GetGamePlatform(int index);
|
||||||
uint32_t ResourceMgr_GetGameRegion(int index);
|
uint32_t ResourceMgr_GetGameRegion(int index);
|
||||||
void ResourceMgr_LoadDirectory(const char* resName);
|
void ResourceMgr_LoadDirectory(const char* resName);
|
||||||
|
void ResourceMgr_UnloadResource(const char* resName);
|
||||||
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
|
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
|
||||||
uint8_t ResourceMgr_FileExists(const char* resName);
|
uint8_t ResourceMgr_FileExists(const char* resName);
|
||||||
|
uint8_t ResourceMgr_FileAltExists(const char* resName);
|
||||||
|
void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName);
|
||||||
char* GetResourceDataByNameHandlingMQ(const char* path);
|
char* GetResourceDataByNameHandlingMQ(const char* path);
|
||||||
void ResourceMgr_LoadFile(const char* resName);
|
void ResourceMgr_LoadFile(const char* resName);
|
||||||
char* ResourceMgr_LoadFileFromDisk(const char* filePath);
|
char* ResourceMgr_LoadFileFromDisk(const char* filePath);
|
||||||
|
uint8_t ResourceMgr_TexIsRaw(const char* texPath);
|
||||||
uint8_t ResourceMgr_ResourceIsBackground(char* texPath);
|
uint8_t ResourceMgr_ResourceIsBackground(char* texPath);
|
||||||
char* ResourceMgr_LoadJPEG(char* data, size_t dataSize);
|
char* ResourceMgr_LoadJPEG(char* data, size_t dataSize);
|
||||||
uint16_t ResourceMgr_LoadTexWidthByName(char* texPath);
|
uint16_t ResourceMgr_LoadTexWidthByName(char* texPath);
|
||||||
@@ -116,6 +120,7 @@ void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size);
|
|||||||
void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size);
|
void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size);
|
||||||
|
|
||||||
uint64_t GetPerfCounter();
|
uint64_t GetPerfCounter();
|
||||||
|
bool ResourceMgr_IsAltAssetsEnabled();
|
||||||
struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime);
|
struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime);
|
||||||
void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime);
|
void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime);
|
||||||
void ResourceMgr_ClearSkeletons();
|
void ResourceMgr_ClearSkeletons();
|
||||||
@@ -169,6 +174,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();
|
||||||
|
|
||||||
|
|||||||
+57
-40
@@ -9,6 +9,7 @@
|
|||||||
#include <variables.h>
|
#include <variables.h>
|
||||||
#include "soh/Enhancements/boss-rush/BossRush.h"
|
#include "soh/Enhancements/boss-rush/BossRush.h"
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
#include "SohGui.hpp"
|
||||||
|
|
||||||
#define NOGDI // avoid various windows defines that conflict with things in z64.h
|
#define NOGDI // avoid various windows defines that conflict with things in z64.h
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
@@ -1025,51 +1026,67 @@ void SaveManager::SaveGlobal() {
|
|||||||
|
|
||||||
void SaveManager::LoadFile(int fileNum) {
|
void SaveManager::LoadFile(int fileNum) {
|
||||||
SPDLOG_INFO("Load File - fileNum: {}", fileNum);
|
SPDLOG_INFO("Load File - fileNum: {}", fileNum);
|
||||||
assert(std::filesystem::exists(GetFileName(fileNum)));
|
std::filesystem::path fileName = GetFileName(fileNum);
|
||||||
|
assert(std::filesystem::exists(fileName));
|
||||||
InitFile(false);
|
InitFile(false);
|
||||||
|
|
||||||
std::ifstream input(GetFileName(fileNum));
|
std::ifstream input(fileName);
|
||||||
|
|
||||||
saveBlock = nlohmann::json::object();
|
try {
|
||||||
input >> saveBlock;
|
saveBlock = nlohmann::json::object();
|
||||||
if (!saveBlock.contains("version")) {
|
input >> saveBlock;
|
||||||
SPDLOG_ERROR("Save at " + GetFileName(fileNum).string() + " contains no version");
|
if (!saveBlock.contains("version")) {
|
||||||
assert(false);
|
SPDLOG_ERROR("Save at " + fileName.string() + " contains no version");
|
||||||
}
|
|
||||||
switch (saveBlock["version"].get<int>()) {
|
|
||||||
case 1:
|
|
||||||
for (auto& block : saveBlock["sections"].items()) {
|
|
||||||
int sectionVersion = block.value()["version"];
|
|
||||||
std::string sectionName = block.key();
|
|
||||||
if (!sectionLoadHandlers.contains(sectionName)) {
|
|
||||||
// Unloadable sections aren't necessarily errors, they are probably mods that were unloaded
|
|
||||||
// TODO report in a more noticeable manner
|
|
||||||
SPDLOG_WARN("Save " + GetFileName(fileNum).string() + " contains unloadable section " + sectionName);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SectionLoadHandler& handler = sectionLoadHandlers[sectionName];
|
|
||||||
if (!handler.contains(sectionVersion)) {
|
|
||||||
// A section that has a loader without a handler for the specific version means that the user has a mod
|
|
||||||
// at an earlier version than the save has. In this case, the user probably wants to load the save.
|
|
||||||
// Report the error so that the user can rectify the error.
|
|
||||||
// TODO report in a more noticeable manner
|
|
||||||
SPDLOG_ERROR("Save " + GetFileName(fileNum).string() + " contains section " + sectionName +
|
|
||||||
" with an unloadable version " + std::to_string(sectionVersion));
|
|
||||||
assert(false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
currentJsonContext = &block.value()["data"];
|
|
||||||
handler[sectionVersion]();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SPDLOG_ERROR("Unrecognized save version " + std::to_string(saveBlock["version"].get<int>()) + " in " +
|
|
||||||
GetFileName(fileNum).string());
|
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
}
|
||||||
|
switch (saveBlock["version"].get<int>()) {
|
||||||
|
case 1:
|
||||||
|
for (auto& block : saveBlock["sections"].items()) {
|
||||||
|
int sectionVersion = block.value()["version"];
|
||||||
|
std::string sectionName = block.key();
|
||||||
|
if (!sectionLoadHandlers.contains(sectionName)) {
|
||||||
|
// Unloadable sections aren't necessarily errors, they are probably mods that were unloaded
|
||||||
|
// TODO report in a more noticeable manner
|
||||||
|
SPDLOG_WARN("Save " + GetFileName(fileNum).string() + " contains unloadable section " +
|
||||||
|
sectionName);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SectionLoadHandler& handler = sectionLoadHandlers[sectionName];
|
||||||
|
if (!handler.contains(sectionVersion)) {
|
||||||
|
// A section that has a loader without a handler for the specific version means that the user
|
||||||
|
// has a mod at an earlier version than the save has. In this case, the user probably wants to
|
||||||
|
// load the save. Report the error so that the user can rectify the error.
|
||||||
|
// TODO report in a more noticeable manner
|
||||||
|
SPDLOG_ERROR("Save " + GetFileName(fileNum).string() + " contains section " + sectionName +
|
||||||
|
" with an unloadable version " + std::to_string(sectionVersion));
|
||||||
|
assert(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
currentJsonContext = &block.value()["data"];
|
||||||
|
handler[sectionVersion]();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SPDLOG_ERROR("Unrecognized save version " + std::to_string(saveBlock["version"].get<int>()) + " in " +
|
||||||
|
GetFileName(fileNum).string());
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
InitMeta(fileNum);
|
||||||
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
input.close();
|
||||||
|
std::filesystem::path newFile(LUS::Context::GetPathRelativeToAppDirectory("Save") + ("/file" + std::to_string(fileNum + 1) + "-" + std::to_string(GetUnixTimestamp()) + ".bak"));
|
||||||
|
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||||
|
copy_file(fileName.c_str(), newFile.c_str());
|
||||||
|
#else
|
||||||
|
std::filesystem::copy_file(fileName, newFile);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::filesystem::remove(fileName);
|
||||||
|
SohGui::RegisterPopup("Error loading save file", "A problem occurred loading the save in slot " + std::to_string(fileNum + 1) + ".\nSave file corruption is suspected.\n" +
|
||||||
|
"The file has been renamed to prevent further issues.");
|
||||||
}
|
}
|
||||||
InitMeta(fileNum);
|
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnLoadFile>(fileNum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::ThreadPoolWait() {
|
void SaveManager::ThreadPoolWait() {
|
||||||
|
|||||||
+9
-1
@@ -38,7 +38,6 @@
|
|||||||
#include "Enhancements/game-interactor/GameInteractor.h"
|
#include "Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "Enhancements/cosmetics/authenticGfxPatches.h"
|
#include "Enhancements/cosmetics/authenticGfxPatches.h"
|
||||||
|
|
||||||
bool ShouldClearTextureCacheAtEndOfFrame = false;
|
|
||||||
bool isBetaQuestEnabled = false;
|
bool isBetaQuestEnabled = false;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -125,6 +124,7 @@ namespace SohGui {
|
|||||||
std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||||
std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||||
std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
|
std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
|
||||||
|
std::shared_ptr<SohModalWindow> mModalWindow;
|
||||||
|
|
||||||
void SetupGuiElements() {
|
void SetupGuiElements() {
|
||||||
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
|
auto gui = LUS::Context::GetInstance()->GetWindow()->GetGui();
|
||||||
@@ -183,9 +183,13 @@ namespace SohGui {
|
|||||||
gui->AddGuiWindow(mItemTrackerSettingsWindow);
|
gui->AddGuiWindow(mItemTrackerSettingsWindow);
|
||||||
mRandomizerSettingsWindow = std::make_shared<RandomizerSettingsWindow>("gRandomizerSettingsEnabled", "Randomizer Settings");
|
mRandomizerSettingsWindow = std::make_shared<RandomizerSettingsWindow>("gRandomizerSettingsEnabled", "Randomizer Settings");
|
||||||
gui->AddGuiWindow(mRandomizerSettingsWindow);
|
gui->AddGuiWindow(mRandomizerSettingsWindow);
|
||||||
|
mModalWindow = std::make_shared<SohModalWindow>("gOpenWindows.modalWindowEnabled", "Modal Window");
|
||||||
|
gui->AddGuiWindow(mModalWindow);
|
||||||
|
mModalWindow->Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Destroy() {
|
void Destroy() {
|
||||||
|
mModalWindow = nullptr;
|
||||||
mRandomizerSettingsWindow = nullptr;
|
mRandomizerSettingsWindow = nullptr;
|
||||||
mItemTrackerWindow = nullptr;
|
mItemTrackerWindow = nullptr;
|
||||||
mItemTrackerSettingsWindow = nullptr;
|
mItemTrackerSettingsWindow = nullptr;
|
||||||
@@ -205,4 +209,8 @@ namespace SohGui {
|
|||||||
mConsoleWindow = nullptr;
|
mConsoleWindow = nullptr;
|
||||||
mSohMenuBar = nullptr;
|
mSohMenuBar = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function<void()> button1callback, std::function<void()> button2callback) {
|
||||||
|
mModalWindow->RegisterPopup(title, message, button1, button2, button1callback, button2callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
|
#include "Enhancements/randomizer/randomizer_entrance_tracker.h"
|
||||||
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
||||||
#include "Enhancements/randomizer/randomizer_settings_window.h"
|
#include "Enhancements/randomizer/randomizer_settings_window.h"
|
||||||
|
#include "SohModals.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -37,6 +38,7 @@ namespace SohGui {
|
|||||||
void SetupGuiElements();
|
void SetupGuiElements();
|
||||||
void Draw();
|
void Draw();
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function<void()> button1callback = nullptr, std::function<void()> button2callback = nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SohGui_hpp */
|
#endif /* SohGui_hpp */
|
||||||
|
|||||||
+83
-35
@@ -28,7 +28,6 @@
|
|||||||
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
#include "Enhancements/randomizer/randomizer_item_tracker.h"
|
||||||
#include "Enhancements/randomizer/randomizer_settings_window.h"
|
#include "Enhancements/randomizer/randomizer_settings_window.h"
|
||||||
|
|
||||||
extern bool ShouldClearTextureCacheAtEndOfFrame;
|
|
||||||
extern bool isBetaQuestEnabled;
|
extern bool isBetaQuestEnabled;
|
||||||
|
|
||||||
extern "C" PlayState* gPlayState;
|
extern "C" PlayState* gPlayState;
|
||||||
@@ -51,6 +50,13 @@ std::string GetWindowButtonText(const char* text, bool menuOpen) {
|
|||||||
return buttonText;
|
return buttonText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::unordered_map<LUS::WindowBackend, const char*> windowBackendNames = {
|
||||||
|
{ LUS::WindowBackend::DX11, "DirectX" },
|
||||||
|
{ LUS::WindowBackend::SDL_OPENGL, "OpenGL"},
|
||||||
|
{ LUS::WindowBackend::SDL_METAL, "Metal" },
|
||||||
|
{ LUS::WindowBackend::GX2, "GX2"}
|
||||||
|
};
|
||||||
|
|
||||||
static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large" };
|
static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large" };
|
||||||
|
|
||||||
static const char* filters[3] = {
|
static const char* filters[3] = {
|
||||||
@@ -102,6 +108,24 @@ extern "C" SaveContext gSaveContext;
|
|||||||
|
|
||||||
namespace SohGui {
|
namespace SohGui {
|
||||||
|
|
||||||
|
std::unordered_map<LUS::WindowBackend, const char*> availableWindowBackendsMap;
|
||||||
|
LUS::WindowBackend configWindowBackend;
|
||||||
|
|
||||||
|
void UpdateWindowBackendObjects() {
|
||||||
|
LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
||||||
|
int32_t configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
||||||
|
if (configWindowBackendId != -1 && configWindowBackendId < static_cast<int>(LUS::WindowBackend::BACKEND_COUNT)) {
|
||||||
|
configWindowBackend = static_cast<LUS::WindowBackend>(configWindowBackendId);
|
||||||
|
} else {
|
||||||
|
configWindowBackend = runningWindowBackend;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto availableWindowBackends = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends();
|
||||||
|
for (auto& backend : *availableWindowBackends) {
|
||||||
|
availableWindowBackendsMap[backend] = windowBackendNames[backend];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DrawMenuBarIcon() {
|
void DrawMenuBarIcon() {
|
||||||
static bool gameIconLoaded = false;
|
static bool gameIconLoaded = false;
|
||||||
if (!gameIconLoaded) {
|
if (!gameIconLoaded) {
|
||||||
@@ -392,39 +416,23 @@ void DrawSettingsMenu() {
|
|||||||
|
|
||||||
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
|
UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f);
|
||||||
|
|
||||||
static std::unordered_map<LUS::WindowBackend, const char*> windowBackendNames = {
|
|
||||||
{ LUS::WindowBackend::DX11, "DirectX" },
|
|
||||||
{ LUS::WindowBackend::SDL_OPENGL, "OpenGL"},
|
|
||||||
{ LUS::WindowBackend::SDL_METAL, "Metal" },
|
|
||||||
{ LUS::WindowBackend::GX2, "GX2"}
|
|
||||||
};
|
|
||||||
|
|
||||||
ImGui::Text("Renderer API (Needs reload)");
|
ImGui::Text("Renderer API (Needs reload)");
|
||||||
LUS::WindowBackend runningWindowBackend = LUS::Context::GetInstance()->GetWindow()->GetWindowBackend();
|
|
||||||
LUS::WindowBackend configWindowBackend;
|
|
||||||
int configWindowBackendId = LUS::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1);
|
|
||||||
if (configWindowBackendId != -1 && configWindowBackendId < static_cast<int>(LUS::WindowBackend::BACKEND_COUNT)) {
|
|
||||||
configWindowBackend = static_cast<LUS::WindowBackend>(configWindowBackendId);
|
|
||||||
} else {
|
|
||||||
configWindowBackend = runningWindowBackend;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) {
|
if (availableWindowBackendsMap.size() <= 1) {
|
||||||
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
|
UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f);
|
||||||
}
|
}
|
||||||
if (ImGui::BeginCombo("##RApi", windowBackendNames[configWindowBackend])) {
|
if (ImGui::BeginCombo("##RApi", availableWindowBackendsMap[configWindowBackend])) {
|
||||||
for (size_t i = 0; i < LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size(); i++) {
|
for (auto backend : availableWindowBackendsMap) {
|
||||||
auto backend = LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i];
|
if (ImGui::Selectable(backend.second, backend.first == configWindowBackend)) {
|
||||||
if (ImGui::Selectable(windowBackendNames[backend], backend == configWindowBackend)) {
|
LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast<int>(backend.first));
|
||||||
LUS::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast<int>(backend));
|
LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", backend.second);
|
||||||
LUS::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name",
|
|
||||||
windowBackendNames[backend]);
|
|
||||||
LUS::Context::GetInstance()->GetConfig()->Save();
|
LUS::Context::GetInstance()->GetConfig()->Save();
|
||||||
|
UpdateWindowBackendObjects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
if (LUS::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) {
|
if (availableWindowBackendsMap.size() <= 1) {
|
||||||
UIWidgets::ReEnableComponent("");
|
UIWidgets::ReEnableComponent("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,6 +500,8 @@ extern std::shared_ptr<GameplayStatsWindow> mGameplayStatsWindow;
|
|||||||
void DrawEnhancementsMenu() {
|
void DrawEnhancementsMenu() {
|
||||||
if (ImGui::BeginMenu("Enhancements"))
|
if (ImGui::BeginMenu("Enhancements"))
|
||||||
{
|
{
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
|
|
||||||
DrawPresetSelector(PRESET_TYPE_ENHANCEMENTS);
|
DrawPresetSelector(PRESET_TYPE_ENHANCEMENTS);
|
||||||
|
|
||||||
UIWidgets::PaddedSeparator();
|
UIWidgets::PaddedSeparator();
|
||||||
@@ -556,7 +566,7 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song.");
|
UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false);
|
||||||
UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n"
|
UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n"
|
||||||
"This doesn't work if the save was made in a grotto.");
|
"This doesn't work if the save was made in grottos/fairy fountains or dungeons.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false);
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false);
|
||||||
UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen");
|
UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen");
|
||||||
@@ -605,7 +615,7 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false);
|
||||||
UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers.");
|
UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false);
|
||||||
UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots");
|
UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots. (Note this will disable the behaviour of the 'Equip Dupe' glitch)");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Bow as Child/Slingshot as Adult", "gBowSlingShotAmmoFix", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Bow as Child/Slingshot as Adult", "gBowSlingShotAmmoFix", true, false);
|
||||||
UIWidgets::Tooltip("Allows child to use bow with arrows.\nAllows adult to use slingshot with seeds.\n\nRequires glitches or 'Timeless Equipment' cheat to equip.");
|
UIWidgets::Tooltip("Allows child to use bow with arrows.\nAllows adult to use slingshot with seeds.\n\nRequires glitches or 'Timeless Equipment' cheat to equip.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Better Farore's Wind", "gBetterFW", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Better Farore's Wind", "gBetterFW", true, false);
|
||||||
@@ -905,9 +915,7 @@ void DrawEnhancementsMenu() {
|
|||||||
if (ImGui::BeginMenu("Graphics"))
|
if (ImGui::BeginMenu("Graphics"))
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenu("Mods")) {
|
if (ImGui::BeginMenu("Mods")) {
|
||||||
if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false)) {
|
UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", "gAltAssets", false, false);
|
||||||
ShouldClearTextureCacheAtEndOfFrame = true;
|
|
||||||
}
|
|
||||||
UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not.");
|
UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", "gDisableBombBillboarding", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", "gDisableBombBillboarding", true, false);
|
||||||
UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects.");
|
UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects.");
|
||||||
@@ -920,16 +928,39 @@ void DrawEnhancementsMenu() {
|
|||||||
}
|
}
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Disable LOD", "gDisableLOD", true, false);
|
||||||
UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance");
|
UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance");
|
||||||
if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) {
|
if (UIWidgets::EnhancementSliderInt("Increase Actor Draw Distance: %dx", "##IncreaseActorDrawDistance",
|
||||||
if (CVarGetInteger("gDisableDrawDistance", 0) == 0) {
|
"gDisableDrawDistance", 1, 5, "", 1, true, false)) {
|
||||||
|
if (CVarGetInteger("gDisableDrawDistance", 1) <= 1) {
|
||||||
CVarSetInteger("gDisableKokiriDrawDistance", 0);
|
CVarSetInteger("gDisableKokiriDrawDistance", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range");
|
UIWidgets::Tooltip("Increases the range in which actors/objects are drawn");
|
||||||
if (CVarGetInteger("gDisableDrawDistance", 0) == 1) {
|
if (CVarGetInteger("gDisableDrawDistance", 1) > 1) {
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Widescreen Actor Culling", "gEnhancements.WidescreenActorCulling",
|
||||||
|
true, false);
|
||||||
|
UIWidgets::Tooltip("Adjusts the horizontal culling plane to account for widescreen resolutions");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox(
|
||||||
|
"Cull Glitch Useful Actors", "gEnhancements.ExtendedCullingExcludeGlitchActors", true, false,
|
||||||
|
!CVarGetInteger("gEnhancements.WidescreenActorCulling", 0) &&
|
||||||
|
CVarGetInteger("gDisableDrawDistance", 1) <= 1,
|
||||||
|
"Requires Actor Draw Distance to be increased or Widescreen Actor Culling enabled");
|
||||||
|
UIWidgets::Tooltip(
|
||||||
|
"Exclude actors that are useful for glitches from the extended culling ranges.\n"
|
||||||
|
"Some actors may still draw in the extended ranges, but will not \"update\" so that certain "
|
||||||
|
"glitches that leverage the original culling requirements will still work.\n"
|
||||||
|
"\n"
|
||||||
|
"The following actors are excluded:\n"
|
||||||
|
"- White clothed Gerudos\n"
|
||||||
|
"- King Zora\n"
|
||||||
|
"- Gossip Stones\n"
|
||||||
|
"- Boulders\n"
|
||||||
|
"- Blue Warps\n"
|
||||||
|
"- Darunia\n"
|
||||||
|
"- Gold Skulltulas");
|
||||||
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);
|
||||||
@@ -1063,6 +1094,9 @@ void DrawEnhancementsMenu() {
|
|||||||
UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges.");
|
UIWidgets::Tooltip("Prevents immediately falling off climbable surfaces if climbing on the edges.");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", "gFixEyesOpenWhileSleeping", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Fix Link's eyes open while sleeping", "gFixEyesOpenWhileSleeping", true, false);
|
||||||
UIWidgets::Tooltip("Fixes Link's eyes being open in the opening cutscene when he is supposed to be sleeping.");
|
UIWidgets::Tooltip("Fixes Link's eyes being open in the opening cutscene when he is supposed to be sleeping.");
|
||||||
|
UIWidgets::PaddedEnhancementCheckbox("Fix Darunia dancing too fast", "gEnhancements.FixDaruniaDanceSpeed",
|
||||||
|
true, false, false, "", UIWidgets::CheckboxGraphics::Cross, true);
|
||||||
|
UIWidgets::Tooltip("Fixes Darunia's dancing speed so he dances to the beat of Saria's Song, like in vanilla.");
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
@@ -1198,6 +1232,8 @@ void DrawEnhancementsMenu() {
|
|||||||
|
|
||||||
UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
|
UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
|
||||||
|
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
|
||||||
@@ -1239,6 +1275,8 @@ void DrawEnhancementsMenu() {
|
|||||||
void DrawCheatsMenu() {
|
void DrawCheatsMenu() {
|
||||||
if (ImGui::BeginMenu("Cheats"))
|
if (ImGui::BeginMenu("Cheats"))
|
||||||
{
|
{
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Infinite...")) {
|
if (ImGui::BeginMenu("Infinite...")) {
|
||||||
UIWidgets::EnhancementCheckbox("Money", "gInfiniteMoney");
|
UIWidgets::EnhancementCheckbox("Money", "gInfiniteMoney");
|
||||||
UIWidgets::PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false);
|
UIWidgets::PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false);
|
||||||
@@ -1393,6 +1431,8 @@ void DrawCheatsMenu() {
|
|||||||
}
|
}
|
||||||
UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps.");
|
UIWidgets::Tooltip("Clears the cutscene pointer to a value safe for wrong warps.");
|
||||||
|
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1406,6 +1446,8 @@ extern std::shared_ptr<DLViewerWindow> mDLViewerWindow;
|
|||||||
|
|
||||||
void DrawDeveloperToolsMenu() {
|
void DrawDeveloperToolsMenu() {
|
||||||
if (ImGui::BeginMenu("Developer Tools")) {
|
if (ImGui::BeginMenu("Developer Tools")) {
|
||||||
|
ImGui::BeginDisabled(CVarGetInteger("gDisableChangingSettings", 0));
|
||||||
|
|
||||||
UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled");
|
UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled");
|
||||||
UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen");
|
UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen");
|
||||||
if (CVarGetInteger("gDebugEnabled", 0)) {
|
if (CVarGetInteger("gDebugEnabled", 0)) {
|
||||||
@@ -1478,6 +1520,8 @@ void DrawDeveloperToolsMenu() {
|
|||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
|
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1592,6 +1636,10 @@ void DrawRandomizerMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SohMenuBar::InitElement() {
|
||||||
|
UpdateWindowBackendObjects();
|
||||||
|
}
|
||||||
|
|
||||||
void SohMenuBar::DrawElement() {
|
void SohMenuBar::DrawElement() {
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
DrawMenuBarIcon();
|
DrawMenuBarIcon();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class SohMenuBar : public LUS::GuiMenuBar {
|
|||||||
using LUS::GuiMenuBar::GuiMenuBar;
|
using LUS::GuiMenuBar::GuiMenuBar;
|
||||||
protected:
|
protected:
|
||||||
void DrawElement() override;
|
void DrawElement() override;
|
||||||
void InitElement() override {};
|
void InitElement() override;
|
||||||
void UpdateElement() override {};
|
void UpdateElement() override {};
|
||||||
};
|
};
|
||||||
} // namespace SohGui
|
} // namespace SohGui
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#include "SohModals.h"
|
||||||
|
#include "ImGui/imgui.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include <libultraship/libultraship.h>
|
||||||
|
#include "UIWidgets.hpp"
|
||||||
|
#include "OTRGlobals.h"
|
||||||
|
#include "z64.h"
|
||||||
|
|
||||||
|
extern "C" PlayState* gPlayState;
|
||||||
|
struct SohModal {
|
||||||
|
std::string title_;
|
||||||
|
std::string message_;
|
||||||
|
std::string button1_;
|
||||||
|
std::string button2_;
|
||||||
|
std::function<void()> button1callback_;
|
||||||
|
std::function<void()> button2callback_;
|
||||||
|
};
|
||||||
|
std::vector<SohModal> modals;
|
||||||
|
|
||||||
|
void SohModalWindow::DrawElement() {
|
||||||
|
if (modals.size() > 0) {
|
||||||
|
SohModal curModal = modals.at(0);
|
||||||
|
if (!ImGui::IsPopupOpen(curModal.title_.c_str())) {
|
||||||
|
ImGui::OpenPopup(curModal.title_.c_str());
|
||||||
|
}
|
||||||
|
if (ImGui::BeginPopupModal(curModal.title_.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings)) {
|
||||||
|
ImGui::Text(curModal.message_.c_str());
|
||||||
|
if (ImGui::Button(curModal.button1_.c_str())) {
|
||||||
|
if (curModal.button1callback_ != nullptr) {
|
||||||
|
curModal.button1callback_();
|
||||||
|
}
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
modals.erase(modals.begin());
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (curModal.button2_ != "") {
|
||||||
|
if (ImGui::Button(curModal.button2_.c_str())) {
|
||||||
|
if (curModal.button2callback_ != nullptr) {
|
||||||
|
curModal.button2callback_();
|
||||||
|
}
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
modals.erase(modals.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SohModalWindow::RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function<void()> button1callback, std::function<void()> button2callback) {
|
||||||
|
modals.push_back({ title, message, button1, button2, button1callback, button2callback });
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libultraship/libultraship.h>
|
||||||
|
#include "window/gui/GuiMenuBar.h"
|
||||||
|
#include "window/gui/GuiElement.h"
|
||||||
|
|
||||||
|
class SohModalWindow : public LUS::GuiWindow {
|
||||||
|
public:
|
||||||
|
using LUS::GuiWindow::GuiWindow;
|
||||||
|
|
||||||
|
void InitElement() override {};
|
||||||
|
void DrawElement() override;
|
||||||
|
void UpdateElement() override {};
|
||||||
|
void RegisterPopup(std::string title, std::string message, std::string button1 = "OK", std::string button2 = "", std::function<void()> button1callback = nullptr, std::function<void()> button2callback = nullptr);
|
||||||
|
};
|
||||||
@@ -21,7 +21,7 @@ namespace UIWidgets {
|
|||||||
// Automatically adds newlines to break up text longer than a specified number of characters
|
// Automatically adds newlines to break up text longer than a specified number of characters
|
||||||
// Manually included newlines will still be respected and reset the line length
|
// Manually included newlines will still be respected and reset the line length
|
||||||
// If line is midword when it hits the limit, text should break at the last encountered space
|
// If line is midword when it hits the limit, text should break at the last encountered space
|
||||||
char* WrappedText(const char* text, unsigned int charactersPerLine) {
|
std::string WrappedText(const char* text, unsigned int charactersPerLine) {
|
||||||
std::string newText(text);
|
std::string newText(text);
|
||||||
const size_t tipLength = newText.length();
|
const size_t tipLength = newText.length();
|
||||||
int lastSpace = -1;
|
int lastSpace = -1;
|
||||||
@@ -43,17 +43,17 @@ namespace UIWidgets {
|
|||||||
currentLineLength++;
|
currentLineLength++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return strdup(newText.c_str());
|
return newText;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* WrappedText(const std::string& text, unsigned int charactersPerLine) {
|
std::string WrappedText(const std::string& text, unsigned int charactersPerLine) {
|
||||||
return WrappedText(text.c_str(), charactersPerLine);
|
return WrappedText(text.c_str(), charactersPerLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLastItemHoverText(const std::string& text) {
|
void SetLastItemHoverText(const std::string& text) {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text("%s", WrappedText(text, 60));
|
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ namespace UIWidgets {
|
|||||||
void SetLastItemHoverText(const char* text) {
|
void SetLastItemHoverText(const char* text) {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text("%s", WrappedText(text, 60));
|
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ namespace UIWidgets {
|
|||||||
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
|
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text("%s", WrappedText(text, 60));
|
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ namespace UIWidgets {
|
|||||||
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
|
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?");
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
ImGui::Text("%s", WrappedText(text, 60));
|
ImGui::Text("%s", WrappedText(text, 60).c_str());
|
||||||
ImGui::EndTooltip();
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +92,7 @@ namespace UIWidgets {
|
|||||||
|
|
||||||
void Tooltip(const char* text) {
|
void Tooltip(const char* text) {
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("%s", WrappedText(text));
|
ImGui::SetTooltip("%s", WrappedText(text).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ namespace UIWidgets {
|
|||||||
constexpr float sliderButtonWidth = 30.0f;
|
constexpr float sliderButtonWidth = 30.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* WrappedText(const char* text, unsigned int charactersPerLine = 60);
|
std::string WrappedText(const char* text, unsigned int charactersPerLine = 60);
|
||||||
char* WrappedText(const std::string& text, unsigned int charactersPerLine);
|
std::string WrappedText(const std::string& text, unsigned int charactersPerLine);
|
||||||
|
|
||||||
void SetLastItemHoverText(const std::string& text);
|
void SetLastItemHoverText(const std::string& text);
|
||||||
void SetLastItemHoverText(const char* text);
|
void SetLastItemHoverText(const char* text);
|
||||||
|
|||||||
+7
-1
@@ -99,8 +99,14 @@ void aClearBufferImpl(uint16_t addr, int nbytes) {
|
|||||||
memset(BUF_U8(addr), 0, nbytes);
|
memset(BUF_U8(addr), 0, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) {
|
void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes) {
|
||||||
|
#if __SANITIZE_ADDRESS__
|
||||||
|
for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) {
|
||||||
|
BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i];
|
||||||
|
}
|
||||||
|
#else
|
||||||
memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes));
|
memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) {
|
void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) {
|
||||||
|
|||||||
@@ -132,15 +132,15 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
|
|||||||
skeletonLimb->limbData.lodLimb.sibling = skeletonLimb->siblingIndex;
|
skeletonLimb->limbData.lodLimb.sibling = skeletonLimb->siblingIndex;
|
||||||
|
|
||||||
if (skeletonLimb->dListPtr != "") {
|
if (skeletonLimb->dListPtr != "") {
|
||||||
auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dListPtr.c_str());
|
skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
|
||||||
skeletonLimb->limbData.lodLimb.dLists[0] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
|
skeletonLimb->limbData.lodLimb.dLists[0] = (Gfx*)skeletonLimb->dListPtr.c_str();
|
||||||
} else {
|
} else {
|
||||||
skeletonLimb->limbData.lodLimb.dLists[0] = nullptr;
|
skeletonLimb->limbData.lodLimb.dLists[0] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skeletonLimb->dList2Ptr != "") {
|
if (skeletonLimb->dList2Ptr != "") {
|
||||||
auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dList2Ptr.c_str());
|
skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
|
||||||
skeletonLimb->limbData.lodLimb.dLists[1] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
|
skeletonLimb->limbData.lodLimb.dLists[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
|
||||||
} else {
|
} else {
|
||||||
skeletonLimb->limbData.lodLimb.dLists[1] = nullptr;
|
skeletonLimb->limbData.lodLimb.dLists[1] = nullptr;
|
||||||
}
|
}
|
||||||
@@ -153,8 +153,8 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
|
|||||||
skeletonLimb->limbData.standardLimb.dList = nullptr;
|
skeletonLimb->limbData.standardLimb.dList = nullptr;
|
||||||
|
|
||||||
if (!skeletonLimb->dListPtr.empty()) {
|
if (!skeletonLimb->dListPtr.empty()) {
|
||||||
const auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dListPtr.c_str());
|
skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
|
||||||
skeletonLimb->limbData.standardLimb.dList = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
|
skeletonLimb->limbData.standardLimb.dList = (Gfx*)skeletonLimb->dListPtr.c_str();
|
||||||
}
|
}
|
||||||
} else if (skeletonLimb->limbType == LUS::LimbType::Curve) {
|
} else if (skeletonLimb->limbType == LUS::LimbType::Curve) {
|
||||||
skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex;
|
skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex;
|
||||||
@@ -163,13 +163,13 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
|
|||||||
skeletonLimb->limbData.skelCurveLimb.dList[1] = nullptr;
|
skeletonLimb->limbData.skelCurveLimb.dList[1] = nullptr;
|
||||||
|
|
||||||
if (!skeletonLimb->dListPtr.empty()) {
|
if (!skeletonLimb->dListPtr.empty()) {
|
||||||
const auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dListPtr.c_str());
|
skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
|
||||||
skeletonLimb->limbData.skelCurveLimb.dList[0] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
|
skeletonLimb->limbData.skelCurveLimb.dList[0] = (Gfx*)skeletonLimb->dListPtr.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!skeletonLimb->dList2Ptr.empty()) {
|
if (!skeletonLimb->dList2Ptr.empty()) {
|
||||||
const auto dList = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->dList2Ptr.c_str());
|
skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
|
||||||
skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)(dList ? dList->GetRawPointer() : nullptr);
|
skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
|
||||||
}
|
}
|
||||||
} else if (skeletonLimb->limbType == LUS::LimbType::Skin) {
|
} else if (skeletonLimb->limbType == LUS::LimbType::Skin) {
|
||||||
skeletonLimb->limbData.skinLimb.jointPos.x = skeletonLimb->transX;
|
skeletonLimb->limbData.skinLimb.jointPos.x = skeletonLimb->transX;
|
||||||
@@ -189,14 +189,23 @@ void LUS::SkeletonLimbFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> r
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) {
|
if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_DList) {
|
||||||
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->skinDList.c_str());
|
if (skeletonLimb->skinDList != "") {
|
||||||
skeletonLimb->limbData.skinLimb.segment = res ? res->GetRawPointer() : nullptr;
|
skeletonLimb->skinDList = "__OTR__" + skeletonLimb->skinDList;
|
||||||
|
skeletonLimb->limbData.skinLimb.segment = (Gfx*)skeletonLimb->skinDList.c_str();
|
||||||
|
} else {
|
||||||
|
skeletonLimb->limbData.skinLimb.segment = nullptr;
|
||||||
|
}
|
||||||
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) {
|
} else if (skeletonLimb->skinSegmentType == LUS::ZLimbSkinType::SkinType_4) {
|
||||||
skeletonLimb->skinAnimLimbData.totalVtxCount = skeletonLimb->skinVtxCnt;
|
skeletonLimb->skinAnimLimbData.totalVtxCount = skeletonLimb->skinVtxCnt;
|
||||||
skeletonLimb->skinAnimLimbData.limbModifCount = skeletonLimb->skinLimbModifCount;
|
skeletonLimb->skinAnimLimbData.limbModifCount = skeletonLimb->skinLimbModifCount;
|
||||||
skeletonLimb->skinAnimLimbData.limbModifications = skeletonLimb->skinLimbModifArray.data();
|
skeletonLimb->skinAnimLimbData.limbModifications = skeletonLimb->skinLimbModifArray.data();
|
||||||
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(skeletonLimb->skinDList2.c_str());
|
|
||||||
skeletonLimb->skinAnimLimbData.dlist = (Gfx*)(res ? res->GetRawPointer() : nullptr);
|
if (skeletonLimb->skinDList2 != "") {
|
||||||
|
skeletonLimb->skinDList2 = "__OTR__" + skeletonLimb->skinDList2;
|
||||||
|
skeletonLimb->skinAnimLimbData.dlist = (Gfx*)skeletonLimb->skinDList2.c_str();
|
||||||
|
} else {
|
||||||
|
skeletonLimb->skinAnimLimbData.dlist = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < skeletonLimb->skinLimbModifArray.size(); i++) {
|
for (size_t i = 0; i < skeletonLimb->skinLimbModifArray.size(); i++) {
|
||||||
skeletonLimb->skinAnimLimbData.limbModifications[i].vtxCount = skeletonLimb->skinLimbModifVertexArrays[i].size();
|
skeletonLimb->skinAnimLimbData.limbModifications[i].vtxCount = skeletonLimb->skinLimbModifVertexArrays[i].size();
|
||||||
@@ -254,8 +263,8 @@ void SkeletonLimbFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shar
|
|||||||
limbData.lodLimb.jointPos.z = skelLimb->transZ;
|
limbData.lodLimb.jointPos.z = skelLimb->transZ;
|
||||||
|
|
||||||
if (skelLimb->dListPtr != "") {
|
if (skelLimb->dListPtr != "") {
|
||||||
auto res = LUS::Context::GetInstance()->GetResourceManager()->LoadResourceProcess((const char*)skelLimb->dListPtr.c_str());
|
skelLimb->dListPtr = "__OTR__" + skelLimb->dListPtr;
|
||||||
limbData.lodLimb.dLists[0] = (Gfx*)(res ? res->GetRawPointer() : nullptr);
|
limbData.lodLimb.dLists[0] = (Gfx*)skelLimb->dListPtr.c_str();
|
||||||
} else {
|
} else {
|
||||||
limbData.lodLimb.dLists[0] = nullptr;
|
limbData.lodLimb.dLists[0] = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,12 +65,11 @@ void SkeletonPatcher::ClearSkeletons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonPatcher::UpdateSkeletons() {
|
void SkeletonPatcher::UpdateSkeletons() {
|
||||||
bool isHD = CVarGetInteger("gAltAssets", 0);
|
auto resourceMgr = LUS::Context::GetInstance()->GetResourceManager();
|
||||||
|
bool isHD = resourceMgr->IsAltAssetsEnabled();
|
||||||
for (auto skel : skeletons) {
|
for (auto skel : skeletons) {
|
||||||
Skeleton* newSkel =
|
Skeleton* newSkel =
|
||||||
(Skeleton*)LUS::Context::GetInstance()->GetResourceManager()
|
(Skeleton*)resourceMgr->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true).get();
|
||||||
->LoadResource((isHD ? LUS::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
if (newSkel != nullptr) {
|
if (newSkel != nullptr) {
|
||||||
skel.skelAnime->skeleton = newSkel->skeletonData.skeletonHeader.segment;
|
skel.skelAnime->skeleton = newSkel->skeletonData.skeletonHeader.segment;
|
||||||
|
|||||||
+1
-1
@@ -260,7 +260,7 @@ void Audio_osWritebackDCache(void* mem, s32 size)
|
|||||||
|
|
||||||
s32 osAiSetFrequency(u32 freq)
|
s32 osAiSetFrequency(u32 freq)
|
||||||
{
|
{
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 osEPiStartDma(OSPiHandle* handle, OSIoMesg* mb, s32 direction)
|
s32 osEPiStartDma(OSPiHandle* handle, OSIoMesg* mb, s32 direction)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
std::vector<std::string> sceneNames = {
|
std::vector<std::string> sceneNames = {
|
||||||
"Inside the Deku Tree",
|
"Inside the Deku Tree",
|
||||||
@@ -318,3 +319,20 @@ void SohUtils::CopyStringToCharArray(char* destination, std::string source, size
|
|||||||
strncpy(destination, source.c_str(), size - 1);
|
strncpy(destination, source.c_str(), size - 1);
|
||||||
destination[size - 1] = '\0';
|
destination[size - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SohUtils::Sanitize(std::string stringValue) {
|
||||||
|
// Add backslashes.
|
||||||
|
for (auto i = stringValue.begin();;) {
|
||||||
|
auto const pos = std::find_if(i, stringValue.end(), [](char const c) { return '\\' == c || '\'' == c || '"' == c; });
|
||||||
|
if (pos == stringValue.end()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = std::next(stringValue.insert(pos, '\\'), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes others.
|
||||||
|
stringValue.erase(std::remove_if(stringValue.begin(), stringValue.end(), [](char const c) {
|
||||||
|
return '\n' == c || '\r' == c || '\0' == c || '\x1A' == c; }), stringValue.end());
|
||||||
|
|
||||||
|
return stringValue;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,4 +12,6 @@ namespace SohUtils {
|
|||||||
// Copies a string and ensures the destination is null terminated if the source string is larger than size
|
// Copies a string and ensures the destination is null terminated if the source string is larger than size
|
||||||
// Only up to size-1 characters are copied from the source string
|
// Only up to size-1 characters are copied from the source string
|
||||||
void CopyStringToCharArray(char* destination, std::string source, size_t size);
|
void CopyStringToCharArray(char* destination, std::string source, size_t size);
|
||||||
|
|
||||||
|
std::string Sanitize(std::string stringValue);
|
||||||
} // namespace SohUtils
|
} // namespace SohUtils
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) {
|
|||||||
_message_0xFFFC_nes = (char*)file->messages[i].msg.c_str();
|
_message_0xFFFC_nes = (char*)file->messages[i].msg.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that the first message starts at the first text ID
|
||||||
|
assert(table[0].textId == 0x0001);
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +107,9 @@ extern "C" void OTRMessage_Init()
|
|||||||
sStaffMessageEntryTablePtr[i].segment = file2->messages[i].msg.c_str();
|
sStaffMessageEntryTablePtr[i].segment = file2->messages[i].msg.c_str();
|
||||||
sStaffMessageEntryTablePtr[i].msgSize = file2->messages[i].msg.size();
|
sStaffMessageEntryTablePtr[i].msgSize = file2->messages[i].msg.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert staff credits start at the first credits ID
|
||||||
|
assert(sStaffMessageEntryTablePtr[0].textId == 0x0500);
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID);
|
CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID);
|
||||||
|
|||||||
+19
-31
@@ -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 (k >= cmdObj->objects.size() || 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;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -467,7 +467,7 @@ void GameState_Destroy(GameState* gameState) {
|
|||||||
// Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system.
|
// Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system.
|
||||||
ResourceMgr_ClearSkeletons();
|
ResourceMgr_ClearSkeletons();
|
||||||
|
|
||||||
if (CVarGetInteger("gAltAssets", 0)) {
|
if (ResourceMgr_IsAltAssetsEnabled()) {
|
||||||
ResourceUnloadDirectory("alt/*");
|
ResourceUnloadDirectory("alt/*");
|
||||||
gfx_texture_cache_clear();
|
gfx_texture_cache_clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ static const ALIGN_ASSET(2) char rGfxPrintFontDataAlt[] = drGfxPrintFontDataAlt;
|
|||||||
// https://github.com/HarbourMasters/Shipwright/issues/2762
|
// https://github.com/HarbourMasters/Shipwright/issues/2762
|
||||||
typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t;
|
typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t;
|
||||||
font_texture_t GfxPrint_TextureToUse() {
|
font_texture_t GfxPrint_TextureToUse() {
|
||||||
if (CVarGetInteger("gAltAssets", 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) {
|
if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) {
|
||||||
// If we have alt assets enabled, and we have alt prefixed font texture, use that
|
// If we have alt assets enabled, and we have alt prefixed font texture, use that
|
||||||
return otrAlt;
|
return otrAlt;
|
||||||
} else if (ResourceMgr_FileExists(rGfxPrintFontData)) {
|
} else if (ResourceMgr_FileExists(rGfxPrintFontData)) {
|
||||||
|
|||||||
+110
-25
@@ -1208,20 +1208,11 @@ void Actor_Init(Actor* actor, PlayState* play) {
|
|||||||
actor->uncullZoneForward = 1000.0f;
|
actor->uncullZoneForward = 1000.0f;
|
||||||
actor->uncullZoneScale = 350.0f;
|
actor->uncullZoneScale = 350.0f;
|
||||||
actor->uncullZoneDownward = 700.0f;
|
actor->uncullZoneDownward = 700.0f;
|
||||||
if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
|
|
||||||
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
|
|
||||||
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
|
|
||||||
&& (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room
|
|
||||||
actor->uncullZoneForward = 32767.0f;
|
|
||||||
actor->uncullZoneScale = 32767.0f;
|
|
||||||
actor->uncullZoneDownward = 32767.0f;
|
|
||||||
}
|
|
||||||
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;
|
||||||
|
|
||||||
@@ -2549,6 +2540,13 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) {
|
|||||||
Actor_SetObjectDependency(play, actor);
|
Actor_SetObjectDependency(play, actor);
|
||||||
actor->init(actor, play);
|
actor->init(actor, play);
|
||||||
actor->init = NULL;
|
actor->init = NULL;
|
||||||
|
|
||||||
|
GameInteractor_ExecuteOnActorInit(actor);
|
||||||
|
|
||||||
|
// For enemy health bar we need to know the max health during init
|
||||||
|
if (actor->category == ACTORCAT_ENEMY) {
|
||||||
|
actor->maximumHealth = actor->colChkInfo.health;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
actor = actor->next;
|
actor = actor->next;
|
||||||
} else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
} else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) {
|
||||||
@@ -2851,19 +2849,12 @@ s32 func_800314B0(PlayState* play, Actor* actor) {
|
|||||||
s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) {
|
s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) {
|
||||||
f32 var;
|
f32 var;
|
||||||
|
|
||||||
if (CVarGetInteger("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
|
|
||||||
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
|
|
||||||
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
|
|
||||||
&& (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) &&
|
if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) &&
|
||||||
(((arg2->y + actor->uncullZoneDownward) * var) > -2.0f) &&
|
(((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) &&
|
||||||
(((arg2->y - actor->uncullZoneScale) * var) < 2.0f)) {
|
(((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2871,6 +2862,80 @@ s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region SOH [Enhancements] Allows us to increase the draw and update distance independently,
|
||||||
|
// mostly a modified version of the function above and additional tweaks for some specfic actors
|
||||||
|
s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw,
|
||||||
|
bool* shouldUpdate) {
|
||||||
|
f32 clampedProjectedW;
|
||||||
|
|
||||||
|
// Check if the actor passes its original/vanilla culling requirements
|
||||||
|
if (func_800314D4(play, actor, projectedPos, projectedW)) {
|
||||||
|
*shouldUpdate = true;
|
||||||
|
*shouldDraw = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip cutscne actors that depend on culling to hide from camera pans
|
||||||
|
if (actor->id == ACTOR_EN_VIEWER) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 multiplier = CVarGetInteger("gDisableDrawDistance", 1);
|
||||||
|
multiplier = MAX(multiplier, 1);
|
||||||
|
|
||||||
|
// Some actors have a really short forward value, so we need to add to it before the multiplier to increase the
|
||||||
|
// final strength of the forward culling
|
||||||
|
f32 adder = (actor->uncullZoneForward < 500) ? 1000.0f : 0.0f;
|
||||||
|
|
||||||
|
if ((projectedPos->z > -actor->uncullZoneScale) &&
|
||||||
|
(projectedPos->z < (((actor->uncullZoneForward + adder) * multiplier) + actor->uncullZoneScale))) {
|
||||||
|
clampedProjectedW = (projectedW < 1.0f) ? 1.0f : 1.0f / projectedW;
|
||||||
|
|
||||||
|
f32 ratioAdjusted = 1.0f;
|
||||||
|
|
||||||
|
if (CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) {
|
||||||
|
f32 originalAspectRatio = 4.0f / 3.0f;
|
||||||
|
f32 currentAspectRatio = OTRGetAspectRatio();
|
||||||
|
ratioAdjusted = MAX(currentAspectRatio / originalAspectRatio, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((((fabsf(projectedPos->x) - actor->uncullZoneScale) * (clampedProjectedW / ratioAdjusted)) < 1.0f) &&
|
||||||
|
(((projectedPos->y + actor->uncullZoneDownward) * clampedProjectedW) > -1.0f) &&
|
||||||
|
(((projectedPos->y - actor->uncullZoneScale) * clampedProjectedW) < 1.0f)) {
|
||||||
|
|
||||||
|
if (CVarGetInteger("gEnhancements.ExtendedCullingExcludeGlitchActors", 0)) {
|
||||||
|
// These actors are safe to draw without impacting glitches
|
||||||
|
if ((actor->id == ACTOR_OBJ_BOMBIWA || actor->id == ACTOR_OBJ_HAMISHI ||
|
||||||
|
actor->id == ACTOR_EN_ISHI) || // Boulders (hookshot through collision)
|
||||||
|
actor->id == ACTOR_EN_GS || // Gossip stones (text delay)
|
||||||
|
actor->id == ACTOR_EN_GE1 || // White gerudos (gate clip/archery room transition)
|
||||||
|
actor->id == ACTOR_EN_KZ || // King Zora (unfreeze glitch)
|
||||||
|
actor->id == ACTOR_EN_DU || // Darunia (Fire temple BK skip)
|
||||||
|
actor->id == ACTOR_DOOR_WARP1 // Blue warps (wrong warps)
|
||||||
|
) {
|
||||||
|
*shouldDraw = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip these actors entirely as their draw funcs impacts glitches
|
||||||
|
if ((actor->id == ACTOR_EN_SW &&
|
||||||
|
(((actor->params & 0xE000) >> 0xD) == 1 ||
|
||||||
|
((actor->params & 0xE000) >> 0xD) == 2)) // Gold Skulltulas (hitbox at 0,0)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*shouldDraw = true;
|
||||||
|
*shouldUpdate = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
|
|
||||||
void func_800315AC(PlayState* play, ActorContext* actorCtx) {
|
void func_800315AC(PlayState* play, ActorContext* actorCtx) {
|
||||||
s32 invisibleActorCounter;
|
s32 invisibleActorCounter;
|
||||||
Actor* invisibleActors[INVISIBLE_ACTOR_MAX];
|
Actor* invisibleActors[INVISIBLE_ACTOR_MAX];
|
||||||
@@ -2906,18 +2971,35 @@ void func_800315AC(PlayState* play, ActorContext* actorCtx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #region SOH [Enhancement] Extended culling updates
|
||||||
|
bool shipShouldDraw = false;
|
||||||
|
bool shipShouldUpdate = false;
|
||||||
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(70) == 0)) {
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(70) == 0)) {
|
||||||
if (func_800314B0(play, actor)) {
|
if (CVarGetInteger("gDisableDrawDistance", 1) > 1 ||
|
||||||
actor->flags |= ACTOR_FLAG_ACTIVE;
|
CVarGetInteger("gEnhancements.WidescreenActorCulling", 0)) {
|
||||||
|
Ship_CalcShouldDrawAndUpdate(play, actor, &actor->projectedPos, actor->projectedW, &shipShouldDraw,
|
||||||
|
&shipShouldUpdate);
|
||||||
|
|
||||||
|
if (shipShouldUpdate) {
|
||||||
|
actor->flags |= ACTOR_FLAG_ACTIVE;
|
||||||
|
} else {
|
||||||
|
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
if (func_800314B0(play, actor)) {
|
||||||
|
actor->flags |= ACTOR_FLAG_ACTIVE;
|
||||||
|
} else {
|
||||||
|
actor->flags &= ~ACTOR_FLAG_ACTIVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actor->isDrawn = false;
|
actor->isDrawn = false;
|
||||||
|
|
||||||
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) {
|
if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) {
|
||||||
if ((actor->init == NULL) && (actor->draw != NULL) && (actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE))) {
|
if ((actor->init == NULL) && (actor->draw != NULL) &&
|
||||||
|
((actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE)) || shipShouldDraw)) {
|
||||||
|
// #endregion
|
||||||
if ((actor->flags & ACTOR_FLAG_LENS) &&
|
if ((actor->flags & ACTOR_FLAG_LENS) &&
|
||||||
((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) ||
|
((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) ||
|
||||||
play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) {
|
play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) {
|
||||||
@@ -3129,6 +3211,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,
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ s32 CollisionPoly_LineVsPoly(CollisionPoly* poly, Vec3s* vtxList, Vec3f* posA, V
|
|||||||
(poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC +
|
(poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC +
|
||||||
plane.originDist;
|
plane.originDist;
|
||||||
|
|
||||||
#ifdef __WIIU__
|
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||||
// on some platforms this ends up as very small numbers due to rounding issues
|
// on some platforms this ends up as very small numbers due to rounding issues
|
||||||
if (IS_ZERO(planeDistA)) {
|
if (IS_ZERO(planeDistA)) {
|
||||||
planeDistA = 0.0f;
|
planeDistA = 0.0f;
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 ||
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ typedef struct {
|
|||||||
union {
|
union {
|
||||||
u32 unk_00;
|
u32 unk_00;
|
||||||
struct {
|
struct {
|
||||||
u32 unk_bit0 : 1;
|
// SoH [Port] These bitfield values are unused and led to shifting in validModes for little endian systems
|
||||||
u32 unk_bit1 : 1;
|
// Removing those so that validModes can be a complete 32 bit value
|
||||||
u32 validModes : 30;
|
// u32 unk_bit0 : 1;
|
||||||
|
// u32 unk_bit1 : 1;
|
||||||
|
u32 validModes;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
CameraMode* cameraModes;
|
CameraMode* cameraModes;
|
||||||
|
|||||||
@@ -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*));
|
|
||||||
// "MAP texture initialization scene_data_ID=%d mapSegment=%x"
|
// "MAP texture initialization scene_data_ID=%d mapSegment=%x"
|
||||||
osSyncPrintf("\n\n\nMAP テクスチャ初期化 scene_data_ID=%d\nmapSegment=%x\n\n", play->sceneNum,
|
osSyncPrintf("\n\n\nMAP テクスチャ初期化 scene_data_ID=%d\nmapSegment=%x\n\n", play->sceneNum,
|
||||||
interfaceCtx->mapSegment, play);
|
interfaceCtx->mapSegment, play);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "textures/message_static/message_static.h"
|
#include "textures/message_static/message_static.h"
|
||||||
#include "textures/message_texture_static/message_texture_static.h"
|
#include "textures/message_texture_static/message_texture_static.h"
|
||||||
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
|
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
#include "soh/OTRGlobals.h"
|
#include "soh/OTRGlobals.h"
|
||||||
|
|
||||||
@@ -1114,7 +1115,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msgCtx->textDelayTimer == 0) {
|
if (msgCtx->textDelayTimer == 0) {
|
||||||
msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 2);
|
msgCtx->textDrawPos = i + CVarGetInteger("gTextSpeed", 1);
|
||||||
msgCtx->textDelayTimer = msgCtx->textDelay;
|
msgCtx->textDelayTimer = msgCtx->textDelay;
|
||||||
} else {
|
} else {
|
||||||
msgCtx->textDelayTimer--;
|
msgCtx->textDelayTimer--;
|
||||||
@@ -3069,7 +3070,9 @@ void Message_Draw(PlayState* play) {
|
|||||||
POLY_OPA_DISP = plusOne;
|
POLY_OPA_DISP = plusOne;
|
||||||
}
|
}
|
||||||
plusOne = Graph_GfxPlusOne(polyOpaP = POLY_OPA_DISP);
|
plusOne = Graph_GfxPlusOne(polyOpaP = POLY_OPA_DISP);
|
||||||
gSPDisplayList(OVERLAY_DISP++, plusOne);
|
if (!GameInteractor_NoUIActive()) {
|
||||||
|
gSPDisplayList(OVERLAY_DISP++, plusOne);
|
||||||
|
}
|
||||||
Message_DrawMain(play, &plusOne);
|
Message_DrawMain(play, &plusOne);
|
||||||
gSPEndDisplayList(plusOne++);
|
gSPEndDisplayList(plusOne++);
|
||||||
Graph_BranchDlist(polyOpaP, plusOne);
|
Graph_BranchDlist(polyOpaP, plusOne);
|
||||||
@@ -3384,7 +3387,7 @@ void Message_Update(PlayState* play) {
|
|||||||
}
|
}
|
||||||
sLastPlayedSong = 0xFF;
|
sLastPlayedSong = 0xFF;
|
||||||
osSyncPrintf("OCARINA_MODE=%d chk_ocarina_no=%d\n", play->msgCtx.ocarinaMode, msgCtx->unk_E3F2);
|
osSyncPrintf("OCARINA_MODE=%d chk_ocarina_no=%d\n", play->msgCtx.ocarinaMode, msgCtx->unk_E3F2);
|
||||||
CheckTracker_OnMessageClose();
|
// TODO: OnMessageClose hook
|
||||||
break;
|
break;
|
||||||
case MSGMODE_PAUSED:
|
case MSGMODE_PAUSED:
|
||||||
break;
|
break;
|
||||||
|
|||||||
+196
-104
@@ -1436,64 +1436,62 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te
|
|||||||
return displayListHead;
|
return displayListHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inventory_SwapAgeEquipment(void) {
|
void Rando_Inventory_SwapAgeEquipment(void) {
|
||||||
s16 i;
|
s16 i;
|
||||||
u16 shieldEquipValue;
|
u16 shieldEquipValue;
|
||||||
|
|
||||||
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
gSaveContext.childEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
gSaveContext.childEquips.buttonItems[i] =
|
||||||
|
gSaveContext.equips.buttonItems[i];
|
||||||
} else {
|
} else {
|
||||||
gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI;
|
gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
gSaveContext.childEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1];
|
gSaveContext.childEquips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.equips.cButtonSlots[i - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When becoming adult, remove swordless flag since we'll get master sword
|
|
||||||
// (Unless Master Sword is shuffled)
|
|
||||||
// Only in rando to keep swordless link bugs in vanilla
|
|
||||||
if (IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) {
|
|
||||||
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
gSaveContext.childEquips.equipment = gSaveContext.equips.equipment;
|
gSaveContext.childEquips.equipment = gSaveContext.equips.equipment;
|
||||||
|
|
||||||
if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) && gSaveContext.adultEquips.equipment)) {
|
// When becoming adult, remove swordless flag since we'll get master sword
|
||||||
if (!IS_RANDO || !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) {
|
// This gets set back appropriately later in the case of master sword shuffle
|
||||||
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
|
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
||||||
} else {
|
|
||||||
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
|
// This section sets up the equipment on the first time going adult.
|
||||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
// On master sword shuffle the check for the B button is insufficient, and so checking the equipment is completely zero-ed is needed
|
||||||
}
|
// (Could just always use `gSaveContext.adultEquips.equipment == 0` for rando?)
|
||||||
|
if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE && ((IS_RANDO && !Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD)) || (gSaveContext.adultEquips.equipment == 0))) {
|
||||||
|
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
|
||||||
|
|
||||||
if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) {
|
if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) {
|
||||||
gSaveContext.equips.buttonItems[1] = ITEM_NUT;
|
gSaveContext.equips.buttonItems[1] = ITEM_NUT;
|
||||||
gSaveContext.equips.cButtonSlots[0] = SLOT_NUT;
|
gSaveContext.equips.cButtonSlots[0] = SLOT_NUT;
|
||||||
} else {
|
} else {
|
||||||
gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] = ITEM_NONE;
|
gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] =
|
||||||
|
ITEM_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gSaveContext.equips.buttonItems[2] = ITEM_BOMB;
|
gSaveContext.equips.buttonItems[2] = ITEM_BOMB;
|
||||||
gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA];
|
gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA];
|
||||||
gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB;
|
gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB;
|
||||||
gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA;
|
gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA;
|
||||||
|
|
||||||
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) |
|
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) |
|
||||||
(EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) |
|
(EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) |
|
||||||
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||||
|
|
||||||
|
// In Master Sword Shuffle we want to override the equip of the master sword from the vanilla code
|
||||||
|
// First check we have the Master sword in our inventory, and if not, then unequip
|
||||||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
||||||
gSaveContext.equips.buttonItems[0] == ITEM_NONE) {
|
!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) {
|
||||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||||
|
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
|
||||||
|
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the dpad to nothing
|
// Set the dpad to nothing
|
||||||
gSaveContext.equips.buttonItems[4] = ITEM_NONE;
|
gSaveContext.equips.buttonItems[4] = ITEM_NONE;
|
||||||
gSaveContext.equips.buttonItems[5] = ITEM_NONE;
|
gSaveContext.equips.buttonItems[5] = ITEM_NONE;
|
||||||
@@ -1505,10 +1503,170 @@ void Inventory_SwapAgeEquipment(void) {
|
|||||||
gSaveContext.equips.cButtonSlots[6] = SLOT_NONE;
|
gSaveContext.equips.cButtonSlots[6] = SLOT_NONE;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
gSaveContext.equips.buttonItems[i] = gSaveContext.adultEquips.buttonItems[i];
|
gSaveContext.equips.buttonItems[i] =
|
||||||
|
gSaveContext.adultEquips.buttonItems[i];
|
||||||
|
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.adultEquips.cButtonSlots[i - 1];
|
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.adultEquips.cButtonSlots[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||||
|
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||||
|
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||||
|
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||||
|
gSaveContext.equips.buttonItems[i] =
|
||||||
|
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In Master Sword Shuffle we want to set the swordless flag if no item is on the B button
|
||||||
|
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
|
||||||
|
gSaveContext.equips.buttonItems[0] == ITEM_NONE) {
|
||||||
|
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
|
gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
gSaveContext.adultEquips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.equips.cButtonSlots[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment;
|
||||||
|
|
||||||
|
if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) {
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
|
gSaveContext.equips.buttonItems[i] =
|
||||||
|
gSaveContext.childEquips.buttonItems[i];
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.childEquips.cButtonSlots[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||||
|
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||||
|
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||||
|
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||||
|
gSaveContext.equips.buttonItems[i] =
|
||||||
|
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
||||||
|
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||||
|
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
||||||
|
}
|
||||||
|
// In Rando we need an extra case to handle starting as adult. We can use the fact that the childEquips will be uninitialised (i.e. 0) at this point
|
||||||
|
else if (gSaveContext.childEquips.equipment == 0) {
|
||||||
|
|
||||||
|
//zero out items
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
|
gSaveContext.equips.buttonItems[i] = ITEM_NONE;
|
||||||
|
if (i != 0) {
|
||||||
|
gSaveContext.equips.cButtonSlots[i-1] = ITEM_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4)) |
|
||||||
|
(EQUIP_VALUE_SHIELD_DEKU << (EQUIP_TYPE_SHIELD * 4)) |
|
||||||
|
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||||
|
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
// When becoming child in rando, set swordless flag and clear B button if player doesn't have kokiri sword
|
||||||
|
// Otherwise, equip sword and unset flag
|
||||||
|
if (!CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_KOKIRI)) {
|
||||||
|
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||||
|
gSaveContext.equips.buttonItems[0] = ITEM_NONE;
|
||||||
|
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
||||||
|
} else {
|
||||||
|
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||||
|
gSaveContext.equips.equipment |= (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4));
|
||||||
|
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI;
|
||||||
|
Flags_UnsetInfTable(INFTABLE_SWORDLESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment;
|
||||||
|
if (shieldEquipValue) {
|
||||||
|
shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD];
|
||||||
|
if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) {
|
||||||
|
gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inventory_SwapAgeEquipment(void) {
|
||||||
|
s16 i;
|
||||||
|
u16 shieldEquipValue;
|
||||||
|
|
||||||
|
// Mod Enhancments can utilise the rando flow path
|
||||||
|
if (IS_RANDO || CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) {
|
||||||
|
Rando_Inventory_SwapAgeEquipment();
|
||||||
|
CVarSetInteger("gSwitchTimeline", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
|
if (i != 0) {
|
||||||
|
gSaveContext.childEquips.buttonItems[i] =
|
||||||
|
gSaveContext.equips.buttonItems[i];
|
||||||
|
} else {
|
||||||
|
gSaveContext.childEquips.buttonItems[i] = ITEM_SWORD_KOKIRI;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
gSaveContext.childEquips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.equips.cButtonSlots[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveContext.childEquips.equipment = gSaveContext.equips.equipment;
|
||||||
|
|
||||||
|
if (gSaveContext.adultEquips.buttonItems[0] == ITEM_NONE) {
|
||||||
|
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER;
|
||||||
|
|
||||||
|
if (gSaveContext.inventory.items[SLOT_NUT] != ITEM_NONE) {
|
||||||
|
gSaveContext.equips.buttonItems[1] = ITEM_NUT;
|
||||||
|
gSaveContext.equips.cButtonSlots[0] = SLOT_NUT;
|
||||||
|
} else {
|
||||||
|
gSaveContext.equips.buttonItems[1] = gSaveContext.equips.cButtonSlots[0] =
|
||||||
|
ITEM_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gSaveContext.equips.buttonItems[2] = ITEM_BOMB;
|
||||||
|
gSaveContext.equips.buttonItems[3] = gSaveContext.inventory.items[SLOT_OCARINA];
|
||||||
|
gSaveContext.equips.cButtonSlots[1] = SLOT_BOMB;
|
||||||
|
gSaveContext.equips.cButtonSlots[2] = SLOT_OCARINA;
|
||||||
|
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_MASTER << (EQUIP_TYPE_SWORD * 4)) |
|
||||||
|
(EQUIP_VALUE_SHIELD_HYLIAN << (EQUIP_TYPE_SHIELD * 4)) |
|
||||||
|
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
||||||
|
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
||||||
|
// Set the dpad to nothing
|
||||||
|
gSaveContext.equips.buttonItems[4] = ITEM_NONE;
|
||||||
|
gSaveContext.equips.buttonItems[5] = ITEM_NONE;
|
||||||
|
gSaveContext.equips.buttonItems[6] = ITEM_NONE;
|
||||||
|
gSaveContext.equips.buttonItems[7] = ITEM_NONE;
|
||||||
|
gSaveContext.equips.cButtonSlots[3] = SLOT_NONE;
|
||||||
|
gSaveContext.equips.cButtonSlots[4] = SLOT_NONE;
|
||||||
|
gSaveContext.equips.cButtonSlots[5] = SLOT_NONE;
|
||||||
|
gSaveContext.equips.cButtonSlots[6] = SLOT_NONE;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
|
gSaveContext.equips.buttonItems[i] =
|
||||||
|
gSaveContext.adultEquips.buttonItems[i];
|
||||||
|
|
||||||
|
if (i != 0) {
|
||||||
|
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.adultEquips.cButtonSlots[i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||||
@@ -1524,59 +1682,25 @@ void Inventory_SwapAgeEquipment(void) {
|
|||||||
gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment;
|
gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// When becoming child, set swordless flag if player doesn't have kokiri sword
|
|
||||||
// Only in rando to keep swordless link bugs in vanilla
|
|
||||||
if (IS_RANDO && (EQUIP_INV_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4) & gSaveContext.inventory.equipment) == 0) {
|
|
||||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// When using enhancements, set swordless flag if player doesn't have kokiri sword or hasn't equipped a sword yet.
|
|
||||||
// Then set the child equips button items to item none to ensure kokiri sword is not equipped
|
|
||||||
if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) && ((EQUIP_INV_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4) & gSaveContext.inventory.equipment) == 0 || Flags_GetInfTable(INFTABLE_SWORDLESS))) {
|
|
||||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
|
||||||
gSaveContext.childEquips.buttonItems[0] = ITEM_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
gSaveContext.adultEquips.buttonItems[i] = gSaveContext.equips.buttonItems[i];
|
||||||
|
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
gSaveContext.adultEquips.cButtonSlots[i - 1] = gSaveContext.equips.cButtonSlots[i - 1];
|
gSaveContext.adultEquips.cButtonSlots[i - 1] =
|
||||||
|
gSaveContext.equips.cButtonSlots[i - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment;
|
gSaveContext.adultEquips.equipment = gSaveContext.equips.equipment;
|
||||||
// Switching age using enhancements separated out to make vanilla flow clear
|
|
||||||
if (CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) {
|
if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) {
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
||||||
gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i];
|
gSaveContext.equips.buttonItems[i] =
|
||||||
|
gSaveContext.childEquips.buttonItems[i];
|
||||||
|
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1];
|
gSaveContext.equips.cButtonSlots[i - 1] =
|
||||||
}
|
gSaveContext.childEquips.cButtonSlots[i - 1];
|
||||||
|
|
||||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
|
||||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
|
||||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
|
||||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
|
||||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
|
||||||
gSaveContext.equips.buttonItems[i] =
|
|
||||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
|
||||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
|
||||||
// Equips kokiri sword in the inventory screen only if kokiri sword exists in inventory and a sword has been equipped already
|
|
||||||
if (!((EQUIP_INV_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4) & gSaveContext.inventory.equipment) == 0) && !Flags_GetInfTable(INFTABLE_SWORDLESS)) {
|
|
||||||
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
|
||||||
}
|
|
||||||
} else if (gSaveContext.childEquips.buttonItems[0] != ITEM_NONE) {
|
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
|
||||||
gSaveContext.equips.buttonItems[i] = gSaveContext.childEquips.buttonItems[i];
|
|
||||||
|
|
||||||
if (i != 0) {
|
|
||||||
gSaveContext.equips.cButtonSlots[i - 1] = gSaveContext.childEquips.cButtonSlots[i - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
if (((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) &&
|
||||||
@@ -1592,43 +1716,11 @@ void Inventory_SwapAgeEquipment(void) {
|
|||||||
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
|
||||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
||||||
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
|
||||||
} else if (IS_RANDO && Randomizer_GetSettingValue(RSK_STARTING_AGE) == RO_AGE_ADULT) {
|
|
||||||
/*If in rando and starting age is adult, childEquips is not initialized and buttonItems[0]
|
|
||||||
will be ITEM_NONE. When changing age from adult -> child, reset equips to "default"
|
|
||||||
(only kokiri tunic/boots equipped, no sword, no C-button items, no D-Pad items).
|
|
||||||
When becoming child, set swordless flag if player doesn't have kokiri sword
|
|
||||||
Only in rando to keep swordless link bugs in vanilla*/
|
|
||||||
if (EQUIP_INV_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4) & gSaveContext.inventory.equipment == 0) {
|
|
||||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
//zero out items
|
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) {
|
|
||||||
gSaveContext.equips.buttonItems[i] = ITEM_NONE;
|
|
||||||
if (i != 0) {
|
|
||||||
gSaveContext.equips.cButtonSlots[i-1] = ITEM_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gSaveContext.equips.equipment = (EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4)) |
|
|
||||||
(EQUIP_VALUE_SHIELD_DEKU << (EQUIP_TYPE_SHIELD * 4)) |
|
|
||||||
(EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
|
||||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((CVarGetInteger("gSwitchAge", 0) || CVarGetInteger("gSwitchTimeline", 0)) &&
|
|
||||||
(gSaveContext.equips.buttonItems[0] == ITEM_NONE)) {
|
|
||||||
Flags_SetInfTable(INFTABLE_SWORDLESS);
|
|
||||||
if (gSaveContext.childEquips.equipment == 0) {
|
|
||||||
// force equip kokiri tunic and boots in scenario gSaveContext.childEquips.equipment is uninitialized
|
|
||||||
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
|
|
||||||
gSaveContext.equips.equipment |= (EQUIP_VALUE_TUNIC_KOKIRI << (EQUIP_TYPE_TUNIC * 4)) |
|
|
||||||
(EQUIP_VALUE_BOOTS_KOKIRI << (EQUIP_TYPE_BOOTS * 4));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CVarSetInteger("gSwitchTimeline", 0);
|
|
||||||
shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment;
|
shieldEquipValue = gEquipMasks[EQUIP_TYPE_SHIELD] & gSaveContext.equips.equipment;
|
||||||
if (shieldEquipValue != 0) {
|
if (shieldEquipValue) {
|
||||||
shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD];
|
shieldEquipValue >>= gEquipShifts[EQUIP_TYPE_SHIELD];
|
||||||
if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) {
|
if (!CHECK_OWNED_EQUIP_ALT(EQUIP_TYPE_SHIELD, shieldEquipValue - 1)) {
|
||||||
gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD];
|
gSaveContext.equips.equipment &= gEquipNegMasks[EQUIP_TYPE_SHIELD];
|
||||||
|
|||||||
@@ -2307,10 +2307,12 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f*
|
|||||||
}
|
}
|
||||||
|
|
||||||
srcTable = ResourceMgr_LoadArrayByNameAsVec3s(srcTable);
|
srcTable = ResourceMgr_LoadArrayByNameAsVec3s(srcTable);
|
||||||
|
Vec3s* ogSrcTable = srcTable;
|
||||||
destTable = skelAnime->jointTable;
|
destTable = skelAnime->jointTable;
|
||||||
for (i = 0; i < skelAnime->limbCount; i++) {
|
for (i = 0; i < skelAnime->limbCount; i++) {
|
||||||
*destTable++ = *srcTable++;
|
*destTable++ = *srcTable++;
|
||||||
}
|
}
|
||||||
|
free(ogSrcTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -277,6 +277,11 @@ void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 h
|
|||||||
bg->b.imagePal = 0;
|
bg->b.imagePal = 0;
|
||||||
bg->b.imageFlip = CVarGetInteger("gMirroredWorld", 0) ? G_BG_FLAG_FLIPS : 0;
|
bg->b.imageFlip = CVarGetInteger("gMirroredWorld", 0) ? G_BG_FLAG_FLIPS : 0;
|
||||||
|
|
||||||
|
// When an alt resource exists for the background, we need to unload the original asset
|
||||||
|
// to clear the cache so the alt asset will be loaded instead
|
||||||
|
// OTRTODO: If Alt loading over original cache is fixed, this line can most likely be removed
|
||||||
|
ResourceMgr_UnloadOriginalWhenAltExists((char*) source);
|
||||||
|
|
||||||
if (ResourceMgr_ResourceIsBackground((char*) source)) {
|
if (ResourceMgr_ResourceIsBackground((char*) source)) {
|
||||||
char* blob = (char*) ResourceGetDataByName((char *) source);
|
char* blob = (char*) ResourceGetDataByName((char *) source);
|
||||||
swapAndConvertJPEG(blob);
|
swapAndConvertJPEG(blob);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
|||||||
Vec3f pos;
|
Vec3f pos;
|
||||||
Vec3s rot;
|
Vec3s rot;
|
||||||
|
|
||||||
|
if (CVarGetInteger("gDisableLOD", 0)) {
|
||||||
|
lod = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (skeleton == NULL) {
|
if (skeleton == NULL) {
|
||||||
osSyncPrintf(VT_FGCOL(RED));
|
osSyncPrintf(VT_FGCOL(RED));
|
||||||
osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL."
|
osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL."
|
||||||
@@ -144,6 +148,8 @@ void SkelAnime_DrawFlexLimbLod(PlayState* play, s32 limbIndex, void** skeleton,
|
|||||||
|
|
||||||
newDList = limbDList = limb->dLists[lod];
|
newDList = limbDList = limb->dLists[lod];
|
||||||
|
|
||||||
|
play->flexLimbOverrideMTX = mtx;
|
||||||
|
|
||||||
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) {
|
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) {
|
||||||
Matrix_TranslateRotateZYX(&pos, &rot);
|
Matrix_TranslateRotateZYX(&pos, &rot);
|
||||||
if (newDList != NULL) {
|
if (newDList != NULL) {
|
||||||
@@ -191,6 +197,10 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
|||||||
Vec3s rot;
|
Vec3s rot;
|
||||||
Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx));
|
Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx));
|
||||||
|
|
||||||
|
if (CVarGetInteger("gDisableLOD", 0)) {
|
||||||
|
lod = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (skeleton == NULL) {
|
if (skeleton == NULL) {
|
||||||
osSyncPrintf(VT_FGCOL(RED));
|
osSyncPrintf(VT_FGCOL(RED));
|
||||||
osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL."
|
osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL."
|
||||||
@@ -212,6 +222,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable,
|
|||||||
|
|
||||||
newDList = limbDList = rootLimb->dLists[lod];
|
newDList = limbDList = rootLimb->dLists[lod];
|
||||||
|
|
||||||
|
play->flexLimbOverrideMTX = &mtx;
|
||||||
|
|
||||||
if ((overrideLimbDraw == 0) || !overrideLimbDraw(play, 1, &newDList, &pos, &rot, arg)) {
|
if ((overrideLimbDraw == 0) || !overrideLimbDraw(play, 1, &newDList, &pos, &rot, arg)) {
|
||||||
Matrix_TranslateRotateZYX(&pos, &rot);
|
Matrix_TranslateRotateZYX(&pos, &rot);
|
||||||
if (newDList != NULL) {
|
if (newDList != NULL) {
|
||||||
@@ -298,6 +310,20 @@ void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw,
|
||||||
|
PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx)
|
||||||
|
{
|
||||||
|
if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_NORMAL) {
|
||||||
|
return SkelAnime_Draw(play, skelAnime->skeleton, skelAnime->jointTable, overrideLimbDraw, postLimbDraw, arg, gfx);
|
||||||
|
} else if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
FlexSkeletonHeader* flexHeader = (FlexSkeletonHeader*)skelAnime->skeletonHeader;
|
||||||
|
return SkelAnime_DrawFlex(play, skelAnime->skeleton, skelAnime->jointTable, flexHeader->dListCount,
|
||||||
|
overrideLimbDraw, postLimbDraw, arg, gfx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gfx;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw all limbs of type `StandardLimb` in a given skeleton to the polyOpa buffer
|
* Draw all limbs of type `StandardLimb` in a given skeleton to the polyOpa buffer
|
||||||
*/
|
*/
|
||||||
@@ -375,6 +401,8 @@ void SkelAnime_DrawFlexLimbOpa(PlayState* play, s32 limbIndex, void** skeleton,
|
|||||||
|
|
||||||
newDList = limbDList = limb->dList;
|
newDList = limbDList = limb->dList;
|
||||||
|
|
||||||
|
play->flexLimbOverrideMTX = limbMatricies;
|
||||||
|
|
||||||
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) {
|
if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) {
|
||||||
Matrix_TranslateRotateZYX(&pos, &rot);
|
Matrix_TranslateRotateZYX(&pos, &rot);
|
||||||
if (newDList != NULL) {
|
if (newDList != NULL) {
|
||||||
|
|||||||
+60
-57
@@ -59,65 +59,68 @@ void Sram_OpenSave() {
|
|||||||
|
|
||||||
Save_LoadFile();
|
Save_LoadFile();
|
||||||
|
|
||||||
if (!CVarGetInteger("gRememberSaveLocation", 0) || gSaveContext.savedSceneNum == SCENE_FAIRYS_FOUNTAIN ||
|
switch (gSaveContext.savedSceneNum) {
|
||||||
gSaveContext.savedSceneNum == SCENE_GROTTOS) {
|
case SCENE_DEKU_TREE:
|
||||||
switch (gSaveContext.savedSceneNum) {
|
case SCENE_DODONGOS_CAVERN:
|
||||||
case SCENE_DEKU_TREE:
|
case SCENE_JABU_JABU:
|
||||||
case SCENE_DODONGOS_CAVERN:
|
case SCENE_FOREST_TEMPLE:
|
||||||
case SCENE_JABU_JABU:
|
case SCENE_FIRE_TEMPLE:
|
||||||
case SCENE_FOREST_TEMPLE:
|
case SCENE_WATER_TEMPLE:
|
||||||
case SCENE_FIRE_TEMPLE:
|
case SCENE_SPIRIT_TEMPLE:
|
||||||
case SCENE_WATER_TEMPLE:
|
case SCENE_SHADOW_TEMPLE:
|
||||||
case SCENE_SPIRIT_TEMPLE:
|
case SCENE_BOTTOM_OF_THE_WELL:
|
||||||
case SCENE_SHADOW_TEMPLE:
|
case SCENE_ICE_CAVERN:
|
||||||
case SCENE_BOTTOM_OF_THE_WELL:
|
case SCENE_GANONS_TOWER:
|
||||||
case SCENE_ICE_CAVERN:
|
case SCENE_GERUDO_TRAINING_GROUND:
|
||||||
case SCENE_GANONS_TOWER:
|
case SCENE_THIEVES_HIDEOUT:
|
||||||
case SCENE_GERUDO_TRAINING_GROUND:
|
case SCENE_INSIDE_GANONS_CASTLE:
|
||||||
case SCENE_THIEVES_HIDEOUT:
|
gSaveContext.entranceIndex = dungeonEntrances[gSaveContext.savedSceneNum];
|
||||||
case SCENE_INSIDE_GANONS_CASTLE:
|
break;
|
||||||
gSaveContext.entranceIndex = dungeonEntrances[gSaveContext.savedSceneNum];
|
case SCENE_DEKU_TREE_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0;
|
||||||
case SCENE_DEKU_TREE_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0;
|
case SCENE_DODONGOS_CAVERN_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 4;
|
||||||
case SCENE_DODONGOS_CAVERN_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 4;
|
case SCENE_JABU_JABU_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0x28;
|
||||||
case SCENE_JABU_JABU_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x28;
|
case SCENE_FOREST_TEMPLE_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0x169;
|
||||||
case SCENE_FOREST_TEMPLE_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x169;
|
case SCENE_FIRE_TEMPLE_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0x165;
|
||||||
case SCENE_FIRE_TEMPLE_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x165;
|
case SCENE_WATER_TEMPLE_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0x10;
|
||||||
case SCENE_WATER_TEMPLE_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x10;
|
case SCENE_SPIRIT_TEMPLE_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0x82;
|
||||||
case SCENE_SPIRIT_TEMPLE_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x82;
|
case SCENE_SHADOW_TEMPLE_BOSS:
|
||||||
break;
|
gSaveContext.entranceIndex = 0x37;
|
||||||
case SCENE_SHADOW_TEMPLE_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x37;
|
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
|
||||||
break;
|
case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE:
|
||||||
case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR:
|
case SCENE_GANONDORF_BOSS:
|
||||||
case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE:
|
case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR:
|
||||||
case SCENE_GANONDORF_BOSS:
|
case SCENE_GANON_BOSS:
|
||||||
case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR:
|
gSaveContext.entranceIndex = 0x41B;
|
||||||
case SCENE_GANON_BOSS:
|
break;
|
||||||
gSaveContext.entranceIndex = 0x41B;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (gSaveContext.savedSceneNum != SCENE_LINKS_HOUSE) {
|
// Use the saved entrance value with remember save location, except when in grottos/fairy fountains
|
||||||
gSaveContext.entranceIndex = (LINK_AGE_IN_YEARS == YEARS_CHILD) ? 0xBB : 0x5F4;
|
if (CVarGetInteger("gRememberSaveLocation", 0) && gSaveContext.savedSceneNum != SCENE_FAIRYS_FOUNTAIN &&
|
||||||
} else {
|
gSaveContext.savedSceneNum != SCENE_GROTTOS) {
|
||||||
gSaveContext.entranceIndex = 0xBB;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gSaveContext.savedSceneNum != SCENE_LINKS_HOUSE) {
|
||||||
|
gSaveContext.entranceIndex = (LINK_AGE_IN_YEARS == YEARS_CHILD) ? 0xBB : 0x5F4;
|
||||||
|
} else {
|
||||||
|
gSaveContext.entranceIndex = 0xBB;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex);
|
osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex);
|
||||||
|
|||||||
@@ -417,7 +417,12 @@ void func_800AEFC8(SkyboxContext* skyboxCtx, s16 skyboxId) {
|
|||||||
s32 j;
|
s32 j;
|
||||||
s32 phi_s3 = 0;
|
s32 phi_s3 = 0;
|
||||||
|
|
||||||
if (skyboxId == SKYBOX_BAZAAR || (skyboxId > SKYBOX_HOUSE_KAKARIKO && skyboxId <= SKYBOX_BOMBCHU_SHOP)) {
|
//! @bug All shops only provide 2 faces for their sky box. Mask shop is missing from the condition
|
||||||
|
// meaning that the Mask shop will calculate 4 faces
|
||||||
|
// This effect is not noticed as the faces are behind the camera, but will cause a crash in SoH.
|
||||||
|
// SOH General: We have added the Mask shop to this check so only the 2 expected faces are calculated.
|
||||||
|
if (skyboxId == SKYBOX_BAZAAR || skyboxId == SKYBOX_HAPPY_MASK_SHOP ||
|
||||||
|
(skyboxId >= SKYBOX_KOKIRI_SHOP && skyboxId <= SKYBOX_BOMBCHU_SHOP)) {
|
||||||
for (j = 0, i = 0; i < 2; i++, j += 2) {
|
for (j = 0, i = 0; i < 2; i++, j += 2) {
|
||||||
phi_s3 = func_800ADBB0(skyboxCtx, skyboxCtx->roomVtx, phi_s3, D_8012AEBC[i].unk_0, D_8012AEBC[i].unk_4,
|
phi_s3 = func_800ADBB0(skyboxCtx, skyboxCtx->roomVtx, phi_s3, D_8012AEBC[i].unk_0, D_8012AEBC[i].unk_4,
|
||||||
D_8012AEBC[i].unk_8, D_8012AEBC[i].unk_C, D_8012AEBC[i].unk_10, i, j);
|
D_8012AEBC[i].unk_8, D_8012AEBC[i].unk_C, D_8012AEBC[i].unk_10, i, j);
|
||||||
|
|||||||
@@ -59,8 +59,14 @@ void SkyboxDraw_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyb
|
|||||||
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[2]);
|
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[2]);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[3]);
|
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[3]);
|
||||||
|
|
||||||
if (skyboxId != SKYBOX_BAZAAR) {
|
//! @bug All shops only provide 2 faces for their sky box. Mask shop is missing from the condition
|
||||||
if (skyboxId <= SKYBOX_HOUSE_KAKARIKO || skyboxId > SKYBOX_BOMBCHU_SHOP) {
|
// meaning that the Mask shop will render the previously loaded sky box values, or uninitialized data.
|
||||||
|
// This effect is not noticed as the faces are behind the camera, but will cause a crash in SoH.
|
||||||
|
// SOH General: We have added the Mask shop to this check so only the 2 expected faces are rendered.
|
||||||
|
if (skyboxId != SKYBOX_BAZAAR && skyboxId != SKYBOX_HAPPY_MASK_SHOP) {
|
||||||
|
if (skyboxId < SKYBOX_KOKIRI_SHOP || skyboxId > SKYBOX_BOMBCHU_SHOP) {
|
||||||
|
// Skip remaining faces for most shop skyboxes
|
||||||
|
|
||||||
gDPPipeSync(POLY_OPA_DISP++);
|
gDPPipeSync(POLY_OPA_DISP++);
|
||||||
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[2]);
|
gDPLoadTLUT_pal256(POLY_OPA_DISP++, skyboxCtx->palettes[2]);
|
||||||
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[4]);
|
gSPDisplayList(POLY_OPA_DISP++, skyboxCtx->dListBuf[4]);
|
||||||
|
|||||||
@@ -5,9 +5,17 @@
|
|||||||
#include "scenes/dungeons/ddan_boss/ddan_boss_room_1.h"
|
#include "scenes/dungeons/ddan_boss/ddan_boss_room_1.h"
|
||||||
#include "soh/frame_interpolation.h"
|
#include "soh/frame_interpolation.h"
|
||||||
#include "soh/Enhancements/boss-rush/BossRush.h"
|
#include "soh/Enhancements/boss-rush/BossRush.h"
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||||
|
|
||||||
|
#include <stdlib.h> // malloc
|
||||||
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
#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_HEIGHT 64
|
||||||
|
#define LAVA_TEX_SIZE 2048
|
||||||
|
|
||||||
void BossDodongo_Init(Actor* thisx, PlayState* play);
|
void BossDodongo_Init(Actor* thisx, PlayState* play);
|
||||||
void BossDodongo_Destroy(Actor* thisx, PlayState* play);
|
void BossDodongo_Destroy(Actor* thisx, PlayState* play);
|
||||||
void BossDodongo_Update(Actor* thisx, PlayState* play);
|
void BossDodongo_Update(Actor* thisx, PlayState* play);
|
||||||
@@ -57,7 +65,14 @@ static u8 sMaskTex16x32[16 * 32] = { { 0 } };
|
|||||||
static u8 sMaskTex32x16[32 * 16] = { { 0 } };
|
static u8 sMaskTex32x16[32 * 16] = { { 0 } };
|
||||||
static u8 sMaskTex8x8[8 * 8] = { { 0 } };
|
static u8 sMaskTex8x8[8 * 8] = { { 0 } };
|
||||||
static u8 sMaskTex8x32[8 * 32] = { { 0 } };
|
static u8 sMaskTex8x32[8 * 32] = { { 0 } };
|
||||||
static u8 sMaskTexLava[32 * 64] = { { 0 } };
|
static u8 sMaskTexLava[LAVA_TEX_WIDTH * LAVA_TEX_HEIGHT] = { { 0 } };
|
||||||
|
|
||||||
|
static u32* sLavaFloorModifiedTexRaw = NULL;
|
||||||
|
static u32* sLavaWavyTexRaw = NULL;
|
||||||
|
static u16 sLavaFloorModifiedTex[LAVA_TEX_SIZE];
|
||||||
|
static u16 sLavaWavyTex[LAVA_TEX_SIZE];
|
||||||
|
|
||||||
|
static u8 hasRegisteredBlendedHook = 0;
|
||||||
|
|
||||||
static InitChainEntry sInitChain[] = {
|
static InitChainEntry sInitChain[] = {
|
||||||
ICHAIN_U8(targetMode, 5, ICHAIN_CONTINUE),
|
ICHAIN_U8(targetMode, 5, ICHAIN_CONTINUE),
|
||||||
@@ -66,6 +81,93 @@ static InitChainEntry sInitChain[] = {
|
|||||||
ICHAIN_F32(targetArrowOffset, 8200.0f, ICHAIN_STOP),
|
ICHAIN_F32(targetArrowOffset, 8200.0f, ICHAIN_STOP),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void BossDodongo_RegisterBlendedLavaTextureUpdate() {
|
||||||
|
// Not in scene so there is nothing to do
|
||||||
|
if (gPlayState == NULL || gPlayState->sceneNum != SCENE_DODONGOS_CAVERN_BOSS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free old textures
|
||||||
|
if (sLavaFloorModifiedTexRaw != NULL) {
|
||||||
|
free(sLavaFloorModifiedTexRaw);
|
||||||
|
sLavaFloorModifiedTexRaw = NULL;
|
||||||
|
}
|
||||||
|
if (sLavaWavyTexRaw != NULL) {
|
||||||
|
free(sLavaWavyTexRaw);
|
||||||
|
sLavaWavyTexRaw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload original textures to bypass cache result for lookups
|
||||||
|
ResourceMgr_UnloadOriginalWhenAltExists(sLavaFloorLavaTex);
|
||||||
|
ResourceMgr_UnloadOriginalWhenAltExists(sLavaFloorRockTex);
|
||||||
|
ResourceMgr_UnloadOriginalWhenAltExists(gDodongosCavernBossLavaFloorTex);
|
||||||
|
|
||||||
|
// When the texture is HD (raw) we need to work with u32 values for RGBA32
|
||||||
|
// Otherwise the original asset is u16 for RGBA16
|
||||||
|
if (ResourceMgr_TexIsRaw(gDodongosCavernBossLavaFloorTex)) {
|
||||||
|
u32* lavaTex = ResourceGetDataByName(sLavaFloorLavaTex);
|
||||||
|
size_t lavaSize = ResourceGetSizeByName(sLavaFloorLavaTex);
|
||||||
|
size_t floorSize = ResourceGetSizeByName(gDodongosCavernBossLavaFloorTex);
|
||||||
|
size_t rockSize = ResourceGetSizeByName(sLavaFloorRockTex);
|
||||||
|
|
||||||
|
// If the sizes don't match, then don't bother with the blended effect to avoid crashing
|
||||||
|
if (floorSize != lavaSize || floorSize != rockSize) {
|
||||||
|
uint8_t maskVal = !!Flags_GetClear(gPlayState, gPlayState->roomCtx.curRoom.num);
|
||||||
|
|
||||||
|
if (sMaskTexLava[0] != maskVal) {
|
||||||
|
for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
|
||||||
|
sMaskTexLava[i] = maskVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, NULL);
|
||||||
|
Gfx_TextureCacheDelete(sMaskTexLava);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sLavaFloorModifiedTexRaw = malloc(lavaSize);
|
||||||
|
sLavaWavyTexRaw = malloc(floorSize);
|
||||||
|
|
||||||
|
memcpy(sLavaFloorModifiedTexRaw, lavaTex, lavaSize);
|
||||||
|
|
||||||
|
// When KD is dead, just immediately copy the rock texture
|
||||||
|
if (Flags_GetClear(gPlayState, gPlayState->roomCtx.curRoom.num)) {
|
||||||
|
u32* rockTex = ResourceGetDataByName(sLavaFloorRockTex);
|
||||||
|
memcpy(sLavaFloorModifiedTexRaw, rockTex, rockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(sLavaWavyTexRaw, sLavaFloorModifiedTexRaw, floorSize);
|
||||||
|
|
||||||
|
// Register the blended effect for the raw texture
|
||||||
|
Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, sLavaWavyTexRaw);
|
||||||
|
} else {
|
||||||
|
// When KD is dead, just immediately copy the rock texture
|
||||||
|
if (Flags_GetClear(gPlayState, gPlayState->roomCtx.curRoom.num)) {
|
||||||
|
u16* rockTex = ResourceGetDataByName(sLavaFloorRockTex);
|
||||||
|
memcpy(sLavaFloorModifiedTex, rockTex, sizeof(sLavaFloorModifiedTex));
|
||||||
|
} else {
|
||||||
|
u16* lavaTex = ResourceGetDataByName(sLavaFloorLavaTex);
|
||||||
|
memcpy(sLavaFloorModifiedTex, lavaTex, sizeof(sLavaFloorModifiedTex));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the blended effect for the non-raw texture
|
||||||
|
memcpy(sLavaWavyTex, sLavaFloorModifiedTex, sizeof(sLavaWavyTex));
|
||||||
|
|
||||||
|
Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, sLavaWavyTex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set all true for the lava as it will always replace the scene texture
|
||||||
|
if (sMaskTexLava[0] == 0) {
|
||||||
|
for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
|
||||||
|
sMaskTexLava[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Gfx_TextureCacheDelete(sMaskTexLava);
|
||||||
|
Gfx_TextureCacheDelete(sLavaWavyTex);
|
||||||
|
Gfx_TextureCacheDelete(sLavaFloorModifiedTex);
|
||||||
|
}
|
||||||
|
|
||||||
void func_808C12C4(u8* arg1, s16 arg2) {
|
void func_808C12C4(u8* arg1, s16 arg2) {
|
||||||
if (arg2[arg1] != 0) {
|
if (arg2[arg1] != 0) {
|
||||||
sMaskTex8x16[arg2 / 2] = 1;
|
sMaskTex8x16[arg2 / 2] = 1;
|
||||||
@@ -86,12 +188,54 @@ void func_808C12C4(u8* arg1, s16 arg2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_808C1554(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
|
// Same as func_808C1554 but works with u32 values for RGBA32 raw textures
|
||||||
arg0 = GetResourceDataByNameHandlingMQ(arg0);
|
void func_808C1554_Raw(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
|
||||||
floorTex = ResourceGetDataByName(floorTex);
|
// Raw lava not registered, so abort the wave modification
|
||||||
|
if (sLavaWavyTexRaw == NULL || sLavaFloorModifiedTexRaw == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
u16* temp_s3 = SEGMENTED_TO_VIRTUAL(arg0);
|
u16 width = ResourceGetTexWidthByName(arg0);
|
||||||
u16* temp_s1 = SEGMENTED_TO_VIRTUAL(floorTex);
|
s32 size = ResourceGetTexHeightByName(arg0) * width;
|
||||||
|
|
||||||
|
u32* temp_s3 = sLavaWavyTexRaw;
|
||||||
|
u32* temp_s1 = sLavaFloorModifiedTexRaw;
|
||||||
|
s32 i;
|
||||||
|
s32 i2;
|
||||||
|
u32* sp54 = malloc(size * sizeof(u32)); // Match the size for lava floor tex
|
||||||
|
s32 temp;
|
||||||
|
s32 temp2;
|
||||||
|
|
||||||
|
// Multiplier is used to try to scale the wavy effect to match the scale of the HD texture
|
||||||
|
// Applying sqrt(multiplier) to arg3 is to control how many pixels move left/right for the selected row
|
||||||
|
// Applying to arg2 and M_PI help to space out the wave effect
|
||||||
|
// It's not perfect but close enough
|
||||||
|
u16 multiplier = width / LAVA_TEX_WIDTH;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i += width) {
|
||||||
|
temp = sinf((((i / width) + (s32)(((arg2 * multiplier) * 50.0f) / 100.0f)) & (width - 1)) * (M_PI / (16 * multiplier))) * (arg3 * sqrt(multiplier));
|
||||||
|
for (i2 = 0; i2 < width; i2++) {
|
||||||
|
sp54[i + ((temp + i2) & (width - 1))] = temp_s1[i + i2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < width; i++) {
|
||||||
|
temp = sinf(((i + (s32)(((arg2 * multiplier) * 80.0f) / 100.0f)) & (width - 1)) * (M_PI / (16 * multiplier))) * (arg3 * sqrt(multiplier));
|
||||||
|
temp *= width;
|
||||||
|
for (i2 = 0; i2 < size; i2 += width) {
|
||||||
|
temp2 = (temp + i2) & (size - 1);
|
||||||
|
temp_s3[i + temp2] = sp54[i + i2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(sp54);
|
||||||
|
Gfx_TextureCacheDelete(sLavaWavyTexRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modified to support CPU modified texture with the resource system
|
||||||
|
// Used for the original non-raw asset working with u16 values
|
||||||
|
void func_808C1554(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
|
||||||
|
u16* temp_s3 = sLavaWavyTex;
|
||||||
|
u16* temp_s1 = sLavaFloorModifiedTex;
|
||||||
s16 i;
|
s16 i;
|
||||||
s16 i2;
|
s16 i2;
|
||||||
u16 sp54[2048];
|
u16 sp54[2048];
|
||||||
@@ -112,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) {
|
||||||
@@ -187,27 +333,21 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
|
|||||||
Collider_SetJntSph(play, &this->collider, &this->actor, &sJntSphInit, this->items);
|
Collider_SetJntSph(play, &this->collider, &this->actor, &sJntSphInit, this->items);
|
||||||
|
|
||||||
if (Flags_GetClear(play, play->roomCtx.curRoom.num)) { // KD is dead
|
if (Flags_GetClear(play, play->roomCtx.curRoom.num)) { // KD is dead
|
||||||
u16* LavaFloorTex = ResourceGetDataByName(gDodongosCavernBossLavaFloorTex);
|
// SOH [General]
|
||||||
u16* LavaFloorRockTex = ResourceGetDataByName(sLavaFloorRockTex);
|
// Applying the "cooled off" lava rock CPU modified texture for re-visiting the scene
|
||||||
temp_s1_3 = SEGMENTED_TO_VIRTUAL(LavaFloorTex);
|
// is now handled by BossDodongo_RegisterBlendedLavaTextureUpdate below
|
||||||
temp_s2 = SEGMENTED_TO_VIRTUAL(LavaFloorRockTex);
|
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f,
|
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, -890.0f, -1523.76f,
|
||||||
-3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD);
|
-3304.0f, 0, 0, 0, WARP_DUNGEON_CHILD);
|
||||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, 0x6000, true);
|
Actor_Spawn(&play->actorCtx, play, ACTOR_BG_BREAKWALL, -890.0f, -1523.76f, -3304.0f, 0, 0, 0, 0x6000, true);
|
||||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -690.0f, -1523.76f, -3304.0f, 0, 0, 0, 0, true);
|
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, -690.0f, -1523.76f, -3304.0f, 0, 0, 0, 0, true);
|
||||||
|
|
||||||
for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
|
|
||||||
sMaskTexLava[i] = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
|
|
||||||
sMaskTexLava[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
|
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
|
||||||
|
|
||||||
|
// #region SOH [General]
|
||||||
|
// Init mask values for all KD blended textures
|
||||||
for (int i = 0; i < ARRAY_COUNT(sMaskTex8x16); i++) {
|
for (int i = 0; i < ARRAY_COUNT(sMaskTex8x16); i++) {
|
||||||
sMaskTex8x16[i] = 0;
|
sMaskTex8x16[i] = 0;
|
||||||
}
|
}
|
||||||
@@ -223,6 +363,8 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
|
|||||||
for (int i = 0; i < ARRAY_COUNT(sMaskTex32x16); i++) {
|
for (int i = 0; i < ARRAY_COUNT(sMaskTex32x16); i++) {
|
||||||
sMaskTex32x16[i] = 0;
|
sMaskTex32x16[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register all blended textures
|
||||||
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_015890, sMaskTex8x16, NULL);
|
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_015890, sMaskTex8x16, NULL);
|
||||||
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_017210, sMaskTex8x32, NULL);
|
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_017210, sMaskTex8x32, NULL);
|
||||||
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_015D90, sMaskTex16x16, NULL);
|
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_015D90, sMaskTex16x16, NULL);
|
||||||
@@ -234,10 +376,21 @@ 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);
|
||||||
|
|
||||||
// OTRTODO: This is causing OOB memory reads with HD assets
|
// Clear cache for masks
|
||||||
// commenting this out means the lava will stay lava even after beating king d
|
Gfx_TextureCacheDelete(sMaskTex8x16);
|
||||||
//
|
Gfx_TextureCacheDelete(sMaskTex8x32);
|
||||||
// Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, sLavaFloorRockTex);
|
Gfx_TextureCacheDelete(sMaskTex16x16);
|
||||||
|
Gfx_TextureCacheDelete(sMaskTex16x32);
|
||||||
|
Gfx_TextureCacheDelete(sMaskTex32x16);
|
||||||
|
|
||||||
|
BossDodongo_RegisterBlendedLavaTextureUpdate();
|
||||||
|
|
||||||
|
// Register alt listener to update the blended lava for the replacement texture based on alt path
|
||||||
|
if (!hasRegisteredBlendedHook) {
|
||||||
|
GameInteractor_RegisterOnAssetAltChange(BossDodongo_RegisterBlendedLavaTextureUpdate);
|
||||||
|
hasRegisteredBlendedHook = 1;
|
||||||
|
}
|
||||||
|
// #endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
void BossDodongo_Destroy(Actor* thisx, PlayState* play) {
|
void BossDodongo_Destroy(Actor* thisx, PlayState* play) {
|
||||||
@@ -1014,21 +1167,73 @@ void BossDodongo_Update(Actor* thisx, PlayState* play2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO The lave floor bubbles with an effect that modifies the texture. This needs to be recreated shader-side.
|
// The lava bubbles with a wavy effect as a CPU modified texture
|
||||||
//func_808C1554(gDodongosCavernBossLavaFloorTex, sLavaFloorLavaTex, this->unk_19E, this->unk_224);
|
// This has been done by maintaining copied/modified texture values in the actor code
|
||||||
|
// The "cooling off" effect for the lava is pre-applied to the lava texture before applying
|
||||||
|
// the wavy effect. Since this is two effects and closely related to the actor, I've opted
|
||||||
|
// to handle them here rather than as a shader effect.
|
||||||
|
//
|
||||||
|
// Apply the corresponding wavy effect based on the texture being raw or not
|
||||||
|
if (ResourceMgr_TexIsRaw(gDodongosCavernBossLavaFloorTex)) {
|
||||||
|
func_808C1554_Raw(gDodongosCavernBossLavaFloorTex, sLavaFloorLavaTex, this->unk_19E, this->unk_224);
|
||||||
|
} else {
|
||||||
|
func_808C1554(gDodongosCavernBossLavaFloorTex, sLavaFloorLavaTex, this->unk_19E, this->unk_224);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply the "cooling off" effect for the lava
|
||||||
if (this->unk_1C6 != 0) {
|
if (this->unk_1C6 != 0) {
|
||||||
u16* ptr1 = ResourceGetDataByName(sLavaFloorLavaTex);
|
// Similar to above, the cooling off effect is a CPU modified texture effect
|
||||||
u16* ptr2 = ResourceGetDataByName(sLavaFloorRockTex);
|
// Apply corresponding to the texture being raw or not
|
||||||
s16 i2;
|
if (ResourceMgr_TexIsRaw(sLavaFloorRockTex)) {
|
||||||
|
u32* ptr1 = sLavaFloorModifiedTexRaw;
|
||||||
|
u32* ptr2 = ResourceGetDataByName(sLavaFloorRockTex);
|
||||||
|
u16 width = ResourceGetTexWidthByName(sLavaFloorRockTex);
|
||||||
|
u16 height = ResourceGetTexHeightByName(sLavaFloorRockTex);
|
||||||
|
s16 i2;
|
||||||
|
|
||||||
for (i2 = 0; i2 < 20; i2++) {
|
// Get the scale based on the original texture size
|
||||||
s16 new_var = this->unk_1C2 & 0x7FF;
|
u16 widthScale = width / LAVA_TEX_WIDTH;
|
||||||
|
u16 heightScale = height / LAVA_TEX_HEIGHT;
|
||||||
|
u32 size = width * height;
|
||||||
|
|
||||||
sMaskTexLava[new_var] = 1;
|
for (i2 = 0; i2 < 20; i2++) {
|
||||||
this->unk_1C2 += 37;
|
s16 new_var = this->unk_1C2 & (LAVA_TEX_SIZE - 1);
|
||||||
|
|
||||||
|
// Raw lava must be registered, otherwise skip the effect for incompatible texture pack
|
||||||
|
// and instead set the mask to simulate the lava disappearing by turning black
|
||||||
|
if (sLavaFloorModifiedTexRaw != NULL) {
|
||||||
|
// Compute the index to a scaled position (scaling pseudo x,y as a 1D value)
|
||||||
|
s32 indexStart =
|
||||||
|
((new_var % LAVA_TEX_WIDTH) * widthScale) + ((new_var / LAVA_TEX_WIDTH) * width * heightScale);
|
||||||
|
|
||||||
|
// From the starting index, apply extra pixels right/down based on the scale
|
||||||
|
for (size_t j = 0; j < heightScale; j++) {
|
||||||
|
for (size_t i3 = 0; i3 < widthScale; i3++) {
|
||||||
|
s32 scaledIndex = (indexStart + i3 + (j * width)) & (size - 1);
|
||||||
|
ptr1[scaledIndex] = ptr2[scaledIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sMaskTexLava[new_var] = 1;
|
||||||
|
Gfx_TextureCacheDelete(sMaskTexLava);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->unk_1C2 += 37;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u16* ptr1 = sLavaFloorModifiedTex;
|
||||||
|
u16* ptr2 = ResourceGetDataByName(sLavaFloorRockTex);
|
||||||
|
s16 i2;
|
||||||
|
|
||||||
|
for (i2 = 0; i2 < 20; i2++) {
|
||||||
|
s16 new_var = this->unk_1C2 & 0x7FF;
|
||||||
|
|
||||||
|
ptr1[new_var] = ptr2[new_var];
|
||||||
|
this->unk_1C2 += 37;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Math_SmoothStepToF(&this->unk_224, 0.0f, 1.0f, 0.01f, 0.0f);
|
Math_SmoothStepToF(&this->unk_224, 0.0f, 1.0f, 0.01f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,6 +1288,10 @@ block_1:
|
|||||||
if (*dList != NULL) {
|
if (*dList != NULL) {
|
||||||
OPEN_DISPS(play->state.gfxCtx);
|
OPEN_DISPS(play->state.gfxCtx);
|
||||||
|
|
||||||
|
if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
MATRIX_TOMTX(*play->flexLimbOverrideMTX);
|
||||||
|
}
|
||||||
|
|
||||||
mtxScaleZ = 1.0f;
|
mtxScaleZ = 1.0f;
|
||||||
mtxScaleY = 1.0f;
|
mtxScaleY = 1.0f;
|
||||||
|
|
||||||
@@ -1103,11 +1312,20 @@ block_1:
|
|||||||
Matrix_RotateX(-(this->unk_25C[limbIndex] * 0.115f), MTXMODE_APPLY);
|
Matrix_RotateX(-(this->unk_25C[limbIndex] * 0.115f), MTXMODE_APPLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD);
|
||||||
|
} else {
|
||||||
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||||
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
}
|
||||||
|
|
||||||
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
||||||
Matrix_Pop();
|
Matrix_Pop();
|
||||||
|
|
||||||
|
if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
(*play->flexLimbOverrideMTX)++;
|
||||||
|
}
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
{ s32 pad; } // Required to match
|
{ s32 pad; } // Required to match
|
||||||
@@ -1151,10 +1369,6 @@ void BossDodongo_Draw(Actor* thisx, PlayState* play) {
|
|||||||
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16);
|
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->unk_1C6 != 0) {
|
|
||||||
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTexLava);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
|
|||||||
@@ -2015,12 +2015,26 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f
|
|||||||
Matrix_TranslateRotateZYX(pos, rot);
|
Matrix_TranslateRotateZYX(pos, rot);
|
||||||
|
|
||||||
if (*dList != NULL) {
|
if (*dList != NULL) {
|
||||||
|
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
MATRIX_TOMTX(*play->flexLimbOverrideMTX);
|
||||||
|
}
|
||||||
|
|
||||||
Matrix_Push();
|
Matrix_Push();
|
||||||
Matrix_Scale(this->eyeIrisScaleX, this->eyeIrisScaleY, 1.0f, MTXMODE_APPLY);
|
Matrix_Scale(this->eyeIrisScaleX, this->eyeIrisScaleY, 1.0f, MTXMODE_APPLY);
|
||||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD);
|
||||||
|
} else {
|
||||||
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||||
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
}
|
||||||
|
|
||||||
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
||||||
Matrix_Pop();
|
Matrix_Pop();
|
||||||
|
|
||||||
|
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
(*play->flexLimbOverrideMTX)++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doNotDrawLimb = true;
|
doNotDrawLimb = true;
|
||||||
@@ -2034,14 +2048,28 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f
|
|||||||
Matrix_TranslateRotateZYX(pos, rot);
|
Matrix_TranslateRotateZYX(pos, rot);
|
||||||
|
|
||||||
if (*dList != NULL) {
|
if (*dList != NULL) {
|
||||||
|
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
MATRIX_TOMTX(*play->flexLimbOverrideMTX);
|
||||||
|
}
|
||||||
|
|
||||||
Matrix_Push();
|
Matrix_Push();
|
||||||
Matrix_Scale(this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4],
|
Matrix_Scale(this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4],
|
||||||
this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4],
|
this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4],
|
||||||
this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], MTXMODE_APPLY);
|
this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], MTXMODE_APPLY);
|
||||||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD);
|
||||||
|
} else {
|
||||||
|
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx),
|
||||||
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
}
|
||||||
|
|
||||||
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
gSPDisplayList(POLY_OPA_DISP++, *dList);
|
||||||
Matrix_Pop();
|
Matrix_Pop();
|
||||||
|
|
||||||
|
if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) {
|
||||||
|
(*play->flexLimbOverrideMTX)++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doNotDrawLimb = true;
|
doNotDrawLimb = true;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1055,7 +1055,7 @@ void DoorWarp1_DrawBlueCrystal(DoorWarp1* this, PlayState* play) {
|
|||||||
gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (u8)this->crystalAlpha);
|
gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (u8)this->crystalAlpha);
|
||||||
gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (u8)this->crystalAlpha);
|
gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (u8)this->crystalAlpha);
|
||||||
|
|
||||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL,
|
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL,
|
||||||
&this->actor, POLY_XLU_DISP);
|
&this->actor, POLY_XLU_DISP);
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
@@ -1079,7 +1079,7 @@ void DoorWarp1_DrawPurpleCrystal(DoorWarp1* this, PlayState* play) {
|
|||||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->crystalAlpha);
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->crystalAlpha);
|
||||||
gDPSetEnvColor(POLY_XLU_DISP++, 150, 0, 100, (u8)this->crystalAlpha);
|
gDPSetEnvColor(POLY_XLU_DISP++, 150, 0, 100, (u8)this->crystalAlpha);
|
||||||
|
|
||||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL,
|
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL,
|
||||||
&this->actor, POLY_XLU_DISP);
|
&this->actor, POLY_XLU_DISP);
|
||||||
|
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
|
|||||||
@@ -768,7 +768,7 @@ void EnBili_Draw(Actor* thisx, PlayState* play) {
|
|||||||
gSPSegment(POLY_XLU_DISP++, 0x09, D_809C1700);
|
gSPSegment(POLY_XLU_DISP++, 0x09, D_809C1700);
|
||||||
}
|
}
|
||||||
|
|
||||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||||
EnBili_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
EnBili_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ static InitChainEntry sInitChain[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static UNK_TYPE sUnused;
|
static UNK_TYPE sUnused;
|
||||||
GetItemEntry sItem;
|
|
||||||
|
|
||||||
Gfx gSkullTreasureChestChestSideAndLidDL[116] = {0};
|
Gfx gSkullTreasureChestChestSideAndLidDL[116] = {0};
|
||||||
Gfx gGoldTreasureChestChestSideAndLidDL[116] = {0};
|
Gfx gGoldTreasureChestChestSideAndLidDL[116] = {0};
|
||||||
@@ -472,7 +471,7 @@ void EnBox_WaitOpen(EnBox* this, PlayState* play) {
|
|||||||
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
|
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
|
||||||
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
|
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
|
||||||
Player_IsFacingActor(&this->dyna.actor, 0x3000, play)) {
|
Player_IsFacingActor(&this->dyna.actor, 0x3000, play)) {
|
||||||
sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F);
|
GetItemEntry sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F);
|
||||||
GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE);
|
GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE);
|
||||||
|
|
||||||
// RANDOTODO treasure chest game rando
|
// RANDOTODO treasure chest game rando
|
||||||
@@ -628,7 +627,7 @@ void EnBox_Update(Actor* thisx, PlayState* play) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) ||
|
if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) ||
|
||||||
(IS_RANDO && ABS(sItem.getItemId) == RG_ICE_TRAP)) &&
|
(IS_RANDO && this->getItemEntry.getItemId == RG_ICE_TRAP)) &&
|
||||||
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) {
|
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) {
|
||||||
if (!CVarGetInteger("gAddTraps.enabled", 0)) {
|
if (!CVarGetInteger("gAddTraps.enabled", 0)) {
|
||||||
EnBox_SpawnIceSmoke(this, play);
|
EnBox_SpawnIceSmoke(this, play);
|
||||||
@@ -948,7 +947,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) {
|
|||||||
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
|
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
|
||||||
gSPSegment(POLY_OPA_DISP++, 0x08, EnBox_EmptyDList(play->state.gfxCtx));
|
gSPSegment(POLY_OPA_DISP++, 0x08, EnBox_EmptyDList(play->state.gfxCtx));
|
||||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL,
|
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL,
|
||||||
EnBox_PostLimbDraw, this, POLY_OPA_DISP);
|
EnBox_PostLimbDraw, this, POLY_OPA_DISP);
|
||||||
} else if (this->alpha != 0) {
|
} else if (this->alpha != 0) {
|
||||||
gDPPipeSync(POLY_XLU_DISP++);
|
gDPPipeSync(POLY_XLU_DISP++);
|
||||||
@@ -959,7 +958,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) {
|
|||||||
} else {
|
} else {
|
||||||
gSPSegment(POLY_XLU_DISP++, 0x08, func_809CA4A0(play->state.gfxCtx));
|
gSPSegment(POLY_XLU_DISP++, 0x08, func_809CA4A0(play->state.gfxCtx));
|
||||||
}
|
}
|
||||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL,
|
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL,
|
||||||
EnBox_PostLimbDraw, this, POLY_XLU_DISP);
|
EnBox_PostLimbDraw, this, POLY_XLU_DISP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -856,7 +856,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) {
|
|||||||
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
Gfx_SetupDL_25Opa(play->state.gfxCtx);
|
||||||
gDPSetEnvColor(POLY_OPA_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a);
|
gDPSetEnvColor(POLY_OPA_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a);
|
||||||
gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]);
|
gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]);
|
||||||
POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||||
EnBw_OverrideLimbDraw, NULL, this, POLY_OPA_DISP);
|
EnBw_OverrideLimbDraw, NULL, this, POLY_OPA_DISP);
|
||||||
} else {
|
} else {
|
||||||
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
Gfx_SetupDL_25Xlu(play->state.gfxCtx);
|
||||||
@@ -864,7 +864,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) {
|
|||||||
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 0, 0, 0, this->color1.a);
|
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 0, 0, 0, this->color1.a);
|
||||||
gDPSetEnvColor(POLY_XLU_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a);
|
gDPSetEnvColor(POLY_XLU_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a);
|
||||||
gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]);
|
gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]);
|
||||||
POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
|
POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime,
|
||||||
EnBw_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
EnBw_OverrideLimbDraw, NULL, this, POLY_XLU_DISP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user