Skip to content
Open
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
13 changes: 12 additions & 1 deletion soh/src/overlays/actors/ovl_Bg_Bdan_Objects/z_bg_bdan_objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,17 @@ void BgBdanObjects_FallToLowerPos(BgBdanObjects* this, PlayState* play) {
void BgBdanObjects_Update(Actor* thisx, PlayState* play) {
BgBdanObjects* this = (BgBdanObjects*)thisx;

// https://github.com/HarbourMasters/Shipwright/issues/4339
// Only BgBdanObjects_OctoPlatform_BattleInProgress checks Flags_GetClear, so if the platform is in any other state
// when Big Octo dies, the clear flag goes permanently unread. This fallback catches that case: the clear flag is
// only ever set by Big Octo's death, and the switch flag is only set once the platform has already begun its
// descent.
if (thisx->params == 0 && Flags_GetClear(play, thisx->room) && !Flags_GetSwitch(play, this->switchFlag)) {
Copy link
Copy Markdown
Member

@serprex serprex May 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this only happen due to cutscene skips?

code should be made as a timesaver hook

Copy link
Copy Markdown
Author

@unreference unreference May 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated this angle a bit. The VB_PLAY_ONEPOINT_ACTOR_CS hook fires identically in both successful and failed rando runs. Vanilla runs without the timesaver show the same flag sequence, so the timesaver does not seem to be a factor.

OnePointCutscene_Attention does route through OnePointCutscene_Init, so the ACTOR_BG_BDAN_SWITCH skip in the timesave handler does fire after Big Octo dies, but the Bdan switch is ACTORCAT_SWITCH (cat 0) and the platform is ACTORCAT_BG (cat 1). The switch skip happens one frame after the platform has already transitioned to SinkToFloorHeight, so it can't interfere.

Failed run 1:

[11:06:04.065] VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6
[11:06:39.708] Clear Flag Set - 0x6

Failed run 2:

[11:14:26.621] VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6
[11:15:17.470] Clear Flag Set - 0x6

No fail, rando:

[04:55:28.234] VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6
[04:55:46.784] Clear Flag Set - 0x6
[04:55:46.834] Switch Flag Set - 0x1f

No fail, vanilla:

[04:52:53.185] Clear Flag Set - 0x6
[04:52:53.251] Switch Flag Set - 0x1f

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why doesn't this show up on console?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little suspect in general that this actually happens without the cutscene skip, as this bug definitely didn't exist in Ship before we had those.

Copy link
Copy Markdown
Author

@unreference unreference May 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the OnePoint skip list and neither ACTOR_BG_BDAN_OBJECTS nor ACTOR_EN_BIGOKUTA are in the switch cases that set *should = false:

OnePointCutscene_Init(play, 3070, -99, &this->dyna.actor, MAIN_CAM);

OnePointCutscene_Init(play, 3080, -99, this->dyna.actor.child, MAIN_CAM);

OnePointCutscene_Init(play, 3090, -99, &this->dyna.actor, MAIN_CAM);

OnePointCutscene_Init(play, 3100, 51, &this->dyna.actor, MAIN_CAM);

All four cutscenes pass either the platform (ACTOR_BG_BDAN_OBJECTS) or Big Octo (ACTOR_EN_BIGOKUTA) as the actor parameter, and neither of those actors appear in the skip list, so none of the cutscenes are skipped.

My reproduction logs also confirmed this -- VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6 was logged above, which only occurs when *should is still true (cutscene played, not skipped):

if (*should) {
SPDLOG_INFO("VB_PLAY_ONEPOINT_ACTOR_CS ID:{} Cat:{}", actor->id, actor->category);
}

Is there a different cutscene skip mechanism that you guys are thinking might affect this? I could very well be missing something, but based on what I can trace, the OnePoint skip path doesn't touch the actors involved in the sequence.

Flags_SetSwitch(play, this->switchFlag);
this->dyna.actor.home.rot.y = (s16)(this->dyna.actor.shape.rot.y + 0x2000) & 0xC000;
this->actionFunc = BgBdanObjects_SinkToFloorHeight;
}

Actor_SetFocus(thisx, 50.0f);
this->actionFunc(this, play);
}
Expand All @@ -459,4 +470,4 @@ void BgBdanObjects_Draw(Actor* thisx, PlayState* play) {
} else {
Gfx_DrawDListOpa(play, sDLists[thisx->params]);
}
}
}