diff --git a/.gitignore b/.gitignore index 442be304f..1df76208d 100644 --- a/.gitignore +++ b/.gitignore @@ -441,4 +441,5 @@ compile_commands.json CTestTestfile.cmake _deps */extract_assets_cmake* -/build* \ No newline at end of file +/build* +build.c diff --git a/BUILDING.md b/BUILDING.md index 0ab0d0d52..7606032ba 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -30,8 +30,8 @@ With the cmake build system you have two options for working on the project: #### Visual Studio To develop using Visual Studio you only need to use cmake to generate the solution file: ```powershell -# Generates Ship.sln at the root directory -& 'C:\Program Files\CMake\bin\cmake' -S . -G "Visual Studio 17 2022" -T v142 -A x64 +# Generates Ship.sln at `build/x64` +& 'C:\Program Files\CMake\bin\cmake' -S . -B "build/x64" -G "Visual Studio 17 2022" -T v142 -A x64 ``` #### Visual Studio Code or another editor @@ -53,7 +53,7 @@ cd "build/x64" ``` ## Linux -1. Requires `gcc, x11, curl, python3, sdl2, libpng, glew, ninja, cmake` +1. Requires `gcc >= 10, x11, curl, python3, sdl2 >= 2.0.22, libpng, glew >= 2.2, ninja, cmake, lld` **Important: For maximum performance make sure you have ninja build tools installed!** diff --git a/CMakeLists.txt b/CMakeLists.txt index 753c34523..fb31fc818 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,7 @@ add_custom_target( COMMAND ${CMAKE_COMMAND} -E rm -f oot.otr COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets_cmake2.py COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${CMAKE_BINARY_DIR}/soh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter COMMENT "Running asset extraction..." DEPENDS ZAPD diff --git a/Dockerfile b/Dockerfile index e44a08286..1c23dafa4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,8 @@ RUN curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz && \ cd SDL2-${SDL2VER} && \ ./configure --build=x86_64-linux-gnu && \ make -j$(nproc) && make install && \ - rm ../SDL2-${SDL2VER}.tar.gz + rm ../SDL2-${SDL2VER}.tar.gz && \ + cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ RUN \ ln -sf /proc/self/mounts /etc/mtab && \ diff --git a/libultraship/libultraship/CMakeLists.txt b/libultraship/libultraship/CMakeLists.txt index 8070d5f93..78331cbaf 100644 --- a/libultraship/libultraship/CMakeLists.txt +++ b/libultraship/libultraship/CMakeLists.txt @@ -456,6 +456,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang") "NDEBUG" ">" "ENABLE_OPENGL;" + "SPDLOG_ACTIVE_LEVEL=0;" ) endif() ################################################################################ diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp index c80dc4be5..3e81f56fa 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_dxgi.cpp @@ -239,8 +239,8 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par dxgi.current_height = (uint32_t)(l_param >> 16); break; case WM_DESTROY: - Ship::ExecuteHooks(); - exit(0); + PostQuitMessage(0); + break; case WM_PAINT: if (dxgi.in_paint) { dxgi.recursive_paint_detected = true; @@ -378,6 +378,8 @@ static void gfx_dxgi_main_loop(void (*run_one_game_iter)(void)) { TranslateMessage(&msg); DispatchMessage(&msg); } + + Ship::ExecuteHooks(); } static void gfx_dxgi_get_dimensions(uint32_t *width, uint32_t *height) { diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp index 8600aae1f..23cff4698 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp @@ -238,6 +238,8 @@ static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) { Ship::Switch::Exit(); #endif Ship::ExecuteHooks(); + + SDL_Quit(); } static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) { @@ -307,9 +309,8 @@ static void gfx_sdl_handle_events(void) { CVar_Save(); break; case SDL_QUIT: - Ship::ExecuteHooks(); - SDL_Quit(); // bandaid fix for linux window closing issue - exit(0); + is_running = false; + break; } } } diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index faf28ed5c..54700d65d 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -1559,7 +1559,7 @@ set(ALL_FILES ################################################################################ # Target ################################################################################ -add_executable(${PROJECT_NAME} ${ALL_FILES}) +add_executable(${PROJECT_NAME} ${ALL_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/Resource.rc) if (CMAKE_SYSTEM_NAME STREQUAL "Windows") use_props(${PROJECT_NAME} "${CMAKE_CONFIGURATION_TYPES}" "${DEFAULT_CXX_PROPS}") diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 08618e3d1..8be705674 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -374,6 +374,7 @@ typedef enum { FLAG_SCENE_TREASURE, FLAG_SCENE_CLEAR, FLAG_SCENE_COLLECTIBLE, + FLAG_COW_MILKED } FlagType; typedef struct { diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp index 18e5e8acf..6b12d3aac 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp @@ -165,6 +165,11 @@ void LocationTable_Init() { //Zoras River locationTable[ZR_OPEN_GROTTO_CHEST] = ItemLocation::Chest (0x3E, 0x09, "ZR Open Grotto Chest", ZR_OPEN_GROTTO_CHEST, RED_RUPEE, {Category::cZorasRiver, Category::cGrotto,}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); locationTable[ZR_MAGIC_BEAN_SALESMAN] = ItemLocation::Base (0x54, 0x16, "ZR Magic Bean Salesman", ZR_MAGIC_BEAN_SALESMAN, MAGIC_BEAN, {Category::cZorasRiver,}, SpoilerCollectionCheck::MagicBeans(0x54, 0x01), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[ZR_FROGS_ZELDAS_LULLABY] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Zelda's Lullaby", ZR_FROGS_ZELDAS_LULLABY, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[ZR_FROGS_EPONAS_SONG] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Epona's Song", ZR_FROGS_EPONAS_SONG, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[ZR_FROGS_SARIAS_SONG] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Saria's Song", ZR_FROGS_SARIAS_SONG, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[ZR_FROGS_SUNS_SONG] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Sun's Song", ZR_FROGS_SUNS_SONG, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); + locationTable[ZR_FROGS_SONG_OF_TIME] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs Song of Time", ZR_FROGS_SONG_OF_TIME, PURPLE_RUPEE, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); locationTable[ZR_FROGS_IN_THE_RAIN] = ItemLocation::Base (0x54, 0x3E, "ZR Frogs in the Rain", ZR_FROGS_IN_THE_RAIN, PIECE_OF_HEART, {Category::cZorasRiver,}, SpoilerCollectionCheck::EventChkInf(0xD6), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); locationTable[ZR_FROGS_OCARINA_GAME] = ItemLocation::Base (0x54, 0x76, "ZR Frogs Ocarina Game", ZR_FROGS_OCARINA_GAME, PIECE_OF_HEART, {Category::cZorasRiver, Category::cMinigame,}, SpoilerCollectionCheck::EventChkInf(0xD0), SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); locationTable[ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH] = ItemLocation::Collectable(0x54, 0x04, "ZR Near Open Grotto Freestanding PoH", ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, PIECE_OF_HEART, {Category::cZorasRiver,}, SpoilerCollectionCheckGroup::GROUP_ZORAS_RIVER); @@ -1302,6 +1307,11 @@ std::vector overworldLocations = { //Zoras River ZR_OPEN_GROTTO_CHEST, ZR_MAGIC_BEAN_SALESMAN, + ZR_FROGS_ZELDAS_LULLABY, + ZR_FROGS_EPONAS_SONG, + ZR_FROGS_SARIAS_SONG, + ZR_FROGS_SUNS_SONG, + ZR_FROGS_SONG_OF_TIME, ZR_FROGS_IN_THE_RAIN, ZR_FROGS_OCARINA_GAME, ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index b46ad395f..e128da21c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -729,6 +729,16 @@ void GenerateItemPool() { PlaceItemInLocation(WASTELAND_BOMBCHU_SALESMAN, BOMBCHU_10, false, true); } + if (ShuffleFrogSongRupees) { + AddItemToMainPool(PURPLE_RUPEE, 5); + } else { + PlaceItemInLocation(ZR_FROGS_ZELDAS_LULLABY, PURPLE_RUPEE, false, true); + PlaceItemInLocation(ZR_FROGS_EPONAS_SONG, PURPLE_RUPEE, false, true); + PlaceItemInLocation(ZR_FROGS_SARIAS_SONG, PURPLE_RUPEE, false, true); + PlaceItemInLocation(ZR_FROGS_SUNS_SONG, PURPLE_RUPEE, false, true); + PlaceItemInLocation(ZR_FROGS_SONG_OF_TIME, PURPLE_RUPEE, false, true); + } + if (ShuffleAdultTradeQuest) { AddItemToMainPool(POCKET_EGG); AddItemToMainPool(COJIRO); diff --git a/soh/soh/Enhancements/randomizer/3drando/keys.hpp b/soh/soh/Enhancements/randomizer/3drando/keys.hpp index 3e8d8f5cd..0ce91d6a4 100644 --- a/soh/soh/Enhancements/randomizer/3drando/keys.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/keys.hpp @@ -472,6 +472,11 @@ typedef enum { //ZORA'S_RIVER ZR_MAGIC_BEAN_SALESMAN, ZR_OPEN_GROTTO_CHEST, + ZR_FROGS_ZELDAS_LULLABY, + ZR_FROGS_EPONAS_SONG, + ZR_FROGS_SARIAS_SONG, + ZR_FROGS_SUNS_SONG, + ZR_FROGS_SONG_OF_TIME, ZR_FROGS_IN_THE_RAIN, ZR_FROGS_OCARINA_GAME, ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, diff --git a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp index bff5d7563..3b257e16a 100644 --- a/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/location_access/locacc_zoras_domain.cpp @@ -31,6 +31,21 @@ void AreaTable_Init_ZorasDomain() { LocationAccess(ZR_FROGS_IN_THE_RAIN, {[]{return IsChild && CanPlay(SongOfStorms);}, /*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SongOfStorms;}}), + LocationAccess(ZR_FROGS_ZELDAS_LULLABY, {[]{return IsChild && CanPlay(ZeldasLullaby);}, + /*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || + ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && ZeldasLullaby;}}), + LocationAccess(ZR_FROGS_EPONAS_SONG, {[]{return IsChild && CanPlay(EponasSong);}, + /*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || + ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && EponasSong;}}), + LocationAccess(ZR_FROGS_SARIAS_SONG, {[]{return IsChild && CanPlay(SariasSong);}, + /*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || + ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SariasSong;}}), + LocationAccess(ZR_FROGS_SUNS_SONG, {[]{return IsChild && CanPlay(SunsSong);}, + /*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || + ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SunsSong;}}), + LocationAccess(ZR_FROGS_SONG_OF_TIME, {[]{return IsChild && CanPlay(SongOfTime);}, + /*Glitched*/[]{return (CanDoGlitch(GlitchType::OutdoorBombOI, GlitchDifficulty::ADVANCED) || ((Bugs || Fish) && CanShield && CanDoGlitch(GlitchType::QPA, GlitchDifficulty::ADVANCED)) || + ((Bugs || Fish) && CanShield && HasBombchus && CanDoGlitch(GlitchType::ActionSwap, GlitchDifficulty::ADVANCED))) && IsChild && SongOfTime;}}), LocationAccess(ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH, {[]{return IsChild || CanUse(HOVER_BOOTS) || (IsAdult && LogicZoraRiverLower);}}), LocationAccess(ZR_NEAR_DOMAIN_FREESTANDING_POH, {[]{return IsChild || CanUse(HOVER_BOOTS) || (IsAdult && LogicZoraRiverUpper);}}), LocationAccess(ZR_GS_LADDER, {[]{return IsChild && AtNight && CanChildAttack && CanGetNightTimeGS;}}), diff --git a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp index edca583e5..0e11fecbd 100644 --- a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.cpp @@ -385,6 +385,13 @@ string_view merchantsHintsDesc = "These hints will make Medigoron and the "The Clearer Hints setting will affect how they\n" // "refer to the item."; // /*------------------------------ // +| SHUFFLE FROG SONG RUPEES | // +------------------------------*/ // +string_view frogSongRupeesDesc = "Enabling this adds 5 Purple Rupees to the item\n" // + "pool and shuffles the rewards from playing Zelda's\n" + "Lullaby, Epona's Song, Saria's Song, Sun's Song,\n" + "and Song of Time to the frogs in Zora's River.\n";// +/*------------------------------ // | SHUFFLE ADULT TRADE | // ------------------------------*/ // string_view adultTradeDesc = "Enabling this adds all of the adult trade quest\n"// diff --git a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp index 396fdd24c..917316ba1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/setting_descriptions.hpp @@ -126,6 +126,8 @@ extern string_view magicBeansDesc; extern string_view merchantsDesc; extern string_view merchantsHintsDesc; +extern string_view frogSongRupeesDesc; + extern string_view adultTradeDesc; extern string_view chestMinigameDesc; diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index c2e01b449..e6a4f1385 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -166,6 +166,7 @@ namespace Settings { Option ShuffleGerudoToken = Option::Bool("Shuffle Gerudo Card", {"Off", "On"}, {gerudoTokenDesc}); Option ShuffleMagicBeans = Option::Bool("Shuffle Magic Beans", {"Off", "On"}, {magicBeansDesc}); Option ShuffleMerchants = Option::U8 ("Shuffle Merchants", {"Off", "On (No Hints)", "On (With Hints)"}, {merchantsDesc, merchantsHintsDesc}); + Option ShuffleFrogSongRupees = Option::Bool("Shuffle Frog Song Rupees",{"Off", "On"}, {frogSongRupeesDesc}); Option ShuffleAdultTradeQuest = Option::Bool("Shuffle Adult Trade", {"Off", "On"}, {adultTradeDesc}); Option ShuffleChestMinigame = Option::U8 ("Shuffle Chest Minigame", {"Off", "On (Separate)", "On (Pack)"}, {chestMinigameDesc}); std::vector