More behavior changes/fixes

This commit is contained in:
EmeraldLockdown 2026-05-04 19:48:39 -05:00
parent 9f91ce3c0f
commit ccf94a6cd7
5 changed files with 65 additions and 29 deletions

View file

@ -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 {

View file

@ -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)) {

View file

@ -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;

View file

@ -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

View file

@ -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;