Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion soh/include/z64player.h
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ typedef struct Player {
/* 0x06A4 */ f32 closestSecretDistSq;
/* 0x06A8 */ Actor* unk_6A8;
/* 0x06AC */ s8 idleType;
/* 0x06AD */ u8 unk_6AD;
/* 0x06AD */ u8 unk_6AD; // Camera related. 0 = normal, 1 = first person without weapon, 2 = first person with weapon, 3 = cutscene action, 4 = cutscene items
/* 0x06AE */ u16 unk_6AE_rotFlags; // See `UNK6AE_ROT_` macros. If its flag isn't set, a rot steps to 0.
/* 0x06B0 */ s16 upperLimbYawSecondary;
/* 0x06B2 */ char unk_6B4[0x004];
Expand Down
9 changes: 9 additions & 0 deletions soh/soh/Enhancements/AlwaysOnFixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ void RegisterAlwaysOnFixes() {
}
});

// Dismounting a ladder in a cutscene or using cutscene item (using restricted items glitch) i.e.
// `player->unk_6AD` == 3 or 4 softlocks as animation update stops. Let animation continue in that case.
COND_VB_SHOULD(VB_INTERRUPT_LADDER_DISMOUNT, true, {
u8* unk_6AD = va_arg(args, u8*);
if (*unk_6AD >= 3) {
*should = false;
}
});

