Skip to content

Commit

Permalink
Add persistent bunny mask enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
garrettjoecox committed May 31, 2024
1 parent e484e0b commit 5c24459
Show file tree
Hide file tree
Showing 13 changed files with 299 additions and 30 deletions.
5 changes: 5 additions & 0 deletions mm/2s2h/BenGui/BenMenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,11 @@ void DrawEnhancementsMenu() {
UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere",
{ .tooltip = "Allow using Fierce Deity's mask outside of boss rooms." });
UIWidgets::CVarCheckbox("No Blast Mask Cooldown", "gEnhancements.Masks.NoBlastMaskCooldown", {});
if (UIWidgets::CVarCheckbox("Persistent Bunny Hood", "gEnhancements.Masks.PersistentBunnyHood.Enabled",
{ .tooltip = "Permanantly toggle a speed boost from the bunny hood by pressing "
"'A' on it in the mask menu." })) {
UpdatePersistentMasksState();
}

ImGui::EndMenu();
}
Expand Down
1 change: 1 addition & 0 deletions mm/2s2h/Enhancements/Enhancements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void InitEnhancements() {
RegisterFastTransformation();
RegisterFierceDeityAnywhere();
RegisterNoBlastMaskCooldown();
RegisterPersistentMasks();

// Minigames
RegisterAlwaysWinDoggyRace();
Expand Down
1 change: 1 addition & 0 deletions mm/2s2h/Enhancements/Enhancements.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Masks/FierceDeityAnywhere.h"
#include "Masks/NoBlastMaskCooldown.h"
#include "Masks/FastTransformation.h"
#include "Masks/PersistentMasks.h"
#include "Minigames/AlwaysWinDoggyRace.h"
#include "Cutscenes/Cutscenes.h"
#include "Restorations/FlipHopVariable.h"
Expand Down
17 changes: 17 additions & 0 deletions mm/2s2h/Enhancements/GameInteractor/GameInteractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ void GameInteractor_ExecuteOnGameStateUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnGameStateUpdate>();
}

void GameInteractor_ExecuteBeforeKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::BeforeKaleidoDrawPage>(pauseCtx, pauseIndex);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::BeforeKaleidoDrawPage>(pauseIndex, pauseCtx,
pauseIndex);
}

void GameInteractor_ExecuteAfterKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::AfterKaleidoDrawPage>(pauseCtx, pauseIndex);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::AfterKaleidoDrawPage>(pauseIndex, pauseCtx, pauseIndex);
}

void GameInteractor_ExecuteOnSaveInit(s16 fileNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSaveInit>(fileNum);
}
Expand Down Expand Up @@ -104,6 +115,12 @@ void GameInteractor_ExecuteOnActorKill(Actor* actor) {
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnActorKill>(actor);
}

void GameInteractor_ExecuteOnPlayerPostLimbDraw(Player* player, s32 limbIndex) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerPostLimbDraw>(player, limbIndex);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnPlayerPostLimbDraw>(limbIndex, player, limbIndex);
GameInteractor::Instance->ExecuteHooksForFilter<GameInteractor::OnPlayerPostLimbDraw>(player, limbIndex);
}

