@@ -317,12 +317,31 @@ extern "C" RST_HOOK int rst_GetGyorgCollisionResponse(game::act::BossGyorg* gyor
317
317
return util::Contains (std::array{stunned, stunned_2, stunned_attacked}, calc_fn) ? 2 : 1 ;
318
318
}
319
319
320
+ struct GyorgFixState {
321
+ std::optional<u32> frames_since_inhale_attack_end;
322
+ };
323
+
320
324
void FixGyorg () {
325
+ static std::optional<GyorgFixState> state{};
321
326
auto * gctx = GetContext ().gctx ;
322
327
auto * gyorg =
323
328
gctx->FindActorWithId <game::act::BossGyorg>(game::act::Id::BossGyorg, game::act::Type::Boss);
324
- if (!gyorg)
329
+ if (!gyorg) {
330
+ state.reset ();
325
331
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 ;
326
345
327
346
// Disable the first stun cutscene, which is known to be buggy.
328
347
gyorg->field_F24 |= 1 ;
@@ -334,12 +353,19 @@ void FixGyorg() {
334
353
// switches to the frozen state (0x20d96c), even though he's supposed to be in the "held" state.
335
354
// If this situation is detected, clear the FreezeLink flag.
336
355
const auto player = gctx->GetPlayerActor ();
337
- const auto gyorg_eating_link = (decltype (gyorg->gyorg_calc ))util::GetAddr (0x557900 );
338
356
const auto link_handle_frozen = (decltype (player->state_handler_fn ))util::GetAddr (0x20D96C );
339
357
if (gyorg->gyorg_calc == gyorg_eating_link && player->state_handler_fn == link_handle_frozen &&
340
358
player->flags1 .TestAndClear (game::act::Player::Flag1::FreezeLink)) {
341
359
util::Print (" %s: clearing FreezeLink flag" , __func__);
342
360
}
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
+ }
343
369
}
344
370
345
371
struct TwinmoldFixState {
0 commit comments