diff --git a/src/game/behaviors/boo.inc.c b/src/game/behaviors/boo.inc.c index 0c41f1ea6..36b7b25e2 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -492,6 +492,8 @@ static void boo_act_3(void) { } } +u8 boo_act_4_continue_dialog(void) { return o->oAction == 4; } + // Called when a Go on a Ghost Hunt boo dies static void boo_act_4(void) { s32 dialogID; @@ -504,7 +506,7 @@ static void boo_act_4(void) { } struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState->playerIndex != 0 || cur_obj_update_dialog(&gMarioStates[0], 2, 2, dialogID, 0)) { + if (marioState->playerIndex != 0 || cur_obj_update_dialog(&gMarioStates[0], 2, 2, dialogID, 0, boo_act_4_continue_dialog)) { create_sound_spawner(SOUND_OBJ_DYING_ENEMY1); obj_mark_for_deletion(o); diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index 6fc93a1f3..dd869c8c7 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -925,6 +925,8 @@ void bowser_dead_hide(void) { o->oGravity = 0; } +u8 bowser_dead_not_bits_end_continue_dialog(void) { return o->oAction == 4 && o->oSubAction == 3; } + s32 bowser_dead_not_bits_end(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); @@ -934,7 +936,7 @@ s32 bowser_dead_not_bits_end(void) { func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40); o->oBowserUnkF8++; } - if (marioState->playerIndex == 0 && cur_obj_update_dialog(marioState, 2, 18, sBowserDefeatedDialogText[o->oBehParams2ndByte], 0)) { + if (marioState->playerIndex == 0 && cur_obj_update_dialog(marioState, 2, 18, sBowserDefeatedDialogText[o->oBehParams2ndByte], 0, bowser_dead_not_bits_end_continue_dialog)) { o->oBowserUnkF8++; cur_obj_play_sound_2(SOUND_GENERAL2_BOWSER_EXPLODE); sequence_player_unlower(SEQ_PLAYER_LEVEL, 60); @@ -950,6 +952,8 @@ s32 bowser_dead_not_bits_end(void) { return ret; } +u8 bowser_dead_bits_end_continue_dialog(void) { return o->oAction == 4 && o->oBowserUnkF8 < 2; } + s32 bowser_dead_bits_end(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); UNUSED s32 unused; @@ -964,7 +968,7 @@ s32 bowser_dead_bits_end(void) { func_8031FFB4(SEQ_PLAYER_LEVEL, 60, 40); o->oBowserUnkF8++; } - if (marioState->playerIndex == 0 && cur_obj_update_dialog(marioState, 2, 18, dialogID, 0)) { + if (marioState->playerIndex == 0 && cur_obj_update_dialog(marioState, 2, 18, dialogID, 0, bowser_dead_bits_end_continue_dialog)) { cur_obj_set_model(MODEL_BOWSER2); sequence_player_unlower(SEQ_PLAYER_LEVEL, 60); sequence_player_fade_out(0, 1); diff --git a/src/game/behaviors/camera_lakitu.inc.c b/src/game/behaviors/camera_lakitu.inc.c index e49deb61e..cb9ca4fd7 100644 --- a/src/game/behaviors/camera_lakitu.inc.c +++ b/src/game/behaviors/camera_lakitu.inc.c @@ -57,6 +57,8 @@ static void camera_lakitu_intro_act_spawn_cloud(void) { } } +u8 camera_lakitu_intro_act_show_dialog_continue_dialog(void) { return o->oCameraLakituFinishedDialog != TRUE; } + /** * Circle down to mario, show the dialog, then fly away. */ @@ -115,7 +117,7 @@ static void camera_lakitu_intro_act_show_dialog(void) { } } } - } else if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG, DIALOG_034) != 0) { + } else if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG, DIALOG_034, camera_lakitu_intro_act_show_dialog_continue_dialog) != 0) { o->oCameraLakituFinishedDialog = TRUE; } } diff --git a/src/game/behaviors/capswitch.inc.c b/src/game/behaviors/capswitch.inc.c index 284f3ebb2..30355828b 100644 --- a/src/game/behaviors/capswitch.inc.c +++ b/src/game/behaviors/capswitch.inc.c @@ -30,6 +30,8 @@ void cap_switch_act_1(void) { } } +u8 cap_switch_act_2_continue_dialog(void) { return o->oAction == 2 && o->oTimer >= 5; } + void cap_switch_act_2(void) { capSwitchForcePress = FALSE; s32 sp1C; @@ -44,10 +46,8 @@ void cap_switch_act_2(void) { } else { struct MarioState* marioState = nearest_mario_state_to_object(o); if (marioState == &gMarioStates[0]) { - sp1C = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 1, 0x0C, CUTSCENE_CAP_SWITCH_PRESS, 0); + sp1C = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 1, 0x0C, CUTSCENE_CAP_SWITCH_PRESS, 0, cap_switch_act_2_continue_dialog); if (sp1C) { o->oAction = 3; } - } else { - o->oAction = 3; } } } diff --git a/src/game/behaviors/eyerok.inc.c b/src/game/behaviors/eyerok.inc.c index 42e2b1e82..a1398f7c0 100644 --- a/src/game/behaviors/eyerok.inc.c +++ b/src/game/behaviors/eyerok.inc.c @@ -62,8 +62,10 @@ static void eyerok_boss_act_wake_up(void) { } } +u8 eyerok_boss_act_show_intro_text_continue_dialog(void) { return o->oAction == EYEROK_BOSS_ACT_SHOW_INTRO_TEXT; } + static void eyerok_boss_act_show_intro_text(void) { - if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, DIALOG_117)) { + if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, DIALOG_117, eyerok_boss_act_show_intro_text_continue_dialog)) { o->oAction = EYEROK_BOSS_ACT_FIGHT; } } @@ -115,9 +117,11 @@ static void eyerok_boss_act_fight(void) { } } +u8 eyerok_boss_act_die_continue_dialog(void) { return o->oAction == EYEROK_BOSS_ACT_DIE; } + static void eyerok_boss_act_die(void) { if (o->oTimer == 60) { - if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, DIALOG_118)) { + if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, DIALOG_118, eyerok_boss_act_die_continue_dialog)) { spawn_default_star(0.0f, -900.0f, -3700.0f); } else { o->oTimer -= 1; diff --git a/src/game/behaviors/koopa.inc.c b/src/game/behaviors/koopa.inc.c index b9d8bbeda..59a19568e 100644 --- a/src/game/behaviors/koopa.inc.c +++ b/src/game/behaviors/koopa.inc.c @@ -580,6 +580,8 @@ static void koopa_the_quick_force_start_race(void) { o->oFlags |= OBJ_FLAG_ACTIVE_FROM_AFAR; } +u8 koopa_the_quick_act_show_init_text_continue_dialog(void) { return o->oAction == KOOPA_THE_QUICK_ACT_SHOW_INIT_TEXT; } + /** * Display the dialog asking mario if he wants to race. Begin the race or * return to the waiting action. @@ -588,7 +590,7 @@ static void koopa_the_quick_act_show_init_text(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); s32 response = 0; if (marioState == &gMarioStates[0]) { - response = obj_update_race_proposition_dialog(&gMarioStates[0], sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].initText); + response = obj_update_race_proposition_dialog(&gMarioStates[0], sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].initText, koopa_the_quick_act_show_init_text_continue_dialog); } if (response == 1) { @@ -778,6 +780,8 @@ static void koopa_the_quick_act_stop(void) { } } +u8 koopa_the_quick_act_after_race_continue_dialog(void) { return o->oAction == KOOPA_THE_QUICK_ACT_AFTER_RACE && o->parentObj->oKoopaRaceEndpointUnk100 > 0; } + /** * Wait for mario to approach, then show text indicating the status of the race. * If mario got to the finish line first and didn't use the cannon, then spawn @@ -812,7 +816,7 @@ static void koopa_the_quick_act_after_race(void) { } } else if (o->parentObj->oKoopaRaceEndpointUnk100 > 0) { if (marioState == &gMarioStates[0]) { - s32 dialogResponse = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, o->parentObj->oKoopaRaceEndpointUnk100); + s32 dialogResponse = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, o->parentObj->oKoopaRaceEndpointUnk100, koopa_the_quick_act_after_race_continue_dialog); if (dialogResponse != 0) { o->parentObj->oKoopaRaceEndpointUnk100 = -1; o->oTimer = 0; diff --git a/src/game/behaviors/racing_penguin.inc.c b/src/game/behaviors/racing_penguin.inc.c index 60e965da4..77f1c1245 100644 --- a/src/game/behaviors/racing_penguin.inc.c +++ b/src/game/behaviors/racing_penguin.inc.c @@ -51,11 +51,13 @@ static void racing_penguin_force_start_race(void) { penguinForceStartRace = FALSE; } +u8 racing_penguin_act_show_init_text_continue_dialog(void) { return o->oAction == RACING_PENGUIN_ACT_SHOW_INIT_TEXT; } + static void racing_penguin_act_show_init_text(void) { s32 response; struct Object *child; - response = obj_update_race_proposition_dialog(&gMarioStates[0], sRacingPenguinData[o->oBehParams2ndByte].text); + response = obj_update_race_proposition_dialog(&gMarioStates[0], sRacingPenguinData[o->oBehParams2ndByte].text, racing_penguin_act_show_init_text_continue_dialog); if (response == 1) { child = cur_obj_nearest_object_with_behavior(bhvPenguinRaceFinishLine); child->parentObj = o; @@ -151,6 +153,8 @@ static void racing_penguin_act_finish_race(void) { } } +u8 racing_penguin_act_show_final_text_continue_dialog(void) { return o->oAction == RACING_PENGUIN_ACT_SHOW_FINAL_TEXT && o->oRacingPenguinFinalTextbox > 0; } + static void racing_penguin_act_show_final_text(void) { s32 textResult; @@ -181,7 +185,7 @@ static void racing_penguin_act_show_final_text(void) { o->oForwardVel = 4.0f; } } else if (o->oRacingPenguinFinalTextbox > 0) { - if ((textResult = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, o->oRacingPenguinFinalTextbox)) != 0) { + if ((textResult = cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, o->oRacingPenguinFinalTextbox, racing_penguin_act_show_final_text_continue_dialog)) != 0) { o->oRacingPenguinFinalTextbox = -1; o->oTimer = 0; } diff --git a/src/game/behaviors/sl_snowman_wind.inc.c b/src/game/behaviors/sl_snowman_wind.inc.c index da518f856..6651c48e6 100644 --- a/src/game/behaviors/sl_snowman_wind.inc.c +++ b/src/game/behaviors/sl_snowman_wind.inc.c @@ -1,5 +1,7 @@ // sl_snowman_wind.c.inc +u8 bhv_sl_snowman_wind_loop_continue_dialog(void) { return o->oSubAction == SL_SNOWMAN_WIND_ACT_TALKING; } + void bhv_sl_snowman_wind_loop(void) { UNUSED s32 unusedVar = 0; s16 marioAngleFromWindSource; @@ -21,7 +23,7 @@ void bhv_sl_snowman_wind_loop(void) { // Mario has come close, begin dialog. } else if (o->oSubAction == SL_SNOWMAN_WIND_ACT_TALKING) { - if (cur_obj_update_dialog(&gMarioStates[0], 2, 2, DIALOG_153, 0)) + if (cur_obj_update_dialog(&gMarioStates[0], 2, 2, DIALOG_153, 0, bhv_sl_snowman_wind_loop_continue_dialog)) o->oSubAction++; // Blowing, spawn wind particles (SL_SNOWMAN_WIND_ACT_BLOWING) diff --git a/src/game/behaviors/tuxie.inc.c b/src/game/behaviors/tuxie.inc.c index 280d1318d..accfda363 100644 --- a/src/game/behaviors/tuxie.inc.c +++ b/src/game/behaviors/tuxie.inc.c @@ -43,6 +43,8 @@ void tuxies_mother_act_2(void) { } } +u8 tuxies_mother_act_1_continue_dialog(void) { return (o->oAction == 1 && o->oSubAction == 0); } + void tuxies_mother_act_1(void) { // only local can interact with mother struct MarioState* marioState = &gMarioStates[0]; @@ -60,7 +62,7 @@ void tuxies_mother_act_1(void) { dialogID = DIALOG_058; else dialogID = DIALOG_059; - if (cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, dialogID)) { + if (cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, dialogID, tuxies_mother_act_1_continue_dialog)) { if (dialogID == DIALOG_058) o->oSubAction = 1; else @@ -102,6 +104,8 @@ void tuxies_mother_act_1(void) { } } +u8 tuxies_mother_act_0_continue_dialog(void) { return (o->oAction == 0 && o->oSubAction == 1); } + void tuxies_mother_act_0(void) { // only local can interact with mother struct MarioState* marioState = &gMarioStates[0]; @@ -116,11 +120,9 @@ void tuxies_mother_act_0(void) { cur_obj_init_animation_with_sound(3); if (sp28 < 500.0f) sp2C = 1; - if (sp24 != NULL && sp28 < 300.0f && sp24->oHeldState != HELD_FREE) { - if (sp24->heldByPlayerIndex == 0) { - o->oAction = 1; - sp24->oSmallPenguinUnk88 = 1; - } + if (sp24->heldByPlayerIndex == 0 && sp24 != NULL && sp28 < 300.0f && sp24->oHeldState != HELD_FREE) { + o->oAction = 1; + sp24->oSmallPenguinUnk88 = 1; o->prevObj = sp24; } else { switch (o->oSubAction) { @@ -130,7 +132,7 @@ void tuxies_mother_act_0(void) { o->oSubAction++; break; case 1: - if (cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, DIALOG_057)) + if (cur_obj_update_dialog_with_cutscene(marioState, 2, 1, CUTSCENE_DIALOG, DIALOG_057, tuxies_mother_act_0_continue_dialog)) o->oSubAction++; break; case 2: diff --git a/src/game/behaviors/ukiki.inc.c b/src/game/behaviors/ukiki.inc.c index 5693cabdb..6003f96ff 100644 --- a/src/game/behaviors/ukiki.inc.c +++ b/src/game/behaviors/ukiki.inc.c @@ -333,6 +333,8 @@ static Trajectory sCageUkikiPath[] = { TRAJECTORY_END(), }; +u8 ukiki_act_go_to_cage_continue_dialog(void) { return o->oAction == UKIKI_ACT_GO_TO_CAGE && o->oSubAction == UKIKI_SUB_ACT_CAGE_TALK_TO_MARIO; } + /** * Travel to the cage, wait for Mario, jump to it, and ride it to * our death. Ukiki is a tad suicidal. @@ -383,7 +385,7 @@ void ukiki_act_go_to_cage(void) { case UKIKI_SUB_ACT_CAGE_TALK_TO_MARIO: cur_obj_init_animation_with_sound(UKIKI_ANIM_HANDSTAND); - if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, DIALOG_080)) { + if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, DIALOG_080, ukiki_act_go_to_cage_continue_dialog)) { o->oSubAction++; } break; @@ -554,6 +556,9 @@ void cage_ukiki_held_loop(void) { } } +u8 hat_ukiki_held_loop_1(void) { return o->oHeldState == HELD_HELD && o->oUkikiTextState == UKIKI_TEXT_STEAL_HAT; } +u8 hat_ukiki_held_loop_2(void) { return o->oHeldState == HELD_HELD && o->oUkikiTextState == UKIKI_TEXT_HAS_HAT; } + /** * Called by the main behavior function for the hat ukiki whenever it is held. */ @@ -567,7 +572,7 @@ void hat_ukiki_held_loop(void) { break; case UKIKI_TEXT_STEAL_HAT: - if (cur_obj_update_dialog(&gMarioStates[0], 2, 2, DIALOG_100, 0)) { + if (cur_obj_update_dialog(&gMarioStates[0], 2, 2, DIALOG_100, 0, hat_ukiki_held_loop_1)) { o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY; o->oUkikiTextState = UKIKI_TEXT_STOLE_HAT; } @@ -577,7 +582,7 @@ void hat_ukiki_held_loop(void) { break; case UKIKI_TEXT_HAS_HAT: - if (cur_obj_update_dialog(&gMarioStates[0], 2, 18, DIALOG_101, 0)) { + if (cur_obj_update_dialog(&gMarioStates[0], 2, 18, DIALOG_101, 0, hat_ukiki_held_loop_2)) { mario_retrieve_cap(); set_mario_npc_dialog(&gMarioStates[0], 0); o->oUkikiHasHat &= ~UKIKI_HAT_ON; diff --git a/src/game/behaviors/whomp.inc.c b/src/game/behaviors/whomp.inc.c index 62757db60..678e6c516 100644 --- a/src/game/behaviors/whomp.inc.c +++ b/src/game/behaviors/whomp.inc.c @@ -14,6 +14,8 @@ void whomp_play_sfx_from_pound_animation(void) { cur_obj_play_sound_2(SOUND_OBJ_POUNDING1); } +u8 whomp_act_0_continue_dialog(void) { return o->oAction == 0; } + void whomp_act_0(void) { struct MarioState* marioState = nearest_mario_state_to_object(o); struct Object* player = marioState->marioObj; @@ -32,7 +34,7 @@ void whomp_act_0(void) { cur_obj_set_pos_to_home(); o->oHealth = 3; } - } else if (marioState == &gMarioStates[0] && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, DIALOG_114)) { + } else if (marioState == &gMarioStates[0] && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 1, CUTSCENE_DIALOG, DIALOG_114, whomp_act_0_continue_dialog)) { o->oAction = 2; network_send_object(o); } @@ -230,10 +232,12 @@ void whomp_act_6(void) { } } +u8 whomp_act_8_continue_dialog(void) { return o->oAction == 8; } + void whomp_act_8(void) { if (o->oBehParams2ndByte != 0) { struct MarioState* marioState = nearest_mario_state_to_object(o); - if (marioState == &gMarioStates[0] && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 2, CUTSCENE_DIALOG, DIALOG_115)) { + if (marioState == &gMarioStates[0] && cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 2, CUTSCENE_DIALOG, DIALOG_115, whomp_act_8_continue_dialog)) { obj_set_angle(o, 0, 0, 0); cur_obj_hide(); cur_obj_become_intangible(); diff --git a/src/game/behaviors/wiggler.inc.c b/src/game/behaviors/wiggler.inc.c index 23a31b895..e01f0a632 100644 --- a/src/game/behaviors/wiggler.inc.c +++ b/src/game/behaviors/wiggler.inc.c @@ -209,6 +209,8 @@ void wiggler_init_segments(void) { } } + u8 wiggler_act_walk_continue_dialog(void) { return o->oAction == WIGGLER_ACT_WALK && o->oWigglerTextStatus < WIGGLER_TEXT_STATUS_COMPLETED_DIALOG; } + /** * Show text if necessary. Then walk toward mario if not at full health, and * otherwise wander in random directions. @@ -228,7 +230,7 @@ static void wiggler_act_walk(void) { // If Mario is positioned below the wiggler, assume he entered through the // lower cave entrance, so don't display text. - if (gMarioObject->oPosY < o->oPosY || cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, DIALOG_150) != 0) { + if (gMarioObject->oPosY < o->oPosY || cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, DIALOG_150, wiggler_act_walk_continue_dialog) != 0) { o->oWigglerTextStatus = WIGGLER_TEXT_STATUS_COMPLETED_DIALOG; } } else { @@ -284,6 +286,9 @@ static void wiggler_act_walk(void) { } } } + +u8 wiggler_act_jumped_on_continue_dialog(void) { return o->oAction == WIGGLER_ACT_JUMPED_ON && o->header.gfx.scale[1] >= 4.0f && o->oTimer > 30; } + /** * Squish and unsquish, then show text and enter either the walking or shrinking * action. @@ -304,7 +309,7 @@ static void wiggler_act_jumped_on(void) { // defeated) or go back to walking if (o->header.gfx.scale[1] >= 4.0f) { if (o->oTimer > 30) { - if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, attackText[o->oHealth - 2]) != 0) { + if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 2, 0, CUTSCENE_DIALOG, attackText[o->oHealth - 2], wiggler_act_jumped_on_continue_dialog) != 0) { // Because we don't want the wiggler to disappear after being // defeated, we leave its health at 1 if (--o->oHealth == 1) { diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 65a59558c..1a07fbe14 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -358,6 +358,8 @@ s32 set_mario_npc_dialog(struct MarioState* m, s32 actionArg) { if (m->playerIndex == 0 && actionArg == 0) { localDialogNPCBehavior = NULL; + continueDialogFunction = NULL; + continueDialogFunctionObject = NULL; } // in dialog @@ -395,8 +397,17 @@ s32 act_reading_npc_dialog(struct MarioState *m) { s32 headTurnAmount = 0; s16 angleToNPC; + if (m->playerIndex != 0) { return FALSE; } + if (m->playerIndex == 0) { - if (m->usedObj == NULL || m->usedObj->activeFlags == ACTIVE_FLAG_DEACTIVATED || m->usedObj->behavior != localDialogNPCBehavior) { + u8 continueDialogCallback = TRUE; + if (continueDialogFunction != NULL && continueDialogFunctionObject != NULL) { + struct Object* tmp = gCurrentObject; + gCurrentObject = continueDialogFunctionObject; + continueDialogCallback = continueDialogFunction(); + gCurrentObject = tmp; + } + if (!continueDialogCallback || m->usedObj == NULL || m->usedObj->activeFlags == ACTIVE_FLAG_DEACTIVATED || m->usedObj->behavior != localDialogNPCBehavior) { set_mario_npc_dialog(m, 0); } } diff --git a/src/game/mario_misc.c b/src/game/mario_misc.c index b3e40c477..d7495c111 100644 --- a/src/game/mario_misc.c +++ b/src/game/mario_misc.c @@ -124,7 +124,7 @@ static void toad_message_opaque(void) { } static void toad_message_talking(void) { - if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId) + if (cur_obj_update_dialog_with_cutscene(&gMarioStates[0], 3, 1, CUTSCENE_DIALOG, gCurrentObject->oToadMessageDialogId, NULL) != 0) { gCurrentObject->oToadMessageRecentlyTalked = 1; gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING; diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index 97969d6cf..c2f73a9ad 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -97,9 +97,8 @@ static s16 obj_get_pitch_from_vel(void) { * If the player declines the race, then disable time stop and allow Mario to * move again. */ -static s32 obj_update_race_proposition_dialog(struct MarioState* m, s16 dialogID) { - s32 dialogResponse = - cur_obj_update_dialog_with_cutscene(m, 2, DIALOG_UNK2_FLAG_0 | DIALOG_UNK2_LEAVE_TIME_STOP_ENABLED, CUTSCENE_RACE_DIALOG, dialogID); +static s32 obj_update_race_proposition_dialog(struct MarioState* m, s16 dialogID, u8 (*inContinueDialogFunction)(void)) { + s32 dialogResponse = cur_obj_update_dialog_with_cutscene(m, 2, DIALOG_UNK2_FLAG_0 | DIALOG_UNK2_LEAVE_TIME_STOP_ENABLED, CUTSCENE_RACE_DIALOG, dialogID, inContinueDialogFunction); if (dialogResponse == 2) { set_mario_npc_dialog(m, 0); diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index c1a457e1e..d3c0fa19f 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -27,6 +27,9 @@ #include "spawn_object.h" #include "spawn_sound.h" +u8 (*continueDialogFunction)(void) = NULL; +struct Object* continueDialogFunctionObject = NULL; + s8 D_8032F0A0[] = { 0xF8, 0x08, 0xFC, 0x04 }; s16 D_8032F0A4[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; static s8 sLevelsWithRooms[] = { LEVEL_BBH, LEVEL_CASTLE, LEVEL_HMC, -1 }; @@ -2663,6 +2666,8 @@ s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 h } static void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) { + if (m->playerIndex != 0) { return 0; } + o->oDialogResponse = dialogResult; o->oDialogState++; @@ -2671,10 +2676,14 @@ static void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialog } } -s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused) { +s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused, u8 (*inContinueDialogFunction)(void)) { s32 dialogResponse = 0; UNUSED s32 doneTurning = TRUE; + if (m->playerIndex != 0) { return 0; } + continueDialogFunctionObject = gCurrentObject; + continueDialogFunction = inContinueDialogFunction; + switch (o->oDialogState) { #ifdef VERSION_JP case DIALOG_UNK1_ENABLE_TIME_STOP: @@ -2748,10 +2757,14 @@ s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, return dialogResponse; } -s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID) { +s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID, u8 (*inContinueDialogFunction)(void)) { s32 dialogResponse = 0; s32 doneTurning = TRUE; + if (m->playerIndex != 0) { return 0; } + continueDialogFunctionObject = gCurrentObject; + continueDialogFunction = inContinueDialogFunction; + switch (o->oDialogState) { #ifdef VERSION_JP case DIALOG_UNK2_ENABLE_TIME_STOP: diff --git a/src/game/object_helpers.h b/src/game/object_helpers.h index 7fd97d922..6b1ada53f 100644 --- a/src/game/object_helpers.h +++ b/src/game/object_helpers.h @@ -67,6 +67,9 @@ struct SpawnParticlesInfo /*0x10*/ f32 sizeRange; }; +extern u8 (*continueDialogFunction)(void); +extern struct Object* continueDialogFunctionObject; + Gfx *geo_update_projectile_pos_from_parent(s32 callContext, UNUSED struct GraphNode *node, Mat4 mtx); Gfx *geo_update_layer_transparency(s32 callContext, struct GraphNode *node, UNUSED void *context); #ifdef AVOID_UB @@ -277,8 +280,8 @@ void set_time_stop_flags(s32 flags); void clear_time_stop_flags(s32 flags); s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused); s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 height); -s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused); -s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID); +s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused, u8 (*inContinueDialogFunction)(void)); +s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID, u8 (*inContinueDialogFunction)(void)); s32 cur_obj_has_model(u16 modelID); void cur_obj_align_gfx_with_floor(void); s32 mario_is_within_rectangle(s16 minX, s16 maxX, s16 minZ, s16 maxZ);