Skip to content

Commit fe301d4

Browse files
committed
Fix a possible softlock after Gyorg's inhale attack
This forces the FreezeLink flag to be cleared after an inhale attack has ended because a very rare bug causes Link to be frozen after the attack, even though a state handler change is already supposed to clear the flag.
1 parent 81ff580 commit fe301d4

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

source/rst/fixes/boss.cpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -317,12 +317,31 @@ extern "C" RST_HOOK int rst_GetGyorgCollisionResponse(game::act::BossGyorg* gyor
317317
return util::Contains(std::array{stunned, stunned_2, stunned_attacked}, calc_fn) ? 2 : 1;
318318
}
319319

320+
struct GyorgFixState {
321+
std::optional<u32> frames_since_inhale_attack_end;
322+
};
323+
320324
void FixGyorg() {
325+
static std::optional<GyorgFixState> state{};
321326
auto* gctx = GetContext().gctx;
322327
auto* gyorg =
323328
gctx->FindActorWithId<game::act::BossGyorg>(game::act::Id::BossGyorg, game::act::Type::Boss);
324-
if (!gyorg)
329+
if (!gyorg) {
330+
state.reset();
325331
return;
332+
}
333+
334+
if (!state) {
335+
util::Print("%s: initialising state", __func__);
336+
state.emplace();
337+
}
338+
339+
if (state->frames_since_inhale_attack_end.has_value())
340+
++*state->frames_since_inhale_attack_end;
341+
342+
const auto gyorg_eating_link = (decltype(gyorg->gyorg_calc))util::GetAddr(0x557900);
343+
if (gyorg->gyorg_calc == gyorg_eating_link)
344+
state->frames_since_inhale_attack_end = 0;
326345

327346
// Disable the first stun cutscene, which is known to be buggy.
328347
gyorg->field_F24 |= 1;
@@ -334,12 +353,19 @@ void FixGyorg() {
334353
// switches to the frozen state (0x20d96c), even though he's supposed to be in the "held" state.
335354
// If this situation is detected, clear the FreezeLink flag.
336355
const auto player = gctx->GetPlayerActor();
337-
const auto gyorg_eating_link = (decltype(gyorg->gyorg_calc))util::GetAddr(0x557900);
338356
const auto link_handle_frozen = (decltype(player->state_handler_fn))util::GetAddr(0x20D96C);
339357
if (gyorg->gyorg_calc == gyorg_eating_link && player->state_handler_fn == link_handle_frozen &&
340358
player->flags1.TestAndClear(game::act::Player::Flag1::FreezeLink)) {
341359
util::Print("%s: clearing FreezeLink flag", __func__);
342360
}
361+
362+
// Hacky workaround for a very rare bug that causes Link to be frozen *after* being spit out of
363+
// Gyorg, despite the fact that a state handler change is supposed to clear the FreezeLink flag...
364+
// This forces the flag to be cleared after an inhale attack has ended.
365+
if (state->frames_since_inhale_attack_end && *state->frames_since_inhale_attack_end <= 30 &&
366+
player->flags1.TestAndClear(game::act::Player::Flag1::FreezeLink)) {
367+
util::Print("%s: clearing FreezeLink flag after inhale attack", __func__);
368+
}
343369
}
344370

345371
struct TwinmoldFixState {

0 commit comments

Comments
 (0)