summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEblo <7004497+Eblo@users.noreply.github.com>2025-10-15 12:37:00 -0400
committerGitHub <noreply@github.com>2025-10-15 12:37:00 -0400
commitedb8cda56dc27caffac92c69e76dabe3a3728ea0 (patch)
treee7a74bfbf7f36754f63501ba857a2beeb83df24c
parent4569ead1ac673165b378fb65ba2cc17ccd46bd37 (diff)
Mask disable adjustments (#1268)
-rw-r--r--mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp20
-rw-r--r--mm/2s2h/Enhancements/Player/UnderwaterOcarina.cpp8
-rw-r--r--mm/2s2h/GameInteractor/GameInteractor.h3
-rw-r--r--mm/2s2h/Rando/ActorBehavior/Souls.cpp13
-rw-r--r--mm/src/code/z_parameter.c18
-rw-r--r--mm/src/overlays/actors/ovl_player_actor/z_player.c2
6 files changed, 49 insertions, 15 deletions
diff --git a/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp b/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp
index ba208b5ec..ac586ea0d 100644
--- a/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp
+++ b/mm/2s2h/Enhancements/Masks/FierceDeityAnywhere.cpp
@@ -206,6 +206,26 @@ void RegisterFierceDeityAnywhere() {
*should = true;
}
});
+
+ /*
+ * Allow the FD Mask to be usable in water. This requires two pieces: using VB_DISABLE_ITEM_UNDERWATER to make the
+ * assigned button itself enabled and using VB_USE_ITEM_CONSIDER_ITEM_ACTION to ensure the item action can be
+ * completed in water. This is how, normally, Zora Mask is the only usable item in water.
+ */
+ COND_VB_SHOULD(VB_USE_ITEM_CONSIDER_ITEM_ACTION, CVAR, {
+ PlayerItemAction itemAction = *va_arg(args, PlayerItemAction*);
+ if (itemAction == PLAYER_IA_MASK_FIERCE_DEITY) {
+ *should = true;
+ }
+ });
+
+ COND_VB_SHOULD(VB_DISABLE_ITEM_UNDERWATER, CVAR, {
+ s32 item = va_arg(args, s32);
+ if (item == ITEM_MASK_FIERCE_DEITY &&
+ Player_GetEnvironmentalHazard(gPlayState) > PLAYER_ENV_HAZARD_UNDERWATER_FLOOR) {
+ *should = false;
+ }
+ });
}
static RegisterShipInitFunc initFunc(RegisterFierceDeityAnywhere, { CVAR_NAME });
diff --git a/mm/2s2h/Enhancements/Player/UnderwaterOcarina.cpp b/mm/2s2h/Enhancements/Player/UnderwaterOcarina.cpp
index b6ff81fdc..9475e0ce3 100644
--- a/mm/2s2h/Enhancements/Player/UnderwaterOcarina.cpp
+++ b/mm/2s2h/Enhancements/Player/UnderwaterOcarina.cpp
@@ -3,16 +3,18 @@
#include "2s2h/ShipInit.hpp"
extern "C" {
-#include "z64item.h"
+#include "variables.h"
+#include "functions.h"
}
#define CVAR_NAME "gEnhancements.Player.UnderwaterOcarina"
#define CVAR CVarGetInteger(CVAR_NAME, 0)
void RegisterUnderwaterOcarina() {
- COND_VB_SHOULD(VB_DISABLE_ITEM_UNDERWATER_FLOOR, CVAR, {
+ COND_VB_SHOULD(VB_DISABLE_ITEM_UNDERWATER, CVAR, {
const auto item = va_arg(args, s32);
- if (item == ITEM_OCARINA_OF_TIME) {
+ if (item == ITEM_OCARINA_OF_TIME &&
+ Player_GetEnvironmentalHazard(gPlayState) == PLAYER_ENV_HAZARD_UNDERWATER_FLOOR) {
*should = false;
}
});
diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h
index 83729fa6c..9bc8a868d 100644
--- a/mm/2s2h/GameInteractor/GameInteractor.h
+++ b/mm/2s2h/GameInteractor/GameInteractor.h
@@ -247,12 +247,13 @@ typedef enum {
VB_BE_NEAR_DOOR,
VB_LOAD_PLAYER_ANIMATION_FRAME,
VB_PLAY_SCENE_SEQUENCE,
- VB_DISABLE_ITEM_UNDERWATER_FLOOR,
+ VB_DISABLE_ITEM_UNDERWATER,
VB_PLAY_SLOW_CHEST_CS,
VB_BE_CLIMBABLE_SURFACE,
VB_PLAYER_CUTSCENE_ACTION,
VB_SET_CAMERA_AT_EYE,
VB_SET_CAMERA_FOV,
+ VB_USE_ITEM_CONSIDER_ITEM_ACTION,
} GIVanillaBehavior;
typedef enum {
diff --git a/mm/2s2h/Rando/ActorBehavior/Souls.cpp b/mm/2s2h/Rando/ActorBehavior/Souls.cpp
index 156193b0d..ff2604bd1 100644
--- a/mm/2s2h/Rando/ActorBehavior/Souls.cpp
+++ b/mm/2s2h/Rando/ActorBehavior/Souls.cpp
@@ -69,4 +69,17 @@ void Rando::ActorBehavior::InitSoulsBehavior() {
COND_ID_HOOK(ShouldActorUpdate, ACTOR_BOSS_02, shouldRegister, [](Actor* actor, bool* should) {
ShouldActorUpdate(actor, should, RANDO_INF_OBTAINED_SOUL_OF_TWINMOLD);
});
+
+ /*
+ * Giant's Mask functionality is handled by two pieces. The scene (Twinmold's Lair) determines whether the mask can
+ * be used, while the Twinmold actor itself handles the transformation. Boss Souls prevent Twinmold from updating
+ * unless its soul has been obtained, which results in a softlock. In this case, disable the item.
+ */
+ COND_VB_SHOULD(VB_ITEM_BE_RESTRICTED, shouldRegister, {
+ ItemId itemId = *va_arg(args, ItemId*);
+ if (itemId == ITEM_MASK_GIANT && gPlayState->sceneId == SCENE_INISIE_BS &&
+ !Flags_GetRandoInf(RANDO_INF_OBTAINED_SOUL_OF_TWINMOLD)) {
+ *should = true;
+ }
+ });
}
diff --git a/mm/src/code/z_parameter.c b/mm/src/code/z_parameter.c
index ffc4f824d..5c409fd46 100644
--- a/mm/src/code/z_parameter.c
+++ b/mm/src/code/z_parameter.c
@@ -3154,12 +3154,11 @@ void Interface_UpdateButtonsPart2(PlayState* play) {
}
for (i = EQUIP_SLOT_C_LEFT; i <= EQUIP_SLOT_C_RIGHT; i++) {
- if (GET_CUR_FORM_BTN_ITEM(i) != ITEM_MASK_ZORA) {
+ if (GameInteractor_Should(VB_DISABLE_ITEM_UNDERWATER, GET_CUR_FORM_BTN_ITEM(i) != ITEM_MASK_ZORA,
+ (s32)GET_CUR_FORM_BTN_ITEM(i))) {
if (Player_GetEnvironmentalHazard(play) == PLAYER_ENV_HAZARD_UNDERWATER_FLOOR) {
- if (GameInteractor_Should(VB_DISABLE_ITEM_UNDERWATER_FLOOR,
- !((GET_CUR_FORM_BTN_ITEM(i) >= ITEM_BOTTLE) &&
- (GET_CUR_FORM_BTN_ITEM(i) <= ITEM_OBABA_DRINK)),
- (s32)GET_CUR_FORM_BTN_ITEM(i))) {
+ if (!((GET_CUR_FORM_BTN_ITEM(i) >= ITEM_BOTTLE) &&
+ (GET_CUR_FORM_BTN_ITEM(i) <= ITEM_OBABA_DRINK))) {
if (gSaveContext.buttonStatus[i] == BTN_ENABLED) {
restoreHudVisibility = true;
}
@@ -3183,12 +3182,11 @@ void Interface_UpdateButtonsPart2(PlayState* play) {
}
// #region 2S2H [Dpad]
for (s16 j = EQUIP_SLOT_D_RIGHT; j <= EQUIP_SLOT_D_UP; j++) {
- if (DPAD_GET_CUR_FORM_BTN_ITEM(j) != ITEM_MASK_ZORA) {
+ if (GameInteractor_Should(VB_DISABLE_ITEM_UNDERWATER, DPAD_GET_CUR_FORM_BTN_ITEM(j) != ITEM_MASK_ZORA,
+ (s32)DPAD_GET_CUR_FORM_BTN_ITEM(j))) {
if (Player_GetEnvironmentalHazard(play) == PLAYER_ENV_HAZARD_UNDERWATER_FLOOR) {
- if (GameInteractor_Should(VB_DISABLE_ITEM_UNDERWATER_FLOOR,
- !((DPAD_GET_CUR_FORM_BTN_ITEM(j) >= ITEM_BOTTLE) &&
- (DPAD_GET_CUR_FORM_BTN_ITEM(j) <= ITEM_OBABA_DRINK)),
- (s32)DPAD_GET_CUR_FORM_BTN_ITEM(j))) {
+ if (!((DPAD_GET_CUR_FORM_BTN_ITEM(j) >= ITEM_BOTTLE) &&
+ (DPAD_GET_CUR_FORM_BTN_ITEM(j) <= ITEM_OBABA_DRINK))) {
if (gSaveContext.shipSaveContext.dpad.status[j] == BTN_ENABLED) {
restoreHudVisibility = true;
}
diff --git a/mm/src/overlays/actors/ovl_player_actor/z_player.c b/mm/src/overlays/actors/ovl_player_actor/z_player.c
index d4b1c832f..966115951 100644
--- a/mm/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/mm/src/overlays/actors/ovl_player_actor/z_player.c
@@ -4629,7 +4629,7 @@ void Player_UseItem(PlayState* play, Player* this, ItemId item) {
((this->itemAction <= PLAYER_IA_MINUS1) &&
((Player_MeleeWeaponFromIA(itemAction) != PLAYER_MELEEWEAPON_NONE) || (itemAction == PLAYER_IA_NONE)))) &&
((itemAction == PLAYER_IA_NONE) || !(this->stateFlags1 & PLAYER_STATE1_8000000) ||
- (itemAction == PLAYER_IA_MASK_ZORA) ||
+ (GameInteractor_Should(VB_USE_ITEM_CONSIDER_ITEM_ACTION, itemAction == PLAYER_IA_MASK_ZORA, &itemAction)) ||
((this->currentBoots >= PLAYER_BOOTS_ZORA_UNDERWATER) && (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND)))) {
s32 var_v1 = ((itemAction >= PLAYER_IA_MASK_MIN) && (itemAction <= PLAYER_IA_MASK_MAX) &&
(!GameInteractor_Should(VB_USE_ITEM_CONSIDER_LINK_HUMAN,