summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlilacLunatic <8488221+lilacLunatic@users.noreply.github.com>2024-12-17 07:35:54 -0300
committerGitHub <noreply@github.com>2024-12-17 04:35:54 -0600
commitd725125f9b12a48a5086944103ca3632daf85de5 (patch)
treea6398becfabb36a3468097db9878310194a7bc0c
parenta10b4d0662f20265cdfc6ff49f22210178701067 (diff)
[Holiday] Custom rainbows (#4698)
* [Holiday] Custom rainbows * Update soh/soh/Enhancements/Holiday/LL.h Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com> --------- Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
-rw-r--r--soh/soh/Enhancements/Holiday/LL.cpp129
-rw-r--r--soh/soh/Enhancements/Holiday/LL.h86
-rw-r--r--soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp42
3 files changed, 254 insertions, 3 deletions
diff --git a/soh/soh/Enhancements/Holiday/LL.cpp b/soh/soh/Enhancements/Holiday/LL.cpp
new file mode 100644
index 000000000..344d8043e
--- /dev/null
+++ b/soh/soh/Enhancements/Holiday/LL.cpp
@@ -0,0 +1,129 @@
+#include "Holiday.hpp"
+#include "LL.h"
+
+extern "C" {
+#include "macros.h"
+#include "functions.h"
+#include "variables.h"
+extern PlayState* gPlayState;
+
+// TODO: Include anything you need here from C land
+}
+
+// TODO: Change this to YourName
+#define AUTHOR "LL"
+#define CVAR(v) "gHoliday." AUTHOR "." v
+
+static ImVec4 customColorZero = RAINBOW_PRESETS[0][0];
+static ImVec4 customColorOne = RAINBOW_PRESETS[0][1];
+static ImVec4 customColorMinusZero = RAINBOW_PRESETS[0][2];
+static ImVec4 customColorMinusOne = RAINBOW_PRESETS[0][3];
+
+ImVec4 Color_LUSToImGui(Color_RGBA8 color) {
+ ImVec4 result;
+
+ result.x = color.r / 255.0f;
+ result.y = color.g / 255.0f;
+ result.z = color.b / 255.0f;
+ result.w = color.a / 255.0f;
+
+ return result;
+}
+
+Color_RGBA8 Color_ImGuiToLUS(ImVec4 color) {
+ Color_RGBA8 result;
+
+ result.r = static_cast<uint8_t>(color.x * 255);
+ result.g = static_cast<uint8_t>(color.y * 255);
+ result.b = static_cast<uint8_t>(color.z * 255);
+ result.a = static_cast<uint8_t>(color.w * 255);
+
+ return result;
+}
+
+static void OnConfigurationChanged() {
+ Color_RGBA8 c1 = CVarGetColor(CVAR("lCustomRainbow1"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][0]));
+ Color_RGBA8 c2 = CVarGetColor(CVAR("lCustomRainbow2"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][1]));
+ Color_RGBA8 c3 = CVarGetColor(CVAR("lCustomRainbow3"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][2]));
+ Color_RGBA8 c4 = CVarGetColor(CVAR("lCustomRainbow4"), Color_ImGuiToLUS(RAINBOW_PRESETS[0][3]));
+
+ customColorZero = Color_LUSToImGui((Color_RGBA8)c1);
+ customColorOne = Color_LUSToImGui((Color_RGBA8)c2);
+ customColorMinusZero = Color_LUSToImGui((Color_RGBA8)c3);
+ customColorMinusOne = Color_LUSToImGui((Color_RGBA8)c4);
+
+ // TODO: Register any hooks or things that need to run on startup and when the main CVar is toggled
+ // Note: Hooks should be registered/unregistered depending on the CVar state (Use COND_HOOK or COND_ID_HOOK)
+
+ // COND_HOOK(OnSceneSpawnActors, CVarGetInteger(CVAR("Enabled"), 0), []() {
+ // // Spawn your own actors?
+ // });
+
+ // COND_ID_HOOK(OnActorInit, ACTOR_OBJ_TSUBO, CVarGetInteger(CVAR("DoSomethingWithPots"), 0), [](void* actorRef) {
+ // // Do something with pots?
+ // });
+}
+
+static void DrawMenu() {
+ ImGui::SeparatorText(AUTHOR);
+ if (ImGui::BeginMenu("Customize Rainbows")) {
+ UIWidgets::EnhancementCheckbox("Enable", CVAR("lEnableCustomRainbows"));
+ if (CVarGetInteger(CVAR("lEnableCustomRainbows"), 0)) {
+ ImGui::ColorEdit3("Color 1", (float*)&customColorZero, ImGuiColorEditFlags_NoInputs);
+ ImGui::ColorEdit3("Color 2", (float*)&customColorOne, ImGuiColorEditFlags_NoInputs);
+ ImGui::ColorEdit3("Color 3", (float*)&customColorMinusZero, ImGuiColorEditFlags_NoInputs);
+ ImGui::ColorEdit3("Color 4", (float*)&customColorMinusOne, ImGuiColorEditFlags_NoInputs);
+
+ UIWidgets::PaddedText("Presets", true, false);
+ size_t rainbowPresetIdx = 0;
+ if (UIWidgets::EnhancementCombobox(CVAR("lCustomRainbowPreset"), RAINBOW_PRESET_NAMES, 0) &&
+ (rainbowPresetIdx = CVarGetInteger(CVAR("lCustomRainbowPreset"), 0)) <= RAINBOW_PRESET_LEN) { //paranoia
+ customColorZero = RAINBOW_PRESETS[rainbowPresetIdx][0];
+ customColorOne = RAINBOW_PRESETS[rainbowPresetIdx][1];
+ customColorMinusZero = RAINBOW_PRESETS[rainbowPresetIdx][2];
+ customColorMinusOne = RAINBOW_PRESETS[rainbowPresetIdx][3];
+ }
+
+ Color_RGBA8 color1, color2, color3, color4;
+ color1.r = static_cast<uint8_t>(customColorZero.x * 255.0f);
+ color1.g = static_cast<uint8_t>(customColorZero.y * 255.0f);
+ color1.b = static_cast<uint8_t>(customColorZero.z * 255.0f);
+
+ color2.r = static_cast<uint8_t>(customColorOne.x * 255.0f);
+ color2.g = static_cast<uint8_t>(customColorOne.y * 255.0f);
+ color2.b = static_cast<uint8_t>(customColorOne.z * 255.0f);
+
+ color3.r = static_cast<uint8_t>(customColorMinusZero.x * 255.0f);
+ color3.g = static_cast<uint8_t>(customColorMinusZero.y * 255.0f);
+ color3.b = static_cast<uint8_t>(customColorMinusZero.z * 255.0f);
+
+ color4.r = static_cast<uint8_t>(customColorMinusOne.x * 255.0f);
+ color4.g = static_cast<uint8_t>(customColorMinusOne.y * 255.0f);
+ color4.b = static_cast<uint8_t>(customColorMinusOne.z * 255.0f);
+
+ CVarSetColor(CVAR("lCustomRainbow1"), color1);
+ CVarSetColor(CVAR("lCustomRainbow2"), color2);
+ CVarSetColor(CVAR("lCustomRainbow3"), color3);
+ CVarSetColor(CVAR("lCustomRainbow4"), color4);
+
+ OnConfigurationChanged();
+ }
+
+ ImGui::EndMenu();
+
+ }
+ //if (UIWidgets::EnhancementCheckbox("DoSomethingWithPots", CVAR("DoSomethingWithPots"))) {
+ // OnConfigurationChanged();
+ //}
+}
+
+static void RegisterMod() {
+ // #region Leave this alone unless you know what you are doing
+ OnConfigurationChanged();
+ // #endregion
+
+ // TODO: Anything you want to run once on startup
+}
+
+// TODO: Uncomment this line to enable the mod
+static Holiday holiday(DrawMenu, RegisterMod);
diff --git a/soh/soh/Enhancements/Holiday/LL.h b/soh/soh/Enhancements/Holiday/LL.h
new file mode 100644
index 000000000..ba936b6c3
--- /dev/null
+++ b/soh/soh/Enhancements/Holiday/LL.h
@@ -0,0 +1,86 @@
+#ifndef LL_H
+#define LL_H
+
+#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
+#include "soh/Enhancements/game-interactor/GameInteractor.h"
+
+const size_t RAINBOW_PRESET_LEN = 9;
+
+static const char* RAINBOW_PRESET_NAMES[RAINBOW_PRESET_LEN] = {
+ "Christmas",
+ "Transgender",
+ "Nonbinary",
+ "Bisexual",
+ "Lesbian",
+ "Gay (MLM)",
+ "Asexual",
+ "Brazil",
+ "Italy"
+};
+
+static const ImVec4 RAINBOW_PRESETS[RAINBOW_PRESET_LEN][4] = {
+ { //christmas
+ {0.0/255.0, 140.0/255.0, 69.0/255.0, 0},
+ {205.0/255.0, 33.0/255.0, 42.0/255.0, 0},
+ {0.0/255.0, 140.0/255.0, 69.0/255.0, 0},
+ {205.0/255.0, 33.0/255.0, 42.0/255.0, 0}
+ },
+ { //trans
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {255.0/255.0, 159.0/255.0, 186.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {71.0/255.0, 186.0/255.0, 230.0/255.0, 0}
+ },
+
+ { //enby
+ {252.0/255.0, 244.0/255.0, 52.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {156.0/255.0, 89.0/255.0, 209.0/255.0, 0},
+ {0.0/255.0, 0.0/255.0, 0.0/255.0, 0}
+ },
+
+ { //bi
+ {155.0/255.0, 79.0/255.0, 150.0/255.0, 0},
+ {0.0/255.0, 56.0/255.0, 168.0/255.0, 0},
+ {155.0/255.0, 79.0/255.0, 150.0/255.0, 0},
+ {214.0/255.0, 2.0/255.0, 112.0/255.0, 0}
+ },
+
+ { //lesbian
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {213.0/255.0, 45.0/255.0, 0.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {163.0/255.0, 2.0/255.0, 98.0/255.0, 0}
+ },
+
+ { //gay
+ {7.0/255.0, 141.0/255.0, 112.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {123.0/255.0, 173.0/255.0, 226.0/255.0, 0},
+ {61.0/255.0, 26.0/255.0, 120.0/255.0, 0}
+ },
+
+ { //ace
+ {0.0/255.0, 0.0/255.0, 0.0/255.0, 0},
+ {163.0/255.0, 163.0/255.0, 163.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {128.0/255.0, 0.0/255.0, 128.0/255.0, 0}
+ },
+
+ { //br
+ {0.0/255.0, 151.0/255.0, 57.0/255.0, 0},
+ {254.0/255.0, 221.0/255.0, 0.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {1.0/255.0, 33.0/255.0, 105.0/255.0, 0}
+ },
+
+ { //it
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {0.0/255.0, 140.0/255.0, 69.0/255.0, 0},
+ {255.0/255.0, 255.0/255.0, 255.0/255.0, 0},
+ {205.0/255.0, 33.0/255.0, 42.0/255.0, 0}
+ }
+
+};
+
+#endif
diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
index ee6b08fd4..426101fdd 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
@@ -493,6 +493,8 @@ void ResetPositionAll() {
int hue = 0;
+#define CVAR_LL(v) "gHoliday." "LL" "." v
+
// Runs every frame to update rainbow hue, a potential future optimization is to only run this a once or twice a second and increase the speed of the rainbow hue rotation.
void CosmeticsUpdateTick() {
int index = 0;
@@ -501,10 +503,44 @@ void CosmeticsUpdateTick() {
if (cosmeticOption.supportsRainbow && CVarGetInteger(cosmeticOption.rainbowCvar, 0)) {
double frequency = 2 * M_PI / (360 * rainbowSpeed);
Color_RGBA8 newColor;
- newColor.r = static_cast<uint8_t>(sin(frequency * (hue + index) + 0) * 127) + 128;
- newColor.g = static_cast<uint8_t>(sin(frequency * (hue + index) + (2 * M_PI / 3)) * 127) + 128;
- newColor.b = static_cast<uint8_t>(sin(frequency * (hue + index) + (4 * M_PI / 3)) * 127) + 128;
+
newColor.a = 255;
+
+ if (!CVarGetInteger(CVAR_LL("lEnableCustomRainbows"), 0)) {
+ newColor.r = static_cast<uint8_t>(sin(frequency * (hue + index) + 0) * 127) + 128;
+ newColor.g = static_cast<uint8_t>(sin(frequency * (hue + index) + (2 * M_PI / 3)) * 127) + 128;
+ newColor.b = static_cast<uint8_t>(sin(frequency * (hue + index) + (4 * M_PI / 3)) * 127) + 128;
+ }
+ else {
+ Color_RGBA8 customColorZero = CVarGetColor(CVAR_LL("lCustomRainbow1"), {});
+ Color_RGBA8 customColorOne = CVarGetColor(CVAR_LL("lCustomRainbow2"), {});
+ Color_RGBA8 customColorMinusZero = CVarGetColor(CVAR_LL("lCustomRainbow3"), {});
+ Color_RGBA8 customColorMinusOne = CVarGetColor(CVAR_LL("lCustomRainbow4"), {});
+ float sinangle = sin(frequency * (hue + index));
+ bool quadrant1 = hue <= (360 * rainbowSpeed) / 4;
+ bool quadrant2 = hue >= (360 * rainbowSpeed) / 4 && hue <= (360 * rainbowSpeed) / 2;
+ bool quadrant3 = hue >= (360 * rainbowSpeed) / 2 && hue <= (360 * rainbowSpeed) * 3 / 4;
+ bool quadrant4 = hue >= (360 * rainbowSpeed) * 3 / 4;
+
+ if (quadrant1) { //zero to one
+ newColor.r = sinangle * (customColorOne.r - customColorZero.r) + customColorZero.r;
+ newColor.g = sinangle * (customColorOne.g - customColorZero.g) + customColorZero.g;
+ newColor.b = sinangle * (customColorOne.b - customColorZero.b) + customColorZero.b;
+ } else if (quadrant2) { //one to zero
+ newColor.r = sinangle * (customColorOne.r - customColorMinusZero.r) + customColorMinusZero.r;
+ newColor.g = sinangle * (customColorOne.g - customColorMinusZero.g) + customColorMinusZero.g;
+ newColor.b = sinangle * (customColorOne.b - customColorMinusZero.b) + customColorMinusZero.b;
+ } else if (quadrant3) { //zero to minus one
+ newColor.r = -sinangle * (customColorMinusOne.r - customColorMinusZero.r) + customColorMinusZero.r;
+ newColor.g = -sinangle * (customColorMinusOne.g - customColorMinusZero.g) + customColorMinusZero.g;
+ newColor.b = -sinangle * (customColorMinusOne.b - customColorMinusZero.b) + customColorMinusZero.b;
+ } else if (quadrant4) { //minus one to zero
+ newColor.r = -sinangle * (customColorMinusOne.r - customColorZero.r) + customColorZero.r;
+ newColor.g = -sinangle * (customColorMinusOne.g - customColorZero.g) + customColorZero.g;
+ newColor.b = -sinangle * (customColorMinusOne.b - customColorZero.b) + customColorZero.b;
+ }
+ }
+
// For alpha supported options, retain the last set alpha instead of overwriting
if (cosmeticOption.supportsAlpha) {
newColor.a = static_cast<uint8_t>(cosmeticOption.currentColor.w * 255.0f);