Mask improvements (#3431)

* Add gKeepMasks

* Add gSaveMasksToFile

* Add gKeepMasksOnDeath & gKeepBunnyHoodThroughTime

* Fix mask bleedthrough

* Update cvar names

* Change bunny hood enhancements to all mask ones

* Consolidate multiple enhancements into PersistentMasks

* Move keeping masks thru loading zones to PersistentMasks

* I forgot

* Update z_player.c

* Update z64save.h

Merge commit excluded this removal for some reason.

---------

Co-authored-by: Malkierian <malkierian@gmail.com>
Co-authored-by: Malkierian <malkierian@live.com>
This commit is contained in:
Pepe20129
2024-10-11 01:16:41 +02:00
committed by GitHub
parent 62713bb551
commit 70a2141351
8 changed files with 72 additions and 61 deletions

View File

@@ -539,14 +539,19 @@ void Play_Init(GameState* thisx) {
(s32)(zAllocAligned + zAllocSize) - (s32)(zAllocAligned - zAlloc));
Fault_AddClient(&D_801614B8, ZeldaArena_Display, NULL, NULL);
// In order to keep bunny hood equipped on first load, we need to pre-set the age reqs for the item and slot
if ((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && CVarGetInteger(CVAR_ENHANCEMENT("AdultBunnyHood"), 0)) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) {
gItemAgeReqs[ITEM_MASK_BUNNY] = AGE_REQ_NONE;
if(INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY)
// In order to keep masks equipped on first load, we need to pre-set the age reqs for the item and slot
if (CVarGetInteger(CVAR_ENHANCEMENT("AdultMasks"), 0) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)) {
for (int i = ITEM_MASK_KEATON; i <= ITEM_MASK_TRUTH; i += 1) {
gItemAgeReqs[i] = AGE_REQ_NONE;
}
if (INV_CONTENT(ITEM_TRADE_CHILD) >= ITEM_MASK_KEATON && INV_CONTENT(ITEM_TRADE_CHILD) <= ITEM_MASK_TRUTH) {
gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_NONE;
}
else {
gItemAgeReqs[ITEM_MASK_BUNNY] = gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_CHILD;
}
} else {
for (int i = ITEM_MASK_KEATON; i <= ITEM_MASK_TRUTH; i += 1) {
gItemAgeReqs[i] = AGE_REQ_CHILD;
}
gSlotAgeReqs[SLOT_TRADE_CHILD] = AGE_REQ_CHILD;
}
func_800304DC(play, &play->actorCtx, play->linkActorEntry);

View File

@@ -140,6 +140,10 @@ void Sram_OpenSave() {
break;
}
if (!CVarGetInteger(CVAR_ENHANCEMENT("PersistentMasks"), 0)) {
gSaveContext.maskMemory = PLAYER_MASK_NONE;
}
osSyncPrintf("scene_no = %d\n", gSaveContext.entranceIndex);
osSyncPrintf(VT_RST);

View File

@@ -1089,7 +1089,6 @@ static s8 sItemActions[] = {
PLAYER_IA_SWORD_BIGGORON, // ITEM_SWORD_BIGGORON
};
static u8 sMaskMemory;
u8 gWalkSpeedToggle1;
u8 gWalkSpeedToggle2;
@@ -2251,37 +2250,20 @@ void Player_ProcessItemButtons(Player* this, PlayState* play) {
s32 item;
s32 i;
if (this->currentMask != PLAYER_MASK_NONE) {
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) {
s32 maskItem = this->currentMask - PLAYER_MASK_KEATON + ITEM_MASK_KEATON;
bool hasOnDpad = false;
if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) {
for (int buttonIndex = 4; buttonIndex < 8; buttonIndex++) {
hasOnDpad |= gSaveContext.equips.buttonItems[buttonIndex] == maskItem;
}
}
if (this->currentMask != PLAYER_MASK_NONE && !CVarGetInteger(CVAR_ENHANCEMENT("PersistentMasks"), 0)) {
maskItemAction = this->currentMask - 1 + PLAYER_IA_MASK_KEATON;
if (gSaveContext.equips.buttonItems[0] != maskItem && gSaveContext.equips.buttonItems[1] != maskItem &&
gSaveContext.equips.buttonItems[2] != maskItem && gSaveContext.equips.buttonItems[3] != maskItem &&
!hasOnDpad) {
this->currentMask = sMaskMemory = PLAYER_MASK_NONE;
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
}
} else {
maskItemAction = this->currentMask - 1 + PLAYER_IA_MASK_KEATON;
bool hasOnDpad = false;
if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) {
for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) {
hasOnDpad |= Player_ItemIsItemAction(DPAD_ITEM(buttonIndex), maskItemAction);
}
}
if (!Player_ItemIsItemAction(C_BTN_ITEM(0), maskItemAction) &&
!Player_ItemIsItemAction(C_BTN_ITEM(1), maskItemAction) &&
!Player_ItemIsItemAction(C_BTN_ITEM(2), maskItemAction) && !hasOnDpad) {
this->currentMask = PLAYER_MASK_NONE;
bool hasOnDpad = false;
if (CVarGetInteger(CVAR_SETTING("DpadEquips"), 0) != 0) {
for (int buttonIndex = 0; buttonIndex < 4; buttonIndex++) {
hasOnDpad |= Player_ItemIsItemAction(DPAD_ITEM(buttonIndex), maskItemAction);
}
}
if (!Player_ItemIsItemAction(C_BTN_ITEM(0), maskItemAction) &&
!Player_ItemIsItemAction(C_BTN_ITEM(1), maskItemAction) &&
!Player_ItemIsItemAction(C_BTN_ITEM(2), maskItemAction) && !hasOnDpad) {
this->currentMask = PLAYER_MASK_NONE;
}
}
if (!(this->stateFlags1 & (PLAYER_STATE1_ITEM_OVER_HEAD | PLAYER_STATE1_IN_CUTSCENE)) && !func_8008F128(this)) {
@@ -3221,7 +3203,8 @@ void Player_UseItem(PlayState* play, Player* this, s32 item) {
this->currentMask = itemAction - PLAYER_IA_MASK_KEATON + 1;
}
sMaskMemory = this->currentMask;
gSaveContext.maskMemory = this->currentMask;
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
} else if (((itemAction >= PLAYER_IA_OCARINA_FAIRY) && (itemAction <= PLAYER_IA_OCARINA_OF_TIME)) ||
(itemAction >= PLAYER_IA_BOTTLE_FISH)) {
@@ -5069,7 +5052,9 @@ void func_8083A0F4(PlayState* play, Player* this) {
this->interactRangeActor->parent = &this->actor;
Player_SetupAction(play, this, Player_Action_8084F608, 0);
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
sMaskMemory = PLAYER_MASK_NONE;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PersistentMasks"), 0) || !CVarGetInteger(CVAR_ENHANCEMENT("AdultMasks"), 0)) {
gSaveContext.maskMemory = PLAYER_MASK_NONE;
}
} else {
LinkAnimationHeader* anim;
@@ -8940,7 +8925,9 @@ void func_80843AE8(PlayState* play, Player* this) {
OnePointCutscene_Init(play, 9908, 125, &this->actor, MAIN_CAM);
} else if (play->gameOverCtx.state == GAMEOVER_DEATH_WAIT_GROUND) {
play->gameOverCtx.state = GAMEOVER_DEATH_DELAY_MENU;
sMaskMemory = PLAYER_MASK_NONE;
if (!CVarGetInteger(CVAR_ENHANCEMENT("PersistentMasks"), 0)) {
gSaveContext.maskMemory = PLAYER_MASK_NONE;
}
}
}
@@ -10191,11 +10178,12 @@ void Player_Init(Actor* thisx, PlayState* play2) {
Player_UseItem(play, this, ITEM_NONE);
Player_SetEquipmentData(play, this);
this->prevBoots = this->currentBoots;
if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) {
//keep masks thru loading zones
if (CVarGetInteger(CVAR_ENHANCEMENT("PersistentMasks"), 0)) {
if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_SOLD_OUT) {
sMaskMemory = PLAYER_MASK_NONE;
gSaveContext.maskMemory = PLAYER_MASK_NONE;
}
this->currentMask = sMaskMemory;
this->currentMask = gSaveContext.maskMemory;
}
Player_InitCommon(this, play, gPlayerSkelHeaders[((void)0, gSaveContext.linkAge)]);
this->giObjectSegment = (void*)(((uintptr_t)ZELDA_ARENA_MALLOC_DEBUG(0x3008) + 8) & ~0xF);

View File

@@ -342,24 +342,25 @@ void KaleidoScope_HandleItemCycles(PlayState* play) {
);
//the slot age requirement for the child trade slot has to be updated
//in case it currently holds the bunny hood
//in case it currently holds a mask
//to allow adult link to wear it if the setting is enabled
gSlotAgeReqs[SLOT_TRADE_CHILD] =
(
((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger(CVAR_ENHANCEMENT("AdultBunnyHood"), 0)) ||
CVarGetInteger(CVAR_ENHANCEMENT("AdultMasks"), 0) ||
CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)
) &&
INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_MASK_BUNNY
? AGE_REQ_NONE
: AGE_REQ_CHILD;
//also update the age requirement for the bunny hood itself
gItemAgeReqs[ITEM_MASK_BUNNY] =
((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && CVarGetInteger(CVAR_ENHANCEMENT("AdultBunnyHood"), 0)) ||
CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)
INV_CONTENT(ITEM_TRADE_CHILD) >= ITEM_MASK_KEATON &&
INV_CONTENT(ITEM_TRADE_CHILD) <= ITEM_MASK_TRUTH
? AGE_REQ_NONE
: AGE_REQ_CHILD;
//also update the age requirements for the masks itself
for (int i = ITEM_MASK_KEATON; i <= ITEM_MASK_TRUTH; i += 1) {
gItemAgeReqs[i] = CVarGetInteger(CVAR_ENHANCEMENT("AdultMasks"), 0) || CVarGetInteger(CVAR_CHEAT("TimelessEquipment"), 0)
? AGE_REQ_NONE
: AGE_REQ_CHILD;
}
//handle the adult trade select
KaleidoScope_HandleItemCycleExtras(
play,