From d18d385746134405316a233e804e0ad78a096593 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Wed, 11 Jun 2025 22:46:26 -0400 Subject: [PATCH] Implement & link ac_npc_restart --- configure.py | 2 +- include/ac_npc_restart.h | 21 +- include/m_card.h | 1 + src/actor/npc/ac_npc_restart.c | 158 ++++++++++ src/actor/npc/ac_npc_restart_schedule.c_inc | 91 ++++++ src/actor/npc/ac_npc_restart_talk.c_inc | 315 ++++++++++++++++++++ 6 files changed, 586 insertions(+), 2 deletions(-) create mode 100644 src/actor/npc/ac_npc_restart.c create mode 100644 src/actor/npc/ac_npc_restart_schedule.c_inc create mode 100644 src/actor/npc/ac_npc_restart_talk.c_inc diff --git a/configure.py b/configure.py index b0524e9a..feca854a 100644 --- a/configure.py +++ b/configure.py @@ -1134,7 +1134,7 @@ config.libs = [ Object(Matching, "actor/npc/ac_npc_post_man.c"), Object(Matching, "actor/npc/ac_npc_rcn_guide.c"), Object(Matching, "actor/npc/ac_npc_rcn_guide2.c"), - Object(NonMatching, "actor/npc/ac_npc_restart.c"), + Object(Matching, "actor/npc/ac_npc_restart.c"), Object(Matching, "actor/npc/ac_npc_rtc.c"), Object(Matching, "actor/npc/ac_npc_sendo.c"), Object(Matching, "actor/npc/ac_npc_shasho.c"), diff --git a/include/ac_npc_restart.h b/include/ac_npc_restart.h index a8eb1e45..2de89094 100644 --- a/include/ac_npc_restart.h +++ b/include/ac_npc_restart.h @@ -3,11 +3,31 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +typedef struct npc_restart_s NPC_RESTART_ACTOR; + +typedef void (*aNRST_TALK_PROC)(NPC_RESTART_ACTOR* actor, GAME_PLAY* play); + +struct npc_restart_s { + NPC_ACTOR npc_class; + int talk_idx; + int next_talk_idx; + aNRST_TALK_PROC talk_proc; + int talk_end; + int _9A4; + int think_idx; + int card_chan; + u8 actor_saved; + u8 auto_nwrite_data_set; + u8 cheated_flag; + u8 force_home; +}; + extern ACTOR_PROFILE Npc_Restart_Profile; #ifdef __cplusplus @@ -15,4 +35,3 @@ extern ACTOR_PROFILE Npc_Restart_Profile; #endif #endif - diff --git a/include/m_card.h b/include/m_card.h index fd721151..1ffc2672 100644 --- a/include/m_card.h +++ b/include/m_card.h @@ -288,6 +288,7 @@ enum { extern int mCD_GetThisLandSlotNo_code(int* player_no, s32* slot_card_results); extern int mCD_GetThisLandSlotNo(void); +extern int mCD_GetSaveHomeSlotNo(void); extern void mCD_save_data_aram_malloc(void); extern void mCD_set_aram_save_data(); extern void mCD_init_card(); diff --git a/src/actor/npc/ac_npc_restart.c b/src/actor/npc/ac_npc_restart.c new file mode 100644 index 00000000..1074d95a --- /dev/null +++ b/src/actor/npc/ac_npc_restart.c @@ -0,0 +1,158 @@ +#include "ac_npc_restart.h" + +#include "m_common_data.h" +#include "m_msg.h" +#include "m_card.h" +#include "m_player_lib.h" +#include "m_soncho.h" +#include "m_house.h" +#include "m_bgm.h" +#include "m_string.h" + +enum { + aNRST_THINK_START, + aNRST_THINK_TITLE, + aNRST_THINK_DOOR, + aNRST_THINK_WAIT, + + aNRST_THINK_NUM +}; + +enum { + aNRST_TALK_SELECT, + aNRST_TALK_BEFORE_SAVE, + aNRST_TALK_SAVE, + aNRST_TALK_SELECT2, + aNRST_TALK_SELECT3, + aNRST_TALK_BEFORE_INIT, + aNRST_TALK_INIT, + aNRST_TALK_WAIT_END, + + aNRST_TALK_NUM +}; + +enum { + aNRST_MSG_GROUP1, + aNRST_MSG_GROUP2, + aNRST_MSG_GROUP3, + + aNRST_MSG_TYPE_NUM +}; + +static void aNRST_actor_ct(ACTOR* actorx, GAME* game); +static void aNRST_actor_dt(ACTOR* actorx, GAME* game); +static void aNRST_actor_move(ACTOR* actorx, GAME* game); +static void aNRST_actor_draw(ACTOR* actorx, GAME* game); +static void aNRST_actor_save(ACTOR* actorx, GAME* game); +static void aNRST_actor_init(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Npc_Restart_Profile = { + mAc_PROFILE_NPC_RESTART, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + SP_NPC_RESTART, + ACTOR_OBJ_BANK_KEEP, + sizeof(NPC_RESTART_ACTOR), + aNRST_actor_ct, + aNRST_actor_dt, + aNRST_actor_init, + mActor_NONE_PROC1, + aNRST_actor_save, +}; +// clang-format on + +static u8 aNRST_sound_mode[] = { 0, 1, 2 }; +static u8 aNRST_voice_mode[] = { 0, 1, 2 }; + +static void aNRST_talk_request(ACTOR* actorx, GAME* game); +static int aNRST_talk_init(ACTOR* actorx, GAME* game); +static int aNRST_talk_end_chk(ACTOR* actorx, GAME* game); + +static void aNRST_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type); +static void aNRST_setup_think_proc(NPC_RESTART_ACTOR* actor, GAME_PLAY* play, int think_idx); +static void aNRST_change_talk_proc(NPC_RESTART_ACTOR* actor, int talk_idx); + +static void aNRST_actor_ct(ACTOR* actorx, GAME* game) { + static aNPC_ct_data_c ct_data = { + aNRST_actor_move, + aNRST_actor_draw, + aNPC_CT_SCHED_TYPE_SPECIAL, + (aNPC_TALK_REQUEST_PROC)none_proc1, + aNRST_talk_init, + aNRST_talk_end_chk, + 0, + }; + GAME_PLAY* play = (GAME_PLAY*)game; + + if (NPC_CLIP->birth_check_proc(actorx, game) == TRUE) { + NPC_RESTART_ACTOR* actor = (NPC_RESTART_ACTOR*)actorx; + + actor->npc_class.schedule.schedule_proc = aNRST_schedule_proc; + NPC_CLIP->ct_proc(actorx, game, &ct_data); + actorx->status_data.weight = MASSTYPE_IMMOVABLE; + + mPlib_request_main_demo_wait_type1(game, FALSE, NULL); + + { + ACTOR* playerx = GET_PLAYER_ACTOR_GAME_ACTOR(game); + + if (playerx != NULL) { + playerx->state_bitfield |= ACTOR_STATE_INVISIBLE; + } + } + + { + xyz_t pos; + xyz_t eye; + + pos.x = 100.0f; + pos.y = 60.0f; + pos.z = 60.0f; + + eye.x = 100.0f; + eye.y = 130.0f; + eye.z = 210.0f; + + Camera2_change_priority(play, 0); + Camera2_request_main_lock(play, &pos, &eye, 40.0f, 0, 100.0f, 400.0f, 5); + } + + sAdo_SetOutMode(aNRST_sound_mode[Save_Get(config).sound_mode]); + sAdo_SetVoiceMode(aNRST_voice_mode[Save_Get(config).voice_mode]); + + actor->npc_class.condition_info.hide_request = FALSE; + actor->npc_class.condition_info.demo_flg = aNPC_COND_DEMO_SKIP_FEEL_CHECK; + actor->npc_class.talk_info.melody_inst = 0; + actor->npc_class.talk_info.memory = 0; + + actor->actor_saved = FALSE; + actor->auto_nwrite_data_set = FALSE; + actor->cheated_flag = Save_Get(cheated_flag); + actor->force_home = Save_Get(npc_force_go_home); + } +} + +static void aNRST_actor_save(ACTOR* actorx, GAME* game) { + NPC_CLIP->save_proc(actorx, game); +} + +static void aNRST_actor_dt(ACTOR* actorx, GAME* game) { + NPC_CLIP->dt_proc(actorx, game); +} + +static void aNRST_actor_init(ACTOR* actorx, GAME* game) { + NPC_CLIP->init_proc(actorx, game); +} + +static void aNRST_actor_move(ACTOR* actorx, GAME* game) { + NPC_CLIP->move_proc(actorx, game); + mSC_change_player_freeze((GAME_PLAY*)game); +} + +#include "../src/actor/npc/ac_npc_restart_schedule.c_inc" +#include "../src/actor/npc/ac_npc_restart_talk.c_inc" + +static void aNRST_actor_draw(ACTOR* actorx, GAME* game) { + NPC_CLIP->draw_proc(actorx, game); +} diff --git a/src/actor/npc/ac_npc_restart_schedule.c_inc b/src/actor/npc/ac_npc_restart_schedule.c_inc new file mode 100644 index 00000000..cbe6d492 --- /dev/null +++ b/src/actor/npc/ac_npc_restart_schedule.c_inc @@ -0,0 +1,91 @@ +static void aNRST_think_start(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + actor->npc_class.talk_info.talk_request_proc = aNRST_talk_request; +} + +static void aNRST_think_title(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + play->fb_wipe_type = 3; + play->fb_fade_type = 4; + mPlib_request_main_invade_type1((GAME*)play); + Actor_info_save_actor(play); + actor->think_idx = aNRST_THINK_WAIT; +} + +static void aNRST_think_door(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + Door_data_c door_data; + static s16 homeX[] = { 2128, 2352, 2128, 2352 }; + static s16 homeZ[] = { 1488, 1488, 1768, 1768 }; + static u8 drt[] = { mSc_DIRECT_SOUTH_EAST, mSc_DIRECT_SOUTH_WEST, mSc_DIRECT_SOUTH_EAST, mSc_DIRECT_SOUTH_WEST }; + int arrange_idx = mHS_get_arrange_idx(Common_Get(player_no)); + + door_data.next_scene_id = SCENE_FG; + door_data.exit_position.x = 2240; + door_data.exit_position.z = 2240; + door_data.exit_type = 1; + door_data.extra_data = 1; + door_data.exit_position.y = 0; + door_data.door_actor_name = EMPTY_NO; + door_data.wipe_type = 3; + + // set with real data? + // this is strange and I suspect this was toggled on/off for debugging + door_data.exit_position.x = homeX[arrange_idx]; + door_data.exit_position.z = homeZ[arrange_idx]; + door_data.exit_orientation = drt[arrange_idx]; + door_data.door_actor_name = HOUSE0 + arrange_idx; + + goto_other_scene(play, &door_data, TRUE); + Common_Get(transition).wipe_type = 1; + play->fb_fade_type = 9; + mBGMPsComp_make_ps_wipe(0x31C2); +} + +typedef void (*aNRST_THINK_PROC)(NPC_RESTART_ACTOR* actor, GAME_PLAY* play); + +// clang-format off +static aNRST_THINK_PROC aNRST_proc_table[] = { + aNRST_think_start, + aNRST_think_title, + aNRST_think_door, + (aNRST_THINK_PROC)none_proc1, +}; +// clang-format on + +static void aNRST_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + NPC_RESTART_ACTOR* actor = (NPC_RESTART_ACTOR*)nactorx; + + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + (*aNRST_proc_table[actor->think_idx])(actor, play); + } +} + +static void aNRST_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->request.act_priority = 4; + nactorx->request.act_idx = aNPC_ACT_WAIT; + nactorx->request.act_type = aNPC_ACT_TYPE_DEFAULT; +} + +static void aNRST_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC think_proc[] = { aNRST_think_init_proc, aNRST_think_main_proc }; + + (*think_proc[type])(nactorx, play); +} + +static void aNRST_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + NPC_RESTART_ACTOR* actor = (NPC_RESTART_ACTOR*)nactorx; + + nactorx->think.think_proc = aNRST_think_proc; + actor->think_idx = aNRST_THINK_START; + NPC_CLIP->think_proc(nactorx, play, aNPC_THINK_IN_BLOCK, aNPC_THINK_TYPE_INIT); +} + +static void aNRST_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (!NPC_CLIP->think_proc(nactorx, play, -1, aNPC_THINK_TYPE_CHK_INTERRUPT)) { + NPC_CLIP->think_proc(nactorx, play, -1, aNPC_THINK_TYPE_MAIN); + } +} + +static void aNRST_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC sche_proc[] = { aNRST_schedule_init_proc, aNRST_schedule_main_proc }; + + (*sche_proc[type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc_restart_talk.c_inc b/src/actor/npc/ac_npc_restart_talk.c_inc new file mode 100644 index 00000000..fd750f82 --- /dev/null +++ b/src/actor/npc/ac_npc_restart_talk.c_inc @@ -0,0 +1,315 @@ +static int aNRST_get_message(NPC_RESTART_ACTOR* actor, int idx, int group) { + static int msg_table[] = { 0x30CD, 0x30E1, 0x30F5, 0x3109, 0x311D, 0x3131 }; + static int msg_table2[] = { 0x2B09, 0x2B0F, 0x2B15, 0x2B1B, 0x2B21, 0x2B27 }; + static int msg_table3[] = { 0x3B14, 0x3B1E, 0x3B28, 0x3B32, 0x3B3C, 0x3B46 }; + int looks = mNpc_GetNpcLooks((ACTOR*)actor); + int msg_no; + + switch (group) { + case aNRST_MSG_GROUP1: + msg_no = msg_table[looks] + idx; + break; + case aNRST_MSG_GROUP2: + msg_no = msg_table2[looks] + idx; + break; + case aNRST_MSG_GROUP3: + msg_no = msg_table3[looks] + idx; + break; + default: + msg_no = msg_table[looks] + idx; + break; + } + + return msg_no; +} + +static void aNRST_set_slot_name(int chan) { + static u8 str[mString_DEFAULT_STR_SIZE]; + + mString_Load_StringFromRom(str, sizeof(str), 0x6CD + chan); + mMsg_SET_FREE_STR(mMsg_FREE_STR4, str, sizeof(str)); +} + +static void aNRST_set_slot_before_save(void) { + int chan = 0; + int slot_no = mCD_GetSaveHomeSlotNo(); + + if (slot_no == mCD_SLOT_A || slot_no == mCD_SLOT_B) { + chan = slot_no; + } + + aNRST_set_slot_name(chan); +} + +static void aNRST_select2(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order != 0 && mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + + switch (mChoice_GET_CHOSENUM()) { + case mChoice_CHOICE0: + actor->think_idx = aNRST_THINK_TITLE; + aNRST_change_talk_proc(actor, aNRST_TALK_BEFORE_SAVE); + aNRST_set_slot_before_save(); + break; + case mChoice_CHOICE1: + actor->think_idx = aNRST_THINK_DOOR; + aNRST_change_talk_proc(actor, aNRST_TALK_BEFORE_SAVE); + Save_Set(cheated_flag, actor->cheated_flag); + Save_Set(npc_force_go_home, actor->force_home); + aNRST_set_slot_before_save(); + break; + case mChoice_CHOICE2: + actor->think_idx = aNRST_THINK_TITLE; + aNRST_change_talk_proc(actor, aNRST_TALK_WAIT_END); + break; + case mChoice_CHOICE3: + actor->think_idx = aNRST_THINK_DOOR; + Save_Set(cheated_flag, actor->cheated_flag); + Save_Set(npc_force_go_home, actor->force_home); + break; + } + + if (!actor->actor_saved) { + Actor_info_save_actor(play); + actor->actor_saved = TRUE; + } + } +} + +static void aNRST_select(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order != 0 && mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + + switch (mChoice_GET_CHOSENUM()) { + case mChoice_CHOICE1: + actor->think_idx = aNRST_THINK_DOOR; + Save_Set(cheated_flag, actor->cheated_flag); + Save_Set(npc_force_go_home, actor->force_home); + break; + case mChoice_CHOICE0: + actor->think_idx = aNRST_THINK_TITLE; + break; + } + + aNRST_change_talk_proc(actor, aNRST_TALK_BEFORE_SAVE); + aNRST_set_slot_before_save(); + if (!actor->actor_saved) { + Actor_info_save_actor(play); + actor->actor_saved = TRUE; + } + } +} + +static void aNRST_select3(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order != 0 && mMsg_CHECK_MAINNORMALCONTINUE() == TRUE) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + + switch (mChoice_GET_CHOSENUM()) { + case mChoice_CHOICE0: + aNRST_change_talk_proc(actor, aNRST_TALK_BEFORE_INIT); + break; + case mChoice_CHOICE1: + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT2); + break; + } + } +} + +static void aNRST_before_save(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order != 0) { + if (!actor->auto_nwrite_data_set) { + mNtc_set_auto_nwrite_data(); + actor->auto_nwrite_data_set = TRUE; + } + + if (actor->think_idx == aNRST_THINK_TITLE) { + Save_Set(cheated_flag, FALSE); + Save_Set(npc_force_go_home, FALSE); + } + + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + mMsg_SET_LOCKCONTINUE(); + aNRST_change_talk_proc(actor, aNRST_TALK_SAVE); + } +} + +static void aNRST_before_init(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order != 0) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + mMsg_SET_LOCKCONTINUE(); + aNRST_change_talk_proc(actor, aNRST_TALK_INIT); + } +} + +static void aNRST_init(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + switch (mCD_card_format_bg(actor->card_chan)) { + case mCD_RESULT_SUCCESS: + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT); + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, 16, 0)); + mMsg_Unset_LockContinue(msg_p); + break; + case mCD_RESULT_BUSY: + break; + case mCD_RESULT_ERROR: + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT2); + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, 17, 0)); + mMsg_Unset_LockContinue(msg_p); + break; + } +} + +static void aNRST_unset_lock_select2(NPC_RESTART_ACTOR* actor, int msg_idx, int msg_type) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT2); + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, msg_idx, msg_type)); + mMsg_Unset_LockContinue(msg_p); +} + +static void aNRST_save(NPC_RESTART_ACTOR* actor, GAME_PLAY* play) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + int param; + + if (actor->think_idx == aNRST_THINK_DOOR) { + param = 1; + } else { + param = 0; + } + + switch (mCD_SaveHome_bg(param, &actor->card_chan)) { + case mCD_TRANS_ERR_NONE: + aNRST_change_talk_proc(actor, aNRST_TALK_WAIT_END); + if (actor->think_idx == aNRST_THINK_DOOR) { + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, 6, aNRST_MSG_GROUP1)); + } else { + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, 19, aNRST_MSG_GROUP1)); + } + mMsg_Unset_LockContinue(msg_p); + break; + case mCD_TRANS_ERR_NOCARD: + if (!Save_Get(save_exist)) { + aNRST_unset_lock_select2(actor, 2, aNRST_MSG_GROUP2); + } else { + aNRST_unset_lock_select2(actor, 3, aNRST_MSG_GROUP1); + } + break; + case mCD_TRANS_ERR_INVALID_NOLAND_CODE: + aNRST_unset_lock_select2(actor, 1, aNRST_MSG_GROUP2); + break; + case mCD_TRANS_ERR_IOERROR: + aNRST_unset_lock_select2(actor, 7, aNRST_MSG_GROUP1); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_BROKEN_WRONGENCODING: + case mCD_TRANS_ERR_REPAIR: + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT3); + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, 13, aNRST_MSG_GROUP1)); + mMsg_Unset_LockContinue(msg_p); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_NO_SPACE: + aNRST_unset_lock_select2(actor, 18, aNRST_MSG_GROUP1); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_WRONG_LAND: + aNRST_unset_lock_select2(actor, 5, aNRST_MSG_GROUP2); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_LAND_EXIST: + aNRST_unset_lock_select2(actor, 3, aNRST_MSG_GROUP2); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_PASSPORT_EXIST: + aNRST_unset_lock_select2(actor, 4, aNRST_MSG_GROUP2); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_NO_FILES: + aNRST_unset_lock_select2(actor, 0, aNRST_MSG_GROUP3); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_DAMAGED: + aNRST_unset_lock_select2(actor, 1, aNRST_MSG_GROUP3); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_NOT_MEMCARD: + aNRST_unset_lock_select2(actor, 2, aNRST_MSG_GROUP3); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_WRONGDEVICE: + aNRST_unset_lock_select2(actor, 3, aNRST_MSG_GROUP3); + aNRST_set_slot_name(actor->card_chan); + break; + case mCD_TRANS_ERR_BUSY: + break; + default: + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT2); + mMsg_SET_CONTINUE_MSG_NUM(aNRST_get_message(actor, 1, aNRST_MSG_GROUP2)); + mMsg_Unset_LockContinue(msg_p); + break; + } +} + +static void aNRST_change_talk_proc(NPC_RESTART_ACTOR* actor, int talk_idx) { + // clang-format off + static aNRST_TALK_PROC process[] = { + aNRST_select, + aNRST_before_save, + aNRST_save, + aNRST_select2, + aNRST_select3, + aNRST_before_init, + aNRST_init, + (aNRST_TALK_PROC)none_proc1, + }; + // clang-format on + + actor->talk_idx = talk_idx; + actor->talk_proc = process[talk_idx]; +} + +static void aNRST_set_talk_info_talk_request(ACTOR* actorx) { + NPC_RESTART_ACTOR* actor = (NPC_RESTART_ACTOR*)actorx; + + mDemo_Set_msg_num(aNRST_get_message(actor, 0, aNRST_MSG_GROUP1)); + mDemo_Set_camera(CAMERA2_PROCESS_NORMAL); +} + +static void aNRST_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, aNRST_set_talk_info_talk_request); +} + +static int aNRST_talk_init(ACTOR* actorx, GAME* game) { + NPC_RESTART_ACTOR* actor = (NPC_RESTART_ACTOR*)actorx; + + mDemo_Set_ListenAble(); + aNRST_change_talk_proc(actor, aNRST_TALK_SELECT); + actor->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)none_proc1; + return TRUE; +} + +static int aNRST_talk_end_chk(ACTOR* actorx, GAME* game) { + NPC_RESTART_ACTOR* actor = (NPC_RESTART_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int ret = FALSE; + + actor->talk_proc(actor, play); + if (!mDemo_Check(mDemo_TYPE_SPEAK, actorx)) { + aNRST_think_init_proc((NPC_ACTOR*)actorx, play); + actor->talk_end = TRUE; + ret = TRUE; + } + + return ret; +}