diff --git a/include/z64player.h b/include/z64player.h index d44da08ae8..6d3749206e 100644 --- a/include/z64player.h +++ b/include/z64player.h @@ -927,6 +927,7 @@ typedef struct Player { s16 csDelayTimer; // Player_Action_WaitForCutscene: Number of frames to wait before responding to a cutscene s16 playedLandingSfx; // Player_Action_BlueWarpArrive: Played sfx when landing on the ground s16 appearTimer; // Player_Action_FaroresWindArrive: Counts up, appear at 20 frames (1 second) + s16 drinkingState; // Player_Action_DrinkFromBottle: Uses values 0-2 to determine which part of the drinking action is currently active } av2; // "Action Variable 2": context dependent variable that has different meanings depending on what action is currently running /* 0x0854 */ f32 unk_854; diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 8ce71a8480..68667ac804 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -304,7 +304,7 @@ void Player_Action_8084E3C4(Player* this, PlayState* play); void Player_Action_8084E604(Player* this, PlayState* play); void Player_Action_8084E6D4(Player* this, PlayState* play); void Player_Action_TimeTravelEnd(Player* this, PlayState* play); -void Player_Action_8084EAC0(Player* this, PlayState* play); +void Player_Action_DrinkFromBottle(Player* this, PlayState* play); void Player_Action_SwingBottle(Player* this, PlayState* play); void Player_Action_8084EED8(Player* this, PlayState* play); void Player_Action_8084EFC0(Player* this, PlayState* play); @@ -6097,7 +6097,7 @@ s32 Player_ActionHandler_13(Player* this, PlayState* play) { Player_AnimPlayOnceAdjusted(play, this, &gPlayerAnim_link_bottle_fish_out); func_80835EA4(play, (sp2C == 1) ? 1 : 5); } else { - Player_SetupActionPreserveItemAction(play, this, Player_Action_8084EAC0, 0); + Player_SetupActionPreserveItemAction(play, this, Player_Action_DrinkFromBottle, 0); Player_AnimChangeOnceMorphAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_start); func_80835EA4(play, 2); } @@ -6417,7 +6417,7 @@ void func_8083C0B8(Player* this, PlayState* play) { func_8083BF50(this, play); } -void func_8083C0E8(Player* this, PlayState* play) { +void Player_SetupIdleAndPlayIdleAnim(Player* this, PlayState* play) { Player_SetupAction(play, this, Player_Action_Idle, 1); Player_AnimPlayOnce(play, this, Player_GetIdleAnim(this)); this->yaw = this->actor.shape.rot.y; @@ -8660,7 +8660,7 @@ void Player_Action_TurnInPlace(Player* this, PlayState* play) { this->actor.shape.rot.y = yawTarget; func_8083C858(this, play); } else if (Math_ScaledStepToS(&this->actor.shape.rot.y, yawTarget, this->turnRate)) { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); } this->yaw = this->actor.shape.rot.y; @@ -10060,7 +10060,7 @@ void Player_Action_80845668(Player* this, PlayState* play) { } if ((sp3C != 0) || (interruptResult >= PLAYER_INTERRUPT_MOVE)) { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); this->stateFlags1 &= ~(PLAYER_STATE1_14 | PLAYER_STATE1_18); return; } @@ -10268,7 +10268,7 @@ void Player_Action_80845EF8(Player* this, PlayState* play) { this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f; } } else { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); if (play->roomCtx.prevRoom.num >= 0) { Room_FinishRoomChange(play, &play->roomCtx); } @@ -12778,7 +12778,7 @@ void Player_Action_8084BDFC(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { Player_ApplyAnimMovementScaledByAge(this, ANIM_FLAG_UPDATE_XZ); - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); return; } @@ -12967,7 +12967,7 @@ void Player_Action_8084C5F8(Player* this, PlayState* play) { } if ((interruptResult >= PLAYER_INTERRUPT_MOVE) || LinkAnimation_Update(play, &this->skelAnime)) { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); this->stateFlags1 &= ~PLAYER_STATE1_21; return; } @@ -13044,7 +13044,7 @@ void Player_Action_8084C81C(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { // Player is finished exiting the crawlspace and control is returned - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); this->stateFlags2 &= ~PLAYER_STATE2_CRAWLING; return; } @@ -13380,7 +13380,7 @@ void Player_Action_8084D3E4(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { EnHorse* rideActor = (EnHorse*)this->rideActor; - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); this->stateFlags1 &= ~PLAYER_STATE1_23; this->actor.parent = NULL; AREG(6) = 0; @@ -13649,7 +13649,7 @@ void func_8084DF6C(PlayState* play, Player* this) { void func_8084DFAC(PlayState* play, Player* this) { func_8084DF6C(play, this); Player_ApplyYawFromAnim(this); - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); this->yaw = this->actor.shape.rot.y; } @@ -13870,7 +13870,7 @@ void Player_Action_8084E6D4(Player* this, PlayState* play) { if (this->getItemId != GI_ICE_TRAP) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.world.pos.x, this->actor.world.pos.y + 100.0f, this->actor.world.pos.z, 0, 0, 0, 0); - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); } else { this->actor.colChkInfo.damage = 0; func_80837C0C(play, this, PLAYER_HIT_RESPONSE_ICE_TRAP, 0.0f, 0.0f, 0, 20); @@ -13924,7 +13924,7 @@ void Player_Action_TimeTravelEnd(Player* this, PlayState* play) { this->skelAnime.endFrame = this->skelAnime.animLength - 1.0f; } } else { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); } } else { if (LINK_IS_ADULT && LinkAnimation_OnFrame(&this->skelAnime, 158.0f)) { @@ -13955,13 +13955,24 @@ void Player_Action_TimeTravelEnd(Player* this, PlayState* play) { } } -void Player_Action_8084EAC0(Player* this, PlayState* play) { - if (LinkAnimation_Update(play, &this->skelAnime)) { - if (this->av2.actionVar2 == 0) { - static u8 D_808549FC[] = { - 0x01, 0x03, 0x02, 0x04, 0x04, - }; +// Restores 14 hearts, is overriden by BOTTLE_CONTENT_DRINK_FLAG_HEALTH_SMALL +#define BOTTLE_CONTENT_DRINK_FLAG_HEALTH_BIG 0x01 +// Fully restores magic +#define BOTTLE_CONTENT_DRINK_FLAG_MAGIC 0x02 +// Restores 5 hearts, overrides BOTTLE_CONTENT_DRINK_FLAG_HEALTH_BIG +#define BOTTLE_CONTENT_DRINK_FLAG_HEALTH_SMALL 0x04 +typedef enum DrinkingState { + /* 0 */ DRINGING_STATE_SETUP, + /* 1 */ DRINGING_STATE_DRINKING, + /* 2 */ DRINGING_STATE_FINISHED +} DrinkingState; + +void Player_Action_DrinkFromBottle(Player* this, PlayState* play) { + // When an animation finishes (gPlayerAnim_link_bottle_drink_demo_start when drinkingState == DRINGING_STATE_SETUP, gPlayerAnim_link_bottle_drink_demo_end otherwise) + if (LinkAnimation_Update(play, &this->skelAnime)) { + if (this->av2.drinkingState == DRINGING_STATE_SETUP) { + // Special handling for the poe bottle if (this->itemAction == PLAYER_IA_BOTTLE_POE) { s32 rand = Rand_S16Offset(-1, 3); @@ -13969,6 +13980,7 @@ void Player_Action_8084EAC0(Player* this, PlayState* play) { rand = 3; } + // Prevents the drinking the poe from killing you if ((rand < 0) && (gSaveContext.save.info.playerData.health <= 0x10)) { rand = 3; } @@ -13979,35 +13991,43 @@ void Player_Action_8084EAC0(Player* this, PlayState* play) { gSaveContext.healthAccumulator = rand * 0x10; } } else { - s32 sp28 = D_808549FC[this->itemAction - PLAYER_IA_BOTTLE_POTION_RED]; + static u8 sBottleContentDrinkFlags[] = { + /* PLAYER_IA_BOTTLE_POTION_RED */ BOTTLE_CONTENT_DRINK_FLAG_HEALTH_BIG, + /* PLAYER_IA_BOTTLE_POTION_BLUE */ BOTTLE_CONTENT_DRINK_FLAG_HEALTH_BIG | BOTTLE_CONTENT_DRINK_FLAG_MAGIC, + /* PLAYER_IA_BOTTLE_POTION_GREEN */ BOTTLE_CONTENT_DRINK_FLAG_MAGIC, + /* PLAYER_IA_BOTTLE_MILK_FULL */ BOTTLE_CONTENT_DRINK_FLAG_HEALTH_SMALL, + /* PLAYER_IA_BOTTLE_MILK_HALF */ BOTTLE_CONTENT_DRINK_FLAG_HEALTH_SMALL, + }; - if (sp28 & 1) { + s32 flags = sBottleContentDrinkFlags[this->itemAction - PLAYER_IA_BOTTLE_POTION_RED]; + + if (flags & BOTTLE_CONTENT_DRINK_FLAG_HEALTH_BIG) { gSaveContext.healthAccumulator = 0x140; } - if (sp28 & 2) { + if (flags & BOTTLE_CONTENT_DRINK_FLAG_MAGIC) { Magic_Fill(play); } - if (sp28 & 4) { + if (flags & BOTTLE_CONTENT_DRINK_FLAG_HEALTH_SMALL) { gSaveContext.healthAccumulator = 0x50; } } Player_AnimPlayLoopAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_wait); - this->av2.actionVar2 = 1; + this->av2.drinkingState = DRINGING_STATE_DRINKING; } else { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN)); } - } else if (this->av2.actionVar2 == 1) { + } else if (this->av2.drinkingState == DRINGING_STATE_DRINKING) { if ((gSaveContext.healthAccumulator == 0) && (gSaveContext.magicState != MAGIC_STATE_FILL)) { Player_AnimChangeOnceMorphAdjusted(play, this, &gPlayerAnim_link_bottle_drink_demo_end); - this->av2.actionVar2 = 2; + this->av2.drinkingState = DRINGING_STATE_FINISHED; Player_UpdateBottleHeld(play, this, ITEM_BOTTLE_EMPTY, PLAYER_IA_BOTTLE); } Player_PlayVoiceSfx(this, NA_SE_VO_LI_DRINK - SFX_FLAG); - } else if ((this->av2.actionVar2 == 2) && LinkAnimation_OnFrame(&this->skelAnime, 29.0f)) { + } else if ((this->av2.drinkingState == DRINGING_STATE_FINISHED) && LinkAnimation_OnFrame(&this->skelAnime, 29.0f)) { Player_PlayVoiceSfx(this, NA_SE_VO_LI_BREATH_DRINK); } } @@ -14054,7 +14074,7 @@ void Player_Action_SwingBottle(Player* this, PlayState* play) { Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN)); } } else { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); } } else if (this->av1.bottleCatchType == BOTTLE_CATCH_NONE) { s32 activeFrame = this->skelAnime.curFrame - swingEntry->firstActiveFrame; @@ -14093,7 +14113,7 @@ void Player_Action_SwingBottle(Player* this, PlayState* play) { } } - //! @bug If the animation is changed at any point above (such as by func_8083C0E8() or + //! @bug If the animation is changed at any point above (such as by Player_SetupIdleAndPlayIdleAnim() or //! Player_AnimPlayOnceAdjusted()), it will change the curFrame to 0. This causes this flag to be set for one frame, //! at a time when it does not look like Player is swinging the bottle. if (this->skelAnime.curFrame <= 7.0f) { @@ -14105,7 +14125,7 @@ static Vec3f D_80854A1C = { 0.0f, 0.0f, 5.0f }; void Player_Action_8084EED8(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN)); return; } @@ -14135,7 +14155,7 @@ void Player_Action_8084EFC0(Player* this, PlayState* play) { Player_DecelerateToZero(this); if (LinkAnimation_Update(play, &this->skelAnime)) { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN)); } else if (LinkAnimation_OnFrame(&this->skelAnime, 76.0f)) { BottleDropInfo* dropInfo = &D_80854A28[this->itemAction - PLAYER_IA_BOTTLE_FISH]; @@ -14160,7 +14180,7 @@ void Player_Action_ExchangeItem(Player* this, PlayState* play) { if (LinkAnimation_Update(play, &this->skelAnime)) { if (this->av2.actionVar2 < 0) { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); } else if (this->exchangeItemId == EXCH_ITEM_NONE) { Actor* talkActor = this->talkActor; @@ -14195,7 +14215,7 @@ void Player_Action_ExchangeItem(Player* this, PlayState* play) { Player_AnimPlayOnce(play, this, &gPlayerAnim_link_bottle_read_end); this->av2.actionVar2 = -1; } else { - func_8083C0E8(this, play); + Player_SetupIdleAndPlayIdleAnim(this, play); } Camera_SetFinishedFlag(Play_GetCamera(play, CAM_ID_MAIN));