Skip to content

Commit

Permalink
Add console commands for randomizing sfx and cosmetic groups (Harbour…
Browse files Browse the repository at this point in the history
…Masters#3962)

* Add console commands for randomizing sfx and cosmetic groups

* Update naming and use constexpr

* Update soh/soh/Enhancements/debugconsole.cpp

---------

Co-authored-by: Archez <Archez@users.noreply.github.com>
  • Loading branch information
Tawling and Archez authored Apr 20, 2024
1 parent 2accfc3 commit 16bf03a
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 241 deletions.
1 change: 1 addition & 0 deletions soh/soh/Enhancements/audio/AudioCollection.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#pragma once
#ifdef __cplusplus
#include <map>
#include <string>
Expand Down
14 changes: 14 additions & 0 deletions soh/soh/Enhancements/audio/AudioEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,13 @@ void AudioEditor_RandomizeAll() {
ReplayCurrentBGM();
}

void AudioEditor_RandomizeGroup(SeqType group) {
RandomizeGroup(group);

LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
ReplayCurrentBGM();
}

void AudioEditor_ResetAll() {
for (auto type : allTypes) {
ResetGroup(AudioCollection::Instance->GetAllSequences(), type);
Expand All @@ -723,6 +730,13 @@ void AudioEditor_ResetAll() {
ReplayCurrentBGM();
}

void AudioEditor_ResetGroup(SeqType group) {
ResetGroup(AudioCollection::Instance->GetAllSequences(), group);

LUS::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
ReplayCurrentBGM();
}

void AudioEditor_LockAll() {
for (auto type : allTypes) {
LockGroup(AudioCollection::Instance->GetAllSequences(), type);
Expand Down
3 changes: 3 additions & 0 deletions soh/soh/Enhancements/audio/AudioEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <ImGui/imgui.h>
#include "AudioCollection.h"

class AudioEditor : public LUS::GuiWindow {
public:
Expand All @@ -20,7 +21,9 @@ class AudioEditor : public LUS::GuiWindow {
};

void AudioEditor_RandomizeAll();
void AudioEditor_RandomizeGroup(SeqType group);
void AudioEditor_ResetAll();
void AudioEditor_ResetGroup(SeqType group);
void AudioEditor_LockAll();
void AudioEditor_UnlockAll();

Expand Down
452 changes: 227 additions & 225 deletions soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions soh/soh/Enhancements/cosmetics/CosmeticsEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@
ResourceMgr_UnpatchGfxByName(path, name); \
}

// Not to be confused with tabs, groups are 1:1 with the boxes shown in the UI, grouping them allows us to reset/randomize
// every item in a group at once. If you are looking for tabs they are rendered manually in ImGui in `DrawCosmeticsEditor`
typedef enum {
COSMETICS_GROUP_LINK,
COSMETICS_GROUP_MIRRORSHIELD,
COSMETICS_GROUP_SWORDS,
COSMETICS_GROUP_GLOVES,
COSMETICS_GROUP_EQUIPMENT,
COSMETICS_GROUP_CONSUMABLE,
COSMETICS_GROUP_HUD,
COSMETICS_GROUP_KALEIDO,
COSMETICS_GROUP_TITLE,
COSMETICS_GROUP_NPC,
COSMETICS_GROUP_WORLD,
COSMETICS_GROUP_MAGIC,
COSMETICS_GROUP_ARROWS,
COSMETICS_GROUP_SPIN_ATTACK,
COSMETICS_GROUP_TRAILS,
COSMETICS_GROUP_NAVI,
COSMETICS_GROUP_IVAN,
COSMETICS_GROUP_MAX
} CosmeticGroup;

typedef struct {
const std::string Name;
const std::string ToolTip;
Expand All @@ -26,7 +49,9 @@ static ImGuiTableColumnFlags FlagsCell = ImGuiTableColumnFlags_WidthStretch | Im
void InitCosmeticsEditor();//Init the menu itself
ImVec4 GetRandomValue(int MaximumPossible);
void CosmeticsEditor_RandomizeAll();
void CosmeticsEditor_RandomizeGroup(CosmeticGroup group);
void CosmeticsEditor_ResetAll();
void CosmeticsEditor_ResetGroup(CosmeticGroup group);
void ApplyOrResetCustomGfxPatches(bool manualChange = true);

class CosmeticsEditorWindow : public LUS::GuiWindow {
Expand Down
86 changes: 82 additions & 4 deletions soh/soh/Enhancements/debugconsole.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1289,16 +1289,58 @@ static bool GenerateRandoHandler(std::shared_ptr<LUS::Console> Console, const st
return 1;
}

static constexpr std::array<std::pair<const char*, CosmeticGroup>, COSMETICS_GROUP_MAX> cosmetic_groups = {{
{"link", COSMETICS_GROUP_LINK},
{"mirror_shield", COSMETICS_GROUP_MIRRORSHIELD},
{"swords", COSMETICS_GROUP_SWORDS},
{"gloves", COSMETICS_GROUP_GLOVES},
{"equipment", COSMETICS_GROUP_EQUIPMENT},
{"consumable", COSMETICS_GROUP_CONSUMABLE},
{"hud", COSMETICS_GROUP_HUD},
{"kaleido", COSMETICS_GROUP_KALEIDO},
{"title", COSMETICS_GROUP_TITLE},
{"npc", COSMETICS_GROUP_NPC},
{"world", COSMETICS_GROUP_WORLD},
{"magic", COSMETICS_GROUP_MAGIC},
{"arrows", COSMETICS_GROUP_ARROWS},
{"spin_attack", COSMETICS_GROUP_SPIN_ATTACK},
{"trials", COSMETICS_GROUP_TRAILS},
{"navi", COSMETICS_GROUP_NAVI},
{"ivan", COSMETICS_GROUP_IVAN},
}};

static bool CosmeticsHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1;
}

if (args[1].compare("reset") == 0) {
CosmeticsEditor_ResetAll();
if (args.size() == 2) {
CosmeticsEditor_ResetAll();
} else {
for (const auto& [key, value] : cosmetic_groups) {
if (args[2].compare(key) == 0) {
CosmeticsEditor_ResetGroup(value);
return 0;
}
}
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
return 1;
}
} else if (args[1].compare("randomize") == 0) {
CosmeticsEditor_RandomizeAll();
if (args.size() == 2) {
CosmeticsEditor_RandomizeAll();
} else {
for (const auto& [key, value] : cosmetic_groups) {
if (args[2].compare(key) == 0) {
CosmeticsEditor_RandomizeGroup(value);
return 0;
}
}
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
return 1;
}
} else {
ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'reset' or 'randomize'");
return 1;
Expand All @@ -1307,16 +1349,50 @@ static bool CosmeticsHandler(std::shared_ptr<LUS::Console> Console, const std::v
return 0;
}

static std::map<std::string, SeqType> sfx_groups = {
{"bgm", SEQ_BGM_WORLD},
{"fanfares", SEQ_FANFARE},
{"events", SEQ_BGM_EVENT},
{"battle", SEQ_BGM_BATTLE},
{"ocarina", SEQ_OCARINA},
{"instruments", SEQ_INSTRUMENT},
{"sfx", SEQ_SFX},
{"voices", SEQ_VOICE},
{"custom", SEQ_BGM_CUSTOM},
};

static bool SfxHandler(std::shared_ptr<LUS::Console> Console, const std::vector<std::string>& args, std::string* output) {
if (args.size() < 2) {
ERROR_MESSAGE("[SOH] Unexpected arguments passed");
return 1;
}

if (args[1].compare("reset") == 0) {
AudioEditor_ResetAll();
if (args.size() == 2) {
AudioEditor_ResetAll();
} else {
for (const auto& [key, value] : sfx_groups) {
if (args[2].compare(key) == 0) {
AudioEditor_ResetGroup(value);
return 0;
}
}
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
return 1;
}
} else if (args[1].compare("randomize") == 0) {
AudioEditor_RandomizeAll();
if (args.size() == 2) {
AudioEditor_RandomizeAll();
} else {
for (const auto& [key, value] : sfx_groups) {
if (args[2].compare(key) == 0) {
AudioEditor_RandomizeGroup(value);
return 0;
}
}
ERROR_MESSAGE("[SOH] Invalid argument passed, unrecognized group name");
return 1;
}
} else {
ERROR_MESSAGE("[SOH] Invalid argument passed, must be 'reset' or 'randomize'");
return 1;
Expand Down Expand Up @@ -1506,10 +1582,12 @@ void DebugConsole_Init(void) {

CMD_REGISTER("cosmetics", {CosmeticsHandler, "Change cosmetics.", {
{"reset|randomize", LUS::ArgumentType::TEXT},
{"group name", LUS::ArgumentType::TEXT, true},
}});

CMD_REGISTER("sfx", {SfxHandler, "Change SFX.", {
{"reset|randomize", LUS::ArgumentType::TEXT},
{"group_name", LUS::ArgumentType::TEXT, true},
}});

CVarSave();
Expand Down
16 changes: 4 additions & 12 deletions soh/soh/SohMenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ extern bool isBetaQuestEnabled;

extern "C" PlayState* gPlayState;

enum SeqPlayers {
/* 0 */ SEQ_BGM_MAIN,
/* 1 */ SEQ_FANFARE,
/* 2 */ SEQ_SFX,
/* 3 */ SEQ_BGM_SUB,
/* 4 */ SEQ_MAX
};

std::string GetWindowButtonText(const char* text, bool menuOpen) {
char buttonText[100] = "";
if (menuOpen) {
Expand Down Expand Up @@ -192,16 +184,16 @@ void DrawSettingsMenu() {
if (ImGui::BeginMenu("Audio")) {
UIWidgets::PaddedEnhancementSliderFloat("Master Volume: %.1f %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true);
if (UIWidgets::PaddedEnhancementSliderFloat("Main Music Volume: %.1f %%", "##Main_Music_Vol", "gMainMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) {
Audio_SetGameVolume(SEQ_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f));
Audio_SetGameVolume(SEQ_PLAYER_BGM_MAIN, CVarGetFloat("gMainMusicVolume", 1.0f));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Sub Music Volume: %.1f %%", "##Sub_Music_Vol", "gSubMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) {
Audio_SetGameVolume(SEQ_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f));
Audio_SetGameVolume(SEQ_PLAYER_BGM_SUB, CVarGetFloat("gSubMusicVolume", 1.0f));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Sound Effects Volume: %.1f %%", "##Sound_Effect_Vol", "gSFXMusicVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) {
Audio_SetGameVolume(SEQ_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f));
Audio_SetGameVolume(SEQ_PLAYER_SFX, CVarGetFloat("gSFXMusicVolume", 1.0f));
}
if (UIWidgets::PaddedEnhancementSliderFloat("Fanfare Volume: %.1f %%", "##Fanfare_Vol", "gFanfareVolume", 0.0f, 1.0f, "", 1.0f, true, true, false, true)) {
Audio_SetGameVolume(SEQ_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f));
Audio_SetGameVolume(SEQ_PLAYER_FANFARE, CVarGetFloat("gFanfareVolume", 1.0f));
}

static std::unordered_map<LUS::AudioBackend, const char*> audioBackendNames = {
Expand Down

0 comments on commit 16bf03a

Please sign in to comment.