From ccf94a6cd7ba2cfecb29c89df2bb55f8a0eaa334 Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Mon, 4 May 2026 19:48:39 -0500 Subject: [PATCH] More behavior changes/fixes --- src/game/behaviors/boo.inc.c | 39 +++++++++++++++++-------- src/game/behaviors/eyerok.inc.c | 14 ++++++--- src/game/behaviors/king_bobomb.inc.c | 18 ++++++++---- src/game/behaviors/racing_penguin.inc.c | 2 +- src/game/behaviors/snowman.inc.c | 21 +++++++++---- 5 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/game/behaviors/boo.inc.c b/src/game/behaviors/boo.inc.c index ae30c08a4..d852171f5 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -25,7 +25,7 @@ static u8 boo_ignore_update(void) { struct SyncObject* boo_sync_object_init(void) { // There's lots of different boos, all of the sync objects are initialized via this function - // all of them use distance based syncing which works fine for boos + // all of them use distance based syncing which works fine enough struct SyncObject *so = sync_object_init(o, 4000.0f); if (so == NULL) { return NULL; } so->ignore_if_true = boo_ignore_update; @@ -43,6 +43,7 @@ struct SyncObject* boo_sync_object_init(void) { sync_object_init_field(o, o->oInteractType); sync_object_init_field(o, o->oOpacity); sync_object_init_field(o, o->oRoom); + sync_object_init_field(o, o->globalPlayerIndex); return so; } @@ -350,17 +351,12 @@ static s32 boo_get_attack_status(void) { if (o->oInteractStatus & INT_STATUS_INTERACTED) { if ((o->oInteractStatus & INT_STATUS_WAS_ATTACKED) && !obj_has_attack_type(ATTACK_FROM_ABOVE)) { cur_obj_become_intangible(); - o->oInteractStatus = 0; - cur_obj_play_sound_2(SOUND_OBJ_BOO_LAUGH_SHORT); - attackStatus = BOO_ATTACKED; } else { cur_obj_play_sound_2(SOUND_OBJ_BOO_BOUNCE_TOP); - o->oInteractStatus = 0; - attackStatus = BOO_BOUNCED_ON; } } @@ -469,7 +465,17 @@ static void boo_act_1(void) { } if (attackStatus == BOO_ATTACKED) { - o->oAction = 3; + if (o->oBehParams2ndByte == 0) { + // for go on a ghost hunt, assign global player index to nearest player for dialog + struct MarioState *marioState = nearest_mario_state_to_object(o); + if (marioState && marioState->playerIndex == 0) { // only let local player assign global player index for himself + o->globalPlayerIndex = network_global_index_from_local(marioState->playerIndex); + } + o->oAction = 3; + network_send_object(o); // force send object + } else { + o->oAction = 3; + } } if (attackStatus == BOO_ATTACKED) { @@ -507,13 +513,22 @@ static void boo_act_4(void) { dialogID = gBehaviorValues.dialogs.GhostHuntDialog; } - struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState) { - if (marioState->playerIndex != 0 || cur_obj_update_dialog(&gMarioStates[0], 2, 2, dialogID, 0, boo_act_4_continue_dialog)) { + if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; + struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { + // use player with the smallest global index instead + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); + } + + if (is_player_active(marioState)) { + if (marioState->playerIndex != 0 || cur_obj_update_dialog(marioState, 2, 2, dialogID, 0, boo_act_4_continue_dialog)) { create_sound_spawner(SOUND_OBJ_DYING_ENEMY1); obj_mark_for_deletion(o); - if (dialogID == (s32) gBehaviorValues.dialogs.GhostHuntAfterDialog) { // If the Big Boo should spawn, play the jingle + if (dialogID == (s32)gBehaviorValues.dialogs.GhostHuntAfterDialog) { // If the Big Boo should spawn, play the jingle play_puzzle_jingle(); } } @@ -533,7 +548,7 @@ void bhv_boo_loop(void) { // only sync when Boo isn't in a death state if (o->oAction < 3 || o->oAction == 5) { if (!sync_object_is_initialized(o->oSyncID)) { - struct SyncObject* so = boo_sync_object_init(); + struct SyncObject *so = boo_sync_object_init(); if (so) { so->syncDeathEvent = FALSE; } } } else { diff --git a/src/game/behaviors/eyerok.inc.c b/src/game/behaviors/eyerok.inc.c index acaeffd0b..96e81ccbb 100644 --- a/src/game/behaviors/eyerok.inc.c +++ b/src/game/behaviors/eyerok.inc.c @@ -167,9 +167,12 @@ UNUSED static u8 eyerok_boss_act_show_intro_text_continue_dialog(void) { static void eyerok_boss_act_show_intro_text(void) { if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(marioState, 2, 0, CUTSCENE_DIALOG, gBehaviorValues.dialogs.EyerokIntroDialog, eyerok_boss_act_show_intro_text_continue_dialog)) { o->oAction = EYEROK_BOSS_ACT_FIGHT; @@ -234,9 +237,12 @@ u8 eyerok_boss_act_die_continue_dialog(void) { return o->oAction == EYEROK_BOSS_ static void eyerok_boss_act_die(void) { if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } if (o->oTimer == 60) { if (should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(marioState, 2, 0, CUTSCENE_DIALOG, gBehaviorValues.dialogs.EyerokDefeatedDialog, eyerok_boss_act_die_continue_dialog)) { diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c index e2ce38250..41a5890a4 100644 --- a/src/game/behaviors/king_bobomb.inc.c +++ b/src/game/behaviors/king_bobomb.inc.c @@ -65,9 +65,12 @@ void king_bobomb_act_0(void) { } else { if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombIntroDialog, king_bobomb_act_0_continue_dialog)) { o->oAction = 2; @@ -243,7 +246,7 @@ void king_bobomb_act_7(void) { marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; } // update dialog if we are within king bobomb's area - bool canUpdateDialog = (marioState->pos[1] >= o->oPosY - 100.0f); + bool canUpdateDialog = (marioState->pos[1] >= o->oPosY - 100.0f && marioState->visibleToEnemies); if (!canUpdateDialog) { // iterate through players via global index until we find someone who can for (int i = 0; i < MAX_PLAYERS; i++) { @@ -252,7 +255,7 @@ void king_bobomb_act_7(void) { marioState = &gMarioStates[np->localIndex]; if (!is_player_active(marioState)) continue; - canUpdateDialog = (marioState->pos[1] >= o->oPosY - 100.0f); + canUpdateDialog = (marioState->pos[1] >= o->oPosY - 100.0f && marioState->visibleToEnemies); if (!canUpdateDialog) continue; break; } @@ -376,9 +379,12 @@ void king_bobomb_act_5(void) { // bobomb returns home case 4: if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } if (marioState && should_start_or_continue_dialog(marioState, o) && cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, gBehaviorValues.dialogs.KingBobombCheatDialog, king_bobomb_act_5_continue_dialog)) { o->oAction = 2; diff --git a/src/game/behaviors/racing_penguin.inc.c b/src/game/behaviors/racing_penguin.inc.c index cd7f486c4..1ea4228a1 100644 --- a/src/game/behaviors/racing_penguin.inc.c +++ b/src/game/behaviors/racing_penguin.inc.c @@ -107,7 +107,7 @@ static void racing_penguin_act_show_init_text(void) { if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead struct NetworkPlayer *np = get_network_player_smallest_global(); - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + marioState = &gMarioStates[np->localIndex]; o->globalPlayerIndex = np->globalIndex; // double check that we are actually active and visible this time diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c index 5871ee1c6..98d51116d 100644 --- a/src/game/behaviors/snowman.inc.c +++ b/src/game/behaviors/snowman.inc.c @@ -17,9 +17,12 @@ static void bhv_snowmans_bottom_override_ownership(u8 *shouldOverride, u8 *shoul *shouldOverride = TRUE; if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } *shouldOwn = marioState->playerIndex == 0; } @@ -77,9 +80,12 @@ void adjust_rolling_face_pitch(f32 f12) { void snowmans_bottom_act_1(void) { if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } struct Object *player = marioState->visibleToEnemies ? marioState->marioObj : NULL; s32 angleToPlayer = player ? obj_angle_to_object(o, player) : 0; @@ -161,9 +167,12 @@ static void bhv_snowmans_bottom_handle_dialog() { } else { if (o->globalPlayerIndex >= MAX_PLAYERS) o->globalPlayerIndex = 0; struct MarioState *marioState = &gMarioStates[network_local_index_from_global(o->globalPlayerIndex)]; - if (!is_player_active(marioState)) { + if (!is_player_active(marioState) || !marioState->visibleToEnemies) { // use player with the smallest global index instead - marioState = &gMarioStates[get_network_player_smallest_global()->localIndex]; + struct NetworkPlayer *np = get_network_player_smallest_global(); + marioState = &gMarioStates[np->localIndex]; + o->globalPlayerIndex = np->globalIndex; + network_send_object(o); } if (marioState->playerIndex == 0 && should_start_or_continue_dialog(marioState, o) && (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 400) == 1) && set_mario_npc_dialog(marioState, 1, bhv_snowmans_bottom_loop_continue_dialog) && cutscene_object_with_dialog(CUTSCENE_DIALOG, o, gBehaviorValues.dialogs.SnowmanHeadBodyDialog)) { o->oForwardVel = 10.0f;