From 0a5d4cd2152b9ed42ffdc851b88ed92003900d50 Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 28 Mar 2022 18:57:52 -0700 Subject: [PATCH] Fix softlock when player is grabbed by enemy --- include/types.h | 1 + src/game/behaviors/chuckya.inc.c | 32 +++++++++++++++---- src/game/behaviors/heave_ho.inc.c | 31 ++++++++++++++---- src/game/behaviors/king_bobomb.inc.c | 16 ++++++++-- src/game/interaction.c | 3 ++ src/game/mario_actions_automatic.c | 4 ++- src/game/spawn_object.c | 2 ++ src/pc/controller/controller_keyboard_debug.c | 2 +- 8 files changed, 73 insertions(+), 18 deletions(-) diff --git a/include/types.h b/include/types.h index f077e9bb7..f71edf5c6 100644 --- a/include/types.h +++ b/include/types.h @@ -219,6 +219,7 @@ struct Object /*?????*/ u32 areaTimerDuration; /*?????*/ void (*areaTimerRunOnceCallback)(void); /*?????*/ u8 globalPlayerIndex; + /*?????*/ struct Object* usingObj; }; struct ObjectHitbox diff --git a/src/game/behaviors/chuckya.inc.c b/src/game/behaviors/chuckya.inc.c index cf79ed76b..5b75522c3 100644 --- a/src/game/behaviors/chuckya.inc.c +++ b/src/game/behaviors/chuckya.inc.c @@ -4,7 +4,7 @@ void common_anchor_mario_behavior(f32 sp28, f32 sp2C, s32 sp30) { for (int i = 0; i < MAX_PLAYERS; i++) { if (!is_player_active(&gMarioStates[i])) { continue; } struct MarioState* marioState = &gMarioStates[i]; - struct Object* player = gMarioStates[i].marioObj; + struct Object* player = marioState->marioObj; if (marioState->heldByObj != o->parentObj && marioState->heldByObj != o) { continue; } if (marioState->action != ACT_GRABBED) { continue; } switch (o->parentObj->oChuckyaUnk88) { @@ -150,6 +150,7 @@ void chuckya_act_1(void) { o->oChuckyaUnk88 = 3; o->oAction = 3; o->oInteractStatus &= ~(INT_STATUS_GRABBED_MARIO); + o->usingObj = NULL; } else { cur_obj_init_animation_with_sound(1); o->oMoveAngleYaw += INT_STATUS_GRABBED_MARIO; @@ -165,6 +166,7 @@ void chuckya_act_1(void) { o->oChuckyaUnk88 = 2; o->oAction = 3; o->oInteractStatus &= ~(INT_STATUS_GRABBED_MARIO); + o->usingObj = NULL; } } } @@ -196,17 +198,33 @@ void chuckya_move(void) { o->oAction = 1; o->oChuckyaUnk88 = 1; cur_obj_play_sound_2(SOUND_OBJ_UNKNOWN3); + o->usingObj = nearest_player_to_object(o); } } +void bhv_chuckya_override_ownership(u8* shouldOverride, u8* shouldOwn) { + *shouldOverride = (gMarioStates[0].heldByObj == o); + if (*shouldOverride) { + *shouldOwn = true; + } +} + +u8 bhv_chuckya_ignore_if_true(void) { + return (gMarioStates[0].heldByObj == o); +} + void bhv_chuckya_loop(void) { if (!network_sync_object_initialized(o)) { - network_init_object(o, 4000.0f); - network_init_object_field(o, &o->oChuckyaUnk88); - network_init_object_field(o, &o->oChuckyaUnkF8); - network_init_object_field(o, &o->oChuckyaUnkFC); - network_init_object_field(o, &o->oChuckyaUnk100); - network_init_object_field(o, &o->oFaceAnglePitch); + struct SyncObject* so = network_init_object(o, 4000.0f); + if (so != NULL) { + so->override_ownership = bhv_chuckya_override_ownership; + so->ignore_if_true = bhv_chuckya_ignore_if_true; + network_init_object_field(o, &o->oChuckyaUnk88); + network_init_object_field(o, &o->oChuckyaUnkF8); + network_init_object_field(o, &o->oChuckyaUnkFC); + network_init_object_field(o, &o->oChuckyaUnk100); + network_init_object_field(o, &o->oFaceAnglePitch); + } } f32 sp2C = 20.0f; diff --git a/src/game/behaviors/heave_ho.inc.c b/src/game/behaviors/heave_ho.inc.c index 566c6be81..8d8da3a5a 100644 --- a/src/game/behaviors/heave_ho.inc.c +++ b/src/game/behaviors/heave_ho.inc.c @@ -5,6 +5,8 @@ s16 D_8032F460[][2] = { { 30, 0 }, { 42, 1 }, { 52, 0 }, { 64, 1 }, { 74, 0 }, void bhv_heave_ho_throw_mario_loop(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); + if (gMarioStates[0].heldByObj == o->parentObj) { marioState = &gMarioStates[0]; } + struct Object* player = marioState->marioObj; o->oParentRelativePosX = 200.0f; o->oParentRelativePosY = -50.0f; @@ -21,6 +23,7 @@ void bhv_heave_ho_throw_mario_loop(void) { marioState->forwardVel = -45.0f; marioState->vel[1] = 95.0f; o->parentObj->oHeaveHoUnk88 = 0; + o->parentObj->usingObj = NULL; break; } } @@ -106,17 +109,33 @@ void heave_ho_move(void) { o->oInteractStatus = 0; o->oHeaveHoUnk88 = 1; o->oAction = 3; + o->usingObj = nearest_player_to_object(o); } } +void bhv_heave_ho_override_ownership(u8* shouldOverride, u8* shouldOwn) { + *shouldOverride = (gMarioStates[0].heldByObj == o); + if (*shouldOverride) { + *shouldOwn = true; + } +} + +u8 bhv_heave_ho_ignore_if_true(void) { + return (gMarioStates[0].heldByObj == o); +} + void bhv_heave_ho_loop(void) { if (!network_sync_object_initialized(o)) { - network_init_object(o, 4000.0f); - network_init_object_field(o, &o->oHeaveHoUnk88); - network_init_object_field(o, &o->oHeaveHoUnkF4); - network_init_object_field(o, &o->oInteractStatus); - network_init_object_field(o, &o->oGraphYOffset); - network_init_object_field(o, &o->oFaceAngleYaw); + struct SyncObject* so = network_init_object(o, 4000.0f); + if (so != NULL) { + so->override_ownership = bhv_heave_ho_override_ownership; + so->ignore_if_true = bhv_heave_ho_ignore_if_true; + network_init_object_field(o, &o->oHeaveHoUnk88); + network_init_object_field(o, &o->oHeaveHoUnkF4); + network_init_object_field(o, &o->oInteractStatus); + network_init_object_field(o, &o->oGraphYOffset); + network_init_object_field(o, &o->oFaceAngleYaw); + } } cur_obj_scale(2.0f); diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c index 2404b4da7..9b4a96029 100644 --- a/src/game/behaviors/king_bobomb.inc.c +++ b/src/game/behaviors/king_bobomb.inc.c @@ -133,6 +133,7 @@ void king_bobomb_act_3(void) { o->oAction = 2; o->oKingBobombUnk108 = 35; o->oInteractStatus &= ~(INT_STATUS_GRABBED_MARIO); + o->usingObj = NULL; } else { o->oForwardVel = 3.0f; if (o->oKingBobombUnk104 > 20 && cur_obj_rotate_yaw_toward(0, 0x400)) { @@ -149,6 +150,7 @@ void king_bobomb_act_3(void) { } else if (cur_obj_check_if_near_animation_end()) { o->oAction = 1; o->oInteractStatus &= ~(INT_STATUS_GRABBED_MARIO); + o->usingObj = NULL; } } } @@ -367,15 +369,23 @@ void king_bobomb_move(void) { cur_obj_disable_rendering(); } -u8 king_bobomb_ignore_if_true(void) { - return o->oAction == 8; +void bhv_king_bobomb_override_ownership(u8* shouldOverride, u8* shouldOwn) { + *shouldOverride = (gMarioStates[0].heldByObj == o); + if (*shouldOverride) { + *shouldOwn = true; + } +} + +u8 bhv_king_bobomb_ignore_if_true(void) { + return (o->oAction == 8) || (gMarioStates[0].heldByObj == o); } void bhv_king_bobomb_loop(void) { if (!network_sync_object_initialized(o)) { struct SyncObject* so = network_init_object(o, 4000.0f); if (so) { - so->ignore_if_true = king_bobomb_ignore_if_true; + so->override_ownership = bhv_king_bobomb_override_ownership; + so->ignore_if_true = bhv_king_bobomb_ignore_if_true; network_init_object_field(o, &o->oKingBobombUnk88); network_init_object_field(o, &o->oFlags); network_init_object_field(o, &o->oHealth); diff --git a/src/game/interaction.c b/src/game/interaction.c index ae94ddc1e..41225f29a 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -1836,6 +1836,8 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O } u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { + if (m != &gMarioStates[0]) { return false; } + if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !sInvulnerable) && (o->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO)) { if (object_facing_mario(m, o, 0x2AAA)) { @@ -1849,6 +1851,7 @@ u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struc update_mario_sound_and_camera(m); play_character_sound(m, CHAR_SOUND_OOOF); queue_rumble_data_mario(m, 5, 80); + o->usingObj = m->marioObj; return set_mario_action(m, ACT_GRABBED, 0); } } diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index 595f67b64..6a2ade4ec 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -704,12 +704,14 @@ s32 act_grabbed(struct MarioState *m) { } // error state, get out of grab - if (heldObjIsHeld || m->heldByObj == NULL || !(m->heldByObj->oInteractStatus | INT_STATUS_GRABBED_MARIO)) { + if (heldObjIsHeld || m->heldByObj == NULL || !(m->heldByObj->oInteractStatus | INT_STATUS_GRABBED_MARIO) || (m->heldByObj->usingObj != m->marioObj && m->actionArg != 0)) { m->heldByObj = NULL; return set_mario_action(m, (m->forwardVel >= 0.0f) ? ACT_THROWN_FORWARD : ACT_THROWN_BACKWARD, FALSE); } } + if (m->actionArg == 0) { m->actionArg = 1; } + return FALSE; } diff --git a/src/game/spawn_object.c b/src/game/spawn_object.c index 1d301aa67..ce6d418b7 100644 --- a/src/game/spawn_object.c +++ b/src/game/spawn_object.c @@ -312,6 +312,8 @@ struct Object *allocate_object(struct ObjectNode *objList) { obj->areaTimerDuration = 0; obj->areaTimerRunOnceCallback = NULL; + obj->usingObj = NULL; + return obj; } diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c index 76e705b1e..2222b15a6 100644 --- a/src/pc/controller/controller_keyboard_debug.c +++ b/src/pc/controller/controller_keyboard_debug.c @@ -46,7 +46,7 @@ static void debug_warp_level1() { } static void debug_warp_level2() { - dynos_warp_to_level(LEVEL_BOWSER_1, 1, 1); + dynos_warp_to_level(LEVEL_WDW, 1, 1); } static void debug_grand_star(void) {