void GameInteractor_ExecuteOnSceneFlagSet(s16 sceneId, FlagType flagType, u32 flag) {
SPDLOG_DEBUG("OnSceneFlagSet: sceneId: {}, flagType: {}, flag: {}", sceneId, (u32)flagType, flag);
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneFlagSet>(sceneId, flagType, flag);
Expand Down
17 changes: 13 additions & 4 deletions mm/2s2h/Enhancements/GameInteractor/GameInteractor.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
#ifdef __cplusplus
#include <string>
extern "C" {
#endif
#include "z64actor.h"
#include "z64camera.h"
#ifdef __cplusplus
#include "z64.h"
}
#endif

Expand Down Expand Up @@ -46,6 +43,12 @@ typedef enum {
GI_VB_SONG_AVAILABLE_TO_PLAY,
GI_VB_USE_CUSTOM_CAMERA,
GI_VB_DELETE_OWL_SAVE,
GI_VB_CONSIDER_BUNNY_HOOD_EQUIPPED,
GI_VB_USE_ITEM_EQUIP_MASK,
GI_VB_KALEIDO_DISPLAY_ITEM_TEXT,
GI_VB_USE_ITEM_CONSIDER_LINK_HUMAN,
GI_VB_DRAW_ITEM_EQUIPPED_OUTLINE,

GI_VB_PLAY_TRANSITION_CS,
GI_VB_TATL_INTERUPT_MSG3,
GI_VB_TATL_INTERUPT_MSG6,
Expand Down Expand Up @@ -248,6 +251,8 @@ class GameInteractor {
DEFINE_HOOK(OnGameStateMainFinish, ());
DEFINE_HOOK(OnGameStateDrawFinish, ());
DEFINE_HOOK(OnGameStateUpdate, ());
DEFINE_HOOK(BeforeKaleidoDrawPage, (PauseContext * pauseCtx, u16 pauseIndex));
DEFINE_HOOK(AfterKaleidoDrawPage, (PauseContext * pauseCtx, u16 pauseIndex));
DEFINE_HOOK(OnSaveInit, (s16 fileNum));
DEFINE_HOOK(BeforeEndOfCycleSave, ());
DEFINE_HOOK(AfterEndOfCycleSave, ());
Expand All @@ -263,6 +268,7 @@ class GameInteractor {
DEFINE_HOOK(ShouldActorDraw, (Actor * actor, bool* should));
DEFINE_HOOK(OnActorDraw, (Actor * actor));
DEFINE_HOOK(OnActorKill, (Actor * actor));
DEFINE_HOOK(OnPlayerPostLimbDraw, (Player * player, s32 limbIndex));

DEFINE_HOOK(OnSceneFlagSet, (s16 sceneId, FlagType flagType, u32 flag));
DEFINE_HOOK(OnSceneFlagUnset, (s16 sceneId, FlagType flagType, u32 flag));
Expand All @@ -289,6 +295,8 @@ extern "C" {
void GameInteractor_ExecuteOnGameStateMainFinish();
void GameInteractor_ExecuteOnGameStateDrawFinish();
void GameInteractor_ExecuteOnGameStateUpdate();
void GameInteractor_ExecuteBeforeKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex);
void GameInteractor_ExecuteAfterKaleidoDrawPage(PauseContext* pauseCtx, u16 pauseIndex);
void GameInteractor_ExecuteOnSaveInit(s16 fileNum);
void GameInteractor_ExecuteBeforeEndOfCycleSave();
void GameInteractor_ExecuteAfterEndOfCycleSave();
Expand All @@ -304,6 +312,7 @@ void GameInteractor_ExecuteOnActorUpdate(Actor* actor);
bool GameInteractor_ShouldActorDraw(Actor* actor);
void GameInteractor_ExecuteOnActorDraw(Actor* actor);
void GameInteractor_ExecuteOnActorKill(Actor* actor);
void GameInteractor_ExecuteOnPlayerPostLimbDraw(Player* player, s32 limbIndex);

void GameInteractor_ExecuteOnSceneFlagSet(s16 sceneId, FlagType flagType, u32 flag);
void GameInteractor_ExecuteOnSceneFlagUnset(s16 sceneId, FlagType flagType, u32 flag);
Expand Down
195 changes: 195 additions & 0 deletions mm/2s2h/Enhancements/Masks/PersistentMasks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#include <libultraship/bridge.h>
#include <spdlog/spdlog.h>
#include "Enhancements/GameInteractor/GameInteractor.h"
#include "Enhancements/FrameInterpolation/FrameInterpolation.h"

extern "C" {
#include "z64.h"
#include "z64player.h"
#include "functions.h"
#include "macros.h"
#include "gfx.h"
#include "src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
#include "assets/interface/parameter_static/parameter_static.h"

void func_8082E1F0(Player* player, u16 sfxId);
void Player_DrawBunnyHood(PlayState* play);
extern PlayState* gPlayState;
extern const char* D_801C0B20[28];
extern SaveContext gSaveContext;
}

static Vtx* persistantMasksVtx = {};

void UpdatePersistentMasksState() {
static HOOK_ID beforePageDrawHook = 0;
static HOOK_ID onPlayerPostLimbDrawHook = 0;
GameInteractor::Instance->UnregisterGameHook<GameInteractor::BeforeKaleidoDrawPage>(beforePageDrawHook);
GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::OnPlayerPostLimbDraw>(onPlayerPostLimbDrawHook);

if (!CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) {
CVarClear("gEnhancements.Masks.PersistentBunnyHood.State");
return;
}

// If the mask is equipped, unequip it
if (gSaveContext.save.equippedMask == PLAYER_MASK_BUNNY) {
gSaveContext.save.equippedMask = PLAYER_MASK_NONE;
CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 1);

if (gPlayState != NULL) {
Player* player = GET_PLAYER(gPlayState);
player->prevMask = player->currentMask;
player->currentMask = PLAYER_MASK_NONE;
}
}

// If they don't have the mask, clear the state
if (INV_CONTENT(ITEM_MASK_BUNNY) != ITEM_MASK_BUNNY) {
CVarClear("gEnhancements.Masks.PersistentBunnyHood.State");
}

onPlayerPostLimbDrawHook = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnPlayerPostLimbDraw>(
PLAYER_LIMB_HEAD, [](Player* player, s32 limbIndex) {
// Ensure they aren't in first person
if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0) && !(player->stateFlags1 & PLAYER_STATE1_100000)) {
OPEN_DISPS(gPlayState->state.gfxCtx);
Matrix_Push();
Player_DrawBunnyHood(gPlayState);
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)D_801C0B20[PLAYER_MASK_BUNNY - 1]);
Matrix_Pop();
CLOSE_DISPS(gPlayState->state.gfxCtx);
}
});

