mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-23 06:02:08 -05:00
Merge branch 'rando-next' of https://github.com/HarbourMasters/Shipwright into keysanity
This commit is contained in:
commit
8b59466ce5
3
.gitignore
vendored
3
.gitignore
vendored
@ -441,4 +441,5 @@ compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
*/extract_assets_cmake*
|
||||
/build*
|
||||
/build*
|
||||
build.c
|
||||
|
@ -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!**
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 && \
|
||||
|
@ -456,6 +456,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
|
||||
"NDEBUG"
|
||||
">"
|
||||
"ENABLE_OPENGL;"
|
||||
"SPDLOG_ACTIVE_LEVEL=0;"
|
||||
)
|
||||
endif()
|
||||
################################################################################
|
||||
|
@ -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<Ship::ExitGame>();
|
||||
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<Ship::ExitGame>();
|
||||
}
|
||||
|
||||
static void gfx_dxgi_get_dimensions(uint32_t *width, uint32_t *height) {
|
||||
|
@ -238,6 +238,8 @@ static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) {
|
||||
Ship::Switch::Exit();
|
||||
#endif
|
||||
Ship::ExecuteHooks<Ship::ExitGame>();
|
||||
|
||||
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<Ship::ExitGame>();
|
||||
SDL_Quit(); // bandaid fix for linux window closing issue
|
||||
exit(0);
|
||||
is_running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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}")
|
||||
|
@ -374,6 +374,7 @@ typedef enum {
|
||||
FLAG_SCENE_TREASURE,
|
||||
FLAG_SCENE_CLEAR,
|
||||
FLAG_SCENE_COLLECTIBLE,
|
||||
FLAG_COW_MILKED
|
||||
} FlagType;
|
||||
|
||||
typedef struct {
|
||||
|
@ -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<uint32_t> 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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;}}),
|
||||
|
@ -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"//
|
||||
|
@ -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;
|
||||
|
@ -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<Option *> shuffleOptions = {
|
||||
@ -183,6 +184,7 @@ namespace Settings {
|
||||
&ShuffleGerudoToken,
|
||||
&ShuffleMagicBeans,
|
||||
&ShuffleMerchants,
|
||||
&ShuffleFrogSongRupees,
|
||||
&ShuffleAdultTradeQuest,
|
||||
&ShuffleChestMinigame,
|
||||
};
|
||||
@ -1263,6 +1265,7 @@ namespace Settings {
|
||||
ctx.shuffleGerudoToken = (ShuffleGerudoToken) ? 1 : 0;
|
||||
ctx.shuffleMagicBeans = (ShuffleMagicBeans) ? 1 : 0;
|
||||
ctx.shuffleMerchants = ShuffleMerchants.Value<uint8_t>();
|
||||
ctx.shuffleFrogSongRupees= (ShuffleFrogSongRupees) ? 1 : 0;
|
||||
ctx.shuffleAdultTradeQuest = (ShuffleAdultTradeQuest) ? 1 : 0;
|
||||
ctx.shuffleChestMinigame = ShuffleChestMinigame.Value<uint8_t>();
|
||||
|
||||
@ -1724,6 +1727,21 @@ namespace Settings {
|
||||
IncludeAndHide({WASTELAND_BOMBCHU_SALESMAN});
|
||||
}
|
||||
|
||||
//Force include frog song rupees if they're not shuffled
|
||||
if (ShuffleFrogSongRupees) {
|
||||
Unhide({ZR_FROGS_ZELDAS_LULLABY});
|
||||
Unhide({ZR_FROGS_EPONAS_SONG});
|
||||
Unhide({ZR_FROGS_SARIAS_SONG});
|
||||
Unhide({ZR_FROGS_SUNS_SONG});
|
||||
Unhide({ZR_FROGS_SONG_OF_TIME});
|
||||
} else {
|
||||
IncludeAndHide({ZR_FROGS_ZELDAS_LULLABY});
|
||||
IncludeAndHide({ZR_FROGS_EPONAS_SONG});
|
||||
IncludeAndHide({ZR_FROGS_SARIAS_SONG});
|
||||
IncludeAndHide({ZR_FROGS_SUNS_SONG});
|
||||
IncludeAndHide({ZR_FROGS_SONG_OF_TIME});
|
||||
}
|
||||
|
||||
//Force include adult trade quest if Shuffle Adult Trade Quest is off
|
||||
std::vector<uint32_t> adultTradeLocations = {KAK_TRADE_POCKET_CUCCO, LW_TRADE_COJIRO, KAK_TRADE_ODD_MUSHROOM, LW_TRADE_ODD_POTION, GV_TRADE_SAW, DMT_TRADE_BROKEN_SWORD, ZD_TRADE_PRESCRIPTION, LH_TRADE_FROG, DMT_TRADE_EYEDROPS};
|
||||
if (ShuffleAdultTradeQuest) {
|
||||
@ -2261,6 +2279,7 @@ namespace Settings {
|
||||
&ShuffleCows,
|
||||
&ShuffleMagicBeans,
|
||||
&ShuffleMerchants,
|
||||
&ShuffleFrogSongRupees,
|
||||
&ShuffleAdultTradeQuest,
|
||||
&GossipStoneHints,
|
||||
};
|
||||
@ -2516,6 +2535,7 @@ namespace Settings {
|
||||
SkipChildStealth.SetSelectedIndex(cvarSettings[RSK_SKIP_CHILD_STEALTH]);
|
||||
|
||||
ShuffleGerudoToken.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]);
|
||||
ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]);
|
||||
|
||||
// the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina"
|
||||
StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]);
|
||||
|
@ -403,6 +403,7 @@ typedef struct {
|
||||
uint8_t shuffleGerudoToken;
|
||||
uint8_t shuffleMagicBeans;
|
||||
uint8_t shuffleMerchants;
|
||||
uint8_t shuffleFrogSongRupees;
|
||||
uint8_t shuffleAdultTradeQuest;
|
||||
uint8_t shuffleChestMinigame;
|
||||
|
||||
@ -904,6 +905,7 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
|
||||
extern Option ShuffleGerudoToken;
|
||||
extern Option ShuffleMagicBeans;
|
||||
extern Option ShuffleMerchants;
|
||||
extern Option ShuffleFrogSongRupees;
|
||||
extern Option ShuffleAdultTradeQuest;
|
||||
extern Option ShuffleChestMinigame;
|
||||
|
||||
|
@ -183,6 +183,11 @@ std::unordered_map<std::string, RandomizerCheck> SpoilerfileCheckNameToEnum = {
|
||||
{ "DMC Deku Scrub Grotto Center", RC_DMC_DEKU_SCRUB_GROTTO_CENTER },
|
||||
{ "ZR Open Grotto Chest", RC_ZR_OPEN_GROTTO_CHEST },
|
||||
{ "ZR Magic Bean Salesman", RC_ZR_MAGIC_BEAN_SALESMAN },
|
||||
{ "ZR Frogs Zelda's Lullaby", RC_ZR_FROGS_ZELDAS_LULLABY },
|
||||
{ "ZR Frogs Epona's Song", RC_ZR_FROGS_EPONAS_SONG },
|
||||
{ "ZR Frogs Saria's Song", RC_ZR_FROGS_SARIAS_SONG },
|
||||
{ "ZR Frogs Sun's Song", RC_ZR_FROGS_SUNS_SONG },
|
||||
{ "ZR Frogs Song of Time", RC_ZR_FROGS_SONG_OF_TIME },
|
||||
{ "ZR Frogs in the Rain", RC_ZR_FROGS_IN_THE_RAIN },
|
||||
{ "ZR Frogs Ocarina Game", RC_ZR_FROGS_OCARINA_GAME },
|
||||
{ "ZR Near Open Grotto Freestanding PoH", RC_ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH },
|
||||
@ -3525,6 +3530,7 @@ void GenerateRandomizerImgui() {
|
||||
cvarSettings[RSK_SHUFFLE_WEIRD_EGG] = ((CVar_GetS32("gRandomizeSkipChildZelda", 0) == 0) && CVar_GetS32("gRandomizeShuffleWeirdEgg", 0));
|
||||
|
||||
cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD] = CVar_GetS32("gRandomizeShuffleGerudoToken", 0);
|
||||
cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES] = CVar_GetS32("gRandomizeShuffleFrogSongRupees", 0);
|
||||
cvarSettings[RSK_ITEM_POOL] = CVar_GetS32("gRandomizeItemPool", 1);
|
||||
cvarSettings[RSK_ICE_TRAPS] = CVar_GetS32("gRandomizeIceTraps", 1);
|
||||
cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVar_GetS32("gRandomizeGossipStoneHints", 1);
|
||||
@ -3617,6 +3623,7 @@ void DrawRandoEditor(bool& open) {
|
||||
const char* randoShuffleGerudoToken[2] = { "Off", "On" };
|
||||
const char* randoShuffleMagicBeans[2] = { "Off", "On" };
|
||||
const char* randoShuffleMerchants[3] = { "Off", "On (no hints)", "On (with hints)" };
|
||||
const char* randoShuffleFrogSongRupees[2] = { "Off", "On" };
|
||||
const char* randoShuffleAdultTrade[2] = { "Off", "On" };
|
||||
|
||||
// Shuffle Dungeon Items Settings
|
||||
@ -4036,9 +4043,8 @@ void DrawRandoEditor(bool& open) {
|
||||
PaddedSeparator();
|
||||
|
||||
// Shuffle Cows
|
||||
ImGui::Text(Settings::ShuffleCows.GetName().c_str());
|
||||
SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows");
|
||||
InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them.");
|
||||
SohImGui::EnhancementCombobox("gRandomizeShuffleCows", randoShuffleCows, 2, 0);
|
||||
PaddedSeparator();
|
||||
|
||||
if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) {
|
||||
@ -4102,6 +4108,17 @@ void DrawRandoEditor(bool& open) {
|
||||
"The Gerudo Card is required to enter the Gerudo Training Grounds, opening "
|
||||
"the gate to Haunted Wasteland and the Horseback Archery minigame."
|
||||
);
|
||||
PaddedSeparator();
|
||||
|
||||
// Shuffle Frog Song Rupees
|
||||
SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees");
|
||||
InsertHelpHoverText(
|
||||
"Shuffles 5 Purple Rupees into to the item pool, and allows\n"
|
||||
"you to earn items by playing songs at the Frog Choir.\n"
|
||||
"\n"
|
||||
"This setting does not effect the item earned from playing\n"
|
||||
"the Song of Storms and the frog song minigame."
|
||||
);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
|
@ -978,6 +978,7 @@ typedef enum {
|
||||
RSK_SHUFFLE_COWS,
|
||||
RSK_SHUFFLE_WEIRD_EGG,
|
||||
RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD,
|
||||
RSK_SHUFFLE_FROG_SONG_RUPEES,
|
||||
RSK_ITEM_POOL,
|
||||
RSK_ICE_TRAPS,
|
||||
RSK_GOSSIP_STONE_HINTS,
|
||||
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
static struct {
|
||||
std::thread thread;
|
||||
std::condition_variable cv_to_thread, cv_from_thread;
|
||||
std::mutex mutex;
|
||||
bool initialized;
|
||||
bool running;
|
||||
bool processing;
|
||||
} audio;
|
||||
|
@ -83,11 +83,73 @@ extern "C" void ResourceMgr_CacheDirectory(const char* resName);
|
||||
extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path);
|
||||
std::unordered_map<std::string, ExtensionEntry> ExtensionCache;
|
||||
|
||||
void OTRAudio_Thread() {
|
||||
while (audio.running) {
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
while (!audio.processing && audio.running) {
|
||||
audio.cv_to_thread.wait(Lock);
|
||||
}
|
||||
|
||||
if (!audio.running) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
//AudioMgr_ThreadEntry(&gAudioMgr);
|
||||
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
|
||||
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
|
||||
//#define SAMPLES_HIGH 560
|
||||
//#define SAMPLES_LOW 528
|
||||
// PAL values
|
||||
//#define SAMPLES_HIGH 656
|
||||
//#define SAMPLES_LOW 624
|
||||
|
||||
// 44KHZ values
|
||||
#define SAMPLES_HIGH 752
|
||||
#define SAMPLES_LOW 720
|
||||
|
||||
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
|
||||
#define NUM_AUDIO_CHANNELS 2
|
||||
|
||||
int samples_left = AudioPlayer_Buffered();
|
||||
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
|
||||
|
||||
// 3 is the maximum authentic frame divisor.
|
||||
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
|
||||
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
|
||||
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
|
||||
}
|
||||
|
||||
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
|
||||
|
||||
audio.processing = false;
|
||||
audio.cv_from_thread.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
// C->C++ Bridge
|
||||
extern "C" void OTRAudio_Init()
|
||||
{
|
||||
// Precache all our samples, sequences, etc...
|
||||
ResourceMgr_CacheDirectory("audio");
|
||||
|
||||
if (!audio.running) {
|
||||
audio.running = true;
|
||||
audio.thread = std::thread(OTRAudio_Thread);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void OTRAudio_Exit() {
|
||||
// Tell the audio thread to stop
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
audio.running = false;
|
||||
}
|
||||
audio.cv_to_thread.notify_all();
|
||||
|
||||
// Wait until the audio thread quit
|
||||
audio.thread.join();
|
||||
}
|
||||
|
||||
extern "C" void OTRExtScanner() {
|
||||
@ -128,6 +190,10 @@ extern "C" void InitOTR() {
|
||||
OTRExtScanner();
|
||||
}
|
||||
|
||||
extern "C" void DeinitOTR() {
|
||||
OTRAudio_Exit();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C" uint64_t GetFrequency() {
|
||||
LARGE_INTEGER nFreq;
|
||||
@ -227,56 +293,10 @@ extern "C" void Graph_StartFrame() {
|
||||
|
||||
// C->C++ Bridge
|
||||
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
||||
#ifndef __SWITCH__
|
||||
if (!audio.initialized) {
|
||||
audio.initialized = true;
|
||||
std::thread([]() {
|
||||
for (;;) {
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
while (!audio.processing) {
|
||||
audio.cv_to_thread.wait(Lock);
|
||||
}
|
||||
}
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
//AudioMgr_ThreadEntry(&gAudioMgr);
|
||||
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
|
||||
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
|
||||
//#define SAMPLES_HIGH 560
|
||||
//#define SAMPLES_LOW 528
|
||||
// PAL values
|
||||
//#define SAMPLES_HIGH 656
|
||||
//#define SAMPLES_LOW 624
|
||||
|
||||
// 44KHZ values
|
||||
#define SAMPLES_HIGH 752
|
||||
#define SAMPLES_LOW 720
|
||||
|
||||
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
|
||||
#define NUM_AUDIO_CHANNELS 2
|
||||
|
||||
int samples_left = AudioPlayer_Buffered();
|
||||
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
|
||||
|
||||
// 3 is the maximum authentic frame divisor.
|
||||
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
|
||||
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
|
||||
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
|
||||
}
|
||||
|
||||
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
|
||||
|
||||
audio.processing = false;
|
||||
audio.cv_from_thread.notify_one();
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
audio.processing = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
audio.cv_to_thread.notify_one();
|
||||
std::vector<std::unordered_map<Mtx*, MtxF>> mtx_replacements;
|
||||
@ -319,14 +339,12 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
||||
last_fps = fps;
|
||||
last_update_rate = R_UPDATE_RATE;
|
||||
|
||||
#ifndef __SWITCH__
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
while (audio.processing) {
|
||||
audio.cv_from_thread.wait(Lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// OTRTODO: FIGURE OUT END FRAME POINT
|
||||
/* if (OTRGlobals::Instance->context->GetWindow()->lastScancode != -1)
|
||||
|
@ -481,22 +481,6 @@ static void RunFrame()
|
||||
uint64_t ticksA, ticksB;
|
||||
ticksA = GetPerfCounter();
|
||||
|
||||
#ifdef __SWITCH__
|
||||
#define SAMPLES_HIGH 752
|
||||
#define SAMPLES_LOW 720
|
||||
|
||||
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
|
||||
#define NUM_AUDIO_CHANNELS 2
|
||||
int samples_left = AudioPlayer_Buffered();
|
||||
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
|
||||
|
||||
s16 audio_buffer[SAMPLES_HIGH * NUM_AUDIO_CHANNELS * 3];
|
||||
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
|
||||
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
|
||||
}
|
||||
|
||||
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
|
||||
#endif
|
||||
Graph_StartFrame();
|
||||
|
||||
// TODO: Workaround for rumble being too long. Implement os thread functions.
|
||||
|
@ -36,12 +36,14 @@ void Main_LogSystemHeap(void) {
|
||||
osSyncPrintf(VT_RST);
|
||||
}
|
||||
|
||||
void main(int argc, char** argv)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
GameConsole_Init();
|
||||
InitOTR();
|
||||
BootCommands_Init();
|
||||
Main(0);
|
||||
DeinitOTR();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Main(void* arg) {
|
||||
|
@ -18,9 +18,8 @@ void func_809E0070(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
void func_809DF494(EnCow* this, GlobalContext* globalCtx);
|
||||
void func_809DF6BC(EnCow* this, GlobalContext* globalCtx);
|
||||
struct CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx);
|
||||
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx);
|
||||
void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx);
|
||||
GetItemID EnCow_GetRandomizerItem(EnCow* this, GlobalContext* globalCtx);
|
||||
void func_809DF778(EnCow* this, GlobalContext* globalCtx);
|
||||
void func_809DF7D8(EnCow* this, GlobalContext* globalCtx);
|
||||
void func_809DF870(EnCow* this, GlobalContext* globalCtx);
|
||||
@ -216,12 +215,7 @@ void func_809DF730(EnCow* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
struct CowInfo {
|
||||
int cowId;
|
||||
RandomizerCheck randomizerCheck;
|
||||
};
|
||||
|
||||
struct CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) {
|
||||
CowInfo EnCow_GetInfo(EnCow* this, GlobalContext* globalCtx) {
|
||||
struct CowInfo cowInfo;
|
||||
|
||||
cowInfo.cowId = -1;
|
||||
@ -294,21 +288,10 @@ void EnCow_MoveForRandomizer(EnCow* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
|
||||
void EnCow_SetCowMilked(EnCow* this, GlobalContext* globalCtx) {
|
||||
struct CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
|
||||
gSaveContext.cowsMilked[cowInfo.cowId] = 1;
|
||||
}
|
||||
|
||||
GetItemID EnCow_GetRandomizerItem(EnCow* this, GlobalContext* globalCtx) {
|
||||
GetItemID itemId = ITEM_NONE;
|
||||
struct CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
|
||||
|
||||
if (!gSaveContext.cowsMilked[cowInfo.cowId]) {
|
||||
itemId = Randomizer_GetItemIdFromKnownCheck(cowInfo.randomizerCheck, GI_MILK);
|
||||
} else if (Inventory_HasEmptyBottle()) {
|
||||
itemId = GI_MILK;
|
||||
}
|
||||
|
||||
return itemId;
|
||||
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
|
||||
Player* player = GET_PLAYER(globalCtx);
|
||||
player->pendingFlag.flagID = cowInfo.cowId;
|
||||
player->pendingFlag.flagType = FLAG_COW_MILKED;
|
||||
}
|
||||
|
||||
void func_809DF778(EnCow* this, GlobalContext* globalCtx) {
|
||||
@ -316,16 +299,7 @@ void func_809DF778(EnCow* this, GlobalContext* globalCtx) {
|
||||
this->actor.parent = NULL;
|
||||
this->actionFunc = func_809DF730;
|
||||
} else {
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
GetItemID itemId = EnCow_GetRandomizerItem(this, globalCtx);
|
||||
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 100.0f);
|
||||
EnCow_SetCowMilked(this, globalCtx);
|
||||
if (itemId == GI_ICE_TRAP) {
|
||||
Message_StartTextbox(globalCtx, 0xF8, &this->actor);
|
||||
}
|
||||
} else {
|
||||
func_8002F434(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f);
|
||||
}
|
||||
func_8002F434(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,15 +308,13 @@ void func_809DF7D8(EnCow* this, GlobalContext* globalCtx) {
|
||||
this->actor.flags &= ~ACTOR_FLAG_16;
|
||||
Message_CloseTextbox(globalCtx);
|
||||
this->actionFunc = func_809DF778;
|
||||
if (!gSaveContext.n64ddFlag) {
|
||||
func_8002F434(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f);
|
||||
}
|
||||
func_8002F434(&this->actor, globalCtx, GI_MILK, 10000.0f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void func_809DF870(EnCow* this, GlobalContext* globalCtx) {
|
||||
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) {
|
||||
if (Inventory_HasEmptyBottle() || (gSaveContext.n64ddFlag && EnCow_GetRandomizerItem(this, globalCtx) != ITEM_NONE)) {
|
||||
if (Inventory_HasEmptyBottle()) {
|
||||
Message_ContinueTextbox(globalCtx, 0x2007);
|
||||
this->actionFunc = func_809DF7D8;
|
||||
} else {
|
||||
@ -363,6 +335,23 @@ void func_809DF8FC(EnCow* this, GlobalContext* globalCtx) {
|
||||
func_809DF494(this, globalCtx);
|
||||
}
|
||||
|
||||
bool EnCow_HasBeenMilked(EnCow* this, GlobalContext* globalCtx) {
|
||||
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
|
||||
return gSaveContext.cowsMilked[cowInfo.cowId];
|
||||
}
|
||||
|
||||
void EnCow_GivePlayerRandomizedItem(EnCow* this, GlobalContext* globalCtx) {
|
||||
if (!EnCow_HasBeenMilked(this, globalCtx)) {
|
||||
CowInfo cowInfo = EnCow_GetInfo(this, globalCtx);
|
||||
GetItemID itemId = Randomizer_GetItemIdFromKnownCheck(cowInfo.randomizerCheck, GI_MILK);
|
||||
func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 100.0f);
|
||||
} else {
|
||||
// once we've gotten the rando reward from the cow,
|
||||
// return them to the their default action function
|
||||
this->actionFunc = func_809DF96C;
|
||||
}
|
||||
}
|
||||
|
||||
void func_809DF96C(EnCow* this, GlobalContext* globalCtx) {
|
||||
if ((globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_00) || (globalCtx->msgCtx.ocarinaMode == OCARINA_MODE_04)) {
|
||||
if (DREG(53) != 0) {
|
||||
@ -373,6 +362,19 @@ void func_809DF96C(EnCow* this, GlobalContext* globalCtx) {
|
||||
if ((this->actor.xzDistToPlayer < 150.0f) &&
|
||||
(ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) < 0x61A8)) {
|
||||
DREG(53) = 0;
|
||||
// when randomized with cowsanity, if we haven't gotten the
|
||||
// reward from this cow yet, give that, otherwise use the
|
||||
// vanilla cow behavior
|
||||
if (gSaveContext.n64ddFlag &&
|
||||
Randomizer_GetSettingValue(RSK_SHUFFLE_COWS) &&
|
||||
!EnCow_HasBeenMilked(this, globalCtx)) {
|
||||
EnCow_SetCowMilked(this, globalCtx);
|
||||
// setting the ocarina mode here prevents intermittent issues
|
||||
// with the item get not triggering until walking away
|
||||
globalCtx->msgCtx.ocarinaMode = OCARINA_MODE_00;
|
||||
this->actionFunc = EnCow_GivePlayerRandomizedItem;
|
||||
return;
|
||||
}
|
||||
this->actionFunc = func_809DF8FC;
|
||||
this->actor.flags |= ACTOR_FLAG_16;
|
||||
func_8002F2CC(&this->actor, globalCtx, 170.0f);
|
||||
|
@ -21,4 +21,9 @@ typedef struct EnCow {
|
||||
/* 0x027C */ EnCowActionFunc actionFunc;
|
||||
} EnCow; // size = 0x0280
|
||||
|
||||
typedef struct CowInfo {
|
||||
int cowId;
|
||||
RandomizerCheck randomizerCheck;
|
||||
} CowInfo;
|
||||
|
||||
#endif
|
||||
|
@ -43,6 +43,7 @@ void EnFr_OcarinaMistake(EnFr* this, GlobalContext* globalCtx);
|
||||
void EnFr_SetupReward(EnFr* this, GlobalContext* globalCtx, u8 unkCondition);
|
||||
void EnFr_PrintTextBox(EnFr* this, GlobalContext* globalCtx);
|
||||
void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx);
|
||||
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex);
|
||||
void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx);
|
||||
|
||||
// Deactivate
|
||||
@ -920,6 +921,23 @@ void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
}
|
||||
|
||||
RandomizerCheck EnFr_RandomizerCheckFromSongIndex(u16 songIndex) {
|
||||
switch (songIndex) {
|
||||
case FROG_ZL:
|
||||
return RC_ZR_FROGS_ZELDAS_LULLABY;
|
||||
case FROG_EPONA:
|
||||
return RC_ZR_FROGS_EPONAS_SONG;
|
||||
case FROG_SARIA:
|
||||
return RC_ZR_FROGS_SARIAS_SONG;
|
||||
case FROG_SUNS:
|
||||
return RC_ZR_FROGS_SUNS_SONG;
|
||||
case FROG_SOT:
|
||||
return RC_ZR_FROGS_SONG_OF_TIME;
|
||||
default:
|
||||
return RC_UNKNOWN_CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) {
|
||||
u16 songIndex;
|
||||
|
||||
@ -930,7 +948,11 @@ void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) {
|
||||
if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) {
|
||||
if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) {
|
||||
gSaveContext.eventChkInf[13] |= sSongIndex[songIndex];
|
||||
this->reward = GI_RUPEE_PURPLE;
|
||||
if (!gSaveContext.n64ddFlag) {
|
||||
this->reward = GI_RUPEE_PURPLE;
|
||||
} else {
|
||||
this->reward = Randomizer_GetItemIdFromKnownCheck(EnFr_RandomizerCheckFromSongIndex(songIndex), GI_RUPEE_PURPLE);
|
||||
}
|
||||
} else {
|
||||
this->reward = GI_RUPEE_BLUE;
|
||||
}
|
||||
@ -1016,7 +1038,7 @@ void EnFr_GiveReward(EnFr* this, GlobalContext* globalCtx) {
|
||||
}
|
||||
|
||||
void EnFr_SetIdle(EnFr* this, GlobalContext* globalCtx) {
|
||||
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
|
||||
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx) || (gSaveContext.n64ddFlag && this->reward == GI_ICE_TRAP)) {
|
||||
this->actionFunc = EnFr_Idle;
|
||||
}
|
||||
}
|
||||
|
@ -6262,6 +6262,9 @@ void Player_SetPendingFlag(Player* this, GlobalContext* globalCtx) {
|
||||
case FLAG_SCENE_TREASURE:
|
||||
Flags_SetTreasure(globalCtx, this->pendingFlag.flagID);
|
||||
break;
|
||||
case FLAG_COW_MILKED:
|
||||
gSaveContext.cowsMilked[this->pendingFlag.flagID] = 1;
|
||||
break;
|
||||
case FLAG_NONE:
|
||||
default:
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user