diff --git a/mm/2s2h/BenGui/BenMenuBar.cpp b/mm/2s2h/BenGui/BenMenuBar.cpp index 0c4daed28..c6dc851c9 100644 --- a/mm/2s2h/BenGui/BenMenuBar.cpp +++ b/mm/2s2h/BenGui/BenMenuBar.cpp @@ -8,6 +8,7 @@ #include #include "2s2h/Enhancements/Enhancements.h" #include "2s2h/Enhancements/Graphics/MotionBlur.h" +#include "2s2h/Enhancements/Graphics/PlayAsKafei.h" #include "2s2h/DeveloperTools/DeveloperTools.h" #include "2s2h/DeveloperTools/WarpPoint.h" #include "HudEditor.h" @@ -359,6 +360,15 @@ void DrawEnhancementsMenu() { ImGui::EndMenu(); } + if (UIWidgets::BeginMenu("Modes")) { + if (UIWidgets::CVarCheckbox("Play As Kafei", "gModes.PlayAsKafei", { + .tooltip = "Requires scene reload to take effect." + })) { + UpdatePlayAsKafeiSkeletons(); + } + ImGui::EndMenu(); + } + if (mHudEditorWindow) { UIWidgets::WindowButton("Hud Editor", "gWindows.HudEditor", mHudEditorWindow, { .tooltip = "Enables the Hud Editor window, allowing you to edit your hud" diff --git a/mm/2s2h/Enhancements/Enhancements.cpp b/mm/2s2h/Enhancements/Enhancements.cpp index 44de70c9a..fac376a60 100644 --- a/mm/2s2h/Enhancements/Enhancements.cpp +++ b/mm/2s2h/Enhancements/Enhancements.cpp @@ -18,5 +18,8 @@ void InitEnhancements() { // Cutscenes RegisterSkipEntranceCutscenes(); RegisterHideTitleCards(); + + // Modes + RegisterPlayAsKafei(); } diff --git a/mm/2s2h/Enhancements/Enhancements.h b/mm/2s2h/Enhancements/Enhancements.h index 5da214300..59668ae89 100644 --- a/mm/2s2h/Enhancements/Enhancements.h +++ b/mm/2s2h/Enhancements/Enhancements.h @@ -9,6 +9,7 @@ #include "Cutscenes/SkipEntranceCutscenes.h" #include "Cutscenes/HideTitleCards.h" #include "Restorations/SideRoll.h" +#include "Graphics/PlayAsKafei.h" #ifdef __cplusplus extern "C" { diff --git a/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp b/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp new file mode 100644 index 000000000..f16c6d09e --- /dev/null +++ b/mm/2s2h/Enhancements/Graphics/PlayAsKafei.cpp @@ -0,0 +1,86 @@ +#include "PlayAsKafei.h" +#include "libultraship/libultraship.h" +#include "2s2h/Enhancements/GameInteractor/GameInteractor.h" + +extern "C" { +#include "z64.h" +#include "functions.h" +extern PlayState* gPlayState; +#include "objects/object_link_child/object_link_child.h" +#include "objects/object_test3/object_test3.h" +void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); +void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); +extern TexturePtr sPlayerEyesTextures[PLAYER_FORM_MAX][PLAYER_EYES_MAX]; +extern TexturePtr sPlayerMouthTextures[PLAYER_FORM_MAX][PLAYER_MOUTH_MAX]; +} + +static SkeletonHeader gLinkHumanSkelBackup; +static SkeletonHeader gKafeiSkelBackup; + +void UpdatePlayAsKafeiSkeletons() { + if (CVarGetInteger("gModes.PlayAsKafei", 0)) { + auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); + SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); + memcpy(gLinkHumanSkelPtr, &gKafeiSkelBackup, sizeof(SkeletonHeader)); + } else { + auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); + SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); + memcpy(gLinkHumanSkelPtr, &gLinkHumanSkelBackup, sizeof(SkeletonHeader)); + } +} + +void UpdatePlayAsKafeiOther() { + if (CVarGetInteger("gModes.PlayAsKafei", 0)) { + ResourceMgr_PatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL0", 0, gsSPDisplayListOTRFilePath(gKafeiWaistDL)); + ResourceMgr_PatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL1", 1, gsSPEndDisplayList()); + + sPlayerEyesTextures[PLAYER_FORM_HUMAN][0] = (TexturePtr)gKafeiEyesOpenTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][1] = (TexturePtr)gKafeiEyesHalfTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][2] = (TexturePtr)gKafeiEyesClosedTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][3] = (TexturePtr)gKafeiEyesRollRightTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][4] = (TexturePtr)gKafeiEyesRollLeftTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][5] = (TexturePtr)gKafeiEyesRollUpTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][6] = (TexturePtr)gKafeiEyesRollDownTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][7] = (TexturePtr)object_test3_Tex_006680; + + sPlayerMouthTextures[PLAYER_FORM_HUMAN][0] = (TexturePtr)gKafeiMouthClosedTex; + sPlayerMouthTextures[PLAYER_FORM_HUMAN][1] = (TexturePtr)gKafeiMouthTeethTex; + sPlayerMouthTextures[PLAYER_FORM_HUMAN][2] = (TexturePtr)gKafeiMouthAngryTex; + sPlayerMouthTextures[PLAYER_FORM_HUMAN][3] = (TexturePtr)gKafeiMouthHappyTex; + } else { + ResourceMgr_UnpatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL0"); + ResourceMgr_UnpatchGfxByName(gLinkHumanWaistDL, "gLinkHumanWaistDL1"); + + sPlayerEyesTextures[PLAYER_FORM_HUMAN][0] = (TexturePtr)gLinkHumanEyesOpenTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][1] = (TexturePtr)gLinkHumanEyesHalfTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][2] = (TexturePtr)gLinkHumanEyesClosedTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][3] = (TexturePtr)gLinkHumanEyesRollRightTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][4] = (TexturePtr)gLinkHumanEyesRollLeftTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][5] = (TexturePtr)gLinkHumanEyesRollUpTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][6] = (TexturePtr)gLinkHumanEyesRollDownTex; + sPlayerEyesTextures[PLAYER_FORM_HUMAN][7] = (TexturePtr)object_link_child_Tex_003800; + + sPlayerMouthTextures[PLAYER_FORM_HUMAN][0] = (TexturePtr)gLinkHumanMouthClosedTex; + sPlayerMouthTextures[PLAYER_FORM_HUMAN][1] = (TexturePtr)gLinkHumanMouthTeethTex; + sPlayerMouthTextures[PLAYER_FORM_HUMAN][2] = (TexturePtr)gLinkHumanMouthAngryTex; + sPlayerMouthTextures[PLAYER_FORM_HUMAN][3] = (TexturePtr)gLinkHumanMouthHappyTex; + } +} + +void RegisterPlayAsKafei() { + auto gLinkHumanSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gLinkHumanSkel); + auto gKafeiSkelResource = Ship::Context::GetInstance()->GetResourceManager()->LoadResource(gKafeiSkel); + + SkeletonHeader* gLinkHumanSkelPtr = (SkeletonHeader*)gLinkHumanSkelResource->GetRawPointer(); + SkeletonHeader* gKafeiSkelPtr = (SkeletonHeader*)gKafeiSkelResource->GetRawPointer(); + + memcpy(&gLinkHumanSkelBackup, gLinkHumanSkelPtr, sizeof(SkeletonHeader)); + memcpy(&gKafeiSkelBackup, gKafeiSkelPtr, sizeof(SkeletonHeader)); + + UpdatePlayAsKafeiSkeletons(); + UpdatePlayAsKafeiOther(); + + GameInteractor::Instance->RegisterGameHook([] (s8 sceneId, s8 spawnNum) { + UpdatePlayAsKafeiOther(); + }); +} diff --git a/mm/2s2h/Enhancements/Graphics/PlayAsKafei.h b/mm/2s2h/Enhancements/Graphics/PlayAsKafei.h new file mode 100644 index 000000000..0a6cd18e0 --- /dev/null +++ b/mm/2s2h/Enhancements/Graphics/PlayAsKafei.h @@ -0,0 +1,8 @@ +#ifndef GRAPHICS_PLAY_AS_KAFEI_H +#define GRAPHICS_PLAY_AS_KAFEI_H + +void RegisterPlayAsKafei(); +void UpdatePlayAsKafeiSkeletons(); +void UpdatePlayAsKafeiOther(); + +#endif // GRAPHICS_PLAY_AS_KAFEI_H