mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-12 11:22:00 -04:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0da58ac91d | |||
| c29cafa8a2 | |||
| 5e669c8f0f | |||
| 3e625cf006 | |||
| c6f497b525 | |||
| 79d3c7c76a | |||
| 16dd1118d1 | |||
| e9918cc8ed | |||
| 058304dc26 | |||
| d55b44b5a5 | |||
| 7434a0f834 | |||
| 469575fd65 | |||
| 4883c11182 | |||
| 7ac2340312 | |||
| 3352ea3dde | |||
| 6481d12a3d | |||
| 960d016113 | |||
| e02251a669 |
+2
-1
@@ -33,6 +33,7 @@ set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
set(CMAKE_COLOR_DIAGNOSTICS ON)
|
||||
|
||||
# Folder-based instead of target-based organization
|
||||
# in Visual Studio and Xcode generators
|
||||
@@ -518,7 +519,7 @@ if (DUSK_ENABLE_CODE_MODS AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR
|
||||
add_subdirectory(mods/ao_mod)
|
||||
add_subdirectory(mods/shadow_mod)
|
||||
add_subdirectory(mods/window_demo)
|
||||
add_subdirectory(mods/randomizer)
|
||||
add_subdirectory(mods/basic_cosmetics_mod)
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 1d10fa1bc5...8005d336ab
@@ -47,7 +47,7 @@ public:
|
||||
s32 getBgmLoadStatus(u32 wave) { return getWaveLoadStatus(wave, 1); }
|
||||
u8 getDemoSeWaveNum() { return loadedDemoWave; }
|
||||
|
||||
// private:
|
||||
private:
|
||||
/* 0x00 */ JAISoundID BGM_ID;
|
||||
/* 0x04 */ int sceneNum;
|
||||
/* 0x08 */ int timer;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
CPaneMgrAlpha* getNoDatBase() { return mNoDatBase; }
|
||||
void draw() { _draw(); }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ JKRArchive* mArchive;
|
||||
/* 0x08 */ dDlst_FileInfo_c mFileInfo;
|
||||
/* 0x1C */ u8 field_0x1c[4];
|
||||
|
||||
@@ -13,36 +13,8 @@ class dFile_info_c;
|
||||
class J2DPicture;
|
||||
|
||||
#if TARGET_PC
|
||||
static PaneCache mSelDtPanes[] = {
|
||||
{MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('gray_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('b_base'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('b_base1'), 0.0f, 0.0f, false},
|
||||
};
|
||||
|
||||
static PaneCache fileSelPanes[] = {
|
||||
{MULTI_CHAR('w_uzu00'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu01'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu02'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu03'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu04'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu05'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu06'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu07'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu08'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_uzu09'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_er_msg'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_er_msE'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_er_msR'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('er_for0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('er_for1'), 0.0f, 0.0f, false},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class dDlst_FileSel_c : public dDlst_base_c {
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
|
||||
void drawSelf() { mpKanteraIcon->draw(); }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ dDlst_KanteraIcon_c* mpKanteraIcon;
|
||||
/* 0x08 */ CPaneMgr* mpParent;
|
||||
/* 0x0C */ CPaneMgr* mpGauge;
|
||||
|
||||
@@ -15,49 +15,6 @@ class dMenu_Fishing_c;
|
||||
class dMenu_Skill_c;
|
||||
class dMenu_Insect_c;
|
||||
class dSelect_cursor_c;
|
||||
|
||||
#if TARGET_PC
|
||||
struct PaneCache {
|
||||
u64 tag;
|
||||
f32 origTransX;
|
||||
f32 origTransY;
|
||||
bool cached;
|
||||
};
|
||||
|
||||
static PaneCache mpScreenPanes[] = {
|
||||
{MULTI_CHAR('sa_tex_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('op_tex_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('heart_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('wolf_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('item_0_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('item_1_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('item_2_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fish_3_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('lett_4_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('maki_5_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fuku_n0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fuku_n1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('fuku_n2'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('tate_n0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('tate_n1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('ken_n0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('ken_n1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('kabu_6n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('t_t00'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('f_t00'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('itemn_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('infotxtn'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('sa_op_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('title_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('menu_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('w_er_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('center_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('info_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('lavel_n'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('modelbgn'), 0.0f, 0.0f, false},
|
||||
};
|
||||
#endif
|
||||
|
||||
class dMenu_Collect2D_c;
|
||||
class dMenu_Collect2DTop_c : public dDlst_base_c {
|
||||
public:
|
||||
@@ -172,7 +129,7 @@ public:
|
||||
J2DPicture* getBlackTex() { return mpBlackTex; }
|
||||
u8 getSubWindowOpenCheck() { return mSubWindowOpenCheck; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRExpHeap* mpSubHeap;
|
||||
/* 0x00C */ void* field_0xc;
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRArchive* mpArchive;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
|
||||
static DUSK_GAME_DATA dMenu_Fmap_c* MyClass;
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRExpHeap* mpTalkHeap;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ JKRExpHeap* mpHeap;
|
||||
/* 0x08 */ JKRArchive* mpArchive;
|
||||
/* 0x0C */ STControl* mpStick;
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRArchive* mpArchive;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
return ((u8)mUseFlag & (u8)i_flag) != 0 ? true : false;
|
||||
}
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ J2DScreen* mpBackScreen;
|
||||
/* 0x008 */ J2DScreen* mpScreen;
|
||||
/* 0x00C */ J2DScreen* mpClipScreen;
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
void drawFlag0() { mDrawFlag = 0; }
|
||||
void setStatus(u8 i_status) { mStatus = i_status; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ STControl* mpStick;
|
||||
/* 0x00C */ CSTControl* mpCStick;
|
||||
|
||||
@@ -278,7 +278,7 @@ public:
|
||||
u8 getEndStatus() { return mEndStatus; }
|
||||
void setUseType(u8 type) { mUseType = type; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x0004 */ JKRArchive* mpArchive;
|
||||
/* 0x0008 */ mDoDvdThd_mountArchive_c* mpMount;
|
||||
/* 0x000C */ STControl* stick;
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
u8 getStatus() { return mStatus; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ JKRExpHeap* mpHeap;
|
||||
/* 0x008 */ JKRArchive* mpArchive;
|
||||
/* 0x00C */ STControl* mpStick;
|
||||
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ item_params mItemParams[4];
|
||||
/* 0x074 */ JKRExpHeap* heap;
|
||||
/* 0x078 */ J2DScreen* mpScreen;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
void setTextBoxPtr(J2DTextBox* p_textBox) { mpTextBoxPtr = p_textBox; }
|
||||
void resetType() { mType = 0x47; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x04 */ J2DTextBox* mpTextBoxPtr;
|
||||
/* 0x08 */ f32 mPosX;
|
||||
/* 0x0C */ f32 mPosY;
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
|
||||
void setRupeeColor(u8 color) { mRupeeColor = color; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x004 */ COutFontSet_c* mpOfs[35];
|
||||
/* 0x090 */ J2DPicture* mpPane[70];
|
||||
/* 0x1A8 */ f32 mAlphaRatio;
|
||||
|
||||
@@ -12,34 +12,6 @@ class J2DTextBox;
|
||||
class JUTFont;
|
||||
class STControl;
|
||||
|
||||
#if TARGET_PC
|
||||
struct PaneCache {
|
||||
u64 tag;
|
||||
f32 origTransX;
|
||||
f32 origTransY;
|
||||
bool cached;
|
||||
};
|
||||
|
||||
static PaneCache l_tagName[] = {
|
||||
{MULTI_CHAR('m_00_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_00_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_01_3'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m_01_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_02_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_2'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m03_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m03_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_04_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_1'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m_05_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_05_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_06_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_0'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m_07_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_07_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_08_4'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m_09_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_09_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_10_3'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m_10_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m_11_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_0'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_2'), 0.0f, 0.0f, false},
|
||||
{MULTI_CHAR('m12_3'), 0.0f, 0.0f, false}, {MULTI_CHAR('m12_4'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_2'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_1'), 0.0f, 0.0f, false}, {MULTI_CHAR('p_end_0'), 0.0f, 0.0f, false},
|
||||
};
|
||||
|
||||
static PaneCache l_nameTagName[] = {
|
||||
{MULTI_CHAR('name_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('name_07'), 0.0f, 0.0f, false},
|
||||
};
|
||||
|
||||
static PaneCache l_nameCurTagName[] = {
|
||||
{MULTI_CHAR('s__n_00'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_01'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_02'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_03'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_04'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_05'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_06'), 0.0f, 0.0f, false}, {MULTI_CHAR('s__n_07'), 0.0f, 0.0f, false},
|
||||
};
|
||||
#endif
|
||||
|
||||
class dNm_HIO_c {
|
||||
public:
|
||||
dNm_HIO_c();
|
||||
|
||||
@@ -1291,7 +1291,6 @@ public:
|
||||
}
|
||||
void set(const char*, s8, s16, s8, s8, u8);
|
||||
void offEnable() { enabled = 0; }
|
||||
void onEnable() { enabled = 1; }
|
||||
BOOL isEnable() const { return enabled; }
|
||||
s8 getWipe() const { return wipe; }
|
||||
u8 getWipeSpeed() const { return wipe_speed; }
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
JKRMemArchive* getArchive() const { return mArchive; }
|
||||
JKRHeap* getHeap() const { return mHeap; }
|
||||
|
||||
private:
|
||||
// private:
|
||||
/* 0x14 */ u8 mMountDirection;
|
||||
/* 0x18 */ s32 mEntryNumber;
|
||||
/* 0x1C */ JKRMemArchive* mArchive;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
project(basic_cosmetics_mod CXX)
|
||||
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
|
||||
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
if (DUSK_MOD_USE_FULL_TREE)
|
||||
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
|
||||
else ()
|
||||
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(COSMETIC_SOURCES src/color_utils.cpp src/midna_hair_color.cpp src/texture_utils.cpp src/hooks.cpp)
|
||||
|
||||
add_mod(basic_cosmetics_mod
|
||||
FEATURES game fmt
|
||||
SOURCES src/mod.cpp ${COSMETIC_SOURCES}
|
||||
MOD_JSON mod.json
|
||||
RES_DIR res
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"id": "dev.twilitrealm.basic_cosmetics",
|
||||
"name": "Basic Cosmetics",
|
||||
"version": "1.0.0",
|
||||
"author": "Twilit Realm",
|
||||
"description": "Change Basic Cosmetic Colors"
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#include "color_utils.hpp"
|
||||
|
||||
uint8_t desaturate_rgb_565(uint16_t rgb565Val)
|
||||
{
|
||||
const uint32_t r = (rgb565Val & 0xf800) >> 11;
|
||||
const uint32_t g = (rgb565Val & 0x7e0) >> 5;
|
||||
const uint32_t b = rgb565Val & 0x1f;
|
||||
|
||||
// Here we are doing a quicker (0.22 * r + 0.72 * g + 0.06 * b) which
|
||||
// uses multiplies and shifts rather than division.
|
||||
const uint32_t combined = 30480413 * r + 49085341 * g + 8312839 * b;
|
||||
uint8_t shifted = (combined >> 24) & 0xff;
|
||||
|
||||
// Check if should round up shifted value.
|
||||
if (shifted < 0xff && combined & 0x00800000)
|
||||
{
|
||||
shifted += 1;
|
||||
}
|
||||
|
||||
return shifted;
|
||||
}
|
||||
|
||||
uint16_t blend_overlay_rgb_565(uint8_t grayVal, GXColor color)
|
||||
{
|
||||
uint32_t rTimes255, gTimes255, bTimes255;
|
||||
|
||||
if (grayVal <= 0x7f)
|
||||
{
|
||||
const uint32_t grayTimesTwo = 2 * grayVal;
|
||||
|
||||
rTimes255 = grayTimesTwo * color.r;
|
||||
gTimes255 = grayTimesTwo * color.g;
|
||||
bTimes255 = grayTimesTwo * color.b;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t multiplier = 2 * (255 - grayVal);
|
||||
|
||||
rTimes255 = 255 * 255 - multiplier * (255 - color.r);
|
||||
gTimes255 = 255 * 255 - multiplier * (255 - color.g);
|
||||
bTimes255 = 255 * 255 - multiplier * (255 - color.b);
|
||||
}
|
||||
|
||||
// Divide each by 255
|
||||
const uint32_t r = (rTimes255 + 1 + (rTimes255 >> 8)) >> 8;
|
||||
const uint32_t g = (gTimes255 + 1 + (gTimes255 >> 8)) >> 8;
|
||||
const uint32_t b = (bTimes255 + 1 + (bTimes255 >> 8)) >> 8;
|
||||
|
||||
return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
|
||||
}
|
||||
|
||||
// Helper function to perform overlay blending on a single 8-bit color channel
|
||||
uint8_t blend_overlay_channel(uint8_t base, uint8_t blend)
|
||||
{
|
||||
if (base < 128) {
|
||||
return static_cast<uint8_t>((2 * base * blend) / 255);
|
||||
}
|
||||
|
||||
return static_cast<uint8_t>(255 - (2 * (255 - base) * (255 - blend)) / 255);
|
||||
}
|
||||
|
||||
bool is_valid_hex_color_str(std::string_view hexStr) {
|
||||
return hexStr.find_first_not_of("0123456789ABCDEFabcdef") == std::string_view::npos && hexStr.length() == 6;
|
||||
}
|
||||
|
||||
GXColor hex_color_str_to_gx_color(const std::string& hexColorStr) {
|
||||
u8 r = std::stoi(hexColorStr.substr(0, 2), nullptr, 16);
|
||||
u8 g = std::stoi(hexColorStr.substr(2, 2), nullptr, 16);
|
||||
u8 b = std::stoi(hexColorStr.substr(4, 2), nullptr, 16);
|
||||
return GXColor{r, g, b};
|
||||
}
|
||||
|
||||
static f32 rainbowPhaseAngle = 0.f;
|
||||
|
||||
GXColor get_rainbow_rgb(f32 amplitude) {
|
||||
f32 phase_rad = rainbowPhaseAngle * M_PI / 180.0f;
|
||||
|
||||
u8 r_val = (u8)(amplitude * (sinf(phase_rad) + 1.0f) + 0.5f);
|
||||
u8 g_val = (u8)(amplitude * (sinf(phase_rad + 2.0f * M_PI / 3.0f) + 1.0f) + 0.5f);
|
||||
u8 b_val = (u8)(amplitude * (sinf(phase_rad + 4.0f * M_PI / 3.0f) + 1.0f));
|
||||
GXColor rgbColor;
|
||||
rgbColor.r = r_val;
|
||||
rgbColor.g = g_val;
|
||||
rgbColor.b = b_val;
|
||||
rgbColor.a = 0xff;
|
||||
return rgbColor;
|
||||
}
|
||||
|
||||
void update_rainbow_rgb(f32 increment) {
|
||||
rainbowPhaseAngle += increment;
|
||||
if (rainbowPhaseAngle >= 360.0f) {
|
||||
rainbowPhaseAngle -= 360.0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* File originally copied from console TPR with permission from isaac
|
||||
* https://github.com/zsrtp/libtp_rel/blob/master/include/util/color_utils.h
|
||||
*/
|
||||
|
||||
#include <gx.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
// Desaturates an RGB565 color to a u8 gray value (0xFF being white and 0x00
|
||||
// being black).
|
||||
uint8_t desaturate_rgb_565(uint16_t rgb565Val);
|
||||
|
||||
// Performs an "Overlay" blend of a u8 gray value and a pointer to a u8
|
||||
// array of {r,g,b}. Returns the result as an RGB565.
|
||||
uint16_t blend_overlay_rgb_565(uint8_t grayVal, GXColor color);
|
||||
|
||||
// Perform overlay blending on a single 8-bit color channel
|
||||
uint8_t blend_overlay_channel(uint8_t base, uint8_t blend);
|
||||
|
||||
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);
|
||||
@@ -0,0 +1,694 @@
|
||||
#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_a_item_static.h"
|
||||
#include "d/d_bright_check.h"
|
||||
#include "d/d_file_sel_info.h"
|
||||
#include "d/d_file_select.h"
|
||||
#include "d/d_kankyo.h"
|
||||
#include "d/d_kantera_icon_meter.h"
|
||||
#include "d/d_menu_collect.h"
|
||||
#include "d/d_menu_fishing.h"
|
||||
#include "d/d_menu_fmap2D.h"
|
||||
#include "d/d_menu_insect.h"
|
||||
#include "d/d_menu_letter.h"
|
||||
#include "d/d_menu_option.h"
|
||||
#include "d/d_menu_ring.h"
|
||||
#include "d/d_menu_save.h"
|
||||
#include "d/d_menu_skill.h"
|
||||
#include "d/d_meter_button.h"
|
||||
#include "d/d_meter_hakusha.h"
|
||||
#include "d/d_meter2.h"
|
||||
#include "d/d_meter2_draw.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/d_msg_object.h"
|
||||
#include "d/d_msg_out_font.h"
|
||||
#include "d/d_msg_scrn_base.h"
|
||||
#include "d/d_pane_class.h"
|
||||
#include "m_Do/m_Do_dvd_thread.h"
|
||||
#include "SSystem/SComponent/c_phase.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
// Main hook for recoloring textures on load
|
||||
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 configVar color
|
||||
static std::optional<GXColor> get_config_var_color(ConfigVarHandle handle, bool allowRainbow = false) {
|
||||
auto colorStr = get_str_option(handle, "");
|
||||
|
||||
// Convert to lowercase
|
||||
for (auto& c : colorStr) {
|
||||
c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
}
|
||||
|
||||
if (is_valid_hex_color_str(colorStr) || (colorStr == "rainbow" && allowRainbow)) {
|
||||
if (is_valid_hex_color_str(colorStr)) {
|
||||
return hex_color_str_to_gx_color(colorStr);
|
||||
}
|
||||
|
||||
if (allowRainbow) {
|
||||
// Assume rainbow if not a valid hex str
|
||||
auto color = get_rainbow_rgb(127.5f);
|
||||
color.r /= 2;
|
||||
color.g /= 2;
|
||||
color.b /= 2;
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// 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_config_var_color(get_cvars().lanternGlowColor, true);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Lantern Sphere color
|
||||
DEFINE_HOOK(&daAlink_c::preKandelaarDraw, PreKandelaarDraw);
|
||||
void pre_kandelaar_draw_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto maybeLanternColor = get_config_var_color(get_cvars().lanternGlowColor, true);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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_config_var_color(get_cvars().lanternGlowColor, true);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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_config_var_color(get_cvars().lanternGlowColor, true);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// Light Sword Effect Color
|
||||
DEFINE_HOOK(&daAlink_c::setLightningSwordEffect, SetLightningSwordEffect);
|
||||
void set_lightning_sword_effect_post(ModContext*, void* args, void* retval, void* userdata) {
|
||||
auto maybeGlowColor = get_config_var_color(get_cvars().lightSwordGlowColor, true);
|
||||
if (maybeGlowColor.has_value()) {
|
||||
auto glowColor = maybeGlowColor.value();
|
||||
|
||||
auto link = mods::arg<daAlink_c*>(args, 0);
|
||||
// Check copied from inside the hooked function
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void recolor_ui_button(ConfigVarHandle option, u64 tag, J2DScreen* screen) {
|
||||
auto buttonColorStr = get_str_option(option, "");
|
||||
if (is_valid_hex_color_str(buttonColorStr)) {
|
||||
auto color = hex_color_str_to_gx_color(buttonColorStr);
|
||||
auto element = static_cast<J2DPicture*>(screen->search(tag));
|
||||
if (element != nullptr) {
|
||||
element->setBlackWhite(JUtility::TColor(0, 0, 0, 0),
|
||||
JUtility::TColor(color.r, color.g, color.b, 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main gameplay UI. Top left hearts and top right buttons
|
||||
DEFINE_HOOK(&dMeter2Draw_c::init, dMeter2Init);
|
||||
void d_meter_2_init_post(ModContext*, void* args, void*, void*) {
|
||||
auto dMeter2Draw = mods::arg<dMeter2Draw_c*>(args, 0);
|
||||
auto screen = dMeter2Draw->getMainScreenPtr();
|
||||
|
||||
// Heart tags on main UI
|
||||
static constexpr std::array kHeartTags = {
|
||||
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')
|
||||
};
|
||||
|
||||
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
|
||||
if (maybeHeartColor.has_value()) {
|
||||
auto heartColor = maybeHeartColor.value();
|
||||
for (auto tag : kHeartTags) {
|
||||
auto element = static_cast<J2DPicture*>(screen->search(tag));
|
||||
if (element != nullptr) {
|
||||
element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('x_btn'), screen);
|
||||
recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('y_btn'), screen);
|
||||
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen);
|
||||
}
|
||||
|
||||
// Hearts on the file select screen
|
||||
DEFINE_HOOK(&dFile_info_c::setHeartCnt, FileInfoSetHeartCount);
|
||||
void file_info_set_heart_count_post(ModContext*, void* args, void*, void*) {
|
||||
auto fileInfo = mods::arg<dFile_info_c*>(args, 0);
|
||||
|
||||
// Heart tags on file select
|
||||
static constexpr std::array kFileSelectHeartTags {
|
||||
MULTI_CHAR('hear_20'), MULTI_CHAR('hear_21'), MULTI_CHAR('hear_22'), MULTI_CHAR('hear_23'), MULTI_CHAR('hear_24'), MULTI_CHAR('hear_25'), MULTI_CHAR('hear_26'),
|
||||
MULTI_CHAR('hear_27'), MULTI_CHAR('hear_28'), MULTI_CHAR('hear_29'), MULTI_CHAR('hear_30'), MULTI_CHAR('hear_31'), MULTI_CHAR('hear_32'), MULTI_CHAR('hear_33'),
|
||||
MULTI_CHAR('hear_34'), MULTI_CHAR('hear_35'), MULTI_CHAR('hear_36'), MULTI_CHAR('hear_37'), MULTI_CHAR('hear_38'), MULTI_CHAR('hear_39'),
|
||||
};
|
||||
|
||||
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
|
||||
if (maybeHeartColor.has_value()) {
|
||||
auto heartColor = maybeHeartColor.value();
|
||||
for (auto tag : kFileSelectHeartTags) {
|
||||
auto element = static_cast<J2DPicture*>(fileInfo->mFileInfo.Scr->search(tag));
|
||||
if (element != nullptr) {
|
||||
element->setBlackWhite(heartColor, JUtility::TColor(200, 200, 200, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons that appear contextually at the bottom of the screen during gameplay
|
||||
// (Are X, Y ever used there?)
|
||||
DEFINE_HOOK(&dMeterButton_c::screenInitButton, ScreenInitButton);
|
||||
void screen_init_button_post(ModContext*, void* args, void*, void*) {
|
||||
auto meterButton = mods::arg<dMeterButton_c*>(args, 0);
|
||||
auto screen = meterButton->mpButtonScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('x_btn'), screen);
|
||||
recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('y_btn'), screen);
|
||||
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen);
|
||||
}
|
||||
|
||||
// A and B buttons when saving a file
|
||||
DEFINE_HOOK(&dMenu_save_c::screenSet, MenuSaveScreenSet);
|
||||
void menu_save_screen_set_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuSave = mods::arg<dMenu_save_c*>(args, 0);
|
||||
auto screen = menuSave->mSaveSel.Scr;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('wabtn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('wbbtn'), screen);
|
||||
}
|
||||
|
||||
// A and B buttons when selecting a file
|
||||
DEFINE_HOOK(&dFile_select_c::screenSet, FileSelectScreenSet);
|
||||
void file_select_screen_set_post(ModContext*, void* args, void*, void*) {
|
||||
auto fileSelect = mods::arg<dFile_select_c*>(args, 0);
|
||||
auto screen = fileSelect->fileSel.Scr;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('wabtn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('wbbtn'), screen);
|
||||
}
|
||||
|
||||
// A button on brightness check screen
|
||||
DEFINE_HOOK(&dBrightCheck_c::screenSet, BrightCheckScreenSet);
|
||||
void bright_check_screen_set_post(ModContext*, void* args, void*, void*) {
|
||||
auto brightCheck = mods::arg<dBrightCheck_c*>(args, 0);
|
||||
auto screen = brightCheck->mBrightCheck.Scr;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen);
|
||||
}
|
||||
|
||||
// X and Y buttons on the item wheel screen
|
||||
DEFINE_HOOK(&dMenu_Ring_c::_create, MenuRingCreate);
|
||||
void menu_ring_create_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuRing = mods::arg<dMenu_Ring_c*>(args, 0);
|
||||
auto screen = menuRing->mpScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().xButtonColor, MULTI_CHAR('xbtn'), screen);
|
||||
recolor_ui_button(get_cvars().yButtonColor, MULTI_CHAR('ybtn'), screen);
|
||||
}
|
||||
|
||||
// A and B buttons on the main pause screen
|
||||
DEFINE_HOOK(&dMenu_Collect2D_c::_create, MenuCollect2DCreate);
|
||||
void menu_collect_2D_create_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuCollect2D = mods::arg<dMenu_Collect2D_c*>(args, 0);
|
||||
auto screen = menuCollect2D->mpScreenIcon;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
}
|
||||
|
||||
// A and B buttons on the fishing journal screen
|
||||
DEFINE_HOOK(&dMenu_Fishing_c::screenSetDoIcon, MenuFishingScreenSetDoIcon);
|
||||
void menu_fishing_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuFishing = mods::arg<dMenu_Fishing_c*>(args, 0);
|
||||
auto screen = menuFishing->mpIconScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
}
|
||||
|
||||
// A and B buttons on the insect collection screen
|
||||
DEFINE_HOOK(&dMenu_Insect_c::screenSetDoIcon, MenuInsectScreenSetDoIcon);
|
||||
void menu_insect_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuInsect = mods::arg<dMenu_Insect_c*>(args, 0);
|
||||
auto screen = menuInsect->mpIconScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
}
|
||||
|
||||
// A and B buttons on the letters screen
|
||||
DEFINE_HOOK(&dMenu_Letter_c::screenSetDoIcon, MenuLetterScreenSetDoIcon);
|
||||
void menu_letter_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuLetter = mods::arg<dMenu_Letter_c*>(args, 0);
|
||||
auto screen = menuLetter->mpIconScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
}
|
||||
|
||||
// A, B, and Z buttons on option screen
|
||||
DEFINE_HOOK(&dMenu_Option_c::_create, MenuOptionCreate);
|
||||
void menu_option_create_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuOption = mods::arg<dMenu_Option_c*>(args, 0);
|
||||
auto screen = menuOption->mpScreenIcon;
|
||||
auto backScreen = menuOption->mpBackScreen;
|
||||
auto tvScreen = menuOption->mpTVScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('g_zbtn'), backScreen);
|
||||
|
||||
// A Button on option's brightness check screen
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), tvScreen);
|
||||
}
|
||||
|
||||
// A and B buttons on the hidden skills screen
|
||||
DEFINE_HOOK(&dMenu_Skill_c::screenSetDoIcon, MenuSkillScreenSetDoIcon);
|
||||
void menu_skill_screen_set_do_icon_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuSkill = mods::arg<dMenu_Skill_c*>(args, 0);
|
||||
auto screen = menuSkill->mpIconScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn'), screen);
|
||||
}
|
||||
|
||||
// A, B, and Z buttons on the map screen
|
||||
DEFINE_HOOK(&dMenu_Fmap_c::_create, MenuFMapCreate);
|
||||
void menu_fmap_create_post(ModContext*, void* args, void*, void*) {
|
||||
auto menuFMap = mods::arg<dMenu_Fmap_c*>(args, 0);
|
||||
auto screen = menuFMap->mpDraw2DTop->mpTitleScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn'), screen);
|
||||
recolor_ui_button(get_cvars().bButtonColor, MULTI_CHAR('b_btn1'), screen);
|
||||
recolor_ui_button(get_cvars().zButtonColor, MULTI_CHAR('zbtn'), screen);
|
||||
}
|
||||
|
||||
// A button on the howling screen
|
||||
DEFINE_HOOK(&dMsgObject_c::talkStartInit, MsgObjectTalkStartInit);
|
||||
void msg_object_talk_start_init_post(ModContext*, void* args, void*, void*) {
|
||||
auto msgObject = mods::arg<dMsgObject_c*>(args, 0);
|
||||
|
||||
// If textbox kind is howling
|
||||
if (msgObject->mFukiKind == 17) {
|
||||
auto screen = msgObject->mpScrnDraw->mpScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('abtn'), screen);
|
||||
}
|
||||
}
|
||||
|
||||
// A button when on Epona
|
||||
DEFINE_HOOK(&dMeterHakusha_c::_create, MeterHakushaCreate);
|
||||
void meter_hakusha_create_post(ModContext*, void* args, void*, void*) {
|
||||
auto meterHakusha = mods::arg<dMeterHakusha_c*>(args, 0);
|
||||
auto screen = meterHakusha->mpButtonScreen;
|
||||
|
||||
recolor_ui_button(get_cvars().aButtonColor, MULTI_CHAR('a_btn1'), screen);
|
||||
}
|
||||
|
||||
// A, B, X, and Y button icons in text
|
||||
DEFINE_HOOK(&COutFont_c::createPane, OutFontCreatePane);
|
||||
void out_font_create_pane_post(ModContext*, void* args, void*, void*) {
|
||||
auto outFont = mods::arg<COutFont_c*>(args, 0);
|
||||
auto paneArr = outFont->mpPane;
|
||||
|
||||
auto maybeAButtonColor = get_config_var_color(get_cvars().aButtonColor);
|
||||
if (maybeAButtonColor.has_value()) {
|
||||
auto aButtonColor = maybeAButtonColor.value();
|
||||
paneArr[0]->setBlackWhite(
|
||||
JUtility::TColor(255, 255, 255, 0),
|
||||
JUtility::TColor(aButtonColor.r,aButtonColor.g,aButtonColor.b, 255));
|
||||
}
|
||||
|
||||
auto maybeBButtonColor = get_config_var_color(get_cvars().bButtonColor);
|
||||
if (maybeBButtonColor.has_value()) {
|
||||
auto bButtonColor = maybeBButtonColor.value();
|
||||
paneArr[1]->setBlackWhite(
|
||||
JUtility::TColor(255, 255, 255, 0),
|
||||
JUtility::TColor(bButtonColor.r,bButtonColor.g,bButtonColor.b, 255));
|
||||
}
|
||||
|
||||
// Condition copied from hooked function
|
||||
auto xyBlack = JUtility::TColor(255, 255, 255, 0);
|
||||
if (outFont->field_0x242 == 1) {
|
||||
xyBlack = JUtility::TColor(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
auto maybeXButtonColor = get_config_var_color(get_cvars().xButtonColor);
|
||||
if (maybeXButtonColor.has_value()) {
|
||||
auto xButtonColor = maybeXButtonColor.value();
|
||||
paneArr[5]->setBlackWhite(xyBlack, JUtility::TColor(xButtonColor.r,xButtonColor.g,xButtonColor.b, 255));
|
||||
}
|
||||
|
||||
auto maybeYButtonColor = get_config_var_color(get_cvars().yButtonColor);
|
||||
if (maybeYButtonColor.has_value()) {
|
||||
auto yButtonColor = maybeYButtonColor.value();
|
||||
paneArr[6]->setBlackWhite(xyBlack, JUtility::TColor(yButtonColor.r,yButtonColor.g,yButtonColor.b, 255));
|
||||
}
|
||||
}
|
||||
|
||||
// Heart icon in text
|
||||
DEFINE_HOOK(&COutFontSet_c::drawFont, OutFontSetDrawFont);
|
||||
void out_font_set_draw_font_post(ModContext*, void* args, void*, void*) {
|
||||
auto outFontSet = mods::arg<COutFontSet_c*>(args, 0);
|
||||
|
||||
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
|
||||
if (maybeHeartColor.has_value()) {
|
||||
auto heartColor = maybeHeartColor.value();
|
||||
u32 heartColor_u32 = heartColor.r << 24 | heartColor.g << 16 | heartColor.b << 8 | 0xFF;
|
||||
if (outFontSet->getType() == 0x1B) { // Heart icon type
|
||||
outFontSet->mColor = heartColor_u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Heart Drop/Piece of Heart/Heart Container model color
|
||||
DEFINE_HOOK(&daItemBase_c::CreateItemHeap, ItemBaseCreateItemHeap);
|
||||
void item_base_create_item_heap_post(ModContext*, void* args, void*, void*) {
|
||||
auto itemBase = mods::arg<daItemBase_c*>(args, 0);
|
||||
if (itemBase == NULL) {
|
||||
return;
|
||||
}
|
||||
auto itemNo = itemBase->m_itemNo;
|
||||
if (itemNo == dItemNo_HEART_e || itemNo == dItemNo_UTAWA_HEART_e || itemNo == dItemNo_KAKERA_HEART_e) {
|
||||
auto maybeHeartColor = get_config_var_color(get_cvars().heartColor);
|
||||
if (maybeHeartColor.has_value()) {
|
||||
auto heartColor = maybeHeartColor.value();
|
||||
auto heartColorS10 = GXColorS10(heartColor.r, heartColor.g, heartColor.b, heartColor.a);
|
||||
|
||||
// Edit inner heart material color for Piece of Heart / Heart Container
|
||||
if (itemNo == dItemNo_UTAWA_HEART_e || itemNo == dItemNo_KAKERA_HEART_e) {
|
||||
*itemBase->mpModel->getModelData()->getMaterialNodePointer(3)->getTevKColor(1) = heartColor;
|
||||
*itemBase->mpModel->getModelData()->getMaterialNodePointer(3)->getTevColor(1) = heartColorS10;
|
||||
}
|
||||
|
||||
const u8 heartColorRGB[3] = {heartColor.r,heartColor.g,heartColor.b};
|
||||
u8** cRegTable = reinterpret_cast<u8**>(&itemBase->mpBrkAnm->getBrkAnm()->mAnmCRegDataR);
|
||||
u8** kRegTable = reinterpret_cast<u8**>(&itemBase->mpBrkAnm->getBrkAnm()->mAnmKRegDataR);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
u8* cReg = cRegTable[i];
|
||||
u8* kReg = kRegTable[i];
|
||||
|
||||
auto curColor = heartColorRGB[i];
|
||||
|
||||
// Set heart drop inner heart color
|
||||
cReg[0x3] = curColor;
|
||||
cReg[0xB] = curColor;
|
||||
|
||||
// Set heart drop outer heart color
|
||||
kReg[0x3] = curColor;
|
||||
kReg[0xB] = curColor;
|
||||
|
||||
if (itemNo == dItemNo_KAKERA_HEART_e) {
|
||||
cReg[0x13] = curColor;
|
||||
cReg[0x1B] = curColor;
|
||||
kReg[0x13] = curColor;
|
||||
kReg[0x1B] = curColor;
|
||||
|
||||
}
|
||||
if (itemNo == dItemNo_UTAWA_HEART_e) {
|
||||
cReg[0x13] = curColor;
|
||||
kReg[0x13] = curColor;
|
||||
kReg[0x1B] = curColor;
|
||||
kReg[0x23] = curColor;
|
||||
kReg[0x2B] = curColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Midna Hair Color
|
||||
DEFINE_HOOK(&daMidna_c::create, MidnaCreate);
|
||||
void midna_create_post(ModContext*, void* args, void* retval, void*) {
|
||||
auto step = reinterpret_cast<int*>(retval);
|
||||
// Don't set colors if midna isn't done loading
|
||||
if (*step != cPhs_COMPLEATE_e) {
|
||||
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 before setBodyPartMatrix runs
|
||||
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 setBodyPartMatrix 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{};
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
// Reapply the chase that happens in the function
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ADD_POST_HOOK(defined_hook, function, original) \
|
||||
result = mods::hook::add_post<defined_hook>(function); \
|
||||
if (result != MOD_OK) { \
|
||||
mods::log::debug("failed to add post hook to" #original ", Result {}", static_cast<int>(result)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
#define ADD_PRE_HOOK(defined_hook, function, original) \
|
||||
result = mods::hook::add_pre<defined_hook>(function); \
|
||||
if (result != MOD_OK) { \
|
||||
mods::log::debug("failed to add pre hook to" #original ", Result {}", static_cast<int>(result)); \
|
||||
return result; \
|
||||
}
|
||||
|
||||
ModResult add_all_hooks() {
|
||||
ModResult result{};
|
||||
|
||||
// Main hook for texture recoloring
|
||||
ADD_POST_HOOK(MountArchiveExecute, mount_archive_execute_post, mountArchive_execute)
|
||||
|
||||
// Hooks for lantern glow
|
||||
ADD_POST_HOOK(WolfEyeLightSet, wolf_eye_light_set_post, dKy_WolfEyeLight_set)
|
||||
ADD_POST_HOOK(PreKandelaarDraw, pre_kandelaar_draw_post, daAlink_c::preKandelaarDraw)
|
||||
|
||||
// Hooks for lantern meter color
|
||||
ADD_PRE_HOOK(CPaneMgrSetBlackWhite, cpane_mgr_set_black_white_pre, CPaneMgr::setBlackWhite)
|
||||
ADD_POST_HOOK(KanteraIconSetNowGauge, kantera_icon_set_now_gauge_post, dKantera_icon_c::setNowGauge)
|
||||
|
||||
// Hook for midna charge ring
|
||||
ADD_POST_HOOK(SetWolfLockDomeModel, wolf_lock_dome_model_post, daAlink_c::setWolfLockDomeModel)
|
||||
|
||||
// Hook for light sword glow
|
||||
ADD_POST_HOOK(SetLightningSwordEffect, set_lightning_sword_effect_post, daAlink_c::setLightningSwordEffect)
|
||||
|
||||
// Hooks for Midna Hair Color
|
||||
ADD_POST_HOOK(MidnaCreate, midna_create_post, daMidna_c::create)
|
||||
ADD_PRE_HOOK(MidnaSetBodyPartMatrix, midna_set_body_part_matrix_pre, daMidna_c::setBodyPartMatrix)
|
||||
ADD_POST_HOOK(MidnaSetBodyPartMatrix, midna_set_body_part_matrix_post, daMidna_c::setBodyPartMatrix)
|
||||
|
||||
// Hooks for UI colors
|
||||
ADD_POST_HOOK(dMeter2Init, d_meter_2_init_post, dMeter2Draw_c::init)
|
||||
ADD_POST_HOOK(FileInfoSetHeartCount, file_info_set_heart_count_post, dFile_info_c::setHeartCnt)
|
||||
ADD_POST_HOOK(ScreenInitButton, screen_init_button_post, dMeterButton_c::screenInitButton)
|
||||
ADD_POST_HOOK(MenuSaveScreenSet, menu_save_screen_set_post, dMenu_save_c::screenSet)
|
||||
ADD_POST_HOOK(FileSelectScreenSet, file_select_screen_set_post, dFile_select_c::screenSet)
|
||||
ADD_POST_HOOK(BrightCheckScreenSet, bright_check_screen_set_post, dBrightCheck_c::screenSet)
|
||||
ADD_POST_HOOK(MenuRingCreate, menu_ring_create_post, dMenu_Ring_c::_create)
|
||||
ADD_POST_HOOK(MenuCollect2DCreate, menu_collect_2D_create_post, dMenu_Collect2D_c::_create)
|
||||
ADD_POST_HOOK(MenuFishingScreenSetDoIcon, menu_fishing_screen_set_do_icon_post, dMenu_Fishing_c::screenSetDoIcon)
|
||||
ADD_POST_HOOK(MenuInsectScreenSetDoIcon, menu_insect_screen_set_do_icon_post, dMenu_Insect_c::screenSetDoIcon)
|
||||
ADD_POST_HOOK(MenuLetterScreenSetDoIcon, menu_letter_screen_set_do_icon_post, dMenu_Letter_c::screenSetDoIcon)
|
||||
ADD_POST_HOOK(MenuOptionCreate, menu_option_create_post, dMenu_Option_c::_create)
|
||||
ADD_POST_HOOK(MenuSkillScreenSetDoIcon, menu_skill_screen_set_do_icon_post, dMenu_Skill_c::screenSetDoIcon)
|
||||
ADD_POST_HOOK(OutFontCreatePane, out_font_create_pane_post, COutFont_c::createPane)
|
||||
ADD_POST_HOOK(OutFontSetDrawFont, out_font_set_draw_font_post, COutFontSet_c::drawFont)
|
||||
ADD_POST_HOOK(MenuFMapCreate, menu_fmap_create_post, dMenu_Fmap_c::_create)
|
||||
ADD_POST_HOOK(MsgObjectTalkStartInit, msg_object_talk_start_init_post, dMsgObject_c::talkStartInit)
|
||||
ADD_POST_HOOK(MeterHakushaCreate, meter_hakusha_create_post, dMeterHakusha_c::_create)
|
||||
|
||||
// Heart Model Color
|
||||
ADD_POST_HOOK(ItemBaseCreateItemHeap, item_base_create_item_heap_post, daItemBase_c::CreateItemHeap)
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "mods/service.hpp"
|
||||
|
||||
ModResult add_all_hooks();
|
||||
@@ -0,0 +1,141 @@
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "mod.hpp"
|
||||
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
#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 };
|
||||
GXColor l_normalKColor = { 0xB4, 0x87, 0x00, 0x00 };
|
||||
GXColor l_normalKColor2 = { 0x00, 0xC3, 0xC3, 0x00 };
|
||||
GXColorS10 l_bigColor = { 0xFF, 0x64, 0x78, 0x00 };
|
||||
GXColor l_bigKColor = { 0x1E, 0x00, 0x00, 0x00 };
|
||||
GXColor l_lNormalKColor = { 0xFF, 0xDC, 0x00, 0x00 };
|
||||
GXColor l_lNormalKColor2 = { 0x00, 0xC3, 0xEB, 0x00 };
|
||||
GXColorS10 l_lBigColor = { 0xFF, 0x78, 0x00, 0x00 };
|
||||
GXColor l_lBigKColor2 = { 0xAA, 0xFF, 0xC3, 0x00 };
|
||||
} currentMidnaHairColors;
|
||||
|
||||
void set_all_midna_hair_colors() {
|
||||
auto& g_cvars = get_cvars();
|
||||
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];
|
||||
auto& bigColor = midnaHairColors.at(hairBaseColor)[5];
|
||||
auto& lBigColor = midnaHairColors.at(hairBaseColor)[4];
|
||||
|
||||
currentMidnaHairColors.l_normalColor = GXColorS10{normalColor.r, normalColor.g, normalColor.b};
|
||||
currentMidnaHairColors.l_normalKColor = midnaHairColors.at(hairBaseColor)[1];
|
||||
currentMidnaHairColors.l_normalKColor2 = midnaHairColors.at(hairTipsColor)[7];
|
||||
currentMidnaHairColors.l_bigColor = GXColorS10{bigColor.r, bigColor.g, bigColor.b};
|
||||
currentMidnaHairColors.l_bigKColor = midnaHairColors.at(hairBaseColor)[3];
|
||||
currentMidnaHairColors.l_lNormalKColor = midnaHairColors.at(hairBaseColor)[0];
|
||||
currentMidnaHairColors.l_lNormalKColor2 = midnaHairColors.at(hairTipsColor)[6];
|
||||
currentMidnaHairColors.l_lBigColor = GXColorS10{lBigColor.r, lBigColor.g, lBigColor.b};
|
||||
currentMidnaHairColors.l_lBigKColor2 = midnaHairColors.at(hairTipsColor)[8];
|
||||
}
|
||||
|
||||
const GXColorS10* get_midna_hair_normalColor() {
|
||||
return ¤tMidnaHairColors.l_normalColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_normalKColor() {
|
||||
return ¤tMidnaHairColors.l_normalKColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_normalKColor2() {
|
||||
return ¤tMidnaHairColors.l_normalKColor2;
|
||||
}
|
||||
|
||||
const GXColorS10* get_midna_hair_bigColor() {
|
||||
return ¤tMidnaHairColors.l_bigColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_bigKColor() {
|
||||
return ¤tMidnaHairColors.l_bigKColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_lNormalKColor() {
|
||||
return ¤tMidnaHairColors.l_lNormalKColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_lNormalKColor2() {
|
||||
return ¤tMidnaHairColors.l_lNormalKColor2;
|
||||
}
|
||||
|
||||
const GXColorS10* get_midna_hair_lBigColor() {
|
||||
return ¤tMidnaHairColors.l_lBigColor;
|
||||
}
|
||||
|
||||
const GXColor* get_midna_hair_lBigKColor2() {
|
||||
return ¤tMidnaHairColors.l_lBigKColor2;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <gx.h>
|
||||
|
||||
void set_all_midna_hair_colors();
|
||||
|
||||
const GXColorS10* get_midna_hair_normalColor();
|
||||
const GXColor* get_midna_hair_normalKColor();
|
||||
const GXColor* get_midna_hair_normalKColor2();
|
||||
const GXColorS10* get_midna_hair_bigColor();
|
||||
const GXColor* get_midna_hair_bigKColor();
|
||||
const GXColor* get_midna_hair_lNormalKColor();
|
||||
const GXColor* get_midna_hair_lNormalKColor2();
|
||||
const GXColorS10* get_midna_hair_lBigColor();
|
||||
const GXColor* get_midna_hair_lBigKColor2();
|
||||
@@ -0,0 +1,282 @@
|
||||
#include "mod.hpp"
|
||||
#include "hooks.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "midna_hair_color.hpp"
|
||||
#include "option_descriptions.hpp"
|
||||
|
||||
#include "mods/service.hpp"
|
||||
#include "mods/svc/config.h"
|
||||
#include "mods/svc/hook.hpp"
|
||||
#include "mods/svc/log.h"
|
||||
#include "mods/svc/log.hpp"
|
||||
#include "mods/svc/ui.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
DEFINE_MOD();
|
||||
IMPORT_SERVICE(LogService, svc_log);
|
||||
IMPORT_SERVICE(ConfigService, svc_config);
|
||||
IMPORT_SERVICE(HookService, svc_hook);
|
||||
IMPORT_SERVICE(UiService, svc_ui);
|
||||
|
||||
static cvars g_cvars;
|
||||
|
||||
cvars& get_cvars() {
|
||||
return g_cvars;
|
||||
}
|
||||
|
||||
std::string get_str_option(ConfigVarHandle handle, const std::string& fallback) {
|
||||
std::string value{};
|
||||
size_t outLength{};
|
||||
svc_config->get_string(mod_ctx, handle, NULL, 0, &outLength);
|
||||
value.resize(outLength);
|
||||
if (handle == 0 || svc_config->get_string(mod_ctx, handle, value.data(), value.size() + 1, &outLength) != MOD_OK) {
|
||||
return 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;
|
||||
|
||||
ModResult register_str_option(
|
||||
const char* name, const char* defaultValue, ConfigVarHandle& outHandle, ModError* error) {
|
||||
ConfigVarDesc cvarDesc = CONFIG_VAR_DESC_INIT;
|
||||
cvarDesc.name = name;
|
||||
cvarDesc.type = CONFIG_VAR_STRING;
|
||||
cvarDesc.default_string = 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
mods::log::debug("pane_add_control failed {}", static_cast<int>(result));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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", kLinksCapColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.herosTunicTorsoColor, "Hero's Tunic Body Color", kLinksShirtColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.herosTunicSkirtColor, "Hero's Tunic Skirt Color", kLinksSkirtColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorCapColor, "Zora Armor Cap Color", kZoraCapColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorHelmetColor, "Zora Armor Helmet Color", kZoraHelmetColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorTorsoColor, "Zora Armor Torso Color", kZoraTorsoColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorScalesColor, "Zora Armor Scales Color", kZoraScalesColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zoraArmorFlippersColor, "Zora Armor Flippers Color", kZoraFlippersColorsExplanation);
|
||||
add_cosmetic_option_with_rainbow(left, g_cvars.lanternGlowColor, "Lantern Glow Color", kLanternGlowColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.woodenSwordColor, "Wooden Sword Color", kWoodenSwordColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ordonSwordBladeColor, "Ordon Sword Blade Color", kOrdonBladeColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ordonSwordHandleColor, "Ordon Sword Handle Color", kOrdonHandleColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.msBladeColor, "Master Sword Blade Color", kMSBladeColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.msHandleColor, "Master Sword Handle Color", kMSHandleColorsExplanation);
|
||||
add_cosmetic_option_with_rainbow(left, g_cvars.lightSwordGlowColor, "Light Sword Glow Color", kSwordGlowColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.boomerangColor, "Boomerang Color", kBoomerangColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.ironBootsColor, "Iron Boots Color", kIronBootsColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.spinnerColor, "Spinner Color", kSpinnerColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult build_ui_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
add_cosmetic_option(left, g_cvars.aButtonColor, "A Button Color", kAButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.bButtonColor, "B Button Color", kBButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.xButtonColor, "X Button Color", kXButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.yButtonColor, "Y Button Color", kYButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.zButtonColor, "Z Button Color", kZButtonColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.heartColor, "Heart Color", kHeartColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
ModResult build_misc_colors_tab(
|
||||
ModContext*, UiWindowHandle, UiElementHandle left, UiElementHandle right, void*, ModError*) {
|
||||
(void)right;
|
||||
|
||||
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", kLinksHairColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.wolfLinkColor, "Wolf Link Color", kWolfLinkColorsExplanation);
|
||||
add_cosmetic_option(left, g_cvars.eponaColor, "Epona Color", kEponaColorsExplanation);
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
void on_cosmetics_menu_window_closed(ModContext*, UiWindowHandle, void*) {
|
||||
g_cosmeticsWindow = 0;
|
||||
}
|
||||
|
||||
void on_open_cosmetics_menu(ModContext*, void*) {
|
||||
if (g_cosmeticsWindow != 0) {
|
||||
return;
|
||||
}
|
||||
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 = "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);
|
||||
desc.on_closed = on_cosmetics_menu_window_closed;
|
||||
if (svc_ui->window_push(mod_ctx, &desc, &g_cosmeticsWindow) != MOD_OK) {
|
||||
svc_log->error(mod_ctx, "failed to open basic cosmetics window");
|
||||
}
|
||||
}
|
||||
|
||||
ModResult build_panel(ModContext*, UiElementHandle panel, void*, ModError*) {
|
||||
UiControlDesc control = UI_CONTROL_DESC_INIT;
|
||||
control.kind = UI_CONTROL_BUTTON;
|
||||
control.label = "Open Cosmetics Menu";
|
||||
control.on_pressed = on_open_cosmetics_menu;
|
||||
add_control(panel, control);
|
||||
return MOD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#define REGISTER_COSMETIC_OPTION(option) \
|
||||
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)
|
||||
REGISTER_COSMETIC_OPTION(zoraArmorCapColor)
|
||||
REGISTER_COSMETIC_OPTION(zoraArmorHelmetColor)
|
||||
REGISTER_COSMETIC_OPTION(zoraArmorTorsoColor)
|
||||
REGISTER_COSMETIC_OPTION(zoraArmorScalesColor)
|
||||
REGISTER_COSMETIC_OPTION(zoraArmorFlippersColor)
|
||||
REGISTER_COSMETIC_OPTION(lanternGlowColor)
|
||||
REGISTER_COSMETIC_OPTION(woodenSwordColor)
|
||||
REGISTER_COSMETIC_OPTION(ordonSwordBladeColor)
|
||||
REGISTER_COSMETIC_OPTION(ordonSwordHandleColor)
|
||||
REGISTER_COSMETIC_OPTION(msBladeColor)
|
||||
REGISTER_COSMETIC_OPTION(msHandleColor)
|
||||
REGISTER_COSMETIC_OPTION(lightSwordGlowColor)
|
||||
REGISTER_COSMETIC_OPTION(boomerangColor)
|
||||
REGISTER_COSMETIC_OPTION(ironBootsColor)
|
||||
REGISTER_COSMETIC_OPTION(spinnerColor)
|
||||
REGISTER_COSMETIC_OPTION(aButtonColor)
|
||||
REGISTER_COSMETIC_OPTION(bButtonColor)
|
||||
REGISTER_COSMETIC_OPTION(xButtonColor)
|
||||
REGISTER_COSMETIC_OPTION(yButtonColor)
|
||||
REGISTER_COSMETIC_OPTION(zButtonColor)
|
||||
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)
|
||||
REGISTER_COSMETIC_OPTION(eponaColor)
|
||||
|
||||
UiModsPanelDesc panelDesc = UI_MODS_PANEL_DESC_INIT;
|
||||
panelDesc.build = build_panel;
|
||||
svc_ui->register_mods_panel(mod_ctx, &panelDesc);
|
||||
|
||||
// Add all our hooks
|
||||
result = add_all_hooks();
|
||||
if (result != MOD_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
MOD_EXPORT ModResult mod_update(ModError*) {
|
||||
update_rainbow_rgb(1.0f);
|
||||
set_all_midna_hair_colors();
|
||||
return MOD_OK;
|
||||
}
|
||||
|
||||
MOD_EXPORT ModResult mod_shutdown(ModError*) {
|
||||
svc_log->info(mod_ctx, "basic_cosmetics_mod unloaded");
|
||||
g_cosmeticsWindow = 0;
|
||||
return MOD_OK;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "mods/svc/config.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct cvars {
|
||||
ConfigVarHandle herosTunicCapColor = 0;
|
||||
ConfigVarHandle herosTunicTorsoColor = 0;
|
||||
ConfigVarHandle herosTunicSkirtColor = 0;
|
||||
ConfigVarHandle zoraArmorCapColor = 0;
|
||||
ConfigVarHandle zoraArmorHelmetColor = 0;
|
||||
ConfigVarHandle zoraArmorTorsoColor = 0;
|
||||
ConfigVarHandle zoraArmorScalesColor = 0;
|
||||
ConfigVarHandle zoraArmorFlippersColor = 0;
|
||||
ConfigVarHandle lanternGlowColor = 0;
|
||||
ConfigVarHandle woodenSwordColor = 0;
|
||||
ConfigVarHandle ordonSwordBladeColor = 0;
|
||||
ConfigVarHandle ordonSwordHandleColor = 0;
|
||||
ConfigVarHandle msBladeColor = 0;
|
||||
ConfigVarHandle msHandleColor = 0;
|
||||
ConfigVarHandle lightSwordGlowColor = 0;
|
||||
ConfigVarHandle boomerangColor = 0;
|
||||
ConfigVarHandle ironBootsColor = 0;
|
||||
ConfigVarHandle spinnerColor = 0;
|
||||
ConfigVarHandle heartColor = 0;
|
||||
ConfigVarHandle aButtonColor = 0;
|
||||
ConfigVarHandle bButtonColor = 0;
|
||||
ConfigVarHandle xButtonColor = 0;
|
||||
ConfigVarHandle yButtonColor = 0;
|
||||
ConfigVarHandle zButtonColor = 0;
|
||||
ConfigVarHandle midnaHairBaseColor = 0;
|
||||
ConfigVarHandle midnaHairTipsColor = 0;
|
||||
ConfigVarHandle midnaChargeRingColor = 0;
|
||||
ConfigVarHandle linkHairColor = 0;
|
||||
ConfigVarHandle wolfLinkColor = 0;
|
||||
ConfigVarHandle eponaColor = 0;
|
||||
};
|
||||
|
||||
cvars& get_cvars();
|
||||
|
||||
std::string get_str_option(ConfigVarHandle handle, const std::string& fallback);
|
||||
|
||||
int64_t get_int_option(ConfigVarHandle handle, int64_t fallback);
|
||||
@@ -0,0 +1,354 @@
|
||||
#pragma once
|
||||
|
||||
constexpr const char* kLinksCapColorsExplanation =
|
||||
"Set the color of the Hero's Tunic cap with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kLinksShirtColorsExplanation =
|
||||
"Set the color of the Hero's Tunic shirt with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kLinksSkirtColorsExplanation =
|
||||
"Set the color of the Hero's Tunic skirt with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kZoraCapColorsExplanation =
|
||||
"Set the color of the Zora Armor cap with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kZoraHelmetColorsExplanation =
|
||||
"Set the color of the Zora Armor helmet with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kZoraTorsoColorsExplanation =
|
||||
"Set the color of the Zora Armor torso with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kZoraScalesColorsExplanation =
|
||||
"Set the color of the Zora Armor scales with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kZoraFlippersColorsExplanation =
|
||||
"Set the color of the Zora Armor flippers with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kWoodenSwordColorsExplanation =
|
||||
"Set the color with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kLanternGlowColorsExplanation =
|
||||
"Set the color of the lantern light 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/>";
|
||||
|
||||
constexpr const char* kOrdonBladeColorsExplanation =
|
||||
"Set the color of the Ordon Sword's blade 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/>";
|
||||
|
||||
constexpr const char* kOrdonHandleColorsExplanation =
|
||||
"Set the color of the Ordon Sword's handle 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/>";
|
||||
|
||||
constexpr const char* kMSBladeColorsExplanation =
|
||||
"Set the color of the Master Sword's blade 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/>";
|
||||
|
||||
constexpr const char* kMSHandleColorsExplanation =
|
||||
"Set the color of the Master Sword's handle 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/>";
|
||||
|
||||
constexpr const char* kSwordGlowColorsExplanation =
|
||||
"Set the color of the light sword glow 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/>";
|
||||
|
||||
constexpr const char* kBoomerangColorsExplanation =
|
||||
"Set the color of the Gale Boomerang with any 6 digit hex code. Closing and re-opening Dusklight 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/>";
|
||||
|
||||
constexpr const char* kIronBootsColorsExplanation =
|
||||
"Set the color of the Iron Boots with any 6 digit hex code. Closing and re-opening Dusklight 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/>";
|
||||
|
||||
constexpr const char* kSpinnerColorsExplanation =
|
||||
"Set the color of the Spinner with any 6 digit hex code. Closing and re-opening Dusklight 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/>";
|
||||
|
||||
|
||||
constexpr const char* kAButtonColorsExplanation =
|
||||
"Set the color of the A button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff5000<br/>"
|
||||
"- Yellow: ffaf00<br/>"
|
||||
"- Dark Green: 0080ff<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 8000ff<br/>"
|
||||
"- Grey: 5555ff<br/>"
|
||||
"- Pink: ff20ff<br/>";
|
||||
|
||||
constexpr const char* kBButtonColorsExplanation =
|
||||
"Set the color of the B button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Orange: ffff40<br/>"
|
||||
"- Pink: ffa0ff<br/>"
|
||||
"- Green: 00e87b<br/>"
|
||||
"- Blue: 00aaff<br/>"
|
||||
"- Purple: 6078ff<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Teal: 00f3ff<br/>";
|
||||
|
||||
constexpr const char* kXButtonColorsExplanation =
|
||||
"Set the color of the X button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff8200<br/>"
|
||||
"- Yellow: f7df00<br/>"
|
||||
"- Lime Green: 70ff00<br/>"
|
||||
"- Dark Green: 00bd11<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 800088<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Pink: ff00aa<br/>"
|
||||
"- Cyan: 00ffff<br/>";
|
||||
|
||||
constexpr const char* kYButtonColorsExplanation =
|
||||
"Set the color of the Y button with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff8200<br/>"
|
||||
"- Yellow: f7df00<br/>"
|
||||
"- Lime Green: 70ff00<br/>"
|
||||
"- Dark Green: 00bd11<br/>"
|
||||
"- Blue: 0000ff<br/>"
|
||||
"- Purple: 800088<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Pink: ff00aa<br/>"
|
||||
"- Cyan: 00ffff<br/>";
|
||||
|
||||
constexpr const char* kZButtonColorsExplanation =
|
||||
"Set the Z button color with any 6 digit hex code. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Red: ff0000<br/>"
|
||||
"- Orange: ff8200<br/>"
|
||||
"- Yellow: f7df00<br/>"
|
||||
"- Lime Green: 70ff00<br/>"
|
||||
"- Dark Green: 00bd11<br/>"
|
||||
"- Purple: 800088<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Light Blue: 00ffff<br/>";
|
||||
|
||||
constexpr const char* kHeartColorsExplanation =
|
||||
"Set the heart color with any 6 digit hex code. This will also change the color of heart drops. A reload may be necessary to see changes.<br/>"
|
||||
"Common colors:<br/>"
|
||||
"- Orange: ffff40<br/>"
|
||||
"- Pink: ffa0ff<br/>"
|
||||
"- Green: 00e87b<br/>"
|
||||
"- Blue: 00aaff<br/>"
|
||||
"- Purple: 6078ff<br/>"
|
||||
"- Black: 000000<br/>"
|
||||
"- Teal: 00f3ff<br/>";
|
||||
|
||||
constexpr const char* kChargeRingColorsExplanation =
|
||||
"Set the color of Midna's charge ring 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/>";
|
||||
|
||||
constexpr const char* kLinksHairColorsExplanation =
|
||||
"Set the color of Link's hair with any 6 digit hex code. Loading a new area, changing forms, or changing tunics is 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/>";
|
||||
|
||||
constexpr const char* kWolfLinkColorsExplanation =
|
||||
"Set the color of Wolf Link with any 6 digit hex code. Loading a new area or changing forms is 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/>";
|
||||
|
||||
constexpr const char* kEponaColorsExplanation =
|
||||
"Set the color of Wolf Link with any 6 digit hex code. Loading a new area while *not* riding Epona is 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/>";
|
||||
@@ -0,0 +1,549 @@
|
||||
#include "texture_utils.hpp"
|
||||
#include "color_utils.hpp"
|
||||
#include "mod.hpp"
|
||||
|
||||
#include "mods/svc/config.h"
|
||||
#include "mods/svc/log.hpp"
|
||||
|
||||
// Forward declaration needed for J3DModelLoader to be happy
|
||||
class J3DVertexData;
|
||||
#include "JSystem/J3DGraphLoader/J3DModelLoader.h"
|
||||
#include "JSystem/JKernel/JKRMemArchive.h"
|
||||
#include "JSystem/JSupport/JSupport.h"
|
||||
#include "JSystem/JUtility/JUTNameTab.h"
|
||||
#include "JSystem/JUtility/JUTTexture.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "global.h"
|
||||
#include "gx/GXEnum.h"
|
||||
#include "m_Do/m_Do_dvd_thread.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
ResTIMG* find_tex_header_in_tex_1_section(J3DTextureBlock* tex1Ptr, const char* textureName) {
|
||||
if (tex1Ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto strTable = JSUConvertOffsetToPtr<ResNTAB>(tex1Ptr, tex1Ptr->mpNameTable);
|
||||
for (size_t i = 0; i < strTable->mEntryNum && i < tex1Ptr->mTextureNum; i++) {
|
||||
const char* str = strTable->getName(i);
|
||||
|
||||
if (strcmp(str, textureName) == 0) {
|
||||
return &JSUConvertOffsetToPtr<ResTIMG>(tex1Ptr, tex1Ptr->mpTextureRes)[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void recolor_rgb5a3_texture(ResTIMG* texHeaderPtr, GXColor color)
|
||||
{
|
||||
// Precompute lookup tables for both RGB555 (opaque) and RGB444 (translucent) modes
|
||||
uint16_t recolors_rgb555[0x100];
|
||||
uint16_t recolors_rgb444[0x100];
|
||||
|
||||
for (int32_t i = 0; i < 0x100; i++) {
|
||||
const uint8_t r = blend_overlay_channel(i, color.r);
|
||||
const uint8_t g = blend_overlay_channel(i, color.g);
|
||||
const uint8_t b = blend_overlay_channel(i, color.b);
|
||||
|
||||
// Pack as RGB555: Bit 15 set to 1 + 5 bits R, G, B
|
||||
recolors_rgb555[i] = 0x8000 | ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
|
||||
|
||||
// Pack as RGB444: 4 bits R, G, B (Bit 15 remains 0)
|
||||
recolors_rgb444[i] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);
|
||||
}
|
||||
|
||||
constexpr int32_t blockWidth = 4;
|
||||
constexpr int32_t blockHeight = 4;
|
||||
|
||||
const int32_t roundedWidth = texHeaderPtr->width + ((blockWidth - (texHeaderPtr->width % blockWidth)) % blockWidth);
|
||||
const int32_t roundedHeight = texHeaderPtr->height + ((blockHeight - (texHeaderPtr->height % blockHeight)) % blockHeight);
|
||||
|
||||
const int32_t totalPixels = roundedWidth * roundedHeight;
|
||||
|
||||
auto* pixelPtr = reinterpret_cast<BE<uint16_t>*>(JSUConvertOffsetToPtr<u8>(texHeaderPtr, texHeaderPtr->imageOffset));
|
||||
|
||||
for (int32_t i = 0; i < totalPixels; i++) {
|
||||
const uint16_t rawPixel = pixelPtr[i];
|
||||
|
||||
// MSB determines if pixel is opaque or translucent
|
||||
if (rawPixel & 0x8000) {
|
||||
// Pixel is opaque
|
||||
const uint8_t r5 = (rawPixel >> 10) & 0x1F;
|
||||
const uint8_t g5 = (rawPixel >> 5) & 0x1F;
|
||||
const uint8_t b5 = rawPixel & 0x1F;
|
||||
|
||||
// Expand 5-bit to 8-bit
|
||||
const uint8_t r8 = (r5 << 3) | (r5 >> 2);
|
||||
const uint8_t g8 = (g5 << 3) | (g5 >> 2);
|
||||
const uint8_t b8 = (b5 << 3) | (b5 >> 2);
|
||||
|
||||
const uint8_t grayVal = static_cast<uint8_t>((r8 * 77 + g8 * 150 + b8 * 29) >> 8);
|
||||
|
||||
pixelPtr[i] = recolors_rgb555[grayVal];
|
||||
} else {
|
||||
// Pixel is translucent
|
||||
const uint16_t alpha3 = rawPixel & 0x7000;
|
||||
|
||||
const uint8_t r4 = (rawPixel >> 8) & 0x0F;
|
||||
const uint8_t g4 = (rawPixel >> 4) & 0x0F;
|
||||
const uint8_t b4 = rawPixel & 0x0F;
|
||||
|
||||
// Expand 4-bit to 8-bit
|
||||
const uint8_t r8 = (r4 << 4) | r4;
|
||||
const uint8_t g8 = (g4 << 4) | g4;
|
||||
const uint8_t b8 = (b4 << 4) | b4;
|
||||
|
||||
const uint8_t grayVal = static_cast<uint8_t>((r8 * 77 + g8 * 150 + b8 * 29) >> 8);
|
||||
|
||||
// Combine original alpha with recolored RGB444
|
||||
pixelPtr[i] = alpha3 | recolors_rgb444[grayVal];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// When left is greater than right
|
||||
// 0b00 points to the left color
|
||||
// 0b01 points to the right color
|
||||
// 0b10 is closer to left color
|
||||
// 0b11 is closer to right color
|
||||
|
||||
// When left is not greater than right
|
||||
// 0b00 points to the left color
|
||||
// 0b01 points to the right color
|
||||
// 0b10 is midway between the colors
|
||||
// 0b11 is transparent
|
||||
|
||||
// That means when maintaining the relative order, if we have to swap the colors:
|
||||
|
||||
// in the case of left being greater than right:
|
||||
// 0b00 will swap to 0b01
|
||||
// 0b01 will swap to 0b00
|
||||
// 0b10 will swap to 0b11
|
||||
// 0b11 will swap to 0b10
|
||||
// So the left bit stays the same, and the right bit changes
|
||||
// Can do xor (^) like 0b01010101 or 0x55 for each u16
|
||||
|
||||
// in the case of left not being greater than right:
|
||||
// 0b00 will swap to 0b01
|
||||
// 0b01 will swap to 0b00
|
||||
// 0b10 will stay the same
|
||||
// 0b11 will stay the same
|
||||
// so if the left bit is a 0, the right bit will change
|
||||
uint32_t swap_index_bits(bool leftIsGreater, uint32_t bits) {
|
||||
if (leftIsGreater) {
|
||||
return bits ^ 0x55555555;
|
||||
}
|
||||
|
||||
const uint32_t mask = ((bits >> 1) & 0x55555555) ^ 0x55555555;
|
||||
return bits ^ mask;
|
||||
}
|
||||
|
||||
void recolor_cmpr_texture(ResTIMG* texHeaderPtr, GXColor color)
|
||||
{
|
||||
uint16_t recolors[0x100];
|
||||
for (int32_t i = 0; i < 0x100; i++) {
|
||||
recolors[i] = blend_overlay_rgb_565(i, color);
|
||||
}
|
||||
|
||||
constexpr int32_t blockWidth = 8;
|
||||
constexpr int32_t blockHeight = 8;
|
||||
|
||||
const int32_t roundedWidth = texHeaderPtr->width + ((blockWidth - (texHeaderPtr->width % blockWidth)) % blockWidth);
|
||||
const int32_t roundedHeight = texHeaderPtr->height + ((blockHeight - (texHeaderPtr->height % blockHeight)) % blockHeight);
|
||||
|
||||
const int32_t numBlocks = roundedWidth / blockWidth * roundedHeight / blockHeight;
|
||||
|
||||
const int32_t iterations = numBlocks * 4;
|
||||
|
||||
uint8_t* currentAddr = JSUConvertOffsetToPtr<u8>(texHeaderPtr, texHeaderPtr->imageOffset);
|
||||
for (int32_t i = 0; i < iterations; i++) {
|
||||
auto* rgb565Ptr = reinterpret_cast<BE<uint16_t>*>(currentAddr);
|
||||
|
||||
auto leftRgb565 = rgb565Ptr[0];
|
||||
auto rightRgb565 = rgb565Ptr[1];
|
||||
const bool leftIsGreater = leftRgb565 > rightRgb565;
|
||||
|
||||
const uint32_t leftGrayVal = desaturate_rgb_565(leftRgb565);
|
||||
const uint32_t rightGrayVal = desaturate_rgb_565(rightRgb565);
|
||||
|
||||
uint16_t leftNewRgb565 = recolors[leftGrayVal];
|
||||
uint16_t rightNewRgb565 = recolors[rightGrayVal];
|
||||
|
||||
bool needsBitSwap = false;
|
||||
|
||||
if (leftIsGreater) {
|
||||
if (leftNewRgb565 == rightNewRgb565) {
|
||||
// Need to make sure that subtracting 1 does not mess
|
||||
// everything up. For example, 0x1000 - 1 => 0x0fff which is
|
||||
// a completely different color.
|
||||
if ((leftNewRgb565 & 0x1f) == 0)
|
||||
{
|
||||
// If left value has 0 blue, we change its blue to 1.
|
||||
leftNewRgb565 += 1;
|
||||
}
|
||||
rightNewRgb565 = leftNewRgb565 - 1;
|
||||
}
|
||||
else if (leftNewRgb565 < rightNewRgb565) {
|
||||
needsBitSwap = true;
|
||||
}
|
||||
}
|
||||
else if (leftNewRgb565 > rightNewRgb565) {
|
||||
needsBitSwap = true;
|
||||
}
|
||||
|
||||
if (needsBitSwap) {
|
||||
// The left and right colors are swapping so that their values
|
||||
// are relative in the same way. We need to update the bits
|
||||
// referencing the palette entries to handle the swap.
|
||||
|
||||
const uint16_t temp = leftNewRgb565;
|
||||
leftNewRgb565 = rightNewRgb565;
|
||||
rightNewRgb565 = temp;
|
||||
|
||||
auto wordPtr = reinterpret_cast<BE<uint32_t>*>(currentAddr);
|
||||
const uint32_t bits = wordPtr[1];
|
||||
|
||||
const uint32_t newBits = swap_index_bits(leftIsGreater, bits);
|
||||
wordPtr[1] = newBits;
|
||||
}
|
||||
|
||||
rgb565Ptr[0] = leftNewRgb565;
|
||||
rgb565Ptr[1] = rightNewRgb565;
|
||||
|
||||
currentAddr += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to encode a single 4x4 sub-block (16 pixels) into an 8-byte CMPR block
|
||||
static void encode_cmpr_sub_block(uint8_t* dst, const uint8_t pixels[16]) {
|
||||
uint8_t min_val = 255;
|
||||
uint8_t max_val = 0;
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (pixels[i] < min_val) min_val = pixels[i];
|
||||
if (pixels[i] > max_val) max_val = pixels[i];
|
||||
}
|
||||
|
||||
auto intensity_to_rgb565 = [](uint8_t val) -> uint16_t {
|
||||
uint16_t r5 = val >> 3;
|
||||
uint16_t g6 = val >> 2;
|
||||
uint16_t b5 = val >> 3;
|
||||
return static_cast<uint16_t>((r5 << 11) | (g6 << 5) | b5);
|
||||
};
|
||||
|
||||
uint16_t c0_565 = intensity_to_rgb565(max_val);
|
||||
uint16_t c1_565 = intensity_to_rgb565(min_val);
|
||||
uint32_t indices = 0;
|
||||
|
||||
if (max_val > min_val) {
|
||||
// Enforce c0_565 > c1_565 in unsigned 16-bit representation to use 4-color mode
|
||||
if (c0_565 == c1_565) {
|
||||
if ((c0_565 & 0x001F) < 0x001F) {
|
||||
c0_565 += 1;
|
||||
} else {
|
||||
c1_565 -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Interpolated 8-bit intensity values for quantization
|
||||
const int c0 = max_val;
|
||||
const int c1 = min_val;
|
||||
const int c2 = (2 * max_val + min_val) / 3;
|
||||
const int c3 = (max_val + 2 * min_val) / 3;
|
||||
|
||||
// Map each pixel to the nearest palette entry
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
const int p = pixels[i];
|
||||
const int d0 = std::abs(p - c0);
|
||||
const int d1 = std::abs(p - c1);
|
||||
const int d2 = std::abs(p - c2);
|
||||
const int d3 = std::abs(p - c3);
|
||||
|
||||
uint32_t best_idx = 0;
|
||||
int min_d = d0;
|
||||
|
||||
if (d1 < min_d) { min_d = d1; best_idx = 1; }
|
||||
if (d2 < min_d) { min_d = d2; best_idx = 2; }
|
||||
if (d3 < min_d) { min_d = d3; best_idx = 3; }
|
||||
|
||||
indices |= (best_idx << (30 - (2 * i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Account for big endian data expectation
|
||||
dst[0] = static_cast<uint8_t>(c0_565 >> 8);
|
||||
dst[1] = static_cast<uint8_t>(c0_565 & 0xFF);
|
||||
dst[2] = static_cast<uint8_t>(c1_565 >> 8);
|
||||
dst[3] = static_cast<uint8_t>(c1_565 & 0xFF);
|
||||
dst[4] = static_cast<uint8_t>(indices >> 24);
|
||||
dst[5] = static_cast<uint8_t>((indices >> 16) & 0xFF);
|
||||
dst[6] = static_cast<uint8_t>((indices >> 8) & 0xFF);
|
||||
dst[7] = static_cast<uint8_t>(indices & 0xFF);
|
||||
}
|
||||
|
||||
bool convert_i8_to_cmpr(ResTIMG* texHeaderPtr) {
|
||||
|
||||
const uint16_t width = texHeaderPtr->width;
|
||||
const uint16_t height = texHeaderPtr->height;
|
||||
|
||||
if (width % 8 != 0 || height % 8 != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t tilesX = width / 8;
|
||||
const uint32_t blocksY_CMPR = height / 8;
|
||||
|
||||
auto* imageData = JSUConvertOffsetToPtr<uint8_t>(texHeaderPtr, texHeaderPtr->imageOffset);
|
||||
uint8_t* writePtr = imageData;
|
||||
|
||||
// Process image in 8x8 blocks
|
||||
for (uint32_t by = 0; by < blocksY_CMPR; ++by) {
|
||||
for (uint32_t bx = 0; bx < tilesX; ++bx) {
|
||||
// Locate the two stacked 8x4 I8 tiles (32 bytes each) making up the 8x8 block
|
||||
const uint32_t topTileIdx = (2 * by) * tilesX + bx;
|
||||
const uint32_t bottomTileIdx = (2 * by + 1) * tilesX + bx;
|
||||
|
||||
const uint8_t* topTileData = imageData + (topTileIdx * 32);
|
||||
const uint8_t* bottomTileData = imageData + (bottomTileIdx * 32);
|
||||
|
||||
uint8_t subBlockPixels[4][16];
|
||||
|
||||
// Extract Sub-block 0 (Top-Left) and Sub-block 1 (Top-Right)
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
subBlockPixels[0][row * 4 + col] = topTileData[row * 8 + col];
|
||||
subBlockPixels[1][row * 4 + col] = topTileData[row * 8 + col + 4];
|
||||
}
|
||||
}
|
||||
|
||||
// Extract Sub-block 2 (Bottom-Left) and Sub-block 3 (Bottom-Right)
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
subBlockPixels[2][row * 4 + col] = bottomTileData[row * 8 + col];
|
||||
subBlockPixels[3][row * 4 + col] = bottomTileData[row * 8 + col + 4];
|
||||
}
|
||||
}
|
||||
|
||||
// Encode the 4 sub-blocks in CMPR order (32 bytes per 8x8 block)
|
||||
for (const auto& subBlockPixel : subBlockPixels) {
|
||||
encode_cmpr_sub_block(writePtr, subBlockPixel);
|
||||
writePtr += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update ResTIMG header metadata
|
||||
texHeaderPtr->format = GX_TF_CMPR; // 0x0E
|
||||
texHeaderPtr->colorFormat = 0;
|
||||
texHeaderPtr->numColors = 0;
|
||||
texHeaderPtr->paletteOffset = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void recolor_texture(J3DTextureBlock* tex1Ptr, const char* textureName, GXColor color) {
|
||||
ResTIMG* texHeaderPtr = find_tex_header_in_tex_1_section(tex1Ptr, textureName);
|
||||
if (texHeaderPtr == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (texHeaderPtr->format) {
|
||||
case GX_TF_CMPR:
|
||||
recolor_cmpr_texture(texHeaderPtr, color);
|
||||
break;
|
||||
case GX_TF_RGB5A3:
|
||||
recolor_rgb5a3_texture(texHeaderPtr, color);
|
||||
break;
|
||||
case GX_TF_I8:
|
||||
if (convert_i8_to_cmpr(texHeaderPtr)) {
|
||||
recolor_cmpr_texture(texHeaderPtr, color);
|
||||
} else {
|
||||
mods::log::debug("Could not convert {} from i8 to cmpr", textureName);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
J3DTextureBlock* find_tex_1_in_bmd(J3DModelFileData* bmdPtr)
|
||||
{
|
||||
if (bmdPtr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (bmdPtr->mMagic1 != MULTI_CHAR('J3D2')) {
|
||||
// Model was not a BMD or BDL!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (bmdPtr->mMagic2 != MULTI_CHAR('bmd3') && bmdPtr->mMagic2 != MULTI_CHAR('bdl4')) {
|
||||
// Model was not a BMD or BDL!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
J3DModelBlock* curBlock = bmdPtr->mBlocks;
|
||||
for (int32_t i = 0; i < bmdPtr->mBlockNum; i++) {
|
||||
if (curBlock->mBlockType == MULTI_CHAR('TEX1')) {
|
||||
return static_cast<J3DTextureBlock*>(curBlock);
|
||||
}
|
||||
|
||||
// Line taken from J3DModelLoader.cpp
|
||||
curBlock = (J3DModelBlock*)((uintptr_t)curBlock + curBlock->mBlockSize);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct CosmeticOverride {
|
||||
std::list<std::string_view> textures{};
|
||||
ConfigVarHandle hexColor{0};
|
||||
};
|
||||
|
||||
auto& get_cosmetic_overrides() {
|
||||
static std::unordered_map<s32, std::unordered_map<std::string_view, std::list<CosmeticOverride>>> cosmeticOverrides{};
|
||||
if (cosmeticOverrides.empty()) {
|
||||
auto& g_cvars = get_cvars();
|
||||
// Ordon Clothes Link Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Bmdl.arc")]["bmwr/al_swb.bmd"] = {
|
||||
{.textures = {"al_SWB"}, .hexColor = g_cvars.woodenSwordColor},
|
||||
};
|
||||
// Main Link Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Kmdl.arc")]["bmwr/al_head.bmd"] = {
|
||||
{.textures = {"al_cap"}, .hexColor = g_cvars.herosTunicCapColor},
|
||||
{.textures = {"al_hair"}, .hexColor = g_cvars.linkHairColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Kmdl.arc")]["bmwr/al.bmd"] = {
|
||||
{.textures = {"al_upbody"}, .hexColor = g_cvars.herosTunicTorsoColor},
|
||||
{.textures = {"al_lowbody"}, .hexColor = g_cvars.herosTunicSkirtColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Kmdl.arc")]["bmwr/al_bootsh.bmd"] = {
|
||||
{.textures = {"al_bootsH"}, .hexColor = g_cvars.ironBootsColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Kmdl.arc")]["bmwr/al_swb.bmd"] = {
|
||||
{.textures = {"al_SWB"}, .hexColor = g_cvars.woodenSwordColor},
|
||||
};
|
||||
// Zora Armor Link Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Zmdl.arc")]["bmwr/zl_head.bmd"] = {
|
||||
{.textures = {"zl_cap"}, .hexColor = g_cvars.zoraArmorCapColor},
|
||||
{.textures = {"zl_helmet"}, .hexColor = g_cvars.zoraArmorHelmetColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Zmdl.arc")]["bmwr/zl.bmd"] = {
|
||||
{.textures = {"zl_armor", "zl_armL"}, .hexColor = g_cvars.zoraArmorTorsoColor},
|
||||
{.textures = {"zl_body"}, .hexColor = g_cvars.zoraArmorScalesColor},
|
||||
{.textures = {"zl_boots"}, .hexColor = g_cvars.zoraArmorFlippersColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Zmdl.arc")]["bmwr/al_bootsh.bmd"] = {
|
||||
{.textures = {"al_bootsH"}, .hexColor = g_cvars.ironBootsColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Zmdl.arc")]["bmwr/al_swb.bmd"] = {
|
||||
{.textures = {"al_SWB"}, .hexColor = g_cvars.woodenSwordColor},
|
||||
};
|
||||
// Zora Armor field model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/O_gD_zora.arc")]["bmdr/o_gd_al_zora.bmd"] = {
|
||||
{.textures = {"zl_armor"}, .hexColor = g_cvars.zoraArmorTorsoColor},
|
||||
{.textures = {"zl_body"}, .hexColor = g_cvars.zoraArmorScalesColor},
|
||||
{.textures = {"zl_helmet"}, .hexColor = g_cvars.zoraArmorHelmetColor},
|
||||
{.textures = {"zl_cap"}, .hexColor = g_cvars.zoraArmorCapColor},
|
||||
};
|
||||
// Magic Armor Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Mmdl.arc")]["bmwr/al_bootsh.bmd"] = {
|
||||
{.textures = {"al_bootsH"}, .hexColor = g_cvars.ironBootsColor},
|
||||
};
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Mmdl.arc")]["bmwr/al_swb.bmd"] = {
|
||||
{.textures = {"al_SWB"}, .hexColor = g_cvars.woodenSwordColor},
|
||||
};
|
||||
// Ordon Sword Colors
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Alink.arc")]["bmwr/al_swa.bmd"] = {
|
||||
{.textures = {"al_SWA", "hilight01"}, .hexColor = g_cvars.ordonSwordBladeColor},
|
||||
{.textures = {"al_SWgripA"}, .hexColor = g_cvars.ordonSwordHandleColor},
|
||||
};
|
||||
// Master Sword Colors
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Alink.arc")]["bmwe/al_swm.bmd"] = {
|
||||
{.textures = {"al_SWM"}, .hexColor = g_cvars.msBladeColor},
|
||||
{.textures = {"al_SWgripM"}, .hexColor = g_cvars.msHandleColor},
|
||||
};
|
||||
// Boomerang Color
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Alink.arc")]["bmdr/al_boom.bmd"] = {
|
||||
{.textures = {"L_al_boom00"}, .hexColor = g_cvars.boomerangColor},
|
||||
};
|
||||
// Spinner Color
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Alink.arc")]["bmdr/al_sp.bmd"] = {
|
||||
{.textures = {"al_SP"}, .hexColor = g_cvars.spinnerColor},
|
||||
};
|
||||
// Epona Color
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Horse.arc")]["bmdr/hs.bmd"] = {
|
||||
{.textures = {"hs_body", "hs_eye.1", "hs_eye.2", "hs_eye.3"}, .hexColor = g_cvars.eponaColor},
|
||||
};
|
||||
// Wolf Link Color
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/Wmdl.arc")]["bmwr/wl.bmd"] = {
|
||||
{.textures = {"wl_body", "wl_eye.1", "wl_eye.2", "wl_eye.3", "wl_eye.4", "wl_eye.5"}, .hexColor = g_cvars.wolfLinkColor},
|
||||
};
|
||||
// Wooden Sword Item Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/O_gD_SWB.arc")]["bmdr/o_gd_al_swb.bmd"] = {
|
||||
{.textures = {"al_SWB"}, .hexColor = g_cvars.woodenSwordColor},
|
||||
};
|
||||
// Boomerang Item Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/O_gD_boom.arc")]["bmdr/o_gd_boom.bmd"] = {
|
||||
{.textures = {"L_al_boom00"}, .hexColor = g_cvars.boomerangColor},
|
||||
};
|
||||
// Iron Boots Item Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/O_gD_boot.arc")]["bmwr/o_gd_al_bootsh.bmd"] = {
|
||||
{.textures = {"al_bootsH"}, .hexColor = g_cvars.ironBootsColor},
|
||||
};
|
||||
// Spinner Item Model
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/O_gD_SP.arc")]["bmdr/o_gd_al_sp.bmd"] = {
|
||||
{.textures = {"al_SP"}, .hexColor = g_cvars.spinnerColor},
|
||||
};
|
||||
// Gale Boomerang for Ook
|
||||
cosmeticOverrides[DVDConvertPathToEntrynum("/res/Object/E_mk.arc")]["bmdr/bm.bmd"] = {
|
||||
{.textures = {"L_al_boom00", "bm_boom"}, .hexColor = g_cvars.boomerangColor},
|
||||
};
|
||||
}
|
||||
return cosmeticOverrides;
|
||||
}
|
||||
|
||||
s32 get_entry_number(mDoDvdThd_mountArchive_c* mountArchive) {
|
||||
return mountArchive->mEntryNumber;
|
||||
}
|
||||
|
||||
void handle_texture_overrides_on_load(mDoDvdThd_mountArchive_c* mountArchive) {
|
||||
|
||||
auto entryNum = get_entry_number(mountArchive);
|
||||
auto& cosmeticOverrides = get_cosmetic_overrides();
|
||||
if (!cosmeticOverrides.contains(entryNum)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& [resName, overrides] : cosmeticOverrides[entryNum]) {
|
||||
|
||||
auto* archive = mountArchive->getArchive();
|
||||
auto* entry = archive->findFsResource(resName.data(), 0);
|
||||
if (!entry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* tex1Addr = find_tex_1_in_bmd(static_cast<J3DModelFileData*>(archive->fetchResource(entry, NULL)));
|
||||
if (!tex1Addr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& cosmeticOverride : overrides) {
|
||||
const auto& [textures, hexColorVar] = cosmeticOverride;
|
||||
const auto& hexColorStr = get_str_option(hexColorVar, "");
|
||||
if (!is_valid_hex_color_str(hexColorStr)) {
|
||||
mods::log::debug("Invalid Hex Str {}", hexColorStr);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto color = hex_color_str_to_gx_color(hexColorStr);
|
||||
if (tex1Addr) {
|
||||
for (const auto& textureName : textures) {
|
||||
recolor_texture(tex1Addr, textureName.data(), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* File originally copied from console TPR with permission from isaac
|
||||
* https://github.com/zsrtp/libtp_rel/blob/master/include/util/texture_utils.h
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct ResTIMG;
|
||||
struct J3DTextureBlock;
|
||||
class J3DModelFileData;
|
||||
class mDoDvdThd_mountArchive_c;
|
||||
|
||||
ResTIMG* find_tex_header_in_tex_1_section(J3DTextureBlock* tex1Ptr, const char* textureName);
|
||||
|
||||
uint32_t swap_index_bits(bool leftIsGreater, uint32_t bits);
|
||||
|
||||
void recolor_cmpr_texture(J3DTextureBlock* tex1Ptr, const char* textureName, const uint8_t* rgb);
|
||||
|
||||
J3DTextureBlock* find_tex_1_in_bmd(J3DModelFileData* bmdPtr);
|
||||
|
||||
void handle_texture_overrides_on_load(mDoDvdThd_mountArchive_c* mountArchive);
|
||||
@@ -1,145 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
project(randomizer CXX)
|
||||
|
||||
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
||||
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
|
||||
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
if (DUSK_MOD_USE_FULL_TREE)
|
||||
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
|
||||
else ()
|
||||
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Generator dependencies, linked statically into the mod library (no CRT crossing).
|
||||
include(FetchContent)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
|
||||
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "" FORCE)
|
||||
set(YAML_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
|
||||
message(STATUS "randomizer: Fetching yaml-cpp")
|
||||
FetchContent_Declare(
|
||||
yaml-cpp
|
||||
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
|
||||
GIT_TAG yaml-cpp-0.9.0
|
||||
)
|
||||
message(STATUS "randomizer: Fetching base64pp")
|
||||
FetchContent_Declare(
|
||||
base64pp
|
||||
GIT_REPOSITORY https://github.com/matheusgomes28/base64pp.git
|
||||
GIT_TAG v0.2.0-rc0
|
||||
)
|
||||
|
||||
message(STATUS "randomizer: Fetching battery-embed")
|
||||
FetchContent_Declare(
|
||||
battery-embed
|
||||
GIT_REPOSITORY https://github.com/batterycenter/embed.git
|
||||
GIT_TAG fdbae3f
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(yaml-cpp base64pp battery-embed)
|
||||
|
||||
set(RANDOMIZER_GENERATOR_SOURCES
|
||||
generator/logic/area.cpp
|
||||
generator/logic/dungeon.cpp
|
||||
generator/logic/entrance.cpp
|
||||
generator/logic/entrance_shuffle.cpp
|
||||
generator/logic/fill.cpp
|
||||
generator/logic/flatten/bits.cpp
|
||||
generator/logic/flatten/flatten.cpp
|
||||
generator/logic/flatten/simplify_algebraic.cpp
|
||||
generator/logic/hints.cpp
|
||||
generator/logic/item.cpp
|
||||
generator/logic/item_pool.cpp
|
||||
generator/logic/location.cpp
|
||||
generator/logic/plandomizer.cpp
|
||||
generator/logic/requirement.cpp
|
||||
generator/logic/search.cpp
|
||||
generator/logic/spoiler_log.cpp
|
||||
generator/logic/world.cpp
|
||||
generator/randomizer.cpp
|
||||
generator/seedgen/config.cpp
|
||||
generator/seedgen/seed.cpp
|
||||
generator/seedgen/settings.cpp
|
||||
generator/utility/color.cpp
|
||||
generator/utility/common.cpp
|
||||
generator/utility/endian.cpp
|
||||
generator/utility/file.cpp
|
||||
generator/utility/log.cpp
|
||||
generator/utility/path.cpp
|
||||
generator/utility/platform.cpp
|
||||
generator/utility/random.cpp
|
||||
generator/utility/string.cpp
|
||||
generator/utility/text.cpp
|
||||
generator/utility/time.cpp
|
||||
)
|
||||
|
||||
set(RANDOMIZER_SOURCES
|
||||
src/flags.cpp
|
||||
src/messages.cpp
|
||||
src/randomizer_context.cpp
|
||||
src/stages.cpp
|
||||
src/tools.cpp
|
||||
src/verify_item_functions.cpp
|
||||
src/paths.cpp
|
||||
src/session.cpp
|
||||
src/hooks.cpp
|
||||
src/ui/config_store.cpp
|
||||
src/ui/rando_seed_generation.cpp
|
||||
src/ui/rando_config.cpp
|
||||
src/ui/ui.cpp
|
||||
)
|
||||
|
||||
# Embed the generator's YAML data into the mod library. Paths are relative to this
|
||||
# directory and must match the RANDO_DATA_PATH-based b::embed<> identifiers in code.
|
||||
file(GLOB_RECURSE RANDOMIZER_DATA RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/generator/data/*")
|
||||
|
||||
# Create an OBJECT library to hold all battery-embed generated files so we can add it
|
||||
# to both the mod and the standalone generator
|
||||
add_library(randomizer_embeds OBJECT)
|
||||
|
||||
foreach (RANDOMIZER_FILE IN LISTS RANDOMIZER_DATA)
|
||||
if (RANDOMIZER_FILE MATCHES "^generator/data/tests")
|
||||
continue()
|
||||
endif ()
|
||||
b_embed(randomizer_embeds "${RANDOMIZER_FILE}")
|
||||
endforeach ()
|
||||
|
||||
add_mod(randomizer
|
||||
FEATURES game fmt
|
||||
SOURCES src/mod.cpp ${RANDOMIZER_GENERATOR_SOURCES} ${RANDOMIZER_SOURCES}
|
||||
MOD_JSON mod.json
|
||||
RES_DIR res
|
||||
)
|
||||
|
||||
target_link_libraries(randomizer PRIVATE yaml-cpp::yaml-cpp base64pp randomizer_embeds)
|
||||
|
||||
string(LENGTH "${CMAKE_CURRENT_SOURCE_DIR}/" RANDOMIZER_SOURCE_PATH_SIZE)
|
||||
target_compile_definitions(randomizer PRIVATE
|
||||
RANDO_DATA_PATH="generator/data/"
|
||||
SOURCE_PATH_SIZE=${RANDOMIZER_SOURCE_PATH_SIZE}
|
||||
)
|
||||
|
||||
# standalone randomizer generator for testing
|
||||
add_executable(randomizer_generator ${CMAKE_CURRENT_SOURCE_DIR}/generator/generator_only.cpp ${RANDOMIZER_GENERATOR_SOURCES})
|
||||
target_link_libraries(randomizer_generator PRIVATE yaml-cpp::yaml-cpp base64pp fmt::fmt randomizer_embeds)
|
||||
target_compile_definitions(randomizer_generator PRIVATE
|
||||
RANDO_DATA_PATH="generator/data/"
|
||||
SOURCE_PATH_SIZE=${RANDOMIZER_SOURCE_PATH_SIZE}
|
||||
RANDO_SAVE_PATH="${CMAKE_BINARY_DIR}/randomizer/"
|
||||
RANDOMIZER_ONLY)
|
||||
|
||||
# standalone tests
|
||||
add_executable(randomizer_generator_tests ${CMAKE_CURRENT_SOURCE_DIR}/generator/test/test.cpp ${RANDOMIZER_GENERATOR_SOURCES})
|
||||
target_link_libraries(randomizer_generator_tests PRIVATE yaml-cpp::yaml-cpp base64pp fmt::fmt randomizer_embeds)
|
||||
target_compile_definitions(randomizer_generator_tests PRIVATE
|
||||
RANDO_DATA_PATH="generator/data/"
|
||||
SOURCE_PATH_SIZE=${RANDOMIZER_SOURCE_PATH_SIZE}
|
||||
RANDO_SAVE_PATH="${CMAKE_BINARY_DIR}/randomizer/"
|
||||
RANDO_LOGIC_TESTS_PATH="${CMAKE_SOURCE_DIR}/mods/randomizer/generator/data/tests/logic"
|
||||
SETTINGS_PATH="${RANDO_SAVE_PATH}/randomizer_settings.yaml.test"
|
||||
PREFERENCES_PATH="${RANDO_SAVE_PATH}/randomizer_preferences.yaml.test"
|
||||
RANDOMIZER_ONLY)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,614 +0,0 @@
|
||||
# Patches for NPC text flows
|
||||
|
||||
# NOTE: All data is expressed in little endian
|
||||
|
||||
0: # zel_00.bmg
|
||||
# Change the following indices of Midna's flows to jump to our custom choices
|
||||
# instead. These are all the flow jumps that normally determine which "Talk to Midna"
|
||||
# text is displayed.
|
||||
- index:
|
||||
- 0x1
|
||||
- 0x9
|
||||
- 0xC
|
||||
- 0x8F
|
||||
- 0x192
|
||||
- 0x1A4
|
||||
- 0x18F
|
||||
- 0x197
|
||||
- 0x1BC
|
||||
- 0x1C9
|
||||
type: event
|
||||
event: 42
|
||||
parameters: 0x00000000
|
||||
next node index: Custom Midna Call Begin
|
||||
|
||||
1: # zel_01.bmg - Ordon Village
|
||||
# Patch the flow in Bo's house that normally prevents us from leaving without
|
||||
# Having the iron boots. Patch it so we take the flow which allows us to leave
|
||||
# no matter what
|
||||
- index: 0x8F
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 21
|
||||
parameters: 0x0045
|
||||
next node index: 0x4B
|
||||
results:
|
||||
- 0x90
|
||||
- 0x90
|
||||
|
||||
2: # zel_02.bmg
|
||||
# Patch Barnes branch to see if you can buy the bomb bag to use
|
||||
# query 54 (custom event check) instead of query 22 (how many bomb bags the player has)
|
||||
- index: 0x47C
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 53
|
||||
parameters: 0x004D
|
||||
next node index: 0x340
|
||||
|
||||
# Change the flow of buying the red potion item in Kak Malo Mart to not check for an empty bottle first
|
||||
# if the item is randomized. Change both branch paths to lead to the same next node
|
||||
- only if: Shop_Items == On
|
||||
index: 0x43F
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 24
|
||||
parameters: 0x00000001
|
||||
next node index: 0x2EA
|
||||
results:
|
||||
- 0x440
|
||||
- 0x440
|
||||
|
||||
# Change the flow of buying the red potion item in Kak Malo Mart to set the sold out flag if shop
|
||||
# items are randomized
|
||||
- only if: Shop_Items == On
|
||||
index: 0x445
|
||||
type: event
|
||||
event: 3
|
||||
parameters: 0x0000001E
|
||||
next node index: Kakariko Malo Mart Red Potion Sold Out
|
||||
|
||||
# Change the flow of buying the wooden shield in Kak Malo Mart to set the sold out flag if shop
|
||||
# items are randomized
|
||||
- only if: Shop_Items == On
|
||||
index: 0x417
|
||||
type: event
|
||||
event: 3
|
||||
parameters: 0x00000032
|
||||
next node index: Kakariko Malo Mart Wooden Shield Sold Out
|
||||
|
||||
#3: # zel_03.bmg
|
||||
4: # zel_04.bmg - Castle Town
|
||||
# Patch Charlo to check for 100 rupees instead of 30
|
||||
- index: 0x34A
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 6
|
||||
parameters: 0x0064
|
||||
next node index: 0x222
|
||||
|
||||
# Patch Charlo to take 100 rupees from Link instead of 30
|
||||
- index: 0x34E
|
||||
type: event
|
||||
event: 41
|
||||
parameters: 0x00000064
|
||||
next node index: 0x226
|
||||
|
||||
# Patch Charlo to add 100 rupees to his counter instead of 30
|
||||
- index: 0x357
|
||||
type: event
|
||||
event: 3
|
||||
parameters: 0x00000064
|
||||
next node index: 0x22B
|
||||
|
||||
# Patch Malo Mart door person to not check for time of day.
|
||||
# Change from branch node that checks time of day to event node
|
||||
# that does nothing.
|
||||
- index: 0x1A5
|
||||
type: event
|
||||
event: 42
|
||||
parameters: 0x00000000
|
||||
next node index: 0x10C
|
||||
|
||||
# Patch Jovani flow so that we can turn in poe souls before completing MDH
|
||||
- index: 0x832
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 1
|
||||
parameters: 0x01C8
|
||||
next node index: 0x763
|
||||
results:
|
||||
- 0x834 # Skip over 0x833 and go directly to 0x834
|
||||
- 0x84E
|
||||
|
||||
# Patch Jovani to skip checking whether we've received the first
|
||||
# or second reward and skip straight to the second reward if we're
|
||||
# talking to him for the first time with 60 souls
|
||||
- index: 0x844
|
||||
type: message
|
||||
inf index: 0x322
|
||||
next flow index: 0x851
|
||||
|
||||
# Patch Jovani to check if we've received the 20 reward yet at
|
||||
# the end of the 60 reward sequence.
|
||||
- index: 0x81F
|
||||
type: event
|
||||
event: 14
|
||||
parameters: 0x00000063
|
||||
next node index: Jovani Check 20 Reward Obtained
|
||||
|
||||
# Patch the flow of showing the Doctor the Invoice to call our custom
|
||||
# event which calls offWarashibeItem instead of setWarashibeItem
|
||||
- index: 0x2D7
|
||||
type: event
|
||||
event: 47
|
||||
parameters: 0x00000081
|
||||
next node index: 0x1D3
|
||||
|
||||
5: # zel_05.bmg
|
||||
# Patch Yeta flow to always give the map check even if the player has obtained the Ordon Cheese
|
||||
- index: 0x8
|
||||
type: event
|
||||
event: 42
|
||||
parameters: 0x00000000
|
||||
next node index: 0x8
|
||||
|
||||
# Patch Yeta flow to always give the map check even if the player has obtained the Ordon Cheese
|
||||
- index: 0x5
|
||||
type: event
|
||||
event: 42
|
||||
parameters: 0x00000000
|
||||
next node index: 0x3
|
||||
|
||||
# Patch Gor Liggs to not set the flag for the third key shard
|
||||
# Change event index 17 to event index 42 which does nothing
|
||||
- index: 0x258
|
||||
type: event
|
||||
event: 42
|
||||
parameters: 0x00000000
|
||||
next node index: 0x1AC
|
||||
|
||||
# Patch Cave of Ordeals Great Fairy to skip over the check
|
||||
# for an empty bottle the first time
|
||||
- index: 0x850
|
||||
type: message
|
||||
inf index: 0x25B
|
||||
next flow index: 0x202
|
||||
|
||||
#6: # zel_06.bmg
|
||||
#7: # zel_07.bmg
|
||||
8: # zel_08.bmg - HF, Outside CT, LH, UZR, Zora's River, KB2, Title Screen
|
||||
# Skip over the node which deletes auru's memo from the inventory after showing it to Fyer
|
||||
- index: 0x53
|
||||
type: message
|
||||
inf index: 0xA7
|
||||
next flow index: 0x54 # Go directly to 0x54 instead of 0x5D
|
||||
|
||||
# Custom Flow Nodes
|
||||
9:
|
||||
# Start of custom midna call tree. Begin by checking if we can change time
|
||||
# of day to see if we show that choice
|
||||
- name: Custom Midna Call Begin
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 54
|
||||
parameters: 0x0000
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- Custom Midna Call 3 Choice Select Setup # Can change time of day
|
||||
- Custom Midna Call 2 Choice Select Setup # Can not change time of day
|
||||
|
||||
#################################################
|
||||
# CUSTOM MIDNA CALL 2 CHOICE FLOW #
|
||||
#################################################
|
||||
|
||||
- name: Custom Midna Call 2 Choice Select Setup
|
||||
type: event
|
||||
event: 13
|
||||
parameters: 0x00000003
|
||||
next node index: Custom Midna Call 2 Choice Intro
|
||||
|
||||
- name: Custom Midna Call 2 Choice Intro
|
||||
type: message
|
||||
inf index: Custom Midna Call Need Something Text
|
||||
next flow index: Custom Midna Call 2 Choice
|
||||
|
||||
- name: Custom Midna Call 2 Choice
|
||||
type: message
|
||||
inf index: Custom Midna Call 2 Choice Text
|
||||
next flow index: Custom Midna Call 2 Choice Branch
|
||||
|
||||
- name: Custom Midna Call 2 Choice Branch
|
||||
type: branch
|
||||
num results: 3
|
||||
query: 35
|
||||
parameters: 0x0000
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- Custom Midna Call Hints # Hints
|
||||
- Custom Midna Call Return to Spawn Branch # Return to Spawn
|
||||
- 0xFFFF # (B button pressed)
|
||||
|
||||
#################################################
|
||||
# CUSTOM MIDNA CALL 3 CHOICE FLOW #
|
||||
#################################################
|
||||
|
||||
- name: Custom Midna Call 3 Choice Select Setup
|
||||
type: event
|
||||
event: 13
|
||||
parameters: 0x00000004
|
||||
next node index: Custom Midna Call 3 Choice Intro
|
||||
|
||||
- name: Custom Midna Call 3 Choice Intro
|
||||
type: message
|
||||
inf index: Custom Midna Call Need Something Text
|
||||
next flow index: Custom Midna Call 3 Choice
|
||||
|
||||
- name: Custom Midna Call 3 Choice
|
||||
type: message
|
||||
inf index: Custom Midna Call 3 Choice Text
|
||||
next flow index: Custom Midna Call 3 Choice Branch
|
||||
|
||||
- name: Custom Midna Call 3 Choice Branch
|
||||
type: branch
|
||||
num results: 4
|
||||
query: 36
|
||||
parameters: 0x0000
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- Custom Midna Call Hints # Hints
|
||||
- Custom Midna Call Change Time # Change time of day
|
||||
- Custom Midna Call Return to Spawn Branch # Return to Spawn
|
||||
- 0xFFFF # (B button pressed)
|
||||
|
||||
#################################################
|
||||
# CUSTOM MIDNA CALL CHOICE OPTIONS #
|
||||
#################################################
|
||||
|
||||
- name: Custom Midna Call Hints
|
||||
type: message
|
||||
inf index: Custom Midna Call Hints Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Custom Midna Call Change Time
|
||||
type: event
|
||||
event: 44
|
||||
parameters: 0x00000000
|
||||
next node index: 0x116
|
||||
|
||||
- name: Custom Midna Call Return to Spawn Branch
|
||||
type: branch
|
||||
num results: 3
|
||||
query: 55
|
||||
parameters: 0x0000
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- Return to Spawn Dungeon Choice Select Setup
|
||||
- Return to Spawn Dungeon No Choice Select Setup
|
||||
- Return to Base Spawn
|
||||
|
||||
#################################################
|
||||
# RETURN TO SPAWN DUNGEON CHOICE FLOW #
|
||||
#################################################
|
||||
|
||||
- name: Return to Spawn Dungeon Choice Select Setup
|
||||
type: event
|
||||
event: 13
|
||||
parameters: 0x00000004
|
||||
next node index: Return to Spawn Dungeon Choice Intro
|
||||
|
||||
- name: Return to Spawn Dungeon Choice Intro
|
||||
type: message
|
||||
inf index: Return to Spawn Dungeon Intro Text
|
||||
next flow index: Return to Spawn Dungeon Choice
|
||||
|
||||
- name: Return to Spawn Dungeon Choice
|
||||
type: message
|
||||
inf index: Return to Spawn Dungeon Choice Text
|
||||
next flow index: Return to Spawn Dungeon Choice Branch
|
||||
|
||||
- name: Return to Spawn Dungeon Choice Branch
|
||||
type: branch
|
||||
num results: 4
|
||||
query: 36
|
||||
parameters: 0x0000
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- Return to Dungeon Spawn # Dungeon entrance
|
||||
- 0xFFFF # Nevermind
|
||||
- Return to Base Spawn # Spawn
|
||||
- 0xFFFF # (B button pressed)
|
||||
|
||||
#################################################
|
||||
# RETURN TO SPAWN DUNGEON NO CHOICE FLOW #
|
||||
#################################################
|
||||
|
||||
- name: Return to Spawn Dungeon No Choice Select Setup
|
||||
type: event
|
||||
event: 13
|
||||
parameters: 0x00000003
|
||||
next node index: Return to Spawn Dungeon No Choice Intro
|
||||
|
||||
- name: Return to Spawn Dungeon No Choice Intro
|
||||
type: message
|
||||
inf index: Return to Spawn Dungeon Intro Text
|
||||
next flow index: Return to Spawn No Dungeon Choice
|
||||
|
||||
- name: Return to Spawn Dungeon No Choice
|
||||
type: message
|
||||
inf index: Return to Spawn Dungeon No Choice Text
|
||||
next flow index: Return to Spawn Dungeon No Choice Branch
|
||||
|
||||
- name: Return to Spawn Dungeon No Choice Branch
|
||||
type: branch
|
||||
num results: 3
|
||||
query: 35
|
||||
parameters: 0x0000
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- 0xFFFF # Nevermind
|
||||
- Return to Base Spawn # Spawn
|
||||
- 0xFFFF # (B button pressed)
|
||||
|
||||
#################################################
|
||||
# RETURN TO SPAWN EVENTS #
|
||||
#################################################
|
||||
|
||||
# Use custom event index 45 to setup returning to spawn. A non-zero
|
||||
# parameter value indicates to try and use a place override if one
|
||||
# exists for the current stage
|
||||
- name: Return to Dungeon Spawn
|
||||
type: event
|
||||
event: 45
|
||||
parameters: 0x00000001
|
||||
next node index: 0x116
|
||||
|
||||
# Use custom event index 45 to setup returning to spawn. A parameter
|
||||
# value of zero indicates to always return to the starting spawn
|
||||
- name: Return to Base Spawn
|
||||
type: event
|
||||
event: 45
|
||||
parameters: 0x00000000
|
||||
next node index: 0x116
|
||||
|
||||
#################################################
|
||||
# KAKARIKO MALO MART #
|
||||
#################################################
|
||||
|
||||
# Run event 24 which sets the shop sold out flag
|
||||
- name: Kakariko Malo Mart Red Potion Sold Out
|
||||
type: event
|
||||
event: 24
|
||||
parameters: 0x00000000
|
||||
next node index: 0x2F2
|
||||
|
||||
# Run event 24 which sets the shop sold out flag
|
||||
- name: Kakariko Malo Mart Wooden Shield Sold Out
|
||||
type: event
|
||||
event: 24
|
||||
parameters: 0x00000000
|
||||
next node index: 0x2D0
|
||||
|
||||
#################################################
|
||||
# JOVANI #
|
||||
#################################################
|
||||
|
||||
# Check to see if we've obtained the 20 Poe Soul Reward.
|
||||
# If we haven't then branch to giving the reward
|
||||
- name: Jovani Check 20 Reward Obtained
|
||||
type: branch
|
||||
num results: 2
|
||||
query: 1
|
||||
parameters: 0x0272
|
||||
next node index: 0xFFFF
|
||||
results:
|
||||
- 0xFFFF # Yes, we've obtained the reward, do nothing
|
||||
- Jovani Give 20 Reward
|
||||
|
||||
#################################################
|
||||
# HINT SIGNS #
|
||||
#################################################
|
||||
|
||||
- name: Ordon Hint Sign
|
||||
index: 21100
|
||||
type: message
|
||||
inf index: Ordon Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: South Faron Woods Hint Sign
|
||||
index: 21101
|
||||
type: message
|
||||
inf index: South Faron Woods Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Sacred Grove Hint Sign
|
||||
index: 21102
|
||||
type: message
|
||||
inf index: Sacred Grove Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Faron Field Hint Sign
|
||||
index: 21103
|
||||
type: message
|
||||
inf index: Faron Field Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Kakariko Gorge Hint Sign
|
||||
index: 21104
|
||||
type: message
|
||||
inf index: Kakariko Gorge Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Kakariko Village Hint Sign
|
||||
index: 21105
|
||||
type: message
|
||||
inf index: Kakariko Village Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Kakariko Graveyard Hint Sign
|
||||
index: 21106
|
||||
type: message
|
||||
inf index: Kakariko Graveyard Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Eldin Field Hint Sign
|
||||
index: 21107
|
||||
type: message
|
||||
inf index: Eldin Field Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: North Eldin Field Hint Sign
|
||||
index: 21108
|
||||
type: message
|
||||
inf index: North Eldin Field Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Hidden Village Hint Sign
|
||||
index: 21109
|
||||
type: message
|
||||
inf index: Hidden Village Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Lanayru Field Hint Sign
|
||||
index: 21110
|
||||
type: message
|
||||
inf index: Lanayru Field Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Beside Castle Town Hint Sign
|
||||
index: 21111
|
||||
type: message
|
||||
inf index: Beside Castle Town Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Castle Town Center Hint Sign
|
||||
index: 21112
|
||||
type: message
|
||||
inf index: Castle Town Center Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Outside South Castle Town Hint Sign
|
||||
index: 21113
|
||||
type: message
|
||||
inf index: Outside South Castle Town Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Lake Hylia Bridge Hint Sign
|
||||
index: 21114
|
||||
type: message
|
||||
inf index: Lake Hylia Bridge Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Lake Hylia Hint Sign
|
||||
index: 21115
|
||||
type: message
|
||||
inf index: Lake Hylia Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Lanayru Spring Hint Sign
|
||||
index: 21116
|
||||
type: message
|
||||
inf index: Lanayru Spring Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Lake Lantern Cave Hint Sign
|
||||
index: 21117
|
||||
type: message
|
||||
inf index: Lake Lantern Cave Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Fishing Hole Hint Sign
|
||||
index: 21118
|
||||
type: message
|
||||
inf index: Fishing Hole Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Zoras Domain Hint Sign
|
||||
index: 21119
|
||||
type: message
|
||||
inf index: Zoras Domain Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Snowpeak Hint Sign
|
||||
index: 21120
|
||||
type: message
|
||||
inf index: Snowpeak Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Gerudo Desert Hint Sign
|
||||
index: 21121
|
||||
type: message
|
||||
inf index: Gerudo Desert Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Bulblin Camp Hint Sign
|
||||
index: 21122
|
||||
type: message
|
||||
inf index: Bulblin Camp Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Forest Temple Hint Sign
|
||||
index: 21123
|
||||
type: message
|
||||
inf index: Forest Temple Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Goron Mines Hint Sign
|
||||
index: 21124
|
||||
type: message
|
||||
inf index: Goron Mines Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Lakebed Temple Hint Sign
|
||||
index: 21125
|
||||
type: message
|
||||
inf index: Lakebed Temple Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Arbiters Grounds Hint Sign
|
||||
index: 21126
|
||||
type: message
|
||||
inf index: Arbiters Grounds Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Snowpeak Ruins Hint Sign
|
||||
index: 21127
|
||||
type: message
|
||||
inf index: Snowpeak Ruins Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Temple of Time First Hint Sign
|
||||
index: 21128
|
||||
type: message
|
||||
inf index: Temple of Time First Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Temple of Time Second Hint Sign
|
||||
index: 21129
|
||||
type: message
|
||||
inf index: Temple of Time Second Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: City in the Sky Hint Sign
|
||||
index: 21130
|
||||
type: message
|
||||
inf index: City in the Sky Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Palace of Twilight Hint Sign
|
||||
index: 21131
|
||||
type: message
|
||||
inf index: Palace of Twilight Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Hyrule Castle Hint Sign
|
||||
index: 21132
|
||||
type: message
|
||||
inf index: Hyrule Castle Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
|
||||
- name: Cave of Ordeals Hint Sign
|
||||
index: 21133
|
||||
type: message
|
||||
inf index: Cave of Ordeals Hint Sign Text
|
||||
next flow index: 0xFFFF
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,256 +0,0 @@
|
||||
# Macros are a way to shorten or make more explicit the logical requirements
|
||||
# for certain things. Macros can be used on logic statements like any item and do
|
||||
# not need any code modifications to run. Simply add them here and they can be used
|
||||
# in the world graph files.
|
||||
|
||||
Can Open Doors: Human_Link
|
||||
Can Climb Ladders: Human_Link
|
||||
Can Climb Vines: Human_Link
|
||||
Can Talk to Humans: Human_Link
|
||||
Can Swing on Monkeys: Human_Link
|
||||
Can Pickup Bomblings: Human_Link
|
||||
Can Pull Lakebed Levers: Human_Link
|
||||
Can Pull Blocks: Human_Link
|
||||
Can Ride Boars: Human_Link
|
||||
Can Summon Hawk: Human_Link
|
||||
Can Talk to Animals: Wolf_Link
|
||||
Can Use Senses: Wolf_Link
|
||||
Can Dig: Wolf_Link
|
||||
Can Howl: Wolf_Link
|
||||
Can Sniff: Wolf_Link
|
||||
Can Midna Jump: Wolf_Link
|
||||
Can Use Tightrope: Wolf_Link
|
||||
Not Twilight: Human_Link or Wolf_Link
|
||||
|
||||
Slingshot: Slingshot and 'Can_Refill_Slingshot_Seeds' and Human_Link
|
||||
Lantern: Lantern and 'Can_Refill_Lantern_Oil' and Human_Link
|
||||
Gale Boomerang: Gale_Boomerang and Human_Link
|
||||
Iron Boots: Iron_Boots and Human_Link
|
||||
Bow: Progressive_Bow and 'Can_Refill_Arrows' and Human_Link
|
||||
Regular Bombs: Bomb_Bag and 'Can_Refill_Regular_Bombs' and Human_Link
|
||||
Water Bombs: Bomb_Bag and 'Can_Refill_Water_Bombs' and Human_Link
|
||||
Bombs: Regular_Bombs or Water_Bombs
|
||||
Bomb Arrows: Bow and Bombs
|
||||
Spinner: Spinner and Human_Link
|
||||
Ball and Chain: Ball_and_Chain and Human_Link
|
||||
Zora Armor: Zora_Armor and Human_Link
|
||||
Magic Armor: Magic_Armor and Human_Link
|
||||
Shield: Hylian_Shield or 'Can_Buy_Wooden_Shield'
|
||||
Bottle: Empty_Bottle and Lantern # Can't empty lantern oil from a bottle until you have the lantern
|
||||
Asheis Sketch: Asheis_Sketch and Human_Link
|
||||
Aurus Memo: Aurus_Memo and Human_Link
|
||||
Renados Letter: Renados_Letter and Human_Link
|
||||
Invoice: Invoice and Human_Link
|
||||
Wooden Statue: Wooden_Statue and Human_Link
|
||||
Ilias Charm: Ilias_Charm and Human_Link
|
||||
|
||||
Fishing Rod: Progressive_Fishing_Rod and Human_Link
|
||||
Coral Earring: count(Progressive_Fishing_Rod, 2) and Human_Link
|
||||
Sword: Progressive_Sword and Human_Link
|
||||
Ordon Sword: count(Progressive_Sword, 2) and Human_Link
|
||||
Master Sword: count(Progressive_Sword, 3) and Human_Link
|
||||
Light Sword: count(Progressive_Sword, 4) and Human_Link
|
||||
Big Quiver: count(Progressive_Bow, 2) and 'Can_Refill_Arrows' and Human_Link
|
||||
Giant Quiver: count(Progressive_Bow, 3) and 'Can_Refill_Arrows' and Human_Link
|
||||
Clawshot: Progressive_Clawshot and Human_Link
|
||||
Double Clawshots: count(Progressive_Clawshot, 2) and Human_Link
|
||||
Dominion Rod: Progressive_Dominion_Rod and Human_Link
|
||||
Restored Dominion Rod: count(Progressive_Dominion_Rod, 2) and Human_Link
|
||||
Big Wallet: Progressive_Wallet
|
||||
Giant Wallet: count(Progressive_Wallet, 2)
|
||||
Collosal Wallet: count(Progressive_Wallet, 3)
|
||||
|
||||
Ending Blow: Sword and Progressive_Hidden_Skill
|
||||
Shield Attack: Shield and count(Progressive_Hidden_Skill, 2)
|
||||
Back Slice: Sword and count(Progressive_Hidden_Skill, 3)
|
||||
Helm Splitter: Sword and Shield_Attack and count(Progressive_Hidden_Skill, 4)
|
||||
Mortal Draw: Sword and count(Progressive_Hidden_Skill, 5)
|
||||
Jump Strike: Sword and count(Progressive_Hidden_Skill, 6)
|
||||
Great Spin: Sword and count(Progressive_Hidden_Skill, 7)
|
||||
|
||||
Can Use Back Slice as Sword: Back_Slice_as_Sword == On and count(Progressive_Hidden_Skill, 3)
|
||||
|
||||
Can Do Niche Stuff: Impossible # TODO: Make settings for all of these
|
||||
Can Do Difficult Combat: Impossible # TODO: Make settings for all of these
|
||||
|
||||
Can Use Hot Spring Water: Bottle and 'Can_Buy_Hot_Spring_Water'
|
||||
Can Use Bottled Fairy: Bottle and 'Fairy_Access'
|
||||
# This will have to change if we allow players to start with less than 3 hearts
|
||||
Can Survive Damage: Logic_Damage_Multiplier != OHKO or Can_Use_Bottled_Fairy
|
||||
Can Survive One Bonk: Bonks_Do_Damage == Off or Can_Survive_Damage
|
||||
Can Survive Two Bonks: Bonks_Do_Damage == Off or Logic_Damage_Multiplier != OHKO or
|
||||
(Can_Use_Bottled_Fairy and count(Empty_Bottle, 2))
|
||||
Can Survive Three Bonks: Bonks_Do_Damage == Off or Logic_Damage_Multiplier != OHKO or
|
||||
(Can_Use_Bottled_Fairy and count(Empty_Bottle, 3))
|
||||
Can Smash: Bombs or Ball_and_Chain
|
||||
Can Break Webs: Lantern or Bombs or (Ball_and_Chain and Ball_and_Chain_Webs == On)
|
||||
Can Light Torches: Lantern
|
||||
Can Extinguish Torches: Gale_Boomerang
|
||||
Can Launch Bombs: Bombs and (Gale_Boomerang or Bow)
|
||||
Can Break Monkey Cage: Sword or Iron_Boots or Spinner or Ball_and_Chain or Wolf_Link or Bombs or
|
||||
Bow or Clawshot or (Can_Do_Niche_Stuff and Shield_Attack)
|
||||
Can Cut Hanging Web: Clawshot or Bow or Gale_Boomerang or Ball_and_Chain
|
||||
Can Break Wooden Barrier: Sword or Can_Smash or Wolf_Link or Can_Use_Back_Slice_as_Sword
|
||||
Can Refill Air: Zora_Armor # or glitched logic water bombs
|
||||
Can Cross Quicksand: Wolf_Link or Spinner
|
||||
Can Break Armor: Ball_and_Chain
|
||||
Can Break Ice: Ball_and_Chain
|
||||
Can Launch Canonball: Bombs
|
||||
Can Knock Down Hyrule Castle Painting: Bow or (Can_Do_Niche_Stuff and (Bombs or Jump_Strike))
|
||||
Can Knock Down Hanging Baba: Bow or Clawshot or Gale_Boomerang or Slingshot
|
||||
|
||||
Has Damaging Item: Sword or Ball_and_Chain or Bow or Bombs or Iron_Boots or Wolf_Link or Spinner
|
||||
Can Hit Crystal Switch: Clawshot or Has_Damaging_Item
|
||||
Can Hit Crystal Switch at Range: Clawshot or Bow
|
||||
|
||||
Can Complete MDH: Skip_Midna's_Desparate_Hour == On or ('Can_Access_Castle_Town_South' and 'Can_Complete_Lakebed_Temple')
|
||||
|
||||
|
||||
|
||||
# REGULAR ENEMIES
|
||||
|
||||
# A lot of enemies use this identical logical requirement
|
||||
Can Defeat Generic Enemy: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
|
||||
Can Defeat Shadow Beast: Sword or (Wolf_Link and Can_Complete_MDH)
|
||||
Can Defeat Keese: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Slingshot or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Fire Keese: Can_Defeat_Keese
|
||||
Can Defeat Ice Keese: Can_Defeat_Keese
|
||||
Can Defeat Shadow Keese: Can_Defeat_Keese
|
||||
Can Defeat Rat: Slingshot or Can_Defeat_Generic_Enemy
|
||||
Can Defeat Ghoul Rat: Can_Use_Senses
|
||||
Can Defeat Bokoblin: Can_Defeat_Generic_Enemy or Slingshot
|
||||
Can Defeat Red Bokoblin: Sword or Ball_and_Chain or Giant_Quiver or Wolf_Link or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Difficult_Combat and (Iron_Boots or Spinner))
|
||||
Can Defeat Bulblin: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Deku Baba: Sword or Ball_and_Chain or Bow or Spinner or Shield_Attack or Slingshot or Clawshot or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Big Baba: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Baba Serpent: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Walltula: Ball_and_Chain or Slingshot or Bow or Gale_Boomerang or Clawshot
|
||||
Can Defeat Skulltula: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Deku Like: Bombs
|
||||
Can Launch Tileworm: Gale_Boomerang
|
||||
Can Defeat Tileworm: Gale_Boomerang and Can_Defeat_Generic_Enemy
|
||||
Can Defeat Stalhound: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Kargarok: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Goron: Sword or Ball_and_Chain or Bow or Spinner or Shield_Attack or Slingshot or Clawshot or Bombs or
|
||||
(Can_Do_Niche_Stuff and Iron_Boots) or (Can_Do_Difficult_Combat and Lantern) or Can_Use_Back_Slice_as_Sword
|
||||
Can Defeat Torch Slug: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs
|
||||
Can Defeat Dodongo: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Beamos: Ball_and_Chain or Bow or Bombs
|
||||
Can Defeat Leever: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Helmasaur: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Tektite: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Toado: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link
|
||||
Can Defeat Water Toadpoli: Sword or Ball_and_Chain or Bow or Shield_Attack or (Can_Do_Difficult_Combat and Wolf_Link)
|
||||
Can Defeat Shell Blade: Water_Bombs or (Sword and (Iron_Boots or (Can_Do_Niche_Stuff and Magic_Armor)))
|
||||
Can Defeat Lizalfos: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Dinalfos: Sword or Ball_and_Chain or Wolf_Link
|
||||
Can Defeat Chu: Can_Defeat_Generic_Enemy or Clawshot
|
||||
Can Defeat Chu Worm: (Bombs or Clawshot) and (Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Can_Use_Back_Slice_as_Sword)
|
||||
Can Defeat Bubble: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Fire Bubble: Can_Defeat_Bubble
|
||||
Can Defeat Ice Bubble: Can_Defeat_Bubble
|
||||
Can Defeat Skull Kid: Bow
|
||||
Can Defeat Poe: Can_Use_Senses
|
||||
Can Defeat Stalchild: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Stalfos: Can_Smash
|
||||
Can Defeat Redead Knight: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat White Wolfos: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Chilfos: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Mini Freezard: Can_Defeat_Generic_Enemy
|
||||
Can Defeat Freezard: Ball_and_Chain
|
||||
Can Defeat Young Gohma: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or
|
||||
(Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Baby Gohma: Can_Defeat_Generic_Enemy or Slingshot or Clawshot
|
||||
Can Defeat Armos: Can_Defeat_Generic_Enemy or Clawshot
|
||||
Can Defeat Zant Head: Sword or Wolf_Link or Can_Use_Back_Slice_as_Sword
|
||||
|
||||
# MINIBOSSES
|
||||
|
||||
Can Defeat Ook: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Dangoro: Iron_Boots and (Sword or Wolf_Link or Bomb_Arrows or (Can_Do_Niche_Stuff and Ball_and_Chain))
|
||||
Can Defeat Deku Toad: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
|
||||
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat King Bulblin Desert: Sword or Ball_and_Chain or Wolf_Link or Giant_Quiver or Can_Use_Back_Slice_as_Sword or
|
||||
(Can_Do_Difficult_Combat and (Spinner or Iron_Boots or Bombs or Big_Quiver))
|
||||
Can Defeat Deathsword: Can_Use_Senses and Sword and (Clawshot or Bow or Gale_Boomerang)
|
||||
Can Defeat Darkhammer: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
|
||||
(Can_Use_Back_Slice_as_Sword and Can_Do_Difficult_Combat) or (Can_Do_Niche_Stuff and Iron_Boots)
|
||||
Can Defeat Darknut: Sword or (Can_Do_Difficult_Combat and (Bombs or Ball_and_Chain))
|
||||
Can Defeat Aerolfos: Clawshot and (Sword or Ball_and_Chain or Wolf_Link or (Can_Do_Niche_Stuff and Iron_Boots))
|
||||
Can Defeat Phantom Zant: Sword or Wolf_Link
|
||||
Can Defeat King Bulblin Castle: Sword or Ball_and_Chain or Wolf_Link or Big_Quiver or (Can_Do_Difficult_Combat and
|
||||
(Spinner or Iron_Boots or Bombs or Can_Use_Back_Slice_as_Sword))
|
||||
|
||||
# BOSSES
|
||||
|
||||
Can Defeat Diababa: Can_Launch_Bombs or (Gale_Boomerang and
|
||||
(Sword or Ball_and_Chain or Wolf_Link or Bombs or
|
||||
(Can_Do_Difficult_Combat and Can_Use_Back_Slice_as_Sword) or (Can_Do_Niche_Stuff and Iron_Boots)))
|
||||
Can Defeat Fyrus: Bow and Iron_Boots and (Sword or (Can_Do_Difficult_Combat and Can_Use_Back_Slice_as_Sword))
|
||||
Can Defeat Morpheel: Iron_Boots and Clawshot and Sword and Can_Refill_Air
|
||||
Can Defeat Stallord: Spinner and (Sword or Can_Do_Difficult_Combat)
|
||||
Can Defeat Blizzeta: Ball_and_Chain
|
||||
Can Defeat Armogohma: Bow and Dominion_Rod
|
||||
Can Defeat Argorok: Double_Clawshots and Ordon_Sword and (Iron_Boots or (Can_Do_Niche_Stuff and Magic_Armor))
|
||||
Can Defeat Zant: Master_Sword and Gale_Boomerang and (Iron_Boots or (Can_Do_Niche_Stuff and Magic_Armor)) and
|
||||
Can_Refill_Air and Clawshot and Ball_and_Chain
|
||||
|
||||
Can Open North Faron Woods Gate: North_Faron_Woods_Gate_Key or Small_Keys == Keysy
|
||||
Can Complete Prologue: Skip_Prologue == On or (Sword and Slingshot and Can_Open_North_Faron_Woods_Gate)
|
||||
|
||||
# You can only use warp portals from certain stages.
|
||||
# 'Can_Warp' is an event added to any logical area
|
||||
# which is part of a stage that players can warp from.
|
||||
Can Use Warp Portals: Wolf_Link and 'Can_Warp' and Can_Complete_Prologue
|
||||
|
||||
Can Free All Monkeys in Forest Temple: "'Can_Free_Monkey_in_Entrance_Room' and 'Can_Free_Monkey_on_Totem' and
|
||||
'Can_Free_Monkey_in_Big_Baba_Room' and 'Can_Free_Monkey_in_West_Tileworm_Room' and
|
||||
'Can_Free_Monkey_in_East_Tileworm_Room' and 'Can_Free_Monkey_in_Dark_Spider_Room' and
|
||||
'Can_Free_Monkey_in_North_Deku_Like_Room'"
|
||||
|
||||
Has Sword For Temple of Time: Temple_of_Time_Sword_Requirement == None or
|
||||
(Temple_of_Time_Sword_Requirement == Wooden_Sword and Sword) or
|
||||
(Temple_of_Time_Sword_Requirement == Ordon_Sword and Ordon_Sword) or
|
||||
(Temple_of_Time_Sword_Requirement == Master_Sword and Master_Sword) or
|
||||
(Temple_of_Time_Sword_Requirement == Light_Sword and Light_Sword)
|
||||
|
||||
Can Complete Faron Twilight: Faron_Twilight_Cleared == On or count(Faron_Twilight_Tear, 16)
|
||||
Can Complete Eldin Twilight: Eldin_Twilight_Cleared == On or count(Eldin_Twilight_Tear, 16)
|
||||
Can Complete Lanayru Twilight: Lanayru_Twilight_Cleared == On or count(Lanayru_Twilight_Tear, 16)
|
||||
Can Complete All Twilight: Can_Complete_Faron_Twilight and Can_Complete_Eldin_Twilight and Can_Complete_Lanayru_Twilight
|
||||
|
||||
Can Defeat Faron Twilit Insect: Twilight
|
||||
Can Defeat Eldin Twilit Insect: Twilight
|
||||
Can Defeat Lanayru Twilit Insect: Twilight and Can_Complete_Eldin_Twilight
|
||||
|
||||
Can Clear Forest: Can_Complete_Faron_Twilight and ('Can_Complete_Forest_Temple' or Faron_Woods_Logic == Open)
|
||||
|
||||
Can Complete All Dungeons: "'Can_Complete_Forest_Temple' and 'Can_Complete_Goron_Mines' and 'Can_Complete_Lakebed_Temple' and
|
||||
'Can_Complete_Arbiters_Grounds' and 'Can_Complete_Snowpeak_Ruins' and 'Can_Complete_Temple_of_Time' and
|
||||
'Can_Complete_City_in_the_Sky' and 'Can_Complete_Palace_of_Twilight'"
|
||||
|
||||
Can Break Hyrule Castle Barrier: Hyrule_Barrier_Requirements == Open or
|
||||
(Hyrule_Barrier_Requirements == Vanilla and 'Can_Complete_Palace_of_Twilight') or
|
||||
(Hyrule_Barrier_Requirements == Fused_Shadows and count(Progressive_Fused_Shadow, Hyrule_Barrier_Fused_Shadows)) or
|
||||
(Hyrule_Barrier_Requirements == Mirror_Shards and count(Progressive_Mirror_Shard, Hyrule_Barrier_Mirror_Shards)) or
|
||||
(Hyrule_Barrier_Requirements == Dungeons and dungeons_completed(Hyrule_Barrier_Dungeons)) or
|
||||
(Hyrule_Barrier_Requirements == Poe_Souls and count(Poe_Soul, Hyrule_Barrier_Poe_Souls)) or
|
||||
(Hyrule_Barrier_Requirements == Hearts and hearts(Hyrule_Barrier_Hearts))
|
||||
|
||||
Can Open Hyrule Castle Big Key Gate: Hyrule_Castle_Big_Key_Requirements == None or
|
||||
(Hyrule_Castle_Big_Key_Requirements == Fused_Shadows and count(Progressive_Fused_Shadow, Hyrule_Castle_Big_Key_Fused_Shadows)) or
|
||||
(Hyrule_Castle_Big_Key_Requirements == Mirror_Shards and count(Progressive_Mirror_Shard, Hyrule_Castle_Big_Key_Mirror_Shards)) or
|
||||
(Hyrule_Castle_Big_Key_Requirements == Dungeons and dungeons_completed(Hyrule_Castle_Big_Key_Dungeons)) or
|
||||
(Hyrule_Castle_Big_Key_Requirements == Poe_Souls and count(Poe_Soul, Hyrule_Castle_Big_Key_Poe_Souls)) or
|
||||
(Hyrule_Castle_Big_Key_Requirements == Hearts and hearts(Hyrule_Castle_Big_Key_Hearts))
|
||||
|
||||
|
||||
Can Talk to Springwater Goron: Nothing # TODO
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,652 +0,0 @@
|
||||
######################
|
||||
## Logic Settings ##
|
||||
######################
|
||||
|
||||
- Name: Logic Rules
|
||||
Default Option: All Locations Reachable
|
||||
Options:
|
||||
- All Locations Reachable: "Logic is considered when placing items. Tricks and Glitches can be enabled for consideration below."
|
||||
- Beatable Only: "Logic is considered when placing items only until the world is beatable. Remaining items are placed without logic consideration. Tricks and Glitches can be enabled for consideration below."
|
||||
- No Logic: "Maximize randomization, logic is not considered when placing items. MAY BE IMPOSSIBLE TO BEAT."
|
||||
# - Vanilla: "Items are placed in their vanilla locations."
|
||||
|
||||
######################
|
||||
## Access Options ##
|
||||
######################
|
||||
|
||||
- Name: Hyrule Barrier Requirements
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Open: "The barrier around Hyrule Castle is dispelled from the beginning."
|
||||
- Vanilla: "The barrier will be dispelled once Palace of Twilight is cleared."
|
||||
- Fused Shadows: "The barrier will be dispelled once the required number of Fused Shadows have been collected."
|
||||
- Mirror Shards: "The barrier will be dispelled once the required number of Mirror Shards have been collected."
|
||||
- Dungeons: "The barrier will be dispelled once the required number of Dungeons have been cleared."
|
||||
- Poe Souls: "The barrier will be dispelled once the required number of Poe Souls have been collected."
|
||||
- Hearts: "The barrier will be dispelled once the required number of Hearts have been reached."
|
||||
|
||||
- Name: Hyrule Barrier Fused Shadows
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-3: No description available.
|
||||
|
||||
- Name: Hyrule Barrier Mirror Shards
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-4: No description available.
|
||||
|
||||
- Name: Hyrule Barrier Dungeons
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-8: No description available.
|
||||
|
||||
- Name: Hyrule Barrier Poe Souls
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-60: No description available.
|
||||
|
||||
- Name: Hyrule Barrier Hearts
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 4
|
||||
Options:
|
||||
- 4-20: No description available. # Hehe 420
|
||||
|
||||
- Name: Palace of Twilight Requirements
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Open: "The Mirror of Twilight is open at the start of the game."
|
||||
- Fused Shadows: "The player must collect all 3 Fused Shadows."
|
||||
- Mirror Shards: "The player must collect all 4 Mirror Shards."
|
||||
- Vanilla: "The player must complete City in the Sky."
|
||||
|
||||
- Name: Faron Woods Logic
|
||||
Tracker Important: True
|
||||
Default Option: Closed
|
||||
Options:
|
||||
- Closed: "Midna will block the player from leaving Faron Woods until Forest Temple is completed."
|
||||
- Open: "Midna will not prevent the player from leaving Faron Woods."
|
||||
|
||||
- Name: Mirror Chamber Access
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: Open
|
||||
Options:
|
||||
- Open: "The entrance is open and operates like normal. If you start with the Mirror Chamber Portal, you can access the Stallord boss fight without going through Arbiter's Grounds."
|
||||
- Barrier: "A barrier is placed in front of the Mirror Chamber entrance and goes away once Stallord is defeated."
|
||||
- Closed: "The Mirror Chamber is isolated from the world and cannot be reached from the Stallord boss room. To access it, players will either need the portal or access from Palace of Twilight."
|
||||
|
||||
######################
|
||||
## Item Pool ##
|
||||
######################
|
||||
|
||||
- Name: Golden Bugs
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The Golden Bug locations across Hyrule will give the golden bug at that location in the base game."
|
||||
- "On": "The Golden Bug locations across Hyrule will be randomized."
|
||||
|
||||
- Name: Sky Characters
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The Sky Character locations across Hyrule will give Sky Characters."
|
||||
- "On": "The Sky Character locations across Hyrule will be randomized."
|
||||
|
||||
- Name: Gifts From NPCs
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Locations which involve an NPC giving you a gift will give the item expected from the base game."
|
||||
- "On": "Locations which involve an NPC giving you a gift will be randomized."
|
||||
|
||||
- Name: Shop Items
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Shop item locations will contain the item they have in the base game."
|
||||
- "On": "Shop items will be randomized."
|
||||
|
||||
- Name: Hidden Skills
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The golden wolf locations across Hyrule will give you Hidden Skills. You will be required to get at least one of them to obtain the Ending Blow."
|
||||
- "On": "The golden wolf locations across Hyrule will be randomized."
|
||||
|
||||
- Name: Hidden Rupees
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Rupees hidden in tricky locations will not be randomized."
|
||||
- "On": "Rupees hidden in tricky locations will be randomized."
|
||||
|
||||
- Name: Freestanding Rupees
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Rupees out in the open will not be randomized."
|
||||
- "On": "Rupees out in the open will be randomized."
|
||||
|
||||
- Name: Poe Souls
|
||||
Tracker Important: True
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Vanilla: "All poes will give poe souls as the item for beating them."
|
||||
- Overworld: "Overworld poes will give randomized items. Poes in dungeons will still give poe souls."
|
||||
- Dungeon: "Poes in dungeons will give randomized items. Overworld poes will will give poe souls."
|
||||
- All: "All poes will be randomized."
|
||||
|
||||
- Name: Ilia Memory Quest
|
||||
Tracker Important: True
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Vanilla: "The Ilia Memory Quest will work the same way as the base game. You'll start it by beating Temple of Time and then talking to Renado in Kakariko Village."
|
||||
- Letter: "Renado's Letter will be shuffled into the world somewhere. You'll start the quest by finding Renado's Letter and then showing it to Telma in her bar."
|
||||
- Invoice: "The Invoice will be shuffled into the world somewhere. You'll start the quest by finding the Invoice and showing it to the Doctor in Castle Town."
|
||||
- Statue: "The Wooden Statue will be shuffled into the world somewhere. You'll start the quest by finding the Wooden Statue and then showing it to Ilia in Kakariko Village."
|
||||
- Charm: "Ilia's Charm will be shuffled into the world somewhere. You'll start the quest by finding Ilia's Charm and then showing it to Ilia in Kakariko Village to complete the quest."
|
||||
|
||||
- Name: Item Scarcity
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Vanilla: "No changes to the item pool."
|
||||
- Minimal: "Removes unrequired items such as Heart Containers and Pieces, Hawkeye, etc. Has as few items as possible for Bomb Bags, Bows, Hidden Skills, and Wallets. No Magic Armor and 1 Hidden Skill if Glitchless logic."
|
||||
- Plentiful: "One extra copy of major items. There are 17 Heart Containers but no Pieces of Heart. Extra keys if `Keysanity` or `Any Dungeon`."
|
||||
|
||||
- Name: Trap Item Frequency
|
||||
Default Option: None
|
||||
Options:
|
||||
- None: "All items in the game will be genuine."
|
||||
- Few: "Approximately 12.5% of non-major items will be replaced with 'traps' that don't give the item they appear to be."
|
||||
- Many: "Approximately 39.1% of non-major items will be replaced with 'traps' that don't give the item they appear to be."
|
||||
- Mayhem: "Approximately 62.7% of non-major items will be replaced with 'traps' that don't give the item they appear to be."
|
||||
- Nightmare: "All of the non-major items will be replaced with 'traps' that don't give the item they appear to be."
|
||||
|
||||
######################
|
||||
## Dungeon Items ##
|
||||
######################
|
||||
|
||||
- Name: Small Keys
|
||||
Tracker Important: True
|
||||
Default Option: Vanilla
|
||||
Random Low: Own Dungeon
|
||||
Random High: Anywhere
|
||||
Options:
|
||||
- Vanilla: "Small Keys will appear in their vanilla locations."
|
||||
- Own Dungeon: "Small Keys will appear inside their respective dungeon."
|
||||
- Any Dungeon: "Small Keys can appear inside any dungeon."
|
||||
# - Own Region: "Small Keys will appear in their dungeon's region."
|
||||
- Overworld: "Small Keys will only appear in the overworld."
|
||||
- Anywhere: "Small Keys can appear anywhere."
|
||||
- Keysy: "Small Keys will not appear anywhere in the world and their locks will start opened."
|
||||
|
||||
- Name: Big Keys
|
||||
Tracker Important: True
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Vanilla: "Big Keys will appear in their vanilla locations."
|
||||
- Own Dungeon: "Big Keys will appear inside their respective dungeon."
|
||||
- Any Dungeon: "Big Keys can appear inside any dungeon."
|
||||
# - Own Region: "Big Keys appear in their dungeon's region."
|
||||
- Overworld: "Big Keys will only appear in the overworld."
|
||||
- Anywhere: "Big Keys can appear anywhere."
|
||||
- Keysy: "Big Keys will not appear anywhere in the world and boss doors will start opened."
|
||||
|
||||
- Name: Maps and Compasses
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Vanilla: "Maps and Compasses will appear in their vanilla locations."
|
||||
- Own Dungeon: "Maps and Compasses can appear anywhere inside their respective dungeon."
|
||||
- Any Dungeon: "Maps and Compasses can appear inside any dungeon."
|
||||
# - Own Region: "Maps and Compasses will appear in their dungeon's region."
|
||||
- Overworld: "Maps and Compasses will only appear in the overworld."
|
||||
- Anywhere: "Maps and Compasses can appear anywhere."
|
||||
- Start With: "The player starts with all Maps and Compasses."
|
||||
|
||||
- Name: Hyrule Castle Big Key Requirements
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: None
|
||||
Options:
|
||||
- None: "The gate is opened and the key is randomized according to the respective Big Key settings."
|
||||
- Fused Shadows: "The gate will open once the required number of Fused Shadows have been collected."
|
||||
- Mirror Shards: "The gate will open once the required number of Mirror Shards have been collected."
|
||||
- Dungeons: "The gate will open once the required number of Dungeons have been cleared."
|
||||
- Poe Souls: "The gate will open once the required number of Poe Souls have been collected."
|
||||
- Hearts: "The gate will open once the required number of Hearts have been reached."
|
||||
|
||||
- Name: Hyrule Castle Big Key Fused Shadows
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-3: No description available.
|
||||
|
||||
- Name: Hyrule Castle Big Key Mirror Shards
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-4: No description available.
|
||||
|
||||
- Name: Hyrule Castle Big Key Dungeons
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-8: No description available.
|
||||
|
||||
- Name: Hyrule Castle Big Key Poe Souls
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 1-60: No description available.
|
||||
|
||||
- Name: Hyrule Castle Big Key Hearts
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: 4
|
||||
Options:
|
||||
- 4-20: No description available. # Hehe 420
|
||||
|
||||
- Name: Dungeon Rewards Can Be Anywhere
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Dungeon reward items (Fused Shadows and Mirror Shards) will only appear at the end of dungeons."
|
||||
- "On": "Dungeon reward items (Fused Shadows and Mirror Shards) can appear anywhere."
|
||||
|
||||
- Name: No Small Keys on Bosses
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Small keys will not be placed on boss heart container or dungeon reward checks."
|
||||
- "On": "Small keys can potentially be placed on boss heart container or dungeon reward checks. You may be expected to defeat a dungeon's boss before progressing further into the dungeon."
|
||||
|
||||
- Name: Unrequired Dungeons Are Barren
|
||||
Tracker Important: True
|
||||
Default Option: "On"
|
||||
Options:
|
||||
- "Off": "Unrequired dungeons may contain items needed to beat the game."
|
||||
- "On": "Unrequired dungeons will not contain any items necessary to beat the game."
|
||||
|
||||
######################
|
||||
## Timesavers ##
|
||||
######################
|
||||
|
||||
- Name: Skip Prologue
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "You will be required to play through the prologue section of the game to begin the randomizer. This includes everything up to the second goat herding sequence."
|
||||
- "On": "The prologue section of the game will be completed from the start."
|
||||
|
||||
- Name: Faron Twilight Cleared
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "You will be required to complete the Castle Sewers and Faron Twilight section of the game."
|
||||
- "On": "The Castle Sewers and Faron Twilight section of the game will be completed from the start."
|
||||
|
||||
- Name: Eldin Twilight Cleared
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "You will be required to complete the Eldin Twilight section of the game."
|
||||
- "On": "The Eldin Twilight section of the game will be completed from the start."
|
||||
|
||||
- Name: Lanayru Twilight Cleared
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "You will be required to complete the Lanayru Twilight section of the game."
|
||||
- "On": "The Lanayru Twilight section of the game will be completed from the start."
|
||||
|
||||
- Name: Skip Midna's Desparate Hour
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "After completing Lakebed Temple, you will be required to complete the Midna's Desperate Hour section of the game. Note that some overworld poes require Midna's Desperate Hour to be completed before they spawn in."
|
||||
- "On": "The Midna's Desperate Hour section of the game will be completed from the start."
|
||||
|
||||
- Name: Skip Minor Cutscenes
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Minor cutscenes such as area introduction cutscenes and Midna text explanations will not be skipped."
|
||||
- "On": "Minor cutscenes such as area introduction cutscenes and Midna text explanations will not play."
|
||||
|
||||
- Name: Skip Major Cutscenes
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "If you want to skip a skippable cutscene, you must press the start button twice while the cutscene is playing."
|
||||
- "On": "The randomizer will automatically skip any skippable cutscene as fast as possible."
|
||||
|
||||
- Name: Unlock Map Regions
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The map will not start filled in at the beginning of the randomizer. You will have to travel to the different sections of the world to get them on the map."
|
||||
- "On": "The map will start as filled in as possible. Certain sections such as Eldin and Lanayru will only be filled in if their Twilight section is cleared from the start."
|
||||
|
||||
- Name: Open Door of Time
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "You will be required to lead the big statue down the Temple of Time to open the big door at the bottom."
|
||||
- "On": "The big statue will already be set in place at the bottom of the Temple of Time and the door will be opened from the start."
|
||||
|
||||
- Name: Active Goron Mines Magnets
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The switches to activate magnets in Goron Mines will need to be activated manually."
|
||||
- "On": "The switches to activate magnets in Goron Mines will be activated from the start except for the highest one in the main room."
|
||||
|
||||
- Name: Lower Hyrule Castle Chandelier
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The chandeliers in Hyrule Castle will all need to be lowered manually."
|
||||
- "On": "One of the chandeliers in the Hyrule Castle main hall will be lowered from the start. This skips requiring Gale Boomerang and either Lantern or Bow to complete Hyrule Castle."
|
||||
|
||||
- Name: Skip Bridge Donation
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "You will need to donate money at Kakariko Malo Mart to build the bridge between Eldin Field and Castle Town."
|
||||
- "On": "The bridge between Eldin Field and Castle Town will be automatically built after Eldin and Lanayru Twilight are both completed."
|
||||
|
||||
######################
|
||||
# Additional Settings#
|
||||
######################
|
||||
|
||||
- Name: Starting Form
|
||||
Tracker Important: True
|
||||
Default Option: Human
|
||||
Options:
|
||||
- Human: Start as Human Link
|
||||
- Wolf: Start as Wolf Link
|
||||
|
||||
- Name: Bonks Do Damage
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": No description available.
|
||||
- "On": No description available.
|
||||
|
||||
- Name: Starting Time of Day
|
||||
Default Option: Noon
|
||||
Options:
|
||||
- Morning: "Time of day will start at 9am."
|
||||
- Noon: "Time of day will start at noon."
|
||||
- Evening: "Time of day will start at 6pm."
|
||||
- Night: "Time of day will start at midnight."
|
||||
|
||||
- Name: Logic Transform Anywhere
|
||||
Default Option: "On"
|
||||
Options:
|
||||
- "Off": "You will not be expected to transform in places that you normally can't."
|
||||
- "On": "You may be expected to transform in places that require turning on the Dusklight Transform Anywhere setting."
|
||||
|
||||
- Name: Logic Increase Wallet Capacity
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Logic will assume you have the same wallet capacities as the base game."
|
||||
- "On": "Logic will assume that you have the Bigger Wallets Dusklight setting turned on."
|
||||
|
||||
- Name: Logic Damage Multiplier
|
||||
Default Option: Vanilla
|
||||
Options:
|
||||
- Vanilla: "Logic will assume your Dusklight Damage Multiplier is x1."
|
||||
- Double: "Logic will assume your Dusklight Damage Multiplier is x2."
|
||||
- Triple: "Logic will assume your Dusklight Damage Multiplier is x3."
|
||||
- Quadruple: "Logic will assume your Dusklight Damage Multiplier is x4."
|
||||
- OHKO: "Logic will assume your Dusklight Instant Death setting is turned on."
|
||||
|
||||
#############################
|
||||
# Dungeon Entrance Settings #
|
||||
#############################
|
||||
|
||||
- Name: Lakebed Does Not Require Water Bombs
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The entrance to Lakebed Temple will be blocked by a boulder and require using Water Bombs to blow up."
|
||||
- "On": "The rock blocking access to the entrance of Lakebed Temple will be gone, meaning you can get in without Water Bombs."
|
||||
|
||||
- Name: Arbiters Does Not Require Bulblin Camp
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Bulblin Camp will have to be completed to access the entrance to Arbiter's Grounds. This will require finding the Gerudo Desert Bulblin Camp Key."
|
||||
- "On": "Bulblin Camp will be cleared at the start of the randomizer."
|
||||
|
||||
- Name: Snowpeak Does Not Require Reekfish Scent
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Getting the reekfish scent will be required for running through the blizzard on Snowpeak Mountain. Getting the reekfish scent requires the Coral Earring."
|
||||
- "On": "The randomizer will start you with the reekfish scent, meaning you can go through the Snowpeak Mountain blizzard without needing the Coral Earring."
|
||||
|
||||
- Name: Sacred Grove Does Not Require Skull Kid
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Getting through the Lost Woods will require completing the Skull Kid chase sequence."
|
||||
- "On": "The Skull Kid chase sequence in the Lost Woods will start already completed."
|
||||
|
||||
- Name: City Does Not Require Filled Skybook
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "The canon to City in the Sky will spawn in Lake Hylia when the Sky Book has been completed."
|
||||
- "On": "The canon to City in the Sky will be in Lake Hylia from the start."
|
||||
|
||||
- Name: Goron Mines Entrance
|
||||
Tracker Important: True
|
||||
Default Option: Closed
|
||||
Options:
|
||||
- Closed: "Accessing Goron Mines will require climbing up to the Death Mountain Sumo Hall and wrestling with the Goron Elder."
|
||||
- No Wrestling: "Accessing Goron Mines will require climbing up to the Death Mountain Sumo Hall, but wrestling the Goron Elder will not be necessary."
|
||||
- Open: "The elevator shortcut to the Death Mountain Sumo Hall will be open, and can be used to access Goron Mines."
|
||||
|
||||
- Name: Temple of Time Sword Requirement
|
||||
Need In Game: True
|
||||
Tracker Important: True
|
||||
Default Option: None
|
||||
Options:
|
||||
- None: "The door to the past will be open from the start."
|
||||
- Wooden Sword: "The door to the past will require striking at least the Wooden Sword into the Master Sword pedestal."
|
||||
- Ordon Sword: "The door to the past will require striking at least the Ordon Sword into the Master Sword pedestal."
|
||||
- Master Sword: "The door to the past will require striking at least the Master Sword into the Master Sword pedestal."
|
||||
- Light Sword: "The door to the past will require striking the Light Sword into the Master Sword pedestal."
|
||||
|
||||
#############################
|
||||
## Hints ##
|
||||
#############################
|
||||
|
||||
- Name: Number of Path Hints
|
||||
Default Option: 3
|
||||
Options:
|
||||
- 0-7: "Select the number of path hints you would like to generate."
|
||||
|
||||
- Name: Path Hints on Midna
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Path Hints will not be part of Midna's hint text."
|
||||
- "On": "Path hints will be part of Midna's hint text. If path hints are also placed on hint signs, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Path Hints on Hint Signs
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Path Hints will not be placed on hint signs."
|
||||
- "Overworld": "Path hints will be placed only on overworld hint signs. If path hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Dungeon": "Path hints will be placed only on dungeon hint signs. If path hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Any": "Path hints can be placed at any hint sign. If path hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Number of Barren Hints
|
||||
Default Option: 3
|
||||
Options:
|
||||
- 0-7: "Select the number of barren hints you would like to generate."
|
||||
|
||||
- Name: Barren Hints on Midna
|
||||
Default Option: "On"
|
||||
Options:
|
||||
- "Off": "Barren Hints will not be part of Midna's hint text."
|
||||
- "On": "Barren hints will be part of Midna's hint text. If barren hints are also placed on hint signs, then the hints will be split evenly between the two options."
|
||||
#- "On + Region Hint Signs": "Barren hints will be part of Midna's hint text. The hint signs within Midna's hinted barren regions will also declare the region as barren. If barren hints are also placed on hint signs, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Barren Hints on Hint Signs
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Barren Hints will not be placed on hint signs."
|
||||
- "Overworld": "Barren hints will be placed only on overworld hint signs. If barren hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Dungeon": "Barren hints will be placed only on dungeon hint signs. If barren hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Any": "Barren hints can be placed at any hint sign. If barren hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Number of Item Hints
|
||||
Default Option: 1
|
||||
Options:
|
||||
- 0-7: "Select the number of item hints you would like to generate."
|
||||
|
||||
- Name: Item Hints on Midna
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Item Hints will not be part of Midna's hint text."
|
||||
- "On": "Item hints will be part of Midna's hint text. If item hints are also placed on hint signs, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Item Hints on Hint Signs
|
||||
Default Option: "Overworld"
|
||||
Options:
|
||||
- "Off": "Item Hints will not be placed on hint signs."
|
||||
- "Overworld": "Item hints will be placed only on overworld hint signs. If item hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Dungeon": "Item hints will be placed only on dungeon hint signs. If item hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Any": "Item hints can be placed at any hint sign. If item hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Number of Location Hints
|
||||
Default Option: 5
|
||||
Options:
|
||||
- 0-7: "Select the number of location hints you would like to generate."
|
||||
|
||||
- Name: Location Hints on Midna
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Location Hints will not be part of Midna's hint text."
|
||||
- "On": "Location hints will be part of Midna's hint text. If location hints are also placed on hint signs, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Location Hints on Hint Signs
|
||||
Default Option: "Overworld"
|
||||
Options:
|
||||
- "Off": "Location Hints will not be placed on hint signs."
|
||||
- "Overworld": "Location hints will be placed only on overworld hint signs. If location hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Dungeon": "Location hints will be placed only on dungeon hint signs. If location hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
- "Any": "Location hints can be placed at any hint sign. If location hints are also part of Midna's hint text, then the hints will be split evenly between the two options."
|
||||
|
||||
- Name: Prioritize Remote Location Hints
|
||||
Default Option: "On"
|
||||
Options:
|
||||
- "Off": "All locations will be treated equally for location hints."
|
||||
- "On": "Certain locations which are time-consuming to check will be given priority for location hints."
|
||||
|
||||
#############################
|
||||
## Entrance Randomizer ##
|
||||
#############################
|
||||
|
||||
- Name: Randomize Starting Spawn
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Link will start outside his house."
|
||||
- "On": "Link will start in a random area."
|
||||
|
||||
- Name: Randomize Dungeon Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a dungeon will lead to the vanilla dungeon."
|
||||
- "On": "Entering a dungeon will lead to a random dungeon."
|
||||
- "On + Hyrule Castle": "Entering a dungeon will lead to a random dungeon. Hyrule Castle's entrance will be shuffled as well."
|
||||
|
||||
- Name: Randomize Boss Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a boss door will lead to the intended boss."
|
||||
- "On": "Entering a boss door will lead to a random boss."
|
||||
|
||||
- Name: Randomize Grotto Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a grotto will lead to the intended grotto."
|
||||
- "On": "Entering a grotto will lead to a random grotto."
|
||||
|
||||
- Name: Randomize Cave Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a door or loadzone that leads to a cave area will lead to the intended cave."
|
||||
- "On": "Entering a door or loadzone that leads to a cave area will lead to a random cave."
|
||||
|
||||
- Name: Randomize Interior Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a door or loadzone that leads to an interior area will lead to the intended area."
|
||||
- "On": "Entering a door or loadzone that leads to an interior area will lead to a random intended area."
|
||||
|
||||
- Name: Randomize Overworld Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a loadzone that leads to an overworld area will lead to the intended area."
|
||||
- "On": "Entering a loadzone that leads to an overworld area will lead to a random area."
|
||||
|
||||
- Name: Decouple Double Door Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a left door will lead to the same location as the corresponding right door."
|
||||
- "On": "Entering a left door may lead somewhere different than the corresponding right door (only if the door's type is randomized)."
|
||||
|
||||
- Name: Decouple Entrances
|
||||
Tracker Important: True
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Entering a location and taking the entrance behind you will take you back to where you came from."
|
||||
- "On": "Entering a location and taking the entrance behind you will take you to a random location."
|
||||
|
||||
|
||||
#############################
|
||||
## Logic Tricks ##
|
||||
#############################
|
||||
|
||||
- Name: Back Slice as Sword
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Back Slicing without a sword can be logically required to do damage."
|
||||
- "On": "Back Slicing without a sword can be logically required to do damage."
|
||||
|
||||
- Name: Ball and Chain Webs
|
||||
Default Option: "Off"
|
||||
Options:
|
||||
- "Off": "Ball and Chain will not be required to break webs."
|
||||
- "On": "Ball and Chain may be required to break webs."
|
||||
@@ -1,611 +0,0 @@
|
||||
# Flag values taken from: https://github.com/lunarsoap5/Randomizer-Web-Generator-1/blob/development/Generator/Assets/Flags.cs
|
||||
|
||||
EventFlags:
|
||||
- 0x0382 # Gave wooden sword to Talo. Talked to squirrel outside link's house
|
||||
- 0x0629 # Tame Epona, KB1 trigger activated, Warped Kakariko Bridge Back.
|
||||
- 0x0F40 # Talked to Doctor for the first time.
|
||||
- 0x1208 # Can use Sera's Shop.
|
||||
- 0x1410 # Put Bo outside, ready to wrestle
|
||||
- 0x0F01 # Got Lantern from Coro (Remove when adding Coro checks)
|
||||
- 0x0A2F # Bridge of Eldin Stolen, KB1 defeated, KB1 started
|
||||
- 0x0F68 # Bridge of Eldin Warped Back, forced text when entering dr. clinic, talked to dr before giving invoice
|
||||
- 0x4088 # Saved monkey from puppets, Visited Gerudo Desert for the first time.
|
||||
- 0x4118 # Talked to Fado after Faron and Eldin Twilight
|
||||
- 0x07A0 # Watched Colin CS after KB1, talked to Bo before sumo
|
||||
- 0x2020 # Master Sword Story Progression
|
||||
- 0x2010 # Arbiters Grounds Story Progression
|
||||
- 0x2C10 # Raised the mirror in the Mirror Chamber
|
||||
- 0x1B38 # Skip Monkey Escort
|
||||
- 0x1C20 # Talked to Bo after opening boots chest.
|
||||
- 0x5F20 # Shad leaves sanctuary.
|
||||
- 0xF701 # Add 256 Rupees to Charlo.
|
||||
- 0xF8F4 # Add 244 Rupees to Charlo.
|
||||
- 0x6001 # Talked to Fyer after Lanayru Twilight
|
||||
- 0x3880 # Talked to Jovani after defeating Poe.
|
||||
- 0x2208 # Talked to Yeto on top of the mountain after clearing SPR
|
||||
- 0x3B40 # Won Snowboard race against Yeto.
|
||||
- 0x2F80 # Talked to Goron outside East Castle Town
|
||||
- 0x1C10 # Win Sumo round 1 against Bo
|
||||
- 0x3902 # Released first caught fish in Ordon Day 2
|
||||
- 0x1002 # Talked to Jaggle after climbing vines.
|
||||
- 0x0B20 # Talked to Yeta in Snowpeak for the first time
|
||||
- 0x4308 # Senses unlocked
|
||||
- 0x4610 # Rode Epona back to Link's House
|
||||
- 0x0C10 # Midna accompanies Wolf
|
||||
- Skip_Prologue == On:
|
||||
- 0x0404 # Talked to Uli Day 1.
|
||||
- 0x4510 # Saved Talo
|
||||
- 0x4A60 # Completed Ordon Day 1 and Finished Sword Training.
|
||||
- 0x1601 # Completed Ordon Day 2.
|
||||
- 0x1580 # Watched CS for Goats 2 Done.
|
||||
- Faron_Twilight_Cleared == On:
|
||||
- 0x057F # Midna Charge Unlocked, Finished Sewers, Met Zelda in swers, Midna cut prison chain, watched sewers intro CS, Escaped Cell in Sewers.
|
||||
- 0x0610 # Cleared Faron Twilight
|
||||
- 0x0C08 # Sword and shield removed from wolf's back.
|
||||
- Eldin_Twilight_Cleared == On:
|
||||
- 0x0708 # Cleared Eldin Twilight
|
||||
- 0x0604 # Map Warping unlocked.
|
||||
- Lanayru_Twilight_Cleared == On:
|
||||
- 0x0880 # Zora's Domain Thawed.
|
||||
- 0x0C02 # Lanayru Twilight Story Flag.
|
||||
- 0x0A10 # Defeated Kargarok Rider at Lake (allows player to howl for Kargorok.);
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x0140 # Talked to Yeto First Time.
|
||||
- 0x0390 # Jaggle Calls out to Link, talked to Squirrel as Wolf in Ordon.
|
||||
- 0x06C0 # CS After beating Ordon Shadow, CS after entering Faron Twilight.
|
||||
- 0x0702 # First Time Talking to Gor Coron in Sumo Hall
|
||||
- 0x1501 # Talked to Agitha for the first time.
|
||||
- 0x2001 # Talked to Telma for the first time.
|
||||
- 0x5E10 # Midna text after beating Forest Temple.
|
||||
- 0x1D40 # Listened to Fyer at drained lake.
|
||||
- 0x2201 # Plumm initial CS watched.
|
||||
- 0x2310 # STAR initial CS watched.
|
||||
- 0x2602 # Talked to Yeto on Snowpeak.
|
||||
- 0x2840 # Used Ooccoo for the first time.
|
||||
- 0x3704 # Postman twilight text.
|
||||
- 0x3806 # Hena cabin first time CS, talked to Hena first time.
|
||||
- 0x3A01 # Talked to Ralis in Graveyard for the first time.
|
||||
- 0x4002 # Agreed to help Rusl after Snowpeak Ruins.
|
||||
- 0x4205 # Watched post-ToT Ooccoo CS. Watched Cutscene with Rusl in North Faron Woods.
|
||||
- 0x4508 # Allows postman letters to show up in inventory.
|
||||
- 0x4A10 # Saw Talo in cage CS.
|
||||
- 0x3E02 # City Ooccoo CS watched.
|
||||
- 0x5940 # Met Postman for the first time.
|
||||
- 0x5D40 # Midna text after Kargarok flight.
|
||||
- 0x2502 # Watched cutscene with Yeto on top of mountain
|
||||
- Faron_Woods_Logic == Open:
|
||||
- 0x0602 # Forest Temple Story Flag
|
||||
- 0x0C40 # Talked to Farone after clearing Forest Temple
|
||||
- 0x5E10 # Midna text after Forest Temple completed
|
||||
- Skip_Midna's_Desparate_Hour == On:
|
||||
- 0x0C01 # Midna's Desperate Hour started.
|
||||
- 0x1E08 # Midna's Deseperate Hour Completed.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x0850 # Zora Escort started and completed.
|
||||
- 0x0480 # Told Yeta about pumpkin.
|
||||
- 0x0003 # Yeto put pumpkin and cheese in soup.
|
||||
- 0x1460 # Snowpeak Ruins North and West doors unlocked.
|
||||
- 0x0120 # Told Yeta about cheese
|
||||
- Hyrule_Barrier_Requirements == Open:
|
||||
- 0x4208 # Remove Castle Barrier
|
||||
- Palace_of_Twilight_Requirements == Open:
|
||||
- 0x2B08 # Mirror of Twilight Repaired.
|
||||
- Goron_Mines_Entrance != Closed:
|
||||
- 0x0706 # Talked to Gor Coron, Won Sumo against Gor Coron.
|
||||
- Arbiters_Does_Not_Require_Bulblin_Camp == On:
|
||||
- 0x0B40 # Escaped Burning Tent in Bulblin Camp.
|
||||
- Snowpeak_Does_Not_Require_Reekfish_Scent == On:
|
||||
- 0x6120 # Got the reekfish and smelled it (removes void in Snowpeak).
|
||||
- City_Does_Not_Require_Filled_Skybook == On:
|
||||
- 0x3B08 # Sky Cannon Repaired.
|
||||
- Randomize_Starting_Spawn == On:
|
||||
- 0x057A # Finished Sewers, Midna text after entering Faron Twilight, Met Zelda in sewers, Midna cut prison chain, Watched Sewers intro CS, Escaped cell in sewers.
|
||||
- Ilia_Memory_Quest >= Letter:
|
||||
- 0x2004 # ToT Story Progression Flag
|
||||
- 0x0F80 # Renados Letter Check
|
||||
- Ilia_Memory_Quest >= Statue:
|
||||
- 0x2710 # Showed Invoice to Doctor
|
||||
- 0x2F04 # Got Medicine Scent
|
||||
- 0x2102 # Talked to Louise after Medicine Scent
|
||||
- 0x2204 # Got Wooden Statue
|
||||
- Ilia_Memory_Quest >= Charm:
|
||||
- 0x2340 # Gave statue to Ilia
|
||||
- 0x2E08 # HV barrier removed
|
||||
- 0x2280 # Got Ilia's Charm
|
||||
- Skip_Bridge_Donation == Off:
|
||||
- 0xF901 # Add 256 Rupees to Malo Mart.
|
||||
- 0xFAF4 # Add 244 Rupees to Malo Mart.
|
||||
|
||||
RegionFlags:
|
||||
Ordona Province:
|
||||
Index: 0x00
|
||||
Flags:
|
||||
- 0x57 # Spider on Link's Ladder killed.
|
||||
- 0x63 # Spawn the Chest in Link's House
|
||||
- 0x7E # Midna jumps to Shop unlocked
|
||||
- 0x6B # Ordon Spring Portal.
|
||||
- 0x44 # Midna Text after Ordon Shield (Spawns sword)
|
||||
- 0x46 # Midna Text after Ordon Sword
|
||||
- 0x68 # Approach faron wall with Midna
|
||||
- 0xA0 # Midna allows player to approach Faron Twilight Wall
|
||||
- 0xBA # Explored area outside Link's house as wolf
|
||||
- 0x61 # Defeated first bulblin outside link's house
|
||||
- 0x62 # Defeated second bulblin outside link's house
|
||||
- 0x60 # Defeated Hugo
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x4A # Ordon Day 3 Intro CS.
|
||||
- 0x4C # Knocked down Ordon bee nest CS.
|
||||
- 0x4E # Ordon Ranch first time CS.
|
||||
- 0x53 # Ilia spring CS watched.
|
||||
- 0x54 # Ilia spring CS started.
|
||||
- 0x55 # Ordon Village first time CS.
|
||||
- 0x56 # Ilia spring CS trigger.
|
||||
- 0x68 # Approach Faron Twilgiht with Midna CS.
|
||||
- 0x6E # Enter shield house as wolf CS.
|
||||
- 0x75 # Midna text after hearing Bo and Jaggle talk about the shield.
|
||||
- 0x7C # Midna text before jumping to Ordon Shop roof.
|
||||
- 0x7D # Rusl talking to Uli during wolf night CS.
|
||||
- 0xB8 # Enter Ordon Village as wolf CS.
|
||||
|
||||
Hyrule Castle Sewers and Rooftops:
|
||||
Index: 0x01
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x42 # Midna text after first gate in sewers.
|
||||
- 0x43 # Midna text after exiting to rooftops.
|
||||
- 0x51 # Zelda tower intro CS.
|
||||
- 0x57 # Outside top door intro CS.
|
||||
- 0x5A # Went to the otherside of the fence in sewers CS.
|
||||
- 0x5B # Top of stairway intro CS.
|
||||
- 0x5C # Stairway intro CS.
|
||||
- 0x7B # Midna text when approaching the rooftop guard.
|
||||
|
||||
Faron Woods:
|
||||
Index: 0x02
|
||||
Flags:
|
||||
- 0x63 # Trill lets you shop at his store.
|
||||
- 0x48 # Talked to Coro after bugs
|
||||
- 0x60 # Got Lantern Back from Monkey
|
||||
- 0x61 # Saw bugs move in Coro's house
|
||||
- 0x7D # Talked to Midna about Coro spirit
|
||||
- 0x4E # Saved Monkey from Puppets.
|
||||
- 0x62 # Midna text before jumping to lost woods
|
||||
- 0x95 # Midna text after warping to North Faron for bridge.
|
||||
- 0xBF # Burned First cobweb in faron cave
|
||||
- 0xBE # Burned second cobweb in faron cave
|
||||
- Skip_Prologue == On:
|
||||
- 0x4B # North Faron Gate Unlocked
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x74 # Faron intro CS.
|
||||
- 0x77 # See Faron Light Spirit from afar CS.
|
||||
- 0x7C # Entered mist area as human.
|
||||
- Faron_Twilight_Cleared == On:
|
||||
- 0x46 # Midna jump 1 mist area.
|
||||
- 0x47 # Midna jump 1 mist area.
|
||||
- 0x98 # South Faron Portal.
|
||||
# Re-enable once key situation is sorted out
|
||||
# - Small_Keys == Keysy:
|
||||
# - 0x53 # Coro gate unlocked.
|
||||
# - 0x4B # North Faron Gate Unlocked.
|
||||
|
||||
Kakariko and Death Mountain:
|
||||
Index: 0x03
|
||||
Flags:
|
||||
- 0xB9 # Barnes sells water bombs.
|
||||
- 0xB3 # Colin Rescued CS (Malo Mart is Open).
|
||||
- 0xA4 # Barnes Sells Bombs.
|
||||
- 0x42 # Big Rock fell at DMT
|
||||
- 0xA7 # Unlock Jumps to top of Sanctuary
|
||||
- 0x9A # Kakariko Village intro CS.
|
||||
- 0x54 # Custom flag. Sets the sign in Kak Malo mart slot 1 to appear.
|
||||
- 0x99 # Remove wooden shield from Kak Malo Mart counter.
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x49 # Death mountain intro CS.
|
||||
- 0x83 # Kakariko Graveyard intro CS.
|
||||
- 0x8C # Midna text after Meteor fell.
|
||||
- Eldin_Twilight_Cleared == On:
|
||||
- 0x14 # Collected Tear From Bomb Storage
|
||||
- 0x1A # Collected Tear From Bomb Storage
|
||||
- 0x1B # Collected Tear From Bomb Storage
|
||||
- 0x67 # Ant house entered from top
|
||||
- 0x64 # Ant house box pushed
|
||||
- 0x5E # Defeated Ant house Tears of Light bug
|
||||
- 0x1E # Collected Tear from Ant house
|
||||
- 0xBD # Done Midna jumps in ant house.
|
||||
- Small_Keys == Keysy:
|
||||
- 0xBA # Followed Rutella to graveyard.
|
||||
- 0xB6 # Started Rutella escort.
|
||||
- Goron_Mines_Entrance == Open:
|
||||
- 0x79 # moved death mountain rock to exit
|
||||
- 0x8F # moved death mountain rock to hot spring water
|
||||
- 0xB0 # Goron lets you enter elevator in sumo hall
|
||||
- Ilia_Memory_Quest >= Charm:
|
||||
- 0x70 # Darbus destroyed HV rocks
|
||||
|
||||
Lake Hylia and Zoras Domain:
|
||||
Index: 0x04
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x58 # Talked to Rutella in Lanayru Twilight.
|
||||
- 0x5F # Zora's domain intro CS twilight.
|
||||
- 0x67 # Midna text after jumping to Lake from burning bridge.
|
||||
- 0x6B # Zora's Domain exit flood water cutscene.
|
||||
- 0x72 # Midna text after arriving at frozen Upper Zora River.
|
||||
- 0x91 # Midna text after frozen Zora Domain intro CS.
|
||||
- 0xB0 # Watched CS of Ooccoo running to Sky Cannon.
|
||||
- Lanayru_Twilight_Cleared == On:
|
||||
- 0x7F # Lake Hylia has water on Lake Hylia Map.
|
||||
- Skip_Midna's_Desparate_Hour == On:
|
||||
- 0x51 # Set flag for MDH Cutscene in Lake Hylia
|
||||
- Lakebed_Does_Not_Require_Water_Bombs == On:
|
||||
- 0x70 # Blew up rock in front of lakebed CS.
|
||||
- 0x78 # Blew up rock in front of lakebed.
|
||||
|
||||
# Not sure what Index 5 is
|
||||
|
||||
Hyrule Field:
|
||||
Index: 0x06
|
||||
Flags:
|
||||
- 0x4C # Bridge of Eldin Warped back CS.
|
||||
- 0x7E # Kakariko Gorge placed CS
|
||||
- 0x83 # Set the flag for the Ganon Barriers in Hyrule Field during Eldin Twilight.
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x68 # Midna text after warping Gorge bridge.
|
||||
- 0x7C # Midna text after Lanayru Field twilight CS.
|
||||
- 0x72 # Faron Field intro CS.
|
||||
- 0x40 # Twilight Lanayru Field intro CS.
|
||||
- 0x4F # Cutscene of gate outside Kakariko Village.
|
||||
- 0xB3 # Midna text after entering Lanayru Twilight.
|
||||
- 0xB4 # Midna text when seeing Lanayru Twilight from far away.
|
||||
- 0xB6 # Midna text after entering Eldin Twilight.
|
||||
- 0xB7 # Midna text when seeing Eldin Twilight from far away.
|
||||
- Lanayru_Twilight_Cleared == On:
|
||||
- 0x58 # Lake Hylia has water on Hyrule Field Map
|
||||
- Ilia_Memory_Quest >= Charm:
|
||||
- 0x43 # Remove HV rocks from Hyrule field
|
||||
|
||||
Lost Woods and Sacred Grove:
|
||||
Index: 0x07
|
||||
Flags:
|
||||
- 0x58 # Sacred Grove MS Pedestal Map
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x42 # Midna text after pushing block shortcut as human after Grove 2.
|
||||
- 0x43 # cs after pushing block human
|
||||
- 0x44 # Lost Woods intro CS.
|
||||
- Temple_of_Time_Sword_Requirement == None:
|
||||
- 0x49 # Stairs to Temple of time created.
|
||||
- 0x4A # Struck master sword pedestal with sword.
|
||||
- 0x4B # Stairs and window appear and work properly (Past).
|
||||
- 0xBC # Statue in present is gone. (custom flag)
|
||||
- Sacred_Grove_Does_Not_Require_Skull_Kid == On:
|
||||
- 0xB6 # Skull Kid - Human defeated.
|
||||
- 0xB7 # Lost Woods Turns to day after defeating Skull Kid - Human
|
||||
- 0x5B # Block pushed down
|
||||
- 0x42 # Midna text after block pushed down
|
||||
- 0x43 # cs after pushing block human
|
||||
|
||||
|
||||
Snowpeak Province:
|
||||
Index: 0x08
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x45 # Snowpeak Summit intro CS.
|
||||
- 0x5E # Midna text outside SPR.
|
||||
- 0x5F # Snowpeak intro CS.
|
||||
- Snowpeak_Does_Not_Require_Reekfish_Scent == On:
|
||||
- 0x49 # Snowpeak summit cs.
|
||||
- 0x45 # Snowpeak Summit intro CS.
|
||||
|
||||
Castle Town:
|
||||
Index: 0x09
|
||||
Flags:
|
||||
- 0x40 # Original Jovani Poe killed. It is replaced with a custom actor.
|
||||
- 0x76 # Jovani Chest CS 2
|
||||
- 0x7F # Open Chest to Jovani
|
||||
- 0x7E # Jovani Chest CS
|
||||
- 0x50 # Set flag for Midna breaking Barrier CS.
|
||||
- 0xBC # Spawn Gengle by default as his actor interferes with the poe soul
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x55 # STAR Tent intro CS.
|
||||
- 0x7D # Jovani House intro CS.
|
||||
- Ilia_Memory_Quest >= Statue:
|
||||
- 0x56 # Remove invisible wall from Doctor
|
||||
|
||||
Gerudo Desert:
|
||||
Index: 0x0A
|
||||
Flags:
|
||||
- 0x99 # Desert Entrance CS.
|
||||
- 0x20 # Set Freestanding key flag.
|
||||
- 0x7F # Mirror Raised Cutscene Flag (Places Boar at desert entrance)
|
||||
- Small_Keys == Keysy:
|
||||
- 0x5F # Gate to King Bulblin Tent unlocked
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x53 # Mirror Chamber Intro CS.
|
||||
- Arbiters_Does_Not_Require_Bulblin_Camp == On:
|
||||
- 0x43 # Explored part 9 of the Bulblin camp area
|
||||
- 0x44 # Explored part 8 of the Bulblin camp area
|
||||
- 0x45 # Explored part 7 of the Bulblin camp area
|
||||
- 0x46 # Explored part 6 of the Bulblin camp area
|
||||
- 0x47 # Explored part 5 of the Bulblin camp area
|
||||
- 0x4C # Explored part 2 of the Bulblin camp area
|
||||
- 0x4D # Explored part 4 of the Bulblin camp area
|
||||
- 0x4E # Explored part 3 of the Bulblin camp area
|
||||
|
||||
Forest Temple:
|
||||
Index: 0x10
|
||||
Flags:
|
||||
- 0x49 # FT Ook Bridge Destroyed
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x41 # Midna text after getting Boomerang.
|
||||
- 0x42 # Midna text after Ook breaks the bridge.
|
||||
- 0x47 # Midna text after freeing first monkey.
|
||||
- 0x49 # Bridge before Ook broken.
|
||||
- 0x56 # Bokoblins spot Link in windless bridge room.
|
||||
- 0x57 # Turned bridge in windless bridge room.
|
||||
- 0x72 # West Tile Worm room intro CS.
|
||||
- 0x76 # Second monkey room intro CS.
|
||||
- 0x7C # Big Baba room intro CS.
|
||||
- 0x7D # Midna text in room before boss room.
|
||||
- 0x7E # Midna text after saving monkey after defeating Ook.
|
||||
- 0x85 # Midna text after opening hanging chest.
|
||||
- 0x83 # East outside room intro CS.
|
||||
- 0xB6 # Forest Temple intro CS.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x54 # Unlocked door to Second Monkey.
|
||||
- 0x58 # Unlock windless bridge east door.
|
||||
- 0x61 # Opened big baba monkey cage.
|
||||
- 0x74 # Opened tile worm monkey cage.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x48 # Unlocked Forest Temple Boss Door.
|
||||
- 0xED # Got Forest Temple Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Forest Temple Compass.
|
||||
- 0xEF # Got Forest Temple Dungeon Map.
|
||||
|
||||
Goron Mines:
|
||||
Index: 0x11
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x43 # Cut rope of door in outside room CS.
|
||||
- 0x44 # Pressed second button of the main magnet room of the second floor CS trigger.
|
||||
- 0x45 # Pressed third button in entrance room CS.
|
||||
- 0x46 # Pressed second button in entrance room CS.
|
||||
- 0x47 # Cut rope of door in Toadpoli room CS.
|
||||
- 0x4A # Pressed first button of the main magnet room on the second floor CS.
|
||||
- 0x68 # Pressed outside magnet switch for first time CS.
|
||||
- 0x72 # Main magnet room intro CS.
|
||||
- 0x73 # Main magnet room intro CS trigger.
|
||||
- 0x7A # Outside room intro CS.
|
||||
- 0x80 # Room after Bow chest intro CS.
|
||||
- 0x81 # Pulled Beamos in outside room CS.
|
||||
- 0x84 # Open gate in Toadpoli room CS.
|
||||
- 0x85 # Pressed second button in Toadpoli room CS.
|
||||
- 0x88 # Magnet maze room intro CS.
|
||||
- 0x8A # Goron Mines intro CS.
|
||||
- 0x8B # Pressed first button in entrance room CS.
|
||||
- 0x8C # Open gate in entrance room CS.
|
||||
- 0xBC # Main magnet room second floor intro CS.
|
||||
- 0xBD # Main magnet room second floor intro CS trigger.
|
||||
- 0xBE # Hit crystal switch in room after bow chest CS.
|
||||
- 0xBF # Room after Bow chest intro CS trigger.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x60 # Unlock north door in toadpoli room.
|
||||
- 0x62 # Unlock west locked door in main magnet room.
|
||||
- 0x6C # Unlock east outside door.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x48 # Unlocked Goron Mines Boss Door.
|
||||
- 0xED # Got Goron Mines Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Goron Mines Compass.
|
||||
- 0xEF # Got Goron Mines Dungeon Map.
|
||||
- Active_Goron_Mines_Magnets == On:
|
||||
- 0xBB # activated magnet from water before first elder
|
||||
- 0x8F # activated ceiling maze magnet after first elder
|
||||
- 0x5B # activated main magnet room 1st magnet
|
||||
- 0x4A # watched main magnet room 1st magnet cs
|
||||
- 0x61 # activated main magnet room 2nd magnet
|
||||
- 0x44 # watched main magnet room 2nd magnet cs
|
||||
- 0x9E # crystal switch room 1st Iron Boots switch pressed
|
||||
- 0x83 # crystal switch room 1st Iron Boots switch cs shown
|
||||
- 0x82 # crystal switch room 1st magnet active
|
||||
- 0x9F # crystal switch room 2nd Iron Boots switch pressed
|
||||
- 0x85 # crystal switch room 2nd Iron Boots switch cs shown
|
||||
- 0x86 # crystal switch room 2nd magnet active
|
||||
- 0x54 # activated outside room magnet
|
||||
- 0x68 # watched outside room magnet cs
|
||||
- 0x8d # activated east wing dodongo room magnet
|
||||
# Note: the final magnet is not activated because there is a
|
||||
# softlock when you exit the main magnet room through the top door
|
||||
# as wolf while the gate beyond the door in the Dodongo room is not
|
||||
# open. Alternatively if we do open this gate, it leads to much
|
||||
# more complicated logic and some jank where you can walk through
|
||||
# Dangoro while he sits there (and the gate covering the door
|
||||
# animation is also a bit jank). Also you can die during the
|
||||
# Dangoro fight to appear on the north side of his arena. There are
|
||||
# too many nuances for it to be reasonable for glitchless logic,
|
||||
# and also every small key door would require 3 keys.
|
||||
|
||||
Lakebed Temple:
|
||||
Index: 0x12
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x46 # Midna Stalactite text in second room.
|
||||
- 0x7E # Horizontal wheel is turning in east room CS.
|
||||
- 0x7F # Horizontal wheel is turning in east room CS trigger.
|
||||
- 0xA5 # Central room intro CS.
|
||||
- 0xA6 # South bridge to main room intro CS.
|
||||
- 0xA7 # Lakebed Temple intro CS.
|
||||
- 0xAA # Rotate staircase main room CS.
|
||||
- 0xB4 # East water supply Chu Worm CS.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x6B # Unlock east door main room 2F.
|
||||
- 0x7B # Unlocked door in second east room 2F.
|
||||
- 0x7C # Unlocked door before Deku Toad.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x8A # Unlocked Lakebed Temple Boss Door.
|
||||
- 0xED # Got Lakebed Temple Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Lakebed Temple Compass.
|
||||
- 0xEF # Got Lakebed Temple Dungeon Map.
|
||||
|
||||
Arbiters Grounds:
|
||||
Index: 0x13
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x5A # Turn walls in third room Basement second floor CS.
|
||||
- 0x73 # Arbiters Grounds intro CS.
|
||||
- 0x94 # Risen tracks on pilar before boss CS.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x78 # Unlocked door in second east room 2F.
|
||||
- 0x84 # Unlocked door in elevator room 2B.
|
||||
- 0x85 # Unlocked door in first room.
|
||||
- 0x92 # Unlocked door in first east room 1F.
|
||||
- 0x99 # Unlocked door in fourth east room.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x47 # Unlocked Arbiter's Grounds Boss Door.
|
||||
- 0xED # Got Arbiter's Grounds Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Arbiter's Grounds Compass.
|
||||
- 0xEF # Got Arbiter's Grounds Dungeon Map.
|
||||
|
||||
Snowpeak Ruins:
|
||||
Index: 0x14
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x83 # First Floor Northwest room intro CS.
|
||||
- 0xA1 # Midna text after finding Bedroom Key.
|
||||
- 0xA7 # Snowpeak Ruins intro CS.
|
||||
- 0xAA # Freezard in cage CS.
|
||||
- 0xAC # Courtyard intro CS.
|
||||
- 0xAE # Pumpkin room intro CS.
|
||||
- 0xB2 # Midna text after getting Cheese.
|
||||
- 0xB4 # Midna text after getting Pumpkin.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x4D # Unlock North lobby door.
|
||||
- 0x4C # Unlock West lobby door.
|
||||
- 0x6F # Unlock door in southeast room 2F.
|
||||
- 0x73 # Unlock door in east outside hallway.
|
||||
- 0x74 # Unlock west door in courtyard.
|
||||
- 0x70 # Unlock door to lobby from Freezard room.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x57 # Unlocked Snowpeak Ruins Boss Door.
|
||||
- 0xED # Got Snowpeak Ruins Big Key.
|
||||
- 0x56 # Watched CS of Yeta entering boss room.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Snowpeak Ruins Compass.
|
||||
- 0xEF # Got Snowpeak Ruins Dungeon Map.
|
||||
|
||||
Temple of Time:
|
||||
Index: 0x15
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x40 # Midna text telling you to use your senses on the missing statue.
|
||||
- 0x41 # Midna text after using senses on missing statue.
|
||||
- 0x4A # Temple of Time intro CS.
|
||||
- 0x4B # Scales of Time room intro CS.
|
||||
- 0x4C # CS after changing the balance on the scales for the first time.
|
||||
- 0x4D # CS trigger after changing the balance on the scales for the first time.
|
||||
- 0x90 # Pressed button in room 1 for the first time CS.
|
||||
- 0x91 # Pressed the button on the seventh floor for the first time CS.
|
||||
- 0x94 # Pressed the button on the fifth floor for the first time CS.
|
||||
- 0x95 # Pressed buttons on third floor for the first time CS.
|
||||
- 0x96 # Pressed the button on the second floor for the first time CS.
|
||||
- 0x54 # statue getting possessed for the first time cs
|
||||
- Small_Keys == Keysy:
|
||||
- 0x44 # Unlock door in room 1.
|
||||
- 0x42 # Unlock door in room 6 on 8F.
|
||||
- 0x43 # Unlock door in 5F.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x7F # Unlocked Temple of Time Boss Door.
|
||||
- 0xED # Got Temple of Time Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Temple of Time Compass.
|
||||
- 0xEF # Got Temple of Time Dungeon Map.
|
||||
- Open_Door_of_Time == On:
|
||||
- 0x59 # deactivate statue slot in room 1 (opens door and deactivates statue)
|
||||
- 0x80 # open big door in room 1 cs part 2
|
||||
- 0x81 # open big door in room 1 cs part 1
|
||||
- 0xBC # big door in room 1 opens
|
||||
- 0xBE # open big door in room 1 cs part 1 trigger
|
||||
- 0xBD # open big door in room 1 cs part 2 trigger
|
||||
- 0xBF # statue placed in slot in room 1
|
||||
|
||||
City in the Sky:
|
||||
Index: 0x16
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x64 # North wing main room intro CS.
|
||||
- 0x65 # East wing fan room second floor intro CS.
|
||||
- 0x66 # Went beyond first gate outside shop intro CS.
|
||||
- 0x67 # City in The Sky intro CS.
|
||||
- 0x6E # East bridge extended CS.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x59 # Unlock east bridge door.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x58 # Unlocked City in The Sky Boss Door.
|
||||
- 0xED # Got City in The Sky Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got City in The Sky Compass.
|
||||
- 0xEF # Got City in The Sky Dungeon Map.
|
||||
|
||||
Palace of Twilight:
|
||||
Index: 0x17
|
||||
Flags:
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x4D # Phantom Zant 1 CS.
|
||||
- 0x66 # Midna text when west hand steals sol.
|
||||
- 0x6F # Midna text about black fog in west room.
|
||||
- 0x70 # Midna text after finding west sol.
|
||||
- 0x72 # Midna text trigger when seeing a Twili for the first time.
|
||||
- 0x78 # Midna text when seeing a Twili for the first time.
|
||||
- 0x79 # Midna text after Light Sword cutscene.
|
||||
- 0x95 # Midna text after re-entering west wing after sol was stolen.
|
||||
- 0x9E # Midna text at dungeon entrance.
|
||||
- 0xB3 # Watched east wing second room stairs CS.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x57 # Unlock door in north room 3.
|
||||
- 0x58 # Unlock door in east room 2.
|
||||
- 0x59 # Unlock door in west room 2.
|
||||
- 0x6C # Unlock door in north room 2.
|
||||
- 0x7A # Unlock door in norht room 1.
|
||||
- 0x7B # Unlock door in east room 1.
|
||||
- 0x7C # Unlock door in west room 1.
|
||||
- Big_Keys == Keysy:
|
||||
- 0x56 # Unlocked Palace of Twilight Boss Door.
|
||||
- 0xED # Got Palace of Twilight Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Palace of Twilight Compass.
|
||||
- 0xEF # Got Palace of Twilight Dungeon Map.
|
||||
|
||||
Hyrule Castle:
|
||||
Index: 0x18
|
||||
Flags:
|
||||
- 0x4B # Watched CS with Allies in HC.
|
||||
- Skip_Minor_Cutscenes == On:
|
||||
- 0x4F # Hyrule Castle Graveyard intro CS.
|
||||
- 0x8C # East garden intro CS.
|
||||
- 0x8D # East garden intro CS trigger.
|
||||
- 0x77 # Midna text at the east end of the east garden.
|
||||
- 0x82 # South garden intro CS.
|
||||
- 0x99 # Double Darknut room intro CS
|
||||
- 0xA4 # Midna text after Owl Statue chest in graveyard.
|
||||
- 0xB7 # Lit southeast torch in second floor north room for the first time CS.
|
||||
- 0xB8 # Lit northeast torch in second floor north room for the first time CS.
|
||||
- Small_Keys == Keysy:
|
||||
- 0x93 # Unlock door outside 3F.
|
||||
- 0xB0 # Unlock treasure room door.
|
||||
- 0xA3 # Unlock door in south garden.
|
||||
- Big_Keys == Keysy and Hyrule_Castle_Big_Key_Requirements == None:
|
||||
- 0xA1 # Unlocked Hyrule Castle Boss Door.
|
||||
- 0xED # Got Hyrule Castle Big Key.
|
||||
- Maps_and_Compasses == Start_With:
|
||||
- 0xEE # Got Hyrule Castle Compass.
|
||||
- 0xEF # Got Hyrule Castle Dungeon Map.
|
||||
- Lower_Hyrule_Castle_Chandelier == On:
|
||||
- 0x6F # watched double Dinalfos cs 1
|
||||
- 0x70 # watched double Dinalfos cs 2
|
||||
- 0x85 # watched focus on lowered chandelier cs
|
||||
- 0x9D # lower the main hall chandelier
|
||||
- 0xAF # defeated double Dinalfos (opens gates both sides)
|
||||
- Hyrule_Castle_Big_Key_Requirements == None:
|
||||
- 0x94 # Open HC BK gate
|
||||
@@ -1,66 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Plandomizer: false
|
||||
Generate Spoiler Log: true
|
||||
Arbiters Does Not Require Bulblin Camp: Random
|
||||
Back Slice as Sword: Random
|
||||
Ball and Chain Webs: Random
|
||||
Big Keys: Random
|
||||
Bonks Do Damage: Random
|
||||
City Does Not Require Filled Skybook: Random
|
||||
Damage Multiplier: Random
|
||||
Dungeon Rewards Can Be Anywhere: Random
|
||||
Eldin Twilight Cleared: Random
|
||||
Faron Twilight Cleared: Random
|
||||
Faron Woods Logic: Random
|
||||
Fast Iron Boots: Random
|
||||
Gifts From NPCs: Random
|
||||
Golden Bugs: Random
|
||||
Goron Mines Entrance: Random
|
||||
Hidden Skills: Random
|
||||
Hyrule Barrier Requirements: Random
|
||||
Increase Spinner Speed: Random
|
||||
Increase Wallet Capacity: Random
|
||||
Instant Message Text: Random
|
||||
Item Scarcity: Random
|
||||
Lakebed Does Not Require Water Bombs: Random
|
||||
Lanayru Twilight Cleared: Random
|
||||
Logic Rules: Random
|
||||
Maps and Compasses: Random
|
||||
No Small Keys on Bosses: Random
|
||||
Open Door of Time: Random
|
||||
Palace of Twilight Requirements: Random
|
||||
Poe Souls: Random
|
||||
Quick Transform: Random
|
||||
Random Starting Item Count: 0
|
||||
Randomize Starting Spawn: Random
|
||||
Randomize Dungeon Entrances: Random
|
||||
Randomize Boss Entrances: Random
|
||||
Randomize Grotto Entrances: Random
|
||||
Randomize Cave Entrances: Random
|
||||
Randomize Interior Entrances: Random
|
||||
Randomize Overworld Entrances: Random
|
||||
Decouple Double Door Entrances: Random
|
||||
Decouple Entrances: Random
|
||||
Sacred Grove Does Not Require Skull Kid: Random
|
||||
Shop Items: Random
|
||||
Shops Display The Replaced Item: Random
|
||||
Skip Major Cutscenes: Random
|
||||
Skip Midna's Desparate Hour: Random
|
||||
Skip Minor Cutscenes: Random
|
||||
Skip Prologue: Random
|
||||
Sky Characters: Random
|
||||
Small Keys: Random
|
||||
Snowpeak Does Not Require Reekfish Scent: Random
|
||||
Starting Form: Random
|
||||
Starting Hearts: 3
|
||||
Starting Time of Day: Random
|
||||
Temple of Time Sword Requirement: Random
|
||||
Logic Transform Anywhere: Random
|
||||
Trap Item Frequency: Random
|
||||
Unlock Map Regions: Random
|
||||
Unrequired Dungeons Are Barren: Random
|
||||
trappable_items: major_items
|
||||
Starting Inventory:
|
||||
{}
|
||||
Excluded Locations:
|
||||
[]
|
||||
@@ -1,4 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Small Keys: Any Dungeon
|
||||
Big Keys: Any Dungeon
|
||||
Maps and Compasses: Any Dungeon
|
||||
@@ -1,4 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Small Keys: Anywhere
|
||||
Big Keys: Anywhere
|
||||
Maps and Compasses: Anywhere
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Dungeon Rewards Can Be Anywhere: On
|
||||
@@ -1,5 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Bonks Do Damage: On
|
||||
Damage Multiplier: OHKO
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Eldin Twilight Cleared: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Lanayru Twilight Cleared: On
|
||||
@@ -1 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Twilight Cleared: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Freestanding Rupees: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Gifts From NPCs: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Golden Bugs: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Hidden Rupees: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Hidden Skills: On
|
||||
@@ -1,14 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Number of Path Hints: 4
|
||||
Path Hints on Midna: Off
|
||||
Path Hints on Hint Signs: Dungeon
|
||||
Number of Barren Hints: 4
|
||||
Barren Hints on Midna: Off
|
||||
Barren Hints on Hint Signs: Dungeon
|
||||
Number of Item Hints: 4
|
||||
Item Hints on Midna: Off
|
||||
Item Hints on Hint Signs: Dungeon
|
||||
Number of Location Hints: 4
|
||||
Location Hints on Midna: Off
|
||||
Location Hints on Hint Signs: Dungeon
|
||||
Prioritize Remote Location Hints: On
|
||||
@@ -1,14 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Number of Path Hints: 0
|
||||
Path Hints on Midna: Off
|
||||
Path Hints on Hint Signs: Off
|
||||
Number of Barren Hints: 0
|
||||
Barren Hints on Midna: Off
|
||||
Barren Hints on Hint Signs: Off
|
||||
Number of Item Hints: 0
|
||||
Item Hints on Midna: Off
|
||||
Item Hints on Hint Signs: Off
|
||||
Number of Location Hints: 0
|
||||
Location Hints on Midna: Off
|
||||
Location Hints on Hint Signs: Off
|
||||
Prioritize Remote Location Hints: Off
|
||||
@@ -1,14 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Number of Path Hints: 7
|
||||
Path Hints on Midna: On
|
||||
Path Hints on Hint Signs: Any
|
||||
Number of Barren Hints: 7
|
||||
Barren Hints on Midna: On
|
||||
Barren Hints on Hint Signs: Any
|
||||
Number of Item Hints: 7
|
||||
Item Hints on Midna: On
|
||||
Item Hints on Hint Signs: Any
|
||||
Number of Location Hints: 7
|
||||
Location Hints on Midna: On
|
||||
Location Hints on Hint Signs: Any
|
||||
Prioritize Remote Location Hints: On
|
||||
@@ -1,14 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Number of Path Hints: 4
|
||||
Path Hints on Midna: Off
|
||||
Path Hints on Hint Signs: Overworld
|
||||
Number of Barren Hints: 4
|
||||
Barren Hints on Midna: Off
|
||||
Barren Hints on Hint Signs: Overworld
|
||||
Number of Item Hints: 4
|
||||
Item Hints on Midna: Off
|
||||
Item Hints on Hint Signs: Overworld
|
||||
Number of Location Hints: 4
|
||||
Location Hints on Midna: Off
|
||||
Location Hints on Hint Signs: Overworld
|
||||
Prioritize Remote Location Hints: On
|
||||
@@ -1,3 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Hyrule Barrier Requirements: Dungeons
|
||||
Hyrule Barrier Dungeons: 8
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Hyrule Barrier Requirements: Fused Shadows
|
||||
@@ -1,3 +0,0 @@
|
||||
seed: TESTTESTTEST
|
||||
Hyrule Barrier Requirements: Hearts
|
||||
Hyrule Barrier Hearts: 13
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Hyrule Barrier Requirements: Mirror Shards
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Hyrule Barrier Requirements: Open
|
||||
@@ -1,3 +0,0 @@
|
||||
seed: TESTTESTTEST
|
||||
Hyrule Barrier Requirements: Poe Souls
|
||||
Hyrule Barrier Poe Souls: 30
|
||||
@@ -1,4 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Small Keys: Keysy
|
||||
Big Keys: Keysy
|
||||
Maps and Compasses: Start With
|
||||
@@ -1,16 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
Skip Prologue: On
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Skip Midna's Desparate Hour: On
|
||||
Randomize Starting Spawn: On
|
||||
Randomize Dungeon Entrances: On
|
||||
Randomize Boss Entrances: On
|
||||
Randomize Grotto Entrances: On
|
||||
Randomize Cave Entrances: On
|
||||
Randomize Interior Entrances: On
|
||||
Randomize Overworld Entrances: On
|
||||
Decouple Double Door Entrances: On
|
||||
Decouple Entrances: On
|
||||
@@ -1,15 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
Skip Prologue: On
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Skip Midna's Desparate Hour: On
|
||||
Randomize Starting Spawn: On
|
||||
Randomize Dungeon Entrances: On
|
||||
Randomize Grotto Entrances: On
|
||||
Randomize Cave Entrances: On
|
||||
Randomize Interior Entrances: On
|
||||
Randomize Overworld Entrances: On
|
||||
Mixed Entrance Pools:
|
||||
[["Dungeon", "Grotto"], ["Overworld", "Cave", "Interior"]]
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
@@ -1,7 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Skip Prologue: On
|
||||
Faron Woods Logic: Open
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Unlock Map Regions: On
|
||||
@@ -1,4 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Small Keys: Overworld
|
||||
Big Keys: Overworld
|
||||
Maps and Compasses: Overworld
|
||||
@@ -1,4 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Small Keys: Own Dungeon
|
||||
Big Keys: Own Dungeon
|
||||
Maps and Compasses: Own Dungeon
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Palace of Twilight Requirements: Fused Shadows
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Palace of Twilight Requirements: Mirror Shards
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Palace of Twilight Requirements: Open
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Poe Souls: All
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Poe Souls: Dungeon
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Poe Souls: Overworld
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Randomize Boss Entrances: On
|
||||
@@ -1,8 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
Skip Prologue: On
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Skip Midna's Desparate Hour: On
|
||||
Randomize Cave Entrances: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Randomize Dungeon Entrances: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Randomize Grotto Entrances: On
|
||||
@@ -1,8 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
Skip Prologue: On
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Skip Midna's Desparate Hour: On
|
||||
Randomize Interior Entrances: On
|
||||
@@ -1,8 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
Skip Prologue: On
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Skip Midna's Desparate Hour: On
|
||||
Randomize Overworld Entrances: On
|
||||
@@ -1,8 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Faron Woods Logic: Open
|
||||
Skip Prologue: On
|
||||
Faron Twilight Cleared: On
|
||||
Eldin Twilight Cleared: On
|
||||
Lanayru Twilight Cleared: On
|
||||
Skip Midna's Desparate Hour: On
|
||||
Randomize Starting Spawn: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Item Scarcity: Minimal
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Item Scarcity: Plentiful
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Shop Items: On
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Lakebed Does Not Require Water Bombs: On
|
||||
Arbiters Does Not Require Bulblin Camp: On
|
||||
Snowpeak Does Not Require Reekfish Scent: On
|
||||
Sacred Grove Does Not Require Skull Kid: On
|
||||
City Does Not Require Filled Skybook: On
|
||||
Goron Mines Entrance: On
|
||||
Temple of Time Sword Requirement: None
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Skip Midna's Desparate Hour: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Skip Prologue: On
|
||||
@@ -1,2 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Sky Characters: On
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Unrequired Dungeons Are Barren: On
|
||||
Hyrule Barrier Requirements: Mirror Shards
|
||||
@@ -1,4 +0,0 @@
|
||||
Seed: TESTTESTTEST
|
||||
Starting Form: Wolf
|
||||
Skip Prologue: On
|
||||
Faron Woods Logic: Open
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user