COND_VB_SHOULD(VB_PREVENT_HBA_FANFARE_SOFTLOCK_TIMER, true, {
EnHorse* enHorse = va_arg(args, EnHorse*);
if (enHorse->hbaFlags & 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3270,6 +3270,14 @@ typedef enum {
// - `*EnItem00`
VB_ITEM00_KILL,

// #### `result`
// ```c
// interruptResult == PLAYER_INTERRUPT_NEW_ACTION
// ```
// #### `args`
// - `*u8 (&player->unk_6AD)`
VB_INTERRUPT_LADDER_DISMOUNT,

// #### `result`
// ```c
// true
Expand Down
60 changes: 33 additions & 27 deletions soh/src/overlays/actors/ovl_player_actor/z_player.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ void Player_Action_8084B9E4(Player* this, PlayState* play);
void Player_Action_8084BBE4(Player* this, PlayState* play);
void Player_Action_8084BDFC(Player* this, PlayState* play);
void Player_Action_8084BF1C(Player* this, PlayState* play);
void Player_Action_8084C5F8(Player* this, PlayState* play);
void Player_Action_DismountLadder(Player* this, PlayState* play);
void Player_Action_8084C760(Player* this, PlayState* play);
void Player_Action_8084C81C(Player* this, PlayState* play);
void Player_Action_8084CC98(Player* this, PlayState* play);
Expand Down Expand Up @@ -7597,8 +7597,8 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) {
return false;
}

void func_8083F070(Player* this, LinkAnimationHeader* anim, PlayState* play) {
Player_SetupActionPreserveAnimMovement(play, this, Player_Action_8084C5F8, 0);
void Player_SetupDismountLadder(Player* this, LinkAnimationHeader* anim, PlayState* play) {
Player_SetupActionPreserveAnimMovement(play, this, Player_Action_DismountLadder, 0);
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, (4.0f / 3.0f));
}

Expand Down Expand Up @@ -13233,7 +13233,7 @@ void Player_Action_8084BF1C(Player* this, PlayState* play) {
func_8083A9B8(this, &gPlayerAnim_link_normal_jump_climb_up_free, play);
this->stateFlags1 |= PLAYER_STATE1_CLIMBING_LEDGE;
} else {
func_8083F070(this, this->ageProperties->unk_CC[this->av2.actionVar2], play);
Player_SetupDismountLadder(this, this->ageProperties->unk_CC[this->av2.actionVar2], play);
}
} else {
this->skelAnime.prevTransl = this->ageProperties->unk_4A[sp68];
Expand All @@ -13247,7 +13247,7 @@ void Player_Action_8084BF1C(Player* this, PlayState* play) {
if (this->av2.actionVar2 != 0) {
this->skelAnime.prevTransl = this->ageProperties->unk_44;
}
func_8083F070(this, this->ageProperties->unk_C4[this->av2.actionVar2], play);
Player_SetupDismountLadder(this, this->ageProperties->unk_C4[this->av2.actionVar2], play);
this->av2.actionVar2 = 1;
}
} else {
Expand Down Expand Up @@ -13296,50 +13296,56 @@ void Player_Action_8084BF1C(Player* this, PlayState* play) {
}
}

static f32 D_80854898[] = { 10.0f, 20.0f };
static f32 D_808548A0[] = { 40.0f, 50.0f };
static f32 sUpDismountLadderFrames[] = { 10.0f, 20.0f };
static f32 sDownDismountLadderFrames[] = { 40.0f, 50.0f };

static AnimSfxEntry D_808548A8[] = {
static AnimSfxEntry sDownDismountLadderAnimSfx[] = {
{ NA_SE_PL_WALK_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_GENERAL, 10) },
{ NA_SE_PL_WALK_LADDER, ANIMSFX_DATA(ANIMSFX_TYPE_GENERAL, 20) },
{ NA_SE_PL_WALK_LADDER, -ANIMSFX_DATA(ANIMSFX_TYPE_GENERAL, 30) },
};

void Player_Action_8084C5F8(Player* this, PlayState* play) {
s32 temp;
f32* sp38;
CollisionPoly* sp34;
s32 sp30;
Vec3f sp24;
/**
* Dismounting ladders, both upwards and downwards.
* `actionVar2` true if dismounting down
*/
void Player_Action_DismountLadder(Player* this, PlayState* play) {
s32 interruptResult;
f32* frame;
CollisionPoly* groundPoly;
s32 bgId;
Vec3f raycastPos;

this->stateFlags2 |= PLAYER_STATE2_DISABLE_ROTATION_ALWAYS;

temp = Player_TryActionInterrupt(play, this, &this->skelAnime, 4.0f);
interruptResult = Player_TryActionInterrupt(play, this, &this->skelAnime, 4.0f);

if (temp == 0) {
// SoH: Prevent ladder cutscene softlock
if (GameInteractor_Should(VB_INTERRUPT_LADDER_DISMOUNT, interruptResult == PLAYER_INTERRUPT_NEW_ACTION,
&this->unk_6AD)) {
this->stateFlags1 &= ~PLAYER_STATE1_CLIMBING_LADDER;
return;
}

if ((temp > 0) || LinkAnimation_Update(play, &this->skelAnime)) {
if ((interruptResult > PLAYER_INTERRUPT_NEW_ACTION) || LinkAnimation_Update(play, &this->skelAnime)) {
func_8083C0E8(this, play);
this->stateFlags1 &= ~PLAYER_STATE1_CLIMBING_LADDER;
return;
}

sp38 = D_80854898;
frame = sUpDismountLadderFrames;

if (this->av2.actionVar2 != 0) {
Player_ProcessAnimSfxList(this, D_808548A8);
sp38 = D_808548A0;
if (this->av2.actionVar2 != false) {
Player_ProcessAnimSfxList(this, sDownDismountLadderAnimSfx);
frame = sDownDismountLadderFrames;
}

if (LinkAnimation_OnFrame(&this->skelAnime, sp38[0]) || LinkAnimation_OnFrame(&this->skelAnime, sp38[1])) {
sp24.x = this->actor.world.pos.x;
sp24.y = this->actor.world.pos.y + 20.0f;
sp24.z = this->actor.world.pos.z;
if (BgCheck_EntityRaycastFloor3(&play->colCtx, &sp34, &sp30, &sp24) != 0.0f) {
this->floorSfxOffset = func_80041F10(&play->colCtx, sp34, sp30);
if (LinkAnimation_OnFrame(&this->skelAnime, frame[0]) || LinkAnimation_OnFrame(&this->skelAnime, frame[1])) {
raycastPos.x = this->actor.world.pos.x;
raycastPos.y = this->actor.world.pos.y + 20.0f;
raycastPos.z = this->actor.world.pos.z;
if (BgCheck_EntityRaycastFloor3(&play->colCtx, &groundPoly, &bgId, &raycastPos) != 0.0f) {
this->floorSfxOffset = func_80041F10(&play->colCtx, groundPoly, bgId);
Player_PlayLandingSfx(this);
}
}
Expand Down
Loading