diff options
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); |