beforePageDrawHook = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::BeforeKaleidoDrawPage>(
PAUSE_MASK, [](PauseContext* _, u16 __) {
GraphicsContext* gfxCtx = gPlayState->state.gfxCtx;
PauseContext* pauseCtx = &gPlayState->pauseCtx;
s16 i = 0;
s16 j = 0;
s16 k;

OPEN_DISPS(gfxCtx);

persistantMasksVtx = (Vtx*)GRAPH_ALLOC(gfxCtx, (4 * 4) * sizeof(Vtx));

if ((pauseCtx->state == PAUSE_STATE_MAIN)) {
s16 slot = SLOT_MASK_BUNNY - ITEM_NUM_SLOTS;
s16 slotX = slot % MASK_GRID_COLS;
s16 slotY = slot / MASK_GRID_COLS;
s16 initialX = 0 - (MASK_GRID_COLS * MASK_GRID_CELL_WIDTH) / 2;
s16 initialY = (MASK_GRID_ROWS * MASK_GRID_CELL_HEIGHT) / 2 - 6;
s16 vtxX = (initialX + (slotX * MASK_GRID_CELL_WIDTH)) + MASK_GRID_QUAD_MARGIN;
s16 vtxY = (initialY - (slotY * MASK_GRID_CELL_HEIGHT)) + pauseCtx->offsetY - MASK_GRID_QUAD_MARGIN;
persistantMasksVtx[i + 0].v.ob[0] = persistantMasksVtx[i + 2].v.ob[0] =
vtxX + MASK_GRID_SELECTED_QUAD_MARGIN;
persistantMasksVtx[i + 1].v.ob[0] = persistantMasksVtx[i + 3].v.ob[0] =
persistantMasksVtx[i + 0].v.ob[0] + MASK_GRID_SELECTED_QUAD_WIDTH;
persistantMasksVtx[i + 0].v.ob[1] = persistantMasksVtx[i + 1].v.ob[1] =
vtxY - MASK_GRID_SELECTED_QUAD_MARGIN;

persistantMasksVtx[i + 2].v.ob[1] = persistantMasksVtx[i + 3].v.ob[1] =
persistantMasksVtx[i + 0].v.ob[1] - MASK_GRID_SELECTED_QUAD_HEIGHT;

persistantMasksVtx[i + 0].v.ob[2] = persistantMasksVtx[i + 1].v.ob[2] =
persistantMasksVtx[i + 2].v.ob[2] = persistantMasksVtx[i + 3].v.ob[2] = 0;

persistantMasksVtx[i + 0].v.flag = persistantMasksVtx[i + 1].v.flag = persistantMasksVtx[i + 2].v.flag =
persistantMasksVtx[i + 3].v.flag = 0;

persistantMasksVtx[i + 0].v.tc[0] = persistantMasksVtx[i + 0].v.tc[1] =
persistantMasksVtx[i + 1].v.tc[1] = persistantMasksVtx[i + 2].v.tc[0] = 0;

persistantMasksVtx[i + 1].v.tc[0] = persistantMasksVtx[i + 2].v.tc[1] =
persistantMasksVtx[i + 3].v.tc[0] = persistantMasksVtx[i + 3].v.tc[1] =
MASK_GRID_SELECTED_QUAD_TEX_SIZE * (1 << 5);

persistantMasksVtx[i + 0].v.cn[0] = persistantMasksVtx[i + 1].v.cn[0] =
persistantMasksVtx[i + 2].v.cn[0] = persistantMasksVtx[i + 3].v.cn[0] =
persistantMasksVtx[i + 0].v.cn[1] = persistantMasksVtx[i + 1].v.cn[1] =
persistantMasksVtx[i + 2].v.cn[1] = persistantMasksVtx[i + 3].v.cn[1] =
persistantMasksVtx[i + 0].v.cn[2] = persistantMasksVtx[i + 1].v.cn[2] =
persistantMasksVtx[i + 2].v.cn[2] = persistantMasksVtx[i + 3].v.cn[2] = 255;

persistantMasksVtx[i + 0].v.cn[3] = persistantMasksVtx[i + 1].v.cn[3] =
persistantMasksVtx[i + 2].v.cn[3] = persistantMasksVtx[i + 3].v.cn[3] = pauseCtx->alpha;

if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 200, 255, 255);
gSPVertex(POLY_OPA_DISP++, (uintptr_t)&persistantMasksVtx[0], 4, 0);
POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, (TexturePtr)gEquippedItemOutlineTex, 32, 32, 0);
}
}

