From abe4cfa176c52e79cadd379a773fd07bd4c337e7 Mon Sep 17 00:00:00 2001 From: djevangelia Date: Sun, 21 Jun 2026 14:35:39 +0200 Subject: [PATCH] z_player Player_Action_Frozen --- include/player.h | 3 +- .../actors/ovl_player_actor/z_player.c | 30 ++++++++++++------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/include/player.h b/include/player.h index 63c9d25b658..4afc34ef85b 100644 --- a/include/player.h +++ b/include/player.h @@ -752,7 +752,7 @@ typedef struct WeaponInfo { #define PLAYER_STATE2_11 (1 << 11) #define PLAYER_STATE2_12 (1 << 12) #define PLAYER_STATE2_LOCK_ON_WITH_SWITCH (1 << 13) // Actor lock-on is active, specifically with Switch Targeting. Hold Targeting checks the state of the Z button instead of this flag. -#define PLAYER_STATE2_14 (1 << 14) +#define PLAYER_STATE2_FROZEN (1 << 14) // Used to draw the ice block encasing Link when frozen #define PLAYER_STATE2_15 (1 << 15) #define PLAYER_STATE2_DO_ACTION_ENTER (1 << 16) // Sets the "Enter On A" DoAction #define PLAYER_STATE2_17 (1 << 17) @@ -917,6 +917,7 @@ typedef struct Player { s8 facingUpSlope; // Player_Action_SlideOnSlope: Facing uphill when sliding on a slope s8 isLakeHyliaCs; // Player_Action_BlueWarpArrive: In Lake Hylia CS after Water Temple. Floating down is delayed until a specific point in the cutscene. s8 bottleCatchType; // Player_Action_SwingBottle: entry type for `sBottleCatchInfo`, corresponds to actor caught in a bottle + s8 iceScale; // Player_Action_Frozen: Used to scale the drawn ice encasing when growing. } av1; // "Action Variable 1": context dependent variable that has different meanings depending on what action is currently running /* 0x0850 */ union { diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 84dd1e6f522..beabbadfb67 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -350,7 +350,7 @@ void Player_Action_8084F88C(Player* this, PlayState* play); void Player_Action_TryOpeningDoor(Player* this, PlayState* play); void Player_Action_ExitGrotto(Player* this, PlayState* play); void Player_Action_8084FA54(Player* this, PlayState* play); -void Player_Action_8084FB10(Player* this, PlayState* play); +void Player_Action_Frozen(Player* this, PlayState* play); void Player_Action_8084FBF4(Player* this, PlayState* play); void Player_Action_808502D0(Player* this, PlayState* play); void Player_Action_808505DC(Player* this, PlayState* play); @@ -4645,7 +4645,7 @@ void func_80837C0C(PlayState* play, Player* this, s32 hitResponseType, f32 speed Player_SetIntangibility(this, invincibilityTimer); if (hitResponseType == PLAYER_HIT_RESPONSE_FROZEN) { - Player_SetupAction(play, this, Player_Action_8084FB10, 0); + Player_SetupAction(play, this, Player_Action_Frozen, 0); anim = &gPlayerAnim_link_normal_ice_down; @@ -11964,7 +11964,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { PLAYER_STATE1_SHIELDING); this->stateFlags2 &= ~(PLAYER_STATE2_0 | PLAYER_STATE2_2 | PLAYER_STATE2_3 | PLAYER_STATE2_5 | PLAYER_STATE2_6 | PLAYER_STATE2_8 | PLAYER_STATE2_FORCE_SAND_FLOOR_SOUND | PLAYER_STATE2_12 | - PLAYER_STATE2_14 | PLAYER_STATE2_DO_ACTION_ENTER | PLAYER_STATE2_22 | PLAYER_STATE2_26); + PLAYER_STATE2_FROZEN | PLAYER_STATE2_DO_ACTION_ENTER | PLAYER_STATE2_22 | PLAYER_STATE2_26); this->stateFlags3 &= ~PLAYER_STATE3_4; func_80847298(this); @@ -12048,7 +12048,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { Collider_UpdateCylinder(&this->actor, &this->cylinder); - if (!(this->stateFlags2 & PLAYER_STATE2_14)) { + if (!(this->stateFlags2 & PLAYER_STATE2_FROZEN)) { if (!(this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_13 | PLAYER_STATE1_14 | PLAYER_STATE1_23))) { CollisionCheck_SetOC(play, &play->colChkCtx, &this->cylinder.base); } @@ -12323,7 +12323,7 @@ void Player_Draw(Actor* thisx, PlayState* play2) { POLY_OPA_DISP = Play_SetFog(play, POLY_OPA_DISP); } - if (this->stateFlags2 & PLAYER_STATE2_14) { + if (this->stateFlags2 & PLAYER_STATE2_FROZEN) { f32 scale = (this->av1.actionVar1 >> 1) * 22.0f; gSPSegment(POLY_XLU_DISP++, 0x08, @@ -14440,23 +14440,31 @@ void Player_Action_8084FA54(Player* this, PlayState* play) { } } -void Player_Action_8084FB10(Player* this, PlayState* play) { - if (this->av1.actionVar1 >= 0) { - if (this->av1.actionVar1 < 6) { - this->av1.actionVar1++; +/** + * Frozen by Freezards, ice traps. (Twinrova freeze is entirely different condition.) + * Call try break free function, inflict damage, when free, setup idle. + * Drawing of ice encasing is done in the end of Player_Draw. + */ +void Player_Action_Frozen(Player* this, PlayState* play) { + if (this->av1.iceScale >= 0) { + // When getting frozen, stepwise scale up the ice encasing size + if (this->av1.iceScale < 6) { + this->av1.iceScale++; } + // If break free, set negative av1; else, re-set frozen state if (func_80832594(this, 1, 100)) { - this->av1.actionVar1 = -1; + this->av1.iceScale = -1; EffectSsIcePiece_SpawnBurst(play, &this->actor.world.pos, this->actor.scale.x); Player_PlaySfx(this, NA_SE_PL_ICE_BROKEN); } else { - this->stateFlags2 |= PLAYER_STATE2_14; + this->stateFlags2 |= PLAYER_STATE2_FROZEN; } if ((play->gameplayFrames % 4) == 0) { Player_InflictDamage(play, -1); } + // Broke free } else { if (LinkAnimation_Update(play, &this->skelAnime)) { func_80839F90(this, play);