mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-12 11:22:00 -04:00
add lantern, midna, and heart colors
This commit is contained in:
@@ -423,7 +423,7 @@ public:
|
||||
static DUSK_GAME_DATA daMidna_texData_s const m_texDataTable[21];
|
||||
static DUSK_GAME_DATA daMidna_anmData_s const m_anmDataTable[53];
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x568 */ request_of_phase_process_class mPhase;
|
||||
/* 0x570 */ J3DModel* mpModel;
|
||||
/* 0x574 */ J3DModel* mpShadowModel;
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
|
||||
void drawSelf() { mpKanteraIcon->draw(); }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ dDlst_KanteraIcon_c* mpKanteraIcon;
|
||||
/* 0x08 */ CPaneMgr* mpParent;
|
||||
/* 0x0C */ CPaneMgr* mpGauge;
|
||||
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ item_params mItemParams[4];
|
||||
/* 0x074 */ JKRExpHeap* heap;
|
||||
/* 0x078 */ J2DScreen* mpScreen;
|
||||
|
||||
@@ -60,13 +60,9 @@ GXColor hex_color_str_to_gx_color(const std::string& hexColorStr) {
|
||||
return GXColor{r, g, b};
|
||||
}
|
||||
|
||||
static f32 rainbowPhaseAngle = 0.f;
|
||||
|
||||
GXColor get_rainbow_rgb(f32 amplitude) {
|
||||
static f32 rainbowPhaseAngle = 0.f;
|
||||
f32 angleIncrement = 1.0f; // Degrees per frame (Adjust for speed)
|
||||
rainbowPhaseAngle += angleIncrement;
|
||||
if (rainbowPhaseAngle >= 360.0f) {
|
||||
rainbowPhaseAngle -= 360.0f;
|
||||
}
|
||||
f32 phase_rad = rainbowPhaseAngle * M_PI / 180.0f;
|
||||
|
||||
u8 r_val = (u8)(amplitude * (sinf(phase_rad) + 1.0f) + 0.5f);
|
||||
@@ -78,4 +74,11 @@ GXColor get_rainbow_rgb(f32 amplitude) {
|
||||
rgbColor.b = b_val;
|
||||
rgbColor.a = 0xff;
|
||||
return rgbColor;
|
||||
}
|
||||
|
||||
void update_rainbow_rgb(f32 increment) {
|
||||
rainbowPhaseAngle += increment;
|
||||
if (rainbowPhaseAngle >= 360.0f) {
|
||||
rainbowPhaseAngle -= 360.0f;
|
||||
}
|
||||
}
|
||||
@@ -23,3 +23,5 @@ bool is_valid_hex_color_str(std::string_view hexStr);
|
||||
GXColor hex_color_str_to_gx_color(const std::string& hexColorStr);
|
||||
|
||||
GXColor get_rainbow_rgb(f32 amplitude);
|
||||
|
||||
void update_rainbow_rgb(f32 increment);
|
||||
|
||||
@@ -1,18 +1,300 @@
|
||||
#include "hooks.hpp"
|
||||
|
||||
#include "mod.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "texture_utils.hpp"
|
||||
#include "types.h"
|
||||
|
||||
#include "mods/svc/hook.hpp"
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_midna.h"
|
||||
#include "d/d_kankyo.h"
|
||||
#include "d/d_kantera_icon_meter.h"
|
||||
#include "d/d_meter2.h"
|
||||
#include "d/d_meter2_draw.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/d_pane_class.h"
|
||||
#include "m_Do/m_Do_dvd_thread.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
DEFINE_HOOK_SYMBOL(
|
||||
"mDoDvdThd_mountArchive_c::execute", s32(mDoDvdThd_mountArchive_c*), MountArchiveExecute);
|
||||
|
||||
void mount_archive_execute_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto archive = mods::arg<mDoDvdThd_mountArchive_c*>(args, 0);
|
||||
handle_texture_overrides_on_load(archive);
|
||||
}
|
||||
|
||||
// Helper for getting lantern color
|
||||
std::optional<GXColor> get_lantern_color() {
|
||||
auto lanternColorStr = get_str_option(get_cvars().lanternGlowColor, "");
|
||||
if (is_valid_hex_color_str(lanternColorStr) || lanternColorStr == "rainbow") {
|
||||
if (is_valid_hex_color_str(lanternColorStr)) {
|
||||
return hex_color_str_to_gx_color(lanternColorStr);
|
||||
}
|
||||
|
||||
// Assume rainbow if not a valid hex str
|
||||
auto lanternColor = get_rainbow_rgb(127.5f);
|
||||
lanternColor.r /= 2;
|
||||
lanternColor.g /= 2;
|
||||
lanternColor.b /= 2;
|
||||
return lanternColor;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Override Lantern ambience color
|
||||
DEFINE_HOOK(&dKy_WolfEyeLight_set, WolfEyeLightSet);
|
||||
void wolf_eye_light_set_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto maybeLanternColor = get_lantern_color();
|
||||
if (maybeLanternColor.has_value()) {
|
||||
auto lanternColor = maybeLanternColor.value();
|
||||
|
||||
dScnKy_env_light_c* kankyo = dKy_getEnvlight();
|
||||
kankyo->field_0x0c18[0].mColor.r = lanternColor.r;
|
||||
kankyo->field_0x0c18[0].mColor.g = lanternColor.g;
|
||||
kankyo->field_0x0c18[0].mColor.b = lanternColor.b;
|
||||
}
|
||||
}
|
||||
|
||||
// Override Lantern Sphere color
|
||||
DEFINE_HOOK(&daAlink_c::preKandelaarDraw, PreKandelaarDraw);
|
||||
void pre_kandelaar_draw_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto maybeLanternColor = get_lantern_color();
|
||||
if (maybeLanternColor.has_value()) {
|
||||
auto lanternColor = maybeLanternColor.value();
|
||||
|
||||
J3DMaterial* mat_p = daAlink_getAlinkActorClass()->mpKanteraGlowModel->getModelData()->getMaterialNodePointer(0);
|
||||
|
||||
J3DGXColorS10 color;
|
||||
color.r = lanternColor.r;
|
||||
color.g = lanternColor.g;
|
||||
color.b = lanternColor.b;
|
||||
color.a = 255;
|
||||
mat_p->setTevColor(1, &color);
|
||||
|
||||
color.r = lanternColor.r;
|
||||
color.g = lanternColor.g;
|
||||
color.b = lanternColor.b;
|
||||
mat_p->setTevColor(2, &color);
|
||||
}
|
||||
}
|
||||
|
||||
// Override Main Lantern Meter Color
|
||||
DEFINE_HOOK(&CPaneMgr::setBlackWhite, CPaneMgrSetBlackWhite);
|
||||
HookAction cpane_mgr_set_black_white_pre(ModContext*, void* args, void* retval, void* userdata) {
|
||||
// Check for magic meter
|
||||
auto pane = mods::arg<CPaneMgr*>(args, 0);
|
||||
if (dMeter2Info_getMeterClass() == NULL || pane != dMeter2Info_getMeterClass()->getMeterDrawPtr()->mpMagicMeter) {
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
// If magic meter, check to see we're setting lantern colors
|
||||
auto& black = mods::arg_ref<JUtility::TColor>(args, 1);
|
||||
auto& white = mods::arg_ref<JUtility::TColor>(args, 2);
|
||||
if (black != JUtility::TColor(255, 255, 140, 255) &&
|
||||
white != JUtility::TColor(230, 170, 0, 255)) {
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
auto maybeLanternColor = get_lantern_color();
|
||||
if (maybeLanternColor.has_value()) {
|
||||
auto lanternColor = maybeLanternColor.value();
|
||||
black = JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255);
|
||||
white = JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255);
|
||||
}
|
||||
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
// Override Lantern Icon Meter Color
|
||||
DEFINE_HOOK(&dKantera_icon_c::setNowGauge, KanteraIconSetNowGauge);
|
||||
void kantera_icon_set_now_gauge_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto maybeLanternColor = get_lantern_color();
|
||||
if (maybeLanternColor.has_value()) {
|
||||
auto lanternColor = maybeLanternColor.value();
|
||||
|
||||
auto kanteraIcon = mods::arg<dKantera_icon_c*>(args, 0);
|
||||
kanteraIcon->mpGauge->setBlackWhite(
|
||||
JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255),
|
||||
JUtility::TColor(lanternColor.r, lanternColor.g, lanternColor.b, 255));
|
||||
}
|
||||
}
|
||||
|
||||
// Override Light Sword Effect Color
|
||||
DEFINE_HOOK(&daAlink_c::setLightningSwordEffect, SetLightningSwordEffect);
|
||||
void set_lightning_sword_effect_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto glowColorStr = get_str_option(get_cvars().lightSwordGlowColor, "");
|
||||
if (is_valid_hex_color_str(glowColorStr) || glowColorStr == "rainbow") {
|
||||
GXColor glowColor{};
|
||||
if (glowColorStr == "rainbow") {
|
||||
glowColor = get_rainbow_rgb(127.5f);
|
||||
} else {
|
||||
glowColor = hex_color_str_to_gx_color(glowColorStr);
|
||||
}
|
||||
|
||||
auto link = mods::arg<daAlink_c*>(args, 0);
|
||||
if (link->mEquipItem == 0x103 && link->checkNoResetFlg3(daPy_py_c::FLG3_UNK_100000)) {
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
auto emitter = dComIfGp_particle_getEmitter(link->field_0x327c[i]);
|
||||
if (emitter != NULL) {
|
||||
emitter->setGlobalEnvColor(glowColor.r, glowColor.g, glowColor.b);
|
||||
emitter->setGlobalPrmColor(glowColor.r, glowColor.g, glowColor.b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Heart Icon tags
|
||||
static constexpr std::array heart_tags = {
|
||||
MULTI_CHAR('hear_00'), MULTI_CHAR('hear_01'), MULTI_CHAR('hear_02'), MULTI_CHAR('hear_03'), MULTI_CHAR('hear_04'), MULTI_CHAR('hear_05'), MULTI_CHAR('hear_06'),
|
||||
MULTI_CHAR('hear_07'), MULTI_CHAR('hear_08'), MULTI_CHAR('hear_09'), MULTI_CHAR('hear_10'), MULTI_CHAR('hear_11'), MULTI_CHAR('hear_12'), MULTI_CHAR('hear_13'),
|
||||
MULTI_CHAR('hear_14'), MULTI_CHAR('hear_15'), MULTI_CHAR('hear_16'), MULTI_CHAR('hear_17'), MULTI_CHAR('hear_18'), MULTI_CHAR('hear_19'), MULTI_CHAR('bigh_00'),
|
||||
MULTI_CHAR('bigh_01'), MULTI_CHAR('bigh_02'), MULTI_CHAR('bigh_03'), /*MULTI_CHAR('bigh_n')*/
|
||||
};
|
||||
|
||||
DEFINE_HOOK(&dMeter2Draw_c::init, dMeter2Init);
|
||||
void d_meter_2_init_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto dMeter2Draw = mods::arg<dMeter2Draw_c*>(args, 0);
|
||||
auto heartColorStr = get_str_option(get_cvars().heartColor, "");
|
||||
if (is_valid_hex_color_str(heartColorStr)) {
|
||||
auto heartColor = hex_color_str_to_gx_color(heartColorStr);
|
||||
auto screen = dMeter2Draw->getMainScreenPtr();
|
||||
for (auto tag : heart_tags) {
|
||||
auto element = static_cast<J2DPicture*>(screen->search(tag));
|
||||
if (element != nullptr) {
|
||||
element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override Midna Hair Color
|
||||
DEFINE_HOOK(&daMidna_c::create, MidnaCreate);
|
||||
void midna_create_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto step = reinterpret_cast<int*>(retval);
|
||||
// check for cPhs_Compleate
|
||||
if (*step != 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto midna = mods::arg<daMidna_c*>(args, 0);
|
||||
midna->field_0x6e0 = *get_midna_hair_normalColor();
|
||||
if (dKy_darkworld_check()) {
|
||||
midna->field_0x6e8 = *get_midna_hair_normalKColor();
|
||||
midna->field_0x6ec = *get_midna_hair_normalKColor2();
|
||||
} else {
|
||||
midna->field_0x6e8 = *get_midna_hair_lNormalKColor();
|
||||
midna->field_0x6ec = *get_midna_hair_lNormalKColor2();
|
||||
}
|
||||
}
|
||||
|
||||
// Override Midna Hair Color Part 2
|
||||
DEFINE_HOOK(&daMidna_c::setBodyPartMatrix, MidnaSetBodyPartMatrix);
|
||||
|
||||
static GXColorS10 midnaField0x6e0{};
|
||||
static GXColor midnaField0x6e8{};
|
||||
static GXColor midnaField0x6ec{};
|
||||
|
||||
// Copy the original values from before the function
|
||||
HookAction midna_set_body_part_matrix_pre(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto midna = mods::arg<daMidna_c*>(args, 0);
|
||||
|
||||
midnaField0x6e0 = midna->field_0x6e0;
|
||||
midnaField0x6e8 = midna->field_0x6e8;
|
||||
midnaField0x6ec = midna->field_0x6ec;
|
||||
|
||||
return HOOK_CONTINUE;
|
||||
}
|
||||
|
||||
void midna_set_body_part_matrix_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto midna = mods::arg<daMidna_c*>(args, 0);
|
||||
if (midna->mpHairhandBmd != NULL) {
|
||||
// Restore the original values from before the function ran (this undoes the chase)
|
||||
midna->field_0x6e0 = midnaField0x6e0;
|
||||
midna->field_0x6e8 = midnaField0x6e8;
|
||||
midna->field_0x6ec = midnaField0x6ec;
|
||||
|
||||
// statement copied from inside function to determine colors
|
||||
bool bigColors = midna->checkStateFlg0(daMidna_c::FLG0_UNK_10000000) ||
|
||||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_HAIR].mResID ||
|
||||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_S_TAKES].mResID ||
|
||||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_S_WAITS].mResID ||
|
||||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_S_PACKAWAY].mResID ||
|
||||
midna->mBckHeap[2].getIdx() == daMidna_c::m_anmDataTable[daMidna_c::ANM_GRABST].mResID ||
|
||||
midna->checkEndResetStateFlg0(daMidna_c::ERFLG0_UNK_40) ||
|
||||
dComIfGp_checkPlayerStatus1(0, 0x800000);
|
||||
|
||||
GXColorS10 color{};
|
||||
GXColor kcolor1{};
|
||||
GXColor kcolor2{};
|
||||
|
||||
// Then set our own colors
|
||||
if (bigColors) {
|
||||
kcolor1 = *get_midna_hair_bigKColor();
|
||||
if (dKy_darkworld_check()) {
|
||||
color = *get_midna_hair_bigColor();
|
||||
kcolor2 = *get_midna_hair_normalKColor2();
|
||||
} else {
|
||||
color = *get_midna_hair_lBigColor();
|
||||
kcolor2 = *get_midna_hair_lBigKColor2();
|
||||
}
|
||||
} else {
|
||||
color = *get_midna_hair_normalColor();
|
||||
if (dKy_darkworld_check()) {
|
||||
kcolor1 = *get_midna_hair_normalKColor();
|
||||
kcolor2 = *get_midna_hair_normalKColor2();
|
||||
} else {
|
||||
kcolor1 = *get_midna_hair_lNormalKColor();
|
||||
kcolor2 = *get_midna_hair_lNormalKColor2();
|
||||
}
|
||||
}
|
||||
|
||||
// And reapply the chase
|
||||
cLib_chaseS(&midna->field_0x6e0.r, color.r, 10);
|
||||
cLib_chaseS(&midna->field_0x6e0.g, color.g, 10);
|
||||
cLib_chaseS(&midna->field_0x6e0.b, color.b, 10);
|
||||
cLib_chaseUC(&midna->field_0x6e8.r, kcolor1.r, 10);
|
||||
cLib_chaseUC(&midna->field_0x6e8.g, kcolor1.g, 10);
|
||||
cLib_chaseUC(&midna->field_0x6e8.b, kcolor1.b, 10);
|
||||
cLib_chaseUC(&midna->field_0x6ec.r, kcolor2.r, 10);
|
||||
cLib_chaseUC(&midna->field_0x6ec.g, kcolor2.g, 10);
|
||||
cLib_chaseUC(&midna->field_0x6ec.b, kcolor2.b, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Override Midna Charge Ring Color
|
||||
DEFINE_HOOK(&daAlink_c::setWolfLockDomeModel, SetWolfLockDomeModel);
|
||||
void wolf_lock_dome_model_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto domeRingColorStr = get_str_option(get_cvars().midnaChargeRingColor, "");
|
||||
if (is_valid_hex_color_str(domeRingColorStr)) {
|
||||
auto domeRingColor = hex_color_str_to_gx_color(domeRingColorStr);
|
||||
const u8 domeWave1RGBA[3] = {domeRingColor.r, domeRingColor.g, domeRingColor.b};
|
||||
const u8 domeWave2RGBA[3] = {domeRingColor.r, domeRingColor.g, domeRingColor.b};
|
||||
u8** chromaRegisterTable = reinterpret_cast<u8**>(&daAlink_getAlinkActorClass()->field_0x0724->mAnmCRegDataR);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8* currentTable = chromaRegisterTable[i];
|
||||
const u8 currentWave1Color = domeWave1RGBA[i];
|
||||
const u8 currentWave2Color = domeWave2RGBA[i];
|
||||
const u8 currentBaseColor = (currentWave1Color + currentWave2Color) / 2;
|
||||
|
||||
currentTable[0x3] = currentBaseColor; // Set Alpha for the ring base
|
||||
currentTable[0x13] = currentWave1Color; // Set Alpha for ring wave 1
|
||||
currentTable[0x23] = currentWave2Color; // Set Alpha for ring wave 2
|
||||
currentTable[0xB] = currentBaseColor; // Set Alpha for darkworld ring base
|
||||
currentTable[0x1B] = currentWave1Color; // Set Alpha for darkworld ring wave 1
|
||||
currentTable[0x2B] = currentWave2Color; // Set Alpha for darkworld ring wave 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModResult add_all_hooks() {
|
||||
auto result = mods::hook::add_post<MountArchiveExecute>(mount_archive_execute_post);
|
||||
if (result != MOD_OK) {
|
||||
@@ -20,5 +302,65 @@ ModResult add_all_hooks() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<WolfEyeLightSet>(wolf_eye_light_set_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to dKy_WolfEyeLight_set, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<PreKandelaarDraw>(pre_kandelaar_draw_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to daAlink_c::preKandelaarDraw, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<SetWolfLockDomeModel>(wolf_lock_dome_model_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to daAlink_c::setWolfLockDomeModel, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_pre<CPaneMgrSetBlackWhite>(cpane_mgr_set_black_white_pre);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add pre hook to CPaneMgr::setBlackWhite, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<KanteraIconSetNowGauge>(kantera_icon_set_now_gauge_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to dKantera_icon_c::setNowGauge, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<SetLightningSwordEffect>(set_lightning_sword_effect_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to daAlink_c::setLightningSwordEffect, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<MidnaCreate>(midna_create_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to daMidna_c::create, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_pre<MidnaSetBodyPartMatrix>(midna_set_body_part_matrix_pre);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add pre hook to daMidna_c::setBodyPartMatrix, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<MidnaSetBodyPartMatrix>(midna_set_body_part_matrix_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to daMidna_c::setBodyPartMatrix, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mods::hook::add_post<dMeter2Init>(d_meter_2_init_post);
|
||||
if (result != MOD_OK) {
|
||||
mods::log::debug("failed to add post hook to dMeter2Draw_c::init, Result {}", static_cast<int>(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
@@ -1,55 +1,75 @@
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "mod.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
static std::unordered_map<std::string_view, std::array<GXColor, 9>> const midnaHairColors = {
|
||||
{"Default", {{
|
||||
/*l_lNormalKColor*/ /*l_normalKColor*/ /*l_normalColor*/
|
||||
{0xFF, 0xDC, 0x00}, {0xB4, 0x87, 0x00}, {0x50, 0x00, 0x00},
|
||||
/*l_bigKColor*/ /*l_lBigColor*/ /*l_bigColor*/
|
||||
{0x50, 0x00, 0x00}, {0xFF, 0x78, 0x00}, {0xFF, 0x64, 0x78},
|
||||
/*l_lNormalKColor2*//*l_normalKColor2*/ /*l_lBigKColor2*/
|
||||
{0x00, 0xC3, 0xEB}, {0xC3, 0xC3, 0x00}, {0xAA, 0xFF, 0xC3}}}},
|
||||
{"Pink", {{
|
||||
{0xF5, 0xCF, 0xF3}, {0xAD, 0x7F, 0x7F}, {0x1B, 0x00, 0x20},
|
||||
{0x3C, 0x02, 0x58}, {0xE3, 0x72, 0xF2}, {0xE3, 0x5F, 0xF8},
|
||||
{0xDD, 0x00, 0xEB}, {0xDD, 0x00, 0xC3}, {0xF6, 0x4C, 0xFF}}}},
|
||||
{"Red", {{
|
||||
{0xE4, 0x65, 0x41}, {0xA1, 0x3E, 0x22}, {0x21, 0x00, 0x00},
|
||||
{0x4F, 0x02, 0x01}, {0xF0, 0x3A, 0x25}, {0xF0, 0x30, 0x8C},
|
||||
{0xEB, 0x00, 0x00}, {0xEB, 0x00, 0x00}, {0xFF, 0x4F, 0x3A}}}},
|
||||
{"Yellow", {{
|
||||
{0x91, 0x83, 0x0E}, {0x66, 0x50, 0x07}, {0x0E, 0x0B, 0x00},
|
||||
{0x24, 0x25, 0x02}, {0xCB, 0xB7, 0x00}, {0xCB, 0x99, 0x78},
|
||||
{0xEB, 0xDE, 0x00}, {0xEB, 0xDE, 0x00}, {0xFF, 0xF8, 0xBF}}}},
|
||||
{"Green", {{
|
||||
{0x35, 0x79, 0x53}, {0x25, 0x4A, 0x2B}, {0x00, 0x0E, 0x05},
|
||||
{0x0A, 0x29, 0x10}, {0x00, 0xB6, 0x6F}, {0x00, 0x98, 0xB3},
|
||||
{0x1F, 0xEB, 0x00}, {0x1F, 0xEB, 0x00}, {0x9A, 0xFF, 0x81}}}},
|
||||
{"Blue", {{
|
||||
{0x00, 0x72, 0xFF}, {0x00, 0x46, 0x85}, {0x00, 0x08, 0x28},
|
||||
{0x16, 0x1B, 0x5D}, {0x00, 0x60, 0xFF}, {0x00, 0x50, 0xFF},
|
||||
{0x00, 0x48, 0xEB}, {0x00, 0x48, 0xC3}, {0x3A, 0x66, 0xFF}}}},
|
||||
{"Purple", {{
|
||||
{0x6F, 0x34, 0xFF}, {0x4E, 0x20, 0x85}, {0x0D, 0x00, 0x34},
|
||||
{0x15, 0x08, 0x79}, {0x62, 0x00, 0xFF}, {0x62, 0x00, 0xFF},
|
||||
{0x7B, 0x00, 0xEB}, {0x7B, 0x00, 0xC3}, {0x94, 0x3E, 0xFF}}}},
|
||||
{"Brown", {{
|
||||
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x1A, 0x05, 0x00},
|
||||
{0x3C, 0x19, 0x0E}, {0x3F, 0x1D, 0x0B}, {0x3F, 0x18, 0x7E},
|
||||
{0x3F, 0x1D, 0x0B}, {0x3F, 0x1D, 0x09}, {0x59, 0x32, 0x1E}}}},
|
||||
{"White", {{
|
||||
{0xF0, 0xF1, 0xF1}, {0xA9, 0x94, 0x7E}, {0x09, 0x0B, 0x0C},
|
||||
{0x22, 0x24, 0x24}, {0xFF, 0xFF, 0xFF}, {0xFF, 0xD5, 0xFF},
|
||||
{0xEA, 0xEA, 0xEA}, {0xEA, 0xEA, 0xC2}, {0xF3, 0xF3, 0xF3}}}},
|
||||
{"Black", {{
|
||||
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x0B, 0x0B, 0x0B},
|
||||
{0x23, 0x23, 0x23}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x78},
|
||||
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}}}},
|
||||
};
|
||||
#include <array>
|
||||
|
||||
static constexpr std::array<std::array<GXColor, 9>, 10> midnaHairColors = {{
|
||||
// Default
|
||||
{{
|
||||
/*l_lNormalKColor*/ /*l_normalKColor*/ /*l_normalColor*/
|
||||
{0xFF, 0xDC, 0x00}, {0xB4, 0x87, 0x00}, {0x50, 0x00, 0x00},
|
||||
/*l_bigKColor*/ /*l_lBigColor*/ /*l_bigColor*/
|
||||
{0x50, 0x00, 0x00}, {0xFF, 0x78, 0x00}, {0xFF, 0x64, 0x78},
|
||||
/*l_lNormalKColor2*//*l_normalKColor2*/ /*l_lBigKColor2*/
|
||||
{0x00, 0xC3, 0xEB}, {0xC3, 0xC3, 0x00}, {0xAA, 0xFF, 0xC3}
|
||||
}},
|
||||
// Pink
|
||||
{{
|
||||
{0xF5, 0xCF, 0xF3}, {0xAD, 0x7F, 0x7F}, {0x1B, 0x00, 0x20},
|
||||
{0x3C, 0x02, 0x58}, {0xE3, 0x72, 0xF2}, {0xE3, 0x5F, 0xF8},
|
||||
{0xDD, 0x00, 0xEB}, {0xDD, 0x00, 0xC3}, {0xF6, 0x4C, 0xFF}
|
||||
}},
|
||||
// Red
|
||||
{{
|
||||
{0xE4, 0x65, 0x41}, {0xA1, 0x3E, 0x22}, {0x21, 0x00, 0x00},
|
||||
{0x4F, 0x02, 0x01}, {0xF0, 0x3A, 0x25}, {0xF0, 0x30, 0x8C},
|
||||
{0xEB, 0x00, 0x00}, {0xEB, 0x00, 0x00}, {0xFF, 0x4F, 0x3A}
|
||||
}},
|
||||
// Yellow
|
||||
{{
|
||||
{0x91, 0x83, 0x0E}, {0x66, 0x50, 0x07}, {0x0E, 0x0B, 0x00},
|
||||
{0x24, 0x25, 0x02}, {0xCB, 0xB7, 0x00}, {0xCB, 0x99, 0x78},
|
||||
{0xEB, 0xDE, 0x00}, {0xEB, 0xDE, 0x00}, {0xFF, 0xF8, 0xBF}
|
||||
}},
|
||||
// Green
|
||||
{{
|
||||
{0x35, 0x79, 0x53}, {0x25, 0x4A, 0x2B}, {0x00, 0x0E, 0x05},
|
||||
{0x0A, 0x29, 0x10}, {0x00, 0xB6, 0x6F}, {0x00, 0x98, 0xB3},
|
||||
{0x1F, 0xEB, 0x00}, {0x1F, 0xEB, 0x00}, {0x9A, 0xFF, 0x81}
|
||||
}},
|
||||
// Blue
|
||||
{{
|
||||
{0x00, 0x72, 0xFF}, {0x00, 0x46, 0x85}, {0x00, 0x08, 0x28},
|
||||
{0x16, 0x1B, 0x5D}, {0x00, 0x60, 0xFF}, {0x00, 0x50, 0xFF},
|
||||
{0x00, 0x48, 0xEB}, {0x00, 0x48, 0xC3}, {0x3A, 0x66, 0xFF}
|
||||
}},
|
||||
// Purple
|
||||
{{
|
||||
{0x6F, 0x34, 0xFF}, {0x4E, 0x20, 0x85}, {0x0D, 0x00, 0x34},
|
||||
{0x15, 0x08, 0x79}, {0x62, 0x00, 0xFF}, {0x62, 0x00, 0xFF},
|
||||
{0x7B, 0x00, 0xEB}, {0x7B, 0x00, 0xC3}, {0x94, 0x3E, 0xFF}
|
||||
}},
|
||||
// Brown
|
||||
{{
|
||||
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x1A, 0x05, 0x00},
|
||||
{0x3C, 0x19, 0x0E}, {0x3F, 0x1D, 0x0B}, {0x3F, 0x18, 0x7E},
|
||||
{0x3F, 0x1D, 0x0B}, {0x3F, 0x1D, 0x09}, {0x59, 0x32, 0x1E}
|
||||
}},
|
||||
// White
|
||||
{{
|
||||
{0xF0, 0xF1, 0xF1}, {0xA9, 0x94, 0x7E}, {0x09, 0x0B, 0x0C},
|
||||
{0x22, 0x24, 0x24}, {0xFF, 0xFF, 0xFF}, {0xFF, 0xD5, 0xFF},
|
||||
{0xEA, 0xEA, 0xEA}, {0xEA, 0xEA, 0xC2}, {0xF3, 0xF3, 0xF3}
|
||||
}},
|
||||
// Black
|
||||
{{
|
||||
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x0B, 0x0B, 0x0B},
|
||||
{0x23, 0x23, 0x23}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x78},
|
||||
{0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}
|
||||
}}
|
||||
}};
|
||||
|
||||
static struct {
|
||||
GXColorS10 l_normalColor = { 0x50, 0x00, 0x00, 0x00 };
|
||||
@@ -65,13 +85,8 @@ static struct {
|
||||
|
||||
void set_all_midna_hair_colors() {
|
||||
auto& g_cvars = get_cvars();
|
||||
const auto& hairBaseColor = get_str_option(g_cvars.midnaHairBaseColor, "");
|
||||
const auto& hairTipsColor = get_str_option(g_cvars.midnaHairTipsColor, "");
|
||||
|
||||
// Don't set colors if either is invalid
|
||||
if (!midnaHairColors.contains(hairBaseColor) || !midnaHairColors.contains(hairTipsColor)) {
|
||||
return;
|
||||
}
|
||||
auto hairBaseColor = get_int_option(g_cvars.midnaHairBaseColor, 0);
|
||||
auto hairTipsColor = get_int_option(g_cvars.midnaHairTipsColor, 0);
|
||||
|
||||
// Colors we have to convert to GXColorS10
|
||||
auto& normalColor = midnaHairColors.at(hairBaseColor)[2];
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "mod.hpp"
|
||||
#include "hooks.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "midna_hair_color.hpp"
|
||||
|
||||
#include "mods/service.hpp"
|
||||
#include "mods/svc/config.h"
|
||||
@@ -8,8 +10,6 @@
|
||||
#include "mods/svc/log.hpp"
|
||||
#include "mods/svc/ui.h"
|
||||
|
||||
#include "m_Do/m_Do_dvd_thread.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
DEFINE_MOD();
|
||||
@@ -35,6 +35,14 @@ std::string get_str_option(ConfigVarHandle handle, const std::string& fallback)
|
||||
return value;
|
||||
}
|
||||
|
||||
int64_t get_int_option(ConfigVarHandle handle, int64_t fallback) {
|
||||
int64_t value = fallback;
|
||||
if (handle == 0 || svc_config->get_int(mod_ctx, handle, &value) != MOD_OK) {
|
||||
return fallback;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
namespace {
|
||||
UiWindowHandle g_cosmeticsWindow = 0;
|
||||
|
||||
@@ -50,6 +58,18 @@ ModResult register_str_option(
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult register_int_option(
|
||||
const char* name, int64_t defaultValue, ConfigVarHandle& outHandle, ModError* error) {
|
||||
ConfigVarDesc cvarDesc = CONFIG_VAR_DESC_INIT;
|
||||
cvarDesc.name = name;
|
||||
cvarDesc.type = CONFIG_VAR_INT;
|
||||
cvarDesc.default_int = defaultValue;
|
||||
if (svc_config->register_var(mod_ctx, &cvarDesc, &outHandle) != MOD_OK) {
|
||||
return mods::set_error(error, MOD_ERROR, "failed to register cosmetics option");
|
||||
}
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
void add_control(UiElementHandle pane, const UiControlDesc& desc) {
|
||||
auto result = svc_ui->pane_add_control(mod_ctx, pane, &desc, nullptr);
|
||||
if (result != MOD_OK) {
|
||||
@@ -57,37 +77,121 @@ void add_control(UiElementHandle pane, const UiControlDesc& desc) {
|
||||
}
|
||||
}
|
||||
|
||||
void add_cosmetic_option(UiElementHandle left, ConfigVarHandle cvar, const std::string& name) {
|
||||
const char* kDefaultHexColorsExplanation =
|
||||
"Set the color with any 6 digit hex code. A reload will be required to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ab706e<br/>"
|
||||
"- Blue: 6382a0<br/>"
|
||||
"- Purple: 94749a<br/>"
|
||||
"- Orange: ec8644<br/>"
|
||||
"- Yellow: b9ab00<br/>"
|
||||
"- Pink: ec9fc8<br/>"
|
||||
"- Black: 505154<br/>"
|
||||
"- White: f8f7f4<br/>"
|
||||
"- Brown: 91723e<br/>";
|
||||
|
||||
const char* kGlowColorsExplanation =
|
||||
"Set the color with any 6 digit hex code, or with \"rainbow\" for a rainbow effect.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>";
|
||||
|
||||
const char* kMasterSwordColorsExplanation =
|
||||
"Set the color with any 6 digit hex code. Closing and re-opening Dusklight will be required to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: f68821<br/>"
|
||||
"- Yellow: f6f321<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- White: a0a0a0<br/>"
|
||||
"- Cyan: 30d0d0<br/>";
|
||||
|
||||
const char* kChargeRingColorsExplanation =
|
||||
"Set the color with any 6 digit hex code.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Pink: ff9f9f<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Yellow: ffff00<br/>"
|
||||
"- Green: 00ff00<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: ff00ff<br/>"
|
||||
"- Brown: 331900<br/>"
|
||||
"- White: feffff<br/>"
|
||||
"- Black: 000000<br/>";
|
||||
|
||||
void add_cosmetic_option(UiElementHandle left, ConfigVarHandle cvar, const char* name, const char* helpRml) {
|
||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||
control.kind = UI_CONTROL_STRING;
|
||||
control.label = name.c_str();
|
||||
control.help_rml = "Set the color with a 6 digit hex code. A reload may be required to see changes.";
|
||||
control.label = name;
|
||||
control.help_rml = helpRml;
|
||||
control.binding = UI_BINDING_CONFIG_VAR;
|
||||
control.config_var = cvar;
|
||||
control.max_length = 6;
|
||||
add_control(left, control);
|
||||
}
|
||||
|
||||
void add_cosmetic_option_with_rainbow(UiElementHandle left, ConfigVarHandle cvar, const char* name, const char* helpRml) {
|
||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||
control.kind = UI_CONTROL_STRING;
|
||||
control.label = name;
|
||||
control.help_rml = helpRml;
|
||||
control.binding = UI_BINDING_CONFIG_VAR;
|
||||
control.config_var = cvar;
|
||||
control.max_length = 7;
|
||||
add_control(left, control);
|
||||
}
|
||||
|
||||
void add_midna_hair_option(UiElementHandle left, ConfigVarHandle cvar, const std::string& name) {
|
||||
static const char* kMidnaHairOptions[] = {
|
||||
"Default", "Pink", "Red", "Yellow", "Green", "Blue", "Purple", "Brown", "White", "Black"
|
||||
};
|
||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||
control.kind = UI_CONTROL_SELECT;
|
||||
control.label = name.c_str();
|
||||
control.help_rml = "Choose Midna's hair color.";
|
||||
control.binding = UI_BINDING_CONFIG_VAR;
|
||||
control.config_var = cvar;
|
||||
control.options = kMidnaHairOptions;
|
||||
control.option_count = 10;
|
||||
add_control(left, control);
|
||||
}
|
||||
|
||||
ModResult build_equipment_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
add_cosmetic_option(left, g_cvars.herosTunicCapColor, "Hero's Tunic Cap Color");
|
||||
add_cosmetic_option(left, g_cvars.herosTunicTorsoColor, "Hero's Tunic Body Color");
|
||||
add_cosmetic_option(left, g_cvars.herosTunicSkirtColor, "Hero's Tunic Skirt Color");
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorCapColor, "Zora Armor Cap Color");
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorHelmetColor, "Zora Armor Helmet Color");
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorTorsoColor, "Zora Armor Torso Color");
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorScalesColor, "Zora Armor Scales Color");
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorFlippersColor, "Zora Armor Flippers Color");
|
||||
add_cosmetic_option(left, g_cvars.lanternGlowColor, "Lantern Glow Color");
|
||||
add_cosmetic_option(left, g_cvars.woodenSwordColor, "Wooden Sword Color");
|
||||
add_cosmetic_option(left, g_cvars.msBladeColor, "Master Sword Blade Color");
|
||||
add_cosmetic_option(left, g_cvars.msHandleColor, "Master Sword Handle Color");
|
||||
add_cosmetic_option(left, g_cvars.lightSwordGlowColor, "Light Sword Glow Color");
|
||||
add_cosmetic_option(left, g_cvars.boomerangColor, "Boomerang Color");
|
||||
add_cosmetic_option(left, g_cvars.ironBootsColor, "Iron Boots Color");
|
||||
add_cosmetic_option(left, g_cvars.spinnerColor, "Spinner Color");
|
||||
add_cosmetic_option(left, g_cvars.herosTunicCapColor, "Hero's Tunic Cap Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.herosTunicTorsoColor, "Hero's Tunic Body Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.herosTunicSkirtColor, "Hero's Tunic Skirt Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorCapColor, "Zora Armor Cap Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorHelmetColor, "Zora Armor Helmet Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorTorsoColor, "Zora Armor Torso Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorScalesColor, "Zora Armor Scales Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorFlippersColor, "Zora Armor Flippers Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option_with_rainbow(left, g_cvars.lanternGlowColor, "Lantern Glow Color", kGlowColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.woodenSwordColor, "Wooden Sword Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.msBladeColor, "Master Sword Blade Color", kMasterSwordColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.msHandleColor, "Master Sword Handle Color", kMasterSwordColorsExplanation);
|
||||
add_cosmetic_option_with_rainbow(left, g_cvars.lightSwordGlowColor, "Light Sword Glow Color", kGlowColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.boomerangColor, "Boomerang Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ironBootsColor, "Iron Boots Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.spinnerColor, "Spinner Color", kDefaultHexColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult build_ui_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
add_cosmetic_option(left, g_cvars.heartColor, "Heart Color", kDefaultHexColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
@@ -96,12 +200,12 @@ ModResult build_misc_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
add_cosmetic_option(left, g_cvars.midnaHairBaseColor, "Midna's Hair Base Color");
|
||||
add_cosmetic_option(left, g_cvars.midnaHairTipsColor, "Midna's Hair Tips Color");
|
||||
add_cosmetic_option(left, g_cvars.midnaChargeRingColor, "Midna Charge Ring Color");
|
||||
add_cosmetic_option(left, g_cvars.linkHairColor, "Link's Hair Color");
|
||||
add_cosmetic_option(left, g_cvars.wolfLinkColor, "Wolf Link Color");
|
||||
add_cosmetic_option(left, g_cvars.eponaColor, "Epona Color");
|
||||
add_midna_hair_option(left, g_cvars.midnaHairBaseColor, "Midna's Hair Base Color");
|
||||
add_midna_hair_option(left, g_cvars.midnaHairTipsColor, "Midna's Hair Tips Color");
|
||||
add_cosmetic_option(left, g_cvars.midnaChargeRingColor, "Midna Charge Ring Color", kChargeRingColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.linkHairColor, "Link's Hair Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.wolfLinkColor, "Wolf Link Color", kDefaultHexColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.eponaColor, "Epona Color", kDefaultHexColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
@@ -114,11 +218,13 @@ void on_open_cosmetics_menu(ModContext*, void*) {
|
||||
if (g_cosmeticsWindow != 0) {
|
||||
return;
|
||||
}
|
||||
UiTabDesc tabs[] = {UI_TAB_DESC_INIT, UI_TAB_DESC_INIT};
|
||||
UiTabDesc tabs[] = {UI_TAB_DESC_INIT, UI_TAB_DESC_INIT, UI_TAB_DESC_INIT};
|
||||
tabs[0].title = "Equipment Colors";
|
||||
tabs[0].build = build_equipment_colors_tab;
|
||||
tabs[1].title = "Misc Colors";
|
||||
tabs[1].build = build_misc_colors_tab;
|
||||
tabs[1].title = "UI Colors";
|
||||
tabs[1].build = build_ui_colors_tab;
|
||||
tabs[2].title = "Misc Colors";
|
||||
tabs[2].build = build_misc_colors_tab;
|
||||
UiWindowDesc desc = UI_WINDOW_DESC_INIT;
|
||||
desc.tabs = tabs;
|
||||
desc.tab_count = ARRAY_SIZE(tabs);
|
||||
@@ -139,15 +245,17 @@ ModResult build_panel(ModContext*, UiElementHandle panel, void*, ModError*) {
|
||||
}
|
||||
|
||||
#define REGISTER_COSMETIC_OPTION(option) \
|
||||
auto option##Result = register_str_option(#option, NULL, g_cvars.option, error); \
|
||||
if (option##Result != MOD_OK) { \
|
||||
return option##Result; \
|
||||
result = register_str_option(#option, NULL, g_cvars.option, error); \
|
||||
if (result != MOD_OK) { \
|
||||
return result; \
|
||||
} \
|
||||
|
||||
extern "C" {
|
||||
MOD_EXPORT ModResult mod_initialize(ModError* error) {
|
||||
svc_log->info(mod_ctx, "basic_cosmetics_mod initialized");
|
||||
|
||||
ModResult result{};
|
||||
|
||||
REGISTER_COSMETIC_OPTION(herosTunicCapColor)
|
||||
REGISTER_COSMETIC_OPTION(herosTunicTorsoColor)
|
||||
REGISTER_COSMETIC_OPTION(herosTunicSkirtColor)
|
||||
@@ -164,8 +272,18 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
|
||||
REGISTER_COSMETIC_OPTION(boomerangColor)
|
||||
REGISTER_COSMETIC_OPTION(ironBootsColor)
|
||||
REGISTER_COSMETIC_OPTION(spinnerColor)
|
||||
REGISTER_COSMETIC_OPTION(midnaHairBaseColor)
|
||||
REGISTER_COSMETIC_OPTION(midnaHairTipsColor)
|
||||
REGISTER_COSMETIC_OPTION(heartColor)
|
||||
|
||||
result = register_int_option("midnaHairBaseColor", 0, g_cvars.midnaHairBaseColor, error);
|
||||
if (result != MOD_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = register_int_option("midnaHairTipsColor", 0, g_cvars.midnaHairTipsColor, error);
|
||||
if (result != MOD_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
REGISTER_COSMETIC_OPTION(midnaChargeRingColor)
|
||||
REGISTER_COSMETIC_OPTION(linkHairColor)
|
||||
REGISTER_COSMETIC_OPTION(wolfLinkColor)
|
||||
@@ -176,7 +294,7 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
|
||||
svc_ui->register_mods_panel(mod_ctx, &panelDesc);
|
||||
|
||||
// Add all our hooks
|
||||
auto result = add_all_hooks();
|
||||
result = add_all_hooks();
|
||||
if (result != MOD_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -185,6 +303,8 @@ MOD_EXPORT ModResult mod_initialize(ModError* error) {
|
||||
}
|
||||
|
||||
MOD_EXPORT ModResult mod_update(ModError*) {
|
||||
update_rainbow_rgb(1.0f);
|
||||
set_all_midna_hair_colors();
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ struct cvars {
|
||||
ConfigVarHandle boomerangColor = 0;
|
||||
ConfigVarHandle ironBootsColor = 0;
|
||||
ConfigVarHandle spinnerColor = 0;
|
||||
ConfigVarHandle heartColor = 0;
|
||||
ConfigVarHandle midnaHairBaseColor = 0;
|
||||
ConfigVarHandle midnaHairTipsColor = 0;
|
||||
ConfigVarHandle midnaChargeRingColor = 0;
|
||||
@@ -31,4 +32,6 @@ struct cvars {
|
||||
|
||||
cvars& get_cvars();
|
||||
|
||||
std::string get_str_option(ConfigVarHandle handle, const std::string& fallback);
|
||||
std::string get_str_option(ConfigVarHandle handle, const std::string& fallback);
|
||||
|
||||
int64_t get_int_option(ConfigVarHandle handle, int64_t fallback);
|
||||
@@ -13,7 +13,6 @@ class J3DVertexData;
|
||||
#include "JSystem/JUtility/JUTNameTab.h"
|
||||
#include "JSystem/JUtility/JUTTexture.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "global.h"
|
||||
#include "gx/GXEnum.h"
|
||||
#include "m_Do/m_Do_dvd_thread.h"
|
||||
|
||||
Reference in New Issue
Block a user