CLOSE_DISPS(gfxCtx);
});
}

void RegisterPersistentMasks() {
UpdatePersistentMasksState();

GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSceneInit>(
[](s8 sceneId, s8 spawnNum) { UpdatePersistentMasksState(); });

REGISTER_VB_SHOULD(GI_VB_CONSIDER_BUNNY_HOOD_EQUIPPED, {
if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) {
*should = true;
}
});

REGISTER_VB_SHOULD(GI_VB_USE_ITEM_CONSIDER_LINK_HUMAN, {
if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0) &&
*(PlayerItemAction*)opt == PLAYER_IA_MASK_BUNNY) {
*should = true;
}
});

REGISTER_VB_SHOULD(GI_VB_USE_ITEM_EQUIP_MASK, {
PlayerMask* maskId = (PlayerMask*)opt;
Player* player = GET_PLAYER(gPlayState);

if (*maskId == PLAYER_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) {
*should = false;

CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State",
!CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0));
if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) {
func_8082E1F0(player, NA_SE_PL_CHANGE_ARMS);
} else {
func_8082E1F0(player, NA_SE_PL_TAKE_OUT_SHIELD);
}
}
});

REGISTER_VB_SHOULD(GI_VB_DRAW_ITEM_EQUIPPED_OUTLINE, {
if (*(ItemId*)opt == ITEM_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) {
*should = false;
}
});

REGISTER_VB_SHOULD(GI_VB_ITEM_BE_RESTRICTED, {
if (*(ItemId*)opt == ITEM_MASK_BUNNY && CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0)) {
*should = false;
}
});

REGISTER_VB_SHOULD(GI_VB_KALEIDO_DISPLAY_ITEM_TEXT, {
ItemId* itemId = (ItemId*)opt;
if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.Enabled", 0) && *itemId == ITEM_MASK_BUNNY) {
*should = false;
CVarSetInteger("gEnhancements.Masks.PersistentBunnyHood.State",
!CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0));
if (CVarGetInteger("gEnhancements.Masks.PersistentBunnyHood.State", 0)) {
Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_DOWN);
} else {
Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_UP);
}
} else if (CVarGetInteger("gEnhancements.Masks.PersistentGreatFairyMask.Enabled", 0) &&
*itemId == ITEM_MASK_GREAT_FAIRY) {
*should = false;
CVarSetInteger("gEnhancements.Masks.PersistentGreatFairyMask.State",
!CVarGetInteger("gEnhancements.Masks.PersistentGreatFairyMask.State", 0));
}
});
}
7 changes: 7 additions & 0 deletions mm/2s2h/Enhancements/Masks/PersistentMasks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef MASKS_PERSISTENT_MASKS_H
#define MASKS_PERSISTENT_MASKS_H

void RegisterPersistentMasks();
void UpdatePersistentMasksState();

#endif // MASKS_PERSISTENT_MASKS_H
8 changes: 8 additions & 0 deletions mm/include/gfxprint.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef GFXPRINT_H
#define GFXPRINT_H

#ifdef __cplusplus
#define this thisx
#endif

#include "color.h"
#include "PR/gbi.h"
#include "PR/ultratypes.h"
Expand Down Expand Up @@ -61,4 +65,8 @@ s32 GfxPrint_Printf(GfxPrint* this, const char* fmt, ...);
(void)0
// #endregion

#ifdef __cplusplus
#undef this
#endif

#endif
2 changes: 0 additions & 2 deletions mm/include/z64.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#define Z64_H
#ifdef __cplusplus
extern "C" {
#define this thisx
#endif
#include "libc/math.h"
#include "libc/stdarg.h"
Expand Down Expand Up @@ -308,6 +307,5 @@ typedef enum {
//
#ifdef __cplusplus
}
#undef this
#endif
#endif
3 changes: 3 additions & 0 deletions mm/src/code/z_player_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

// Assets for other actors
#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h"
#include "2s2h/Enhancements/GameInteractor/GameInteractor.h"

void PlayerCall_Init(Actor* thisx, PlayState* play);
void PlayerCall_Destroy(Actor* thisx, PlayState* play);
Expand Down Expand Up @@ -4020,5 +4021,7 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList1, G
Player_SetFeetPos(play, player, limbIndex);
}

GameInteractor_ExecuteOnPlayerPostLimbDraw(player, limbIndex);

func_8012536C();
}
Loading

0 comments on commit 5c24459

Please sign in to comment.