diff options
| author | Glought <Glought@users.noreply.github.com> | 2025-11-20 10:31:41 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-20 13:31:41 -0500 |
| commit | ddee25d7ece8a1cd87cb33c321dac202a4daa4e3 (patch) | |
| tree | bf6dc9cddabeade3d961770c23f462db7c5fe783 | |
| parent | 02d9170d141c9f9f8e6a14568efc7678f0d87236 (diff) | |
[Audio Editor] Port Audio Options from SoH Audio Editor (#1325)
* Ported Audio Options from SoH Audio Editor
*Moved "Mute Low HP Alarm" to Audio Editor -> Audio Options
Changed Cvar
From: "gEnhancements.Sfx.LowHpAlarm"
To: "gAudioEditor.LowHpAlarm"
*Moved "Mute Carpenter Sounds" to Audio Editor -> Audio Options
Changed Cvar
From: "gEnhancements.Sfx.MuteCarpenterSfx"
To: "gAudioEditor.MuteCarpenterSfx"
*Moved "Mute Crying Goron Child" to Audio Editor -> Audio Options
Changed Cvar
From: "gEnhancements.Sfx.ChildGoronCry"
To: "gAudioEditor.ChildGoronCry"
*Added "Disable Tatle Call Audio"
*Added "Disable Enemy Proximity Music"
*Added "Randomize All Music and Sound Effects on New Scene"
*Added "Randomize All Music and Sound Effects on Randomizer Generation"
*Added "Display Sequence Name on Overlay" and "Overlay Duration" Slider
*Added "Link's Voice Pitch Multiplier" Slider
* *Ported "AddSearchWidget" Functionally
Enabled for Audio Editor -> Audio Options
* Cleaned up some code I missed and ran clang format.
* Renamed "OnScene" Hook to "OnSceneChange"
* Made it so "Link's Voice Pitch Multiplier" slider only effects Link's voice.
* Forgot the "AudioHook.cpp" file its needed for the
"Display Sequence Name on Overlay" option.
* Moved the "Sfx" folder to the "Audio" folder.
* Removed extra line breaks between sections in "RegisterAudioWidgets()".
* Renamed "OnGenerationCompletion" hook to "OnRandoSeedGeneration"
* Changed "gAudioEditor.*" to use "CVAR_AUDIO("*") in "AudioEditor.cpp"
* Added "AddAudioSearchWidget" function
Changed all "BenGui::mBenMenu->AddSearchWidget lines to use
"AddAudioSearchWidget".
* Changed the "OnSeqPlayerInit" hook parameters type to use the "s32" Macro.
* Update BenMenu/BenGui include paths: Replaced "../../" with "2s2h/".
* Ran Clang Format.
* Added "DisableEnemyProximityMusic.cpp"
Added "VB_PLAY_ENEMY_PROXIMITY_MUSIC" enum to "GIVanillaBehavior" in
"GameInteractor.h"
"Audio_UpdateEnemyBgmVolume" is now wrapped in a "GameInteractor_Should"
* Added "DisableTatlCallAudio.cpp"
Added "VB_PLAY_TATL_CALL_AUDIO" enum to "GIVanillaBehavior" in
"GameInteractor.h"
"Audio_PlaySfx(NA_SE_VO_NAVY_CALL)" is now wrapped in a "GameInteractor_Should"
* Added "LinksVoicePitchMultiplier.cpp"
Added "Enable Link's Voice Pitch Multiplier" checkbox to Audio Editor
The "Link's Voice Pitch Multiplier" slider is now disabled when
"Enable Link's Voice Pitch Multiplier" is not enabled.
Added "VB_LINK_VOICE_PITCH_MULTIPLIER" enum to "GIVanillaBehavior" in
"GameInteractor.h"
"AudioSfx_PlaySfx" in the file "z_actor.c" in function "Player_PlaySfx"
is now wrapped in a "GameInteractor_Should".
* Removed "OnSceneChange" Hook.
Removed "GameInteractor_ExecuteOnSceneChange".
Removed "GameInteractor_ExecuteOnSceneChange(play->sceneId);" from
"z_play_2SH.cpp:OTRPlay_SpawnScene" function
Renamed "AudioEditorRegisterOnSceneChangeHook" to
AudioEditorRegisterOnRoomInitHook".
* Made Changes requested by Eblo to "LinksVoicePitchMultiplier.cpp" and
"z_actor.c"
* WIP Randomize On New Scene
22 files changed, 346 insertions, 101 deletions
diff --git a/mm/2s2h/BenGui/BenMenu.cpp b/mm/2s2h/BenGui/BenMenu.cpp index 43c71124c..560c129b1 100644 --- a/mm/2s2h/BenGui/BenMenu.cpp +++ b/mm/2s2h/BenGui/BenMenu.cpp @@ -970,17 +970,6 @@ void BenMenu::AddEnhancements() { } }) .Options(CheckboxOptions().Tooltip("Mirrors the world horizontally.")); - AddWidget(path, "SFX", WIDGET_SEPARATOR_TEXT); - AddWidget(path, "Mute Low HP Alarm", WIDGET_CVAR_CHECKBOX) - .CVar("gEnhancements.Sfx.LowHpAlarm") - .Options(CheckboxOptions().Tooltip("Mutes the beeping alarm when you are critically low on health.")); - AddWidget(path, "Mute Carpenter Sounds", WIDGET_CVAR_CHECKBOX) - .CVar("gEnhancements.Sfx.MuteCarpenterSfx") - .Options(CheckboxOptions().Tooltip("Requires scene reload to take effect. Mutes the carpenter sounds coming " - "from the tower in South Clock Town.")); - AddWidget(path, "Mute Crying Goron Child", WIDGET_CVAR_CHECKBOX) - .CVar("gEnhancements.Sfx.ChildGoronCry") - .Options(CheckboxOptions().Tooltip("Mutes the crying Goron child inside Goron Shrine.")); AddWidget(path, "Other", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Milk Run Reward Options", WIDGET_CVAR_COMBOBOX) .CVar("gEnhancements.Minigames.CremiaHugs") @@ -1915,6 +1904,11 @@ void BenMenu::InitElement() { return !CVarGetInteger(CVAR_PREFIX_ADVANCED_RESOLUTION ".VerticalResolutionToggle", 0); }, "Vertical Resolution Toggle is Off" } }, + { DISABLE_FOR_LINKS_VOICE_PITCH_MULTIPLIER_OFF, + { [](disabledInfo& info) -> bool { + return !CVarGetInteger("gAudioEditor.LinkVoiceFreqMultiplier.Enable", 0); + }, + "Enable Link's Voice Pitch Multiplier is Disabled" } }, }; } diff --git a/mm/2s2h/BenGui/Menu.cpp b/mm/2s2h/BenGui/Menu.cpp index e0f565126..16c353014 100644 --- a/mm/2s2h/BenGui/Menu.cpp +++ b/mm/2s2h/BenGui/Menu.cpp @@ -21,6 +21,7 @@ extern std::unordered_map<s16, const char*> warpPointSceneList; extern void Warp(); namespace BenGui {} +std::vector<SearchWidget> extraSearchWidgets = {}; namespace Ship { std::string disabledTempTooltip; @@ -210,6 +211,23 @@ uint32_t Menu::DrawSearchResults(std::string& menuSearchText) { } } } + for (auto& entry : extraSearchWidgets) { + if (entry.info.type == WIDGET_SEARCH || entry.info.type == WIDGET_SEPARATOR || + entry.info.type == WIDGET_SEPARATOR_TEXT || entry.info.isHidden || entry.info.hideInSearch) { + continue; + } + std::string widgetStr = entry.info.name + entry.info.options->tooltip + entry.extraTerms + entry.sidebarName; + std::transform(widgetStr.begin(), widgetStr.end(), widgetStr.begin(), ::tolower); + widgetStr.erase(std::remove(widgetStr.begin(), widgetStr.end(), ' '), widgetStr.end()); + if (widgetStr.find(menuSearchText) != std::string::npos) { + MenuDrawItem(entry.info, 400, menuThemeIndex); + ImGui::PushStyleColor(ImGuiCol_Text, UIWidgets::ColorValues.at(UIWidgets::Colors::Gray)); + std::string origin = fmt::format(" ({} -> {}, {})", entry.menuName, entry.sidebarName, entry.location); + ImGui::Text("%s", origin.c_str()); + ImGui::PopStyleColor(); + searchCount++; + } + } return searchCount; } @@ -218,6 +236,10 @@ void Menu::AddMenuEntry(std::string entryName, const char* entryCvar) { menuOrder.push_back(entryName); } +void Menu::AddSearchWidget(SearchWidget widget) { + extraSearchWidgets.push_back(widget); +} + std::unordered_map<uint32_t, disabledInfo>& Menu::GetDisabledMap() { return disabledMap; } diff --git a/mm/2s2h/BenGui/Menu.h b/mm/2s2h/BenGui/Menu.h index c5cb330ce..ddd3c0695 100644 --- a/mm/2s2h/BenGui/Menu.h +++ b/mm/2s2h/BenGui/Menu.h @@ -28,6 +28,7 @@ class Menu : public GuiWindow { void MenuDrawItem(WidgetInfo& widget, uint32_t width, UIWidgets::Colors menuThemeIndex); void AddMenuEntry(std::string entryName, const char* entryCvar); + void AddSearchWidget(SearchWidget widget); std::unordered_map<uint32_t, disabledInfo>& GetDisabledMap(); protected: diff --git a/mm/2s2h/BenGui/MenuTypes.h b/mm/2s2h/BenGui/MenuTypes.h index da4baffa2..92552d734 100644 --- a/mm/2s2h/BenGui/MenuTypes.h +++ b/mm/2s2h/BenGui/MenuTypes.h @@ -30,6 +30,7 @@ typedef enum { DISABLE_FOR_LOW_RES_MODE_ON, DISABLE_FOR_ADVANCED_RESOLUTION_OFF, DISABLE_FOR_VERTICAL_RESOLUTION_OFF, + DISABLE_FOR_LINKS_VOICE_PITCH_MULTIPLIER_OFF, } DisableOption; struct WidgetInfo; @@ -124,6 +125,7 @@ struct WidgetInfo { const char* windowName = ""; bool isHidden = false; bool sameLine = false; + bool hideInSearch = false; WidgetInfo& CVar(const char* cVar_) { cVar = cVar_; @@ -201,6 +203,11 @@ struct WidgetInfo { customFunction = customFunction_; return *this; } + + WidgetInfo& HideInSearch(bool hide) { + hideInSearch = hide; + return *this; + } }; struct WidgetPath { @@ -253,6 +260,15 @@ struct SidebarEntry { std::vector<std::vector<WidgetInfo>> columnWidgets; }; +struct SearchWidget { + // First four required + WidgetInfo& info; + std::string menuName; + std::string sidebarName; + std::string location; + std::string extraTerms = ""; +}; + // Contains entries for what's listed in the header at the top, including the name displayed on the top bar (label), // a vector of the SidebarEntries for that header entry, and the name of the cvar used to track what sidebar entry is // the last viewed for that header. diff --git a/mm/2s2h/BenGui/Notification.cpp b/mm/2s2h/BenGui/Notification.cpp index e8461ac23..619351a54 100644 --- a/mm/2s2h/BenGui/Notification.cpp +++ b/mm/2s2h/BenGui/Notification.cpp @@ -132,8 +132,10 @@ void Emit(Options notification) { notification.remainingTime = CVarGetFloat("gNotifications.Duration", 10.0f); } notifications.push_back(notification); - AudioSfx_PlaySfx(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultReverb); + if (!notification.mute) { + AudioSfx_PlaySfx(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } } } // namespace Notification diff --git a/mm/2s2h/BenGui/Notification.h b/mm/2s2h/BenGui/Notification.h index a40670dd4..03d484b4e 100644 --- a/mm/2s2h/BenGui/Notification.h +++ b/mm/2s2h/BenGui/Notification.h @@ -17,6 +17,7 @@ struct Options { std::string suffix = ""; ImVec4 suffixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f); float remainingTime = 0.0f; // Seconds + bool mute = false; }; class Window : public Ship::GuiWindow { diff --git a/mm/2s2h/Enhancements/Audio/AudioEditor.cpp b/mm/2s2h/Enhancements/Audio/AudioEditor.cpp index cda516f71..b215ea896 100644 --- a/mm/2s2h/Enhancements/Audio/AudioEditor.cpp +++ b/mm/2s2h/Enhancements/Audio/AudioEditor.cpp @@ -10,13 +10,34 @@ #include "../../BenPort.h" #include <ship/utils/StringHelper.h> #include "../../BenGui/UIWidgets.hpp" +#include "2s2h/BenGui/BenMenu.h" +#include "2s2h/BenGui/BenGui.hpp" #include "AudioCollection.h" +#include "2s2h/GameInteractor/GameInteractor.h" #include <random> extern "C" Vec3f gZeroVec3f; extern "C" f32 gSfxDefaultFreqAndVolScale; extern "C" s8 gSfxDefaultReverb; +using namespace UIWidgets; + +static WidgetInfo lowHpAlarm; +static WidgetInfo muteCarpenterSfx; +static WidgetInfo childGoronCry; +static WidgetInfo tatlCall; +static WidgetInfo enemyProx; +static WidgetInfo displaySeqName; +static WidgetInfo ovlDuration; +static WidgetInfo voicePitch; +static WidgetInfo voicePitchEnable; +static WidgetInfo randoMusicOnSceneChange; +static WidgetInfo randomAudioOnSeedGen; + +namespace BenGui { +extern std::shared_ptr<BenMenu> mBenMenu; +} + // Authentic sequence counts // used to ensure we have enough to shuffle #define SEQ_COUNT_BGM_WORLD 30 @@ -416,17 +437,17 @@ void DrawTypeChip(SeqType type) { ImGui::EndDisabled(); } -void AudioEditorRegisterOnSceneInitHook() { - // BENTODO implement this - // GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>([](int16_t sceneNum) { - // if (CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0)) { - // AudioEditor_RandomizeAll(); - // } - //}); +void AudioEditorRegisterRandomizeAllOnNewScene() { + COND_VB_SHOULD(VB_PLAY_TRANSITION_CS, CVarGetInteger(CVAR_AUDIO("RandomizeAllOnNewScene"), 0), + { AudioEditor_RandomizeAll(); }); } void AudioEditor::InitElement() { - AudioEditorRegisterOnSceneInitHook(); + GameInteractor::Instance->RegisterGameHook<GameInteractor::OnRandoSeedGeneration>([]() { + if (CVarGetInteger(CVAR_AUDIO("RandomizeAllOnRandoGen"), 0)) { + AudioEditor_RandomizeAll(); + } + }); } void AudioEditor::DrawElement() { @@ -454,6 +475,32 @@ void AudioEditor::DrawElement() { UIWidgets::Tooltip("Unlocks all music and sound effects across tab groups"); if (ImGui::BeginTabBar("SfxContextTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { + static ImVec2 cellPadding(8.0f, 8.0f); + if (ImGui::BeginTabItem("Audio Options")) { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); + ImGui::BeginTable("Audio Options", 1, ImGuiTableFlags_SizingStretchSame); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) { + BenGui::mBenMenu->MenuDrawItem(lowHpAlarm, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(muteCarpenterSfx, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(childGoronCry, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(tatlCall, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(enemyProx, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(randoMusicOnSceneChange, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(randomAudioOnSeedGen, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(displaySeqName, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(ovlDuration, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(voicePitchEnable, ImGui::GetContentRegionAvail().x, THEME_COLOR); + BenGui::mBenMenu->MenuDrawItem(voicePitch, ImGui::GetContentRegionAvail().x, THEME_COLOR); + } + ImGui::EndChild(); + ImGui::EndTable(); + ImGui::PopStyleVar(1); + ImGui::EndTabItem(); + } if (ImGui::BeginTabItem("Background Music")) { Draw_SfxTab("backgroundMusic", SEQ_BGM_WORLD); ImGui::EndTabItem(); @@ -491,73 +538,6 @@ void AudioEditor::DrawElement() { Draw_SfxTab("voice", SEQ_VOICE); ImGui::EndTabItem(); #endif - static ImVec2 cellPadding(8.0f, 8.0f); -#if 0 - if (ImGui::BeginTabItem("Options")) { - ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); - ImGui::BeginTable("Options", 1, ImGuiTableFlags_SizingStretchSame); - ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - if (ImGui::BeginChild("SfxOptions", ImVec2(0, -8))) { - ImGui::PushItemWidth(-FLT_MIN); - UIWidgets::EnhancementCheckbox("Disable Enemy Proximity Music", CVAR_AUDIO("EnemyBGMDisable")); - UIWidgets::InsertHelpHoverText( - "Disables the music change when getting close to enemies. Useful for hearing " - "your custom music for each scene more often."); - UIWidgets::EnhancementCheckbox("Disable Leading Music in Lost Woods", - CVAR_AUDIO("LostWoodsConsistentVolume")); - UIWidgets::InsertHelpHoverText( - "Disables the volume shifting in the Lost Woods. Useful for hearing " - "your custom music in the Lost Woods if you don't need the navigation assitance " - "the volume changing provides. If toggling this while in the Lost Woods, reload " - "the area for the effect to kick in."); - UIWidgets::EnhancementCheckbox("Display Sequence Name on Overlay", CVAR_AUDIO("SeqNameOverlay")); - UIWidgets::InsertHelpHoverText( - "Displays the name of the current sequence in the corner of the screen whenever a new sequence " - "is loaded to the main sequence player (does not apply to fanfares or enemy BGM)."); - ImGui::SameLine(); - ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); - UIWidgets::EnhancementSliderInt("Overlay Duration: %d seconds", "##SeqNameOverlayDuration", - CVAR_AUDIO("SeqNameOverlayDuration"), 1, 10, "", 5); - ImGui::PopItemWidth(); - ImGui::NewLine(); - ImGui::PopItemWidth(); - UIWidgets::EnhancementSliderFloat("Link's voice pitch multiplier: %.1f %%", "##linkVoiceFreqMultiplier", - CVAR_AUDIO("LinkVoiceFreqMultiplier"), 0.4, 2.5, "", 1.0, true, true); - ImGui::SameLine(); - const std::string resetButton = "Reset##linkVoiceFreqMultiplier"; - if (ImGui::Button(resetButton.c_str())) { - CVarSetFloat(CVAR_AUDIO("LinkVoiceFreqMultiplier"), 1.0f); - Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); - } - - ImGui::NewLine(); - UIWidgets::EnhancementCheckbox("Randomize All Music and Sound Effects on New Scene", - CVAR_AUDIO("RandomizeAllOnNewScene")); - UIWidgets::Tooltip( - "Enables randomizing all unlocked music and sound effects when you enter a new scene."); - - ImGui::NewLine(); - ImGui::PushItemWidth(-FLT_MIN); - UIWidgets::PaddedSeparator(); - UIWidgets::PaddedText("The following options are experimental and may cause music\nto sound odd or " - "have other undesireable effects."); - UIWidgets::EnhancementCheckbox("Lower Octaves of Unplayable High Notes", - CVAR_AUDIO("ExperimentalOctaveDrop")); - UIWidgets::Tooltip( - "Some custom sequences may have notes that are too high for the game's audio " - "engine to play. Enabling this checkbox will cause these notes to drop a " - "couple of octaves so they can still harmonize with the other notes of the " - "sequence."); - ImGui::PopItemWidth(); - } - ImGui::EndChild(); - ImGui::EndTable(); - ImGui::PopStyleVar(1); - ImGui::EndTabItem(); - } -#endif static bool excludeTabOpen = false; if (ImGui::BeginTabItem("Audio Shuffle Pool Management")) { @@ -760,4 +740,102 @@ void AudioEditor_UnlockAll() { } Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); -}
\ No newline at end of file +} + +void AddAudioSearchWidget(WidgetInfo& widgetInfo) { + BenGui::mBenMenu->AddSearchWidget({ widgetInfo, "Enhancements", "Audio Editor", "Audio Options" }); +} + +void RegisterAudioWidgets() { + + lowHpAlarm = { .name = "Mute Low HP Alarm", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + lowHpAlarm.CVar(CVAR_AUDIO("LowHpAlarm")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Mutes the beeping alarm when you are critically low on health.")); + AddAudioSearchWidget(lowHpAlarm); + + muteCarpenterSfx = { .name = "Mute Carpenter Sounds", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + muteCarpenterSfx.CVar(CVAR_AUDIO("MuteCarpenterSfx")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Requires scene reload to take effect. Mutes the carpenter sounds coming " + "from the tower in South Clock Town.")); + AddAudioSearchWidget(muteCarpenterSfx); + + childGoronCry = { .name = "Mute Crying Goron Child", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + childGoronCry.CVar(CVAR_AUDIO("ChildGoronCry")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Mutes the crying Goron child inside Goron Shrine.")); + AddAudioSearchWidget(childGoronCry); + + tatlCall = { .name = "Disable Tatl Call Audio", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + tatlCall.CVar(CVAR_AUDIO("DisableTatlCallAudio")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Disables the bell audio when Tatl calls you.")); + AddAudioSearchWidget(tatlCall); + + enemyProx = { .name = "Disable Enemy Proximity Music", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + enemyProx.CVar(CVAR_AUDIO("EnemyBGMDisable")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Disables the music change when getting close to enemies. Useful for hearing " + "your custom music for each scene more often.")); + AddAudioSearchWidget(enemyProx); + + randoMusicOnSceneChange = { .name = "Randomize All Music and Sound Effects on New Scene", + .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + randoMusicOnSceneChange.CVar(CVAR_AUDIO("RandomizeAllOnNewScene")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked music and sound effects when you enter a new scene.")); + AddAudioSearchWidget(randoMusicOnSceneChange); + + randomAudioOnSeedGen = { .name = "Randomize All Music and Sound Effects on Randomizer Generation", + .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + randomAudioOnSeedGen.CVar(CVAR_AUDIO("RandomizeAllOnRandoGen")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Enables randomizing all unlocked music and sound effects when you generate a new " + "randomizer. Respects locks already in place.")); + AddAudioSearchWidget(randomAudioOnSeedGen); + + displaySeqName = { .name = "Display Sequence Name on Overlay", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + displaySeqName.CVar(CVAR_AUDIO("SeqNameNotification")) + .Options(CheckboxOptions() + .Color(THEME_COLOR) + .Tooltip("Displays the name of the current sequence in the corner of the screen whenever a new " + "sequence " + "is loaded to the main sequence player (does not apply to fanfares or enemy BGM).")); + AddAudioSearchWidget(displaySeqName); + + ovlDuration = { .name = "Overlay Duration: %d seconds", .type = WidgetType::WIDGET_CVAR_SLIDER_INT }; + ovlDuration.CVar(CVAR_AUDIO("SeqNameNotificationDuration")) + .Options(IntSliderOptions().Color(THEME_COLOR).Min(1).Max(10).DefaultValue(5).Size(ImVec2(300.0f, 0.0f))); + AddAudioSearchWidget(ovlDuration); + + voicePitchEnable = { .name = "Enable Link's Voice Pitch Multiplier", .type = WidgetType::WIDGET_CVAR_CHECKBOX }; + voicePitchEnable.CVar(CVAR_AUDIO("LinkVoiceFreqMultiplier.Enable")) + .Options(CheckboxOptions().Color(THEME_COLOR).Tooltip("Enables Link's Voice Pitch Multiplier.")); + AddAudioSearchWidget(voicePitchEnable); + + voicePitch = { .name = "Link's Voice Pitch Multiplier", .type = WidgetType::WIDGET_CVAR_SLIDER_FLOAT }; + voicePitch.CVar(CVAR_AUDIO("LinkVoiceFreqMultiplier.Scale")) + .PreFunc([](WidgetInfo& info) { + if (BenGui::mBenMenu->GetDisabledMap().at(DISABLE_FOR_LINKS_VOICE_PITCH_MULTIPLIER_OFF).active) { + info.activeDisables.push_back(DISABLE_FOR_LINKS_VOICE_PITCH_MULTIPLIER_OFF); + } + }) + .Options(FloatSliderOptions() + .Color(THEME_COLOR) + .IsPercentage() + .Min(0.4f) + .Max(2.5f) + .DefaultValue(1.0f) + .Size(ImVec2(300.0f, 0.0f)) + .Tooltip("Adjust Link's Voice Pitch Multiplier.Limits are 40% to 250%")); + AddAudioSearchWidget(voicePitch); +} + +static RegisterMenuInitFunc initAudioWidgets(RegisterAudioWidgets); + +static RegisterShipInitFunc initFuncRandomizeAllOnNewScene(AudioEditorRegisterRandomizeAllOnNewScene, + { CVAR_AUDIO("RandomizeAllOnNewScene") });
\ No newline at end of file diff --git a/mm/2s2h/Enhancements/Audio/AudioHook.cpp b/mm/2s2h/Enhancements/Audio/AudioHook.cpp new file mode 100644 index 000000000..f5411b079 --- /dev/null +++ b/mm/2s2h/Enhancements/Audio/AudioHook.cpp @@ -0,0 +1,45 @@ +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" +#include "2s2h/BenPort.h" +#include "2s2h/BenGui/BenMenu.h" +#include "2s2h/Enhancements/Audio/AudioCollection.h" +#include <2s2h/BenGui/Notification.h> + +extern "C" { +#include "variables.h" + +extern PlayState* gPlayState; +} + +#define CVAR_SEQOVERLAY_NAME "gAudioEditor.SeqNameNotification" +#define CVAR_SEQOVERLAY_DEFAULT 0 +#define CVAR_SEQOVERLAY_VALUE CVarGetInteger(CVAR_SEQOVERLAY_NAME, CVAR_SEQOVERLAY_DEFAULT) + +void NotifySequenceName(int32_t playerIdx, int32_t seqId) { + // Keep track of the previous sequence/scene so we don't repeat notifications + static uint16_t previousSeqId = UINT16_MAX; + static int16_t previousSceneNum = INT16_MAX; + + if (playerIdx == SEQ_PLAYER_BGM_MAIN && + (seqId != previousSeqId || (gPlayState != NULL && gPlayState->sceneId != previousSceneNum))) { + + previousSeqId = seqId; + if (gPlayState != NULL) { + previousSceneNum = gPlayState->sceneId; + } + const char* sequenceName = AudioCollection::Instance->GetSequenceName(seqId); + if (sequenceName != NULL) { + Notification::Emit({ + .message = ICON_FA_MUSIC " " + std::string(sequenceName), + .remainingTime = static_cast<float>(CVarGetInteger("gAudioEditor.SeqNameNotificationDuration", 10)), + .mute = true, + }); + } + } +} + +void RegisterAudioNotificationHooks() { + COND_HOOK(OnSeqPlayerInit, CVAR_SEQOVERLAY_VALUE, NotifySequenceName); +} + +static RegisterShipInitFunc initFunc(RegisterAudioNotificationHooks, { CVAR_SEQOVERLAY_NAME });
\ No newline at end of file diff --git a/mm/2s2h/Enhancements/Audio/Sfx/DisableEnemyProximityMusic.cpp b/mm/2s2h/Enhancements/Audio/Sfx/DisableEnemyProximityMusic.cpp new file mode 100644 index 000000000..8d37ca894 --- /dev/null +++ b/mm/2s2h/Enhancements/Audio/Sfx/DisableEnemyProximityMusic.cpp @@ -0,0 +1,12 @@ +#include <libultraship/bridge/consolevariablebridge.h> +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gAudioEditor.EnemyBGMDisable" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void RegisterDisableEnemyProximityMusic() { + COND_VB_SHOULD(VB_PLAY_ENEMY_PROXIMITY_MUSIC, CVAR, { *should = false; }); +} + +static RegisterShipInitFunc initFunc(RegisterDisableEnemyProximityMusic, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Audio/Sfx/DisableTatlCallAudio.cpp b/mm/2s2h/Enhancements/Audio/Sfx/DisableTatlCallAudio.cpp new file mode 100644 index 000000000..1d4c6f7aa --- /dev/null +++ b/mm/2s2h/Enhancements/Audio/Sfx/DisableTatlCallAudio.cpp @@ -0,0 +1,12 @@ +#include <libultraship/bridge/consolevariablebridge.h> +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +#define CVAR_NAME "gAudioEditor.DisableTatlCallAudio" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void RegisterDisableTatlCallAudio() { + COND_VB_SHOULD(VB_PLAY_TATL_CALL_AUDIO, CVAR, { *should = false; }); +} + +static RegisterShipInitFunc initFunc(RegisterDisableTatlCallAudio, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Audio/Sfx/LinksVoicePitchMultiplier.cpp b/mm/2s2h/Enhancements/Audio/Sfx/LinksVoicePitchMultiplier.cpp new file mode 100644 index 000000000..16bcca204 --- /dev/null +++ b/mm/2s2h/Enhancements/Audio/Sfx/LinksVoicePitchMultiplier.cpp @@ -0,0 +1,34 @@ +#include <libultraship/bridge/consolevariablebridge.h> +#include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/ShipInit.hpp" + +extern "C" { +#include "variables.h" +} + +// For Link's voice pitch SFX modifier +static f32 freqMultiplier = 1; + +#define CVAR_NAME "gAudioEditor.LinkVoiceFreqMultiplier.Enable" +#define CVAR CVarGetInteger(CVAR_NAME, 0) + +void RegisterLinksVoicePitchMultiplier() { + COND_VB_SHOULD(VB_LINK_VOICE_PITCH_MULTIPLIER, CVAR, { + Player* player = GET_PLAYER(gPlayState); + u16 sfxId = *va_arg(args, u16*); + + if (sfxId >= NA_SE_VO_LI_SWORD_N && sfxId <= NA_SE_VO_DEMO_394 || sfxId == NA_SE_PL_TRANSFORM_VOICE) { + + *should = false; + freqMultiplier = CVarGetFloat("gAudioEditor.LinkVoiceFreqMultiplier.Scale", 1.0); + if (freqMultiplier <= 0) { + freqMultiplier = 1; + } + + AudioSfx_PlaySfx(sfxId, &player->actor.projectedPos, 4, &freqMultiplier, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultReverb); + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterLinksVoicePitchMultiplier, { CVAR_NAME }); diff --git a/mm/2s2h/Enhancements/Sfx/MuteCarpenterSfx.cpp b/mm/2s2h/Enhancements/Audio/Sfx/MuteCarpenterSfx.cpp index 38af870c5..e0dbcb6ab 100644 --- a/mm/2s2h/Enhancements/Sfx/MuteCarpenterSfx.cpp +++ b/mm/2s2h/Enhancements/Audio/Sfx/MuteCarpenterSfx.cpp @@ -6,7 +6,7 @@ extern "C" { #include "overlays/actors/ovl_Obj_Sound/z_obj_sound.h" } -#define CVAR_NAME "gEnhancements.Sfx.MuteCarpenterSfx" +#define CVAR_NAME "gAudioEditor.MuteCarpenterSfx" #define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterMuteCarpenterSfx() { diff --git a/mm/2s2h/Enhancements/Sfx/MuteCryingGoronChild.cpp b/mm/2s2h/Enhancements/Audio/Sfx/MuteCryingGoronChild.cpp index b9706d0df..74c998172 100644 --- a/mm/2s2h/Enhancements/Sfx/MuteCryingGoronChild.cpp +++ b/mm/2s2h/Enhancements/Audio/Sfx/MuteCryingGoronChild.cpp @@ -2,7 +2,7 @@ #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/ShipInit.hpp" -#define CVAR_NAME "gEnhancements.Sfx.ChildGoronCry" +#define CVAR_NAME "gAudioEditor.ChildGoronCry" #define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterMuteCryingGoronChild() { diff --git a/mm/2s2h/Enhancements/Sfx/MuteLowHpAlarm.cpp b/mm/2s2h/Enhancements/Audio/Sfx/MuteLowHpAlarm.cpp index 2bebef119..f5e1e565d 100644 --- a/mm/2s2h/Enhancements/Sfx/MuteLowHpAlarm.cpp +++ b/mm/2s2h/Enhancements/Audio/Sfx/MuteLowHpAlarm.cpp @@ -2,7 +2,7 @@ #include "2s2h/GameInteractor/GameInteractor.h" #include "2s2h/ShipInit.hpp" -#define CVAR_NAME "gEnhancements.Sfx.LowHpAlarm" +#define CVAR_NAME "gAudioEditor.LowHpAlarm" #define CVAR CVarGetInteger(CVAR_NAME, 0) void RegisterMuteLowHpAlarm() { diff --git a/mm/2s2h/GameInteractor/GameInteractor.cpp b/mm/2s2h/GameInteractor/GameInteractor.cpp index 487af4f19..0a8189765 100644 --- a/mm/2s2h/GameInteractor/GameInteractor.cpp +++ b/mm/2s2h/GameInteractor/GameInteractor.cpp @@ -273,6 +273,10 @@ void GameInteractor_ExecuteOnBottleContentsUpdate(u8 item) { GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnBottleContentsUpdate>(item); } +void GameInteractor_ExecuteOnSeqPlayerInit(int32_t playerIdx, int32_t seqId) { + GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSeqPlayerInit>(playerIdx, seqId); +} + bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...) { // Only the external function can use the Variadic Function syntax // To pass the va args to the next caller must be done using va_list and reading the args into it diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h index c0e74180a..42ba0abab 100644 --- a/mm/2s2h/GameInteractor/GameInteractor.h +++ b/mm/2s2h/GameInteractor/GameInteractor.h @@ -239,6 +239,9 @@ typedef enum { VB_BUY_GORMAN_MILK, VB_PLAY_LOW_HP_ALARM, VB_PLAY_GORON_CHILD_CRY, + VB_PLAY_ENEMY_PROXIMITY_MUSIC, + VB_PLAY_TATL_CALL_AUDIO, + VB_LINK_VOICE_PITCH_MULTIPLIER, VB_SNOWBALL_DROP_COLLECTIBLE, VB_SNOWBALL_SET_FLAG, VB_START_JUMPSLASH, @@ -760,6 +763,8 @@ void GameInteractor_ExecuteOnItemGive(u8 item); void GameInteractor_ExecuteOnBottleContentsUpdate(u8 item); +void GameInteractor_ExecuteOnSeqPlayerInit(int32_t playerIdx, int32_t seqId); + bool GameInteractor_Should(GIVanillaBehavior flag, uint32_t result, ...); #define REGISTER_VB_SHOULD(flag, body) \ GameInteractor::Instance->RegisterGameHookForID<GameInteractor::ShouldVanillaBehavior>( \ diff --git a/mm/2s2h/GameInteractor/GameInteractor_HookTable.h b/mm/2s2h/GameInteractor/GameInteractor_HookTable.h index 688b6091a..cad17ddba 100644 --- a/mm/2s2h/GameInteractor/GameInteractor_HookTable.h +++ b/mm/2s2h/GameInteractor/GameInteractor_HookTable.h @@ -52,3 +52,9 @@ DEFINE_HOOK(OnItemGive, (u8 item)) DEFINE_HOOK(OnBottleContentsUpdate, (u8 item)) DEFINE_HOOK(ShouldVanillaBehavior, (GIVanillaBehavior flag, bool* should, va_list originalArgs)) + +// Audio +DEFINE_HOOK(OnSeqPlayerInit, (s32 playerIdx, s32 seqId)); + +// Rando +DEFINE_HOOK(OnRandoSeedGeneration, ()); diff --git a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp index 6edec7fb1..9891be4ba 100644 --- a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp +++ b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp @@ -467,6 +467,8 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) { RANDO_SAVE_CHECKS[RC_STARTING_ITEM_DEKU_MASK].eligible = true; RANDO_SAVE_CHECKS[RC_STARTING_ITEM_SONG_OF_HEALING].eligible = true; + GameInteractor::Instance->ExecuteHooks<GameInteractor::OnRandoSeedGeneration>(); + } catch (const std::exception& e) { SPDLOG_ERROR("Error with randomizer save creation: {}", e.what()); Audio_PlaySfx(NA_SE_SY_QUIZ_INCORRECT); diff --git a/mm/src/audio/lib/load.c b/mm/src/audio/lib/load.c index 55b41c06e..6e3b1b9ec 100644 --- a/mm/src/audio/lib/load.c +++ b/mm/src/audio/lib/load.c @@ -17,6 +17,7 @@ #include <stdlib.h> #include "2s2h/Enhancements/Audio/AudioCollection.h" #include "2s2h/Enhancements/Audio/AudioEditor.h" +#include "2s2h/GameInteractor/GameInteractor.h" #include "BenPort.h" #include <libultraship/log/luslog.h> // Windows deprecated the use of `strdup` it uses _strdup. Linux/Unix doesn't have _strdup. @@ -658,6 +659,9 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIndex, s32 seqId, s32 arg2) { seqPlayer->delay = 0; seqPlayer->finished = false; seqPlayer->playerIndex = playerIndex; + + GameInteractor_ExecuteOnSeqPlayerInit(playerIndex, seqId); + return 1; //! @bug missing return (but the return value is not used so it's not UB) } diff --git a/mm/src/code/z_actor.c b/mm/src/code/z_actor.c index 8c86e337e..6fed8a875 100644 --- a/mm/src/code/z_actor.c +++ b/mm/src/code/z_actor.c @@ -2486,8 +2486,10 @@ void Player_PlaySfx(Player* player, u16 sfxId) { if (player->currentMask == PLAYER_MASK_GIANT) { Audio_PlaySfx_AtPosWithPresetLowFreqAndHighReverb(&player->actor.projectedPos, sfxId); } else { - AudioSfx_PlaySfx(sfxId, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + if (GameInteractor_Should(VB_LINK_VOICE_PITCH_MULTIPLIER, true, &sfxId)) { + AudioSfx_PlaySfx(sfxId, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } } } diff --git a/mm/src/code/z_parameter.c b/mm/src/code/z_parameter.c index f18287569..9cea7ffce 100644 --- a/mm/src/code/z_parameter.c +++ b/mm/src/code/z_parameter.c @@ -5091,12 +5091,15 @@ void Interface_SetTatlCall(PlayState* play, u16 tatlCallState) { if (((tatlCallState == TATL_STATE_2A) || (tatlCallState == TATL_STATE_2B)) && !interfaceCtx->tatlCalling && (play->csCtx.state == CS_STATE_IDLE)) { - if (tatlCallState == TATL_STATE_2B) { - Audio_PlaySfx(NA_SE_VO_NAVY_CALL); - } - if (tatlCallState == TATL_STATE_2A) { - Audio_PlaySfx_AtPosWithReverb(&gSfxDefaultPos, NA_SE_VO_NA_HELLO_2, 0x20); + if (GameInteractor_Should(VB_PLAY_TATL_CALL_AUDIO, true)) { + if (tatlCallState == TATL_STATE_2B) { + Audio_PlaySfx(NA_SE_VO_NAVY_CALL); + } + if (tatlCallState == TATL_STATE_2A) { + Audio_PlaySfx_AtPosWithReverb(&gSfxDefaultPos, NA_SE_VO_NA_HELLO_2, 0x20); + } } + interfaceCtx->tatlCalling = true; sCUpInvisible = 0; sCUpTimer = 10; diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c index 129ba3dd6..426262461 100644 --- a/mm/src/overlays/actors/ovl_player_actor/z_player.c +++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c @@ -12208,8 +12208,10 @@ void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) { } if (play->actorCtx.attention.bgmEnemy != NULL) { - seqMode = SEQ_MODE_ENEMY; - Audio_UpdateEnemyBgmVolume(sqrtf(play->actorCtx.attention.bgmEnemy->xyzDistToPlayerSq)); + if (GameInteractor_Should(VB_PLAY_ENEMY_PROXIMITY_MUSIC, true)) { + seqMode = SEQ_MODE_ENEMY; + Audio_UpdateEnemyBgmVolume(sqrtf(play->actorCtx.attention.bgmEnemy->xyzDistToPlayerSq)); + } } Audio_SetSequenceMode(seqMode); |
