diff --git a/configure.py b/configure.py index a9f9b03b..537fd42a 100644 --- a/configure.py +++ b/configure.py @@ -1166,7 +1166,7 @@ config.libs = [ Object(NonMatching, "actor/npc/event/ac_ev_broker2.c"), Object(Matching, "actor/npc/event/ac_ev_carpetPeddler.c"), Object(Matching, "actor/npc/event/ac_ev_castaway.c"), - Object(NonMatching, "actor/npc/event/ac_ev_designer.c"), + Object(Matching, "actor/npc/event/ac_ev_designer.c"), Object(Matching, "actor/npc/event/ac_ev_dokutu.c"), Object(Matching, "actor/npc/event/ac_ev_dozaemon.c"), Object(Matching, "actor/npc/event/ac_ev_ghost.c"), diff --git a/include/ac_ev_designer.h b/include/ac_ev_designer.h index 3570587b..c02ba8ef 100644 --- a/include/ac_ev_designer.h +++ b/include/ac_ev_designer.h @@ -3,11 +3,41 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +typedef struct ev_designer_save_data_s { + int button_count; + int result; +} aEv_designer_c; + +typedef struct ev_designer_actor_s EV_DESIGNER_ACTOR; + +typedef void (*aEDSN_TALK_PROC)(EV_DESIGNER_ACTOR* designer, GAME* game); +typedef void (*aEDSN_THINK_PROC)(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play); + +struct ev_designer_actor_s { + NPC_ACTOR npc_class; + u8 think_idx; + u8 next_think_idx; + u8 talk_idx; + u8 melody_save; + aEDSN_THINK_PROC think_proc; + aEDSN_TALK_PROC talk_proc; + mActor_name_t present; + u8 wear_flag; + u8 complete_flag; + s16 wash_time; + u8 camera_flag; + u8 pl_talk_lock; + f32 clean_speed; + aEv_designer_c* tmp_save_p; + ACTOR* s_car_p; +}; + extern ACTOR_PROFILE Ev_Designer_Profile; #ifdef __cplusplus @@ -15,4 +45,3 @@ extern ACTOR_PROFILE Ev_Designer_Profile; #endif #endif - diff --git a/include/ac_npc.h b/include/ac_npc.h index ce810ddc..87edd8b9 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -986,6 +986,11 @@ typedef struct { int anim_idx; } aNPC_anim_info_c; +#define aNPC_DEMO_GIVE_ITEM(item, mode, present) \ + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, (item)); \ + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, (mode)); \ + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, (present)) + extern ACTOR_PROFILE Npc_Profile; #ifdef __cplusplus diff --git a/src/actor/npc/event/ac_ev_designer.c b/src/actor/npc/event/ac_ev_designer.c new file mode 100644 index 00000000..fd882ffb --- /dev/null +++ b/src/actor/npc/event/ac_ev_designer.c @@ -0,0 +1,97 @@ +#include "ac_ev_designer.h" + +#include "m_common_data.h" +#include "m_player_lib.h" +#include "m_msg.h" +#include "libultra/libultra.h" + +enum { + aEDSN_THINK_TALK_START_WAIT, + aEDSN_THINK_GAME_START_CALL_WAIT, + aEDSN_THINK_GAME_START_CALL, + aEDSN_THINK_GAME_END_WAIT, + aEDSN_THINK_GAME_END_CALL, + + aEDSN_THINK_NUM +}; + +static void aEDSN_actor_ct(ACTOR* actorx, GAME* game); +static void aEDSN_actor_dt(ACTOR* actorx, GAME* game); +static void aEDSN_actor_move(ACTOR* actorx, GAME* game); +static void aEDSN_actor_draw(ACTOR* actorx, GAME* game); +static void aEDSN_actor_init(ACTOR* actorx, GAME* game); +static void aEDSN_actor_save(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Ev_Designer_Profile = { + mAc_PROFILE_EV_DESIGNER, + ACTOR_PART_NPC, + ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED, + SP_NPC_DESIGNER, + ACTOR_OBJ_BANK_KEEP, + sizeof(EV_DESIGNER_ACTOR), + aEDSN_actor_ct, + aEDSN_actor_dt, + aEDSN_actor_init, + mActor_NONE_PROC1, + aEDSN_actor_save, +}; +// clang-format on + +static int aEDSN_talk_init(ACTOR* actorx, GAME* game); +static int aEDSN_talk_end_chk(ACTOR* actorx, GAME* game); + +static void aEDSN_change_talk_proc(EV_DESIGNER_ACTOR* designer, int talk_idx); +static void aEDSN_setup_think_proc(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play, u8 think_idx); +static void aEDSN_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type); + +static void aEDSN_actor_ct(ACTOR* actorx, GAME* game) { + static aNPC_ct_data_c ct_data = { + // clang-format off + aEDSN_actor_move, + aEDSN_actor_draw, + aNPC_CT_SCHED_TYPE_SPECIAL, + (aNPC_TALK_REQUEST_PROC)none_proc1, + aEDSN_talk_init, + aEDSN_talk_end_chk, + 0, + // clang-format on + }; + + if (CLIP(npc_clip)->birth_check_proc(actorx, game) == TRUE) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + + designer->npc_class.schedule.schedule_proc = aEDSN_schedule_proc; + CLIP(npc_clip)->ct_proc(actorx, game, &ct_data); + designer->melody_save = designer->npc_class.talk_info.melody_inst; + } +} + +static void aEDSN_actor_save(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->save_proc(actorx, game); +} + +static void aEDSN_actor_dt(ACTOR* actorx, GAME* game) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + + if (designer->camera_flag == TRUE) { + mDemo_Set_camera(CAMERA2_PROCESS_NORMAL); + Camera2_change_priority((GAME_PLAY*)game, 0); + designer->camera_flag = FALSE; + } + + CLIP(npc_clip)->dt_proc(actorx, game); + mEv_actor_dying_message(mEv_EVENT_DESIGNER, actorx); +} + +static void aEDSN_actor_init(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->init_proc(actorx, game); +} + +static void aEDSN_actor_draw(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->draw_proc(actorx, game); +} + +#include "../src/actor/npc/event/ac_ev_designer_move.c_inc" +#include "../src/actor/npc/event/ac_ev_designer_talk.c_inc" +#include "../src/actor/npc/event/ac_ev_designer_schedule.c_inc" diff --git a/src/actor/npc/event/ac_ev_designer_move.c_inc b/src/actor/npc/event/ac_ev_designer_move.c_inc new file mode 100644 index 00000000..dd79ecd9 --- /dev/null +++ b/src/actor/npc/event/ac_ev_designer_move.c_inc @@ -0,0 +1,36 @@ +static int aEDSN_set_request_act(EV_DESIGNER_ACTOR* designer, u8 prio, u8 idx, u8 type, u16 obj, s16 move_x, s16 move_z) { + int ret = FALSE; + + if (prio >= designer->npc_class.request.act_priority) { + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + + bzero(arg_data, sizeof(arg_data)); + arg_data[0] = obj; + arg_data[2] = (u16)move_x; + arg_data[3] = (u16)move_z; + designer->npc_class.request.act_priority = prio; + designer->npc_class.request.act_idx = idx; + designer->npc_class.request.act_type = type; + mem_copy((u8*)designer->npc_class.request.act_args, (u8*)arg_data, sizeof(arg_data)); + ret = TRUE; + } + + return ret; +} + +static void aEDSN_check_s_car(ACTOR* actorx, GAME* game) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + ACTOR* s_car_p = designer->s_car_p; + + if (s_car_p == NULL) { + s_car_p = Actor_info_name_search(&((GAME_PLAY*)game)->actor_info, mAc_PROFILE_S_CAR, ACTOR_PART_ITEM); + designer->s_car_p = s_car_p; + } else if (s_car_p->id != mAc_PROFILE_S_CAR || (s_car_p->mv_proc == NULL && s_car_p->dw_proc == NULL)) { + Actor_delete(actorx); + } +} + +static void aEDSN_actor_move(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->move_proc(actorx, game); + aEDSN_check_s_car(actorx, game); +} diff --git a/src/actor/npc/event/ac_ev_designer_schedule.c_inc b/src/actor/npc/event/ac_ev_designer_schedule.c_inc new file mode 100644 index 00000000..733d74ce --- /dev/null +++ b/src/actor/npc/event/ac_ev_designer_schedule.c_inc @@ -0,0 +1,212 @@ +static void aEDSN_talk_start_wait(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + if (designer->npc_class.action.step == aNPC_ACTION_END_STEP) { + switch (designer->npc_class.action.idx) { + case aNPC_ACT_GREETING: + case aNPC_ACT_TALK: + aEDSN_set_request_act(designer, 1, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, + designer->npc_class.actor_class.world.position.x, + designer->npc_class.actor_class.world.position.z + mFI_UT_WORLDSIZE_Z_F); + break; + case aNPC_ACT_TURN: + aEDSN_set_request_act(designer, 1, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_ACT_OBJ_DEFAULT, 0, 0); + break; + } + } +} + +static void aEDSN_game_start_call_wait(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_WASH_CAR) { + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + ACTOR* s_car_p = Actor_info_fgName_search(&play->actor_info, DESIGNER_CAR, ACTOR_PART_ITEM); + + if (s_car_p != NULL) { + mPlib_request_main_wash_car_type1((GAME*)play, &s_car_p->world.position, &playerx->world.position, + playerx->shape_info.rotation.y, (ACTOR*)designer); + } + } else { + aEDSN_setup_think_proc(designer, play, aEDSN_THINK_GAME_START_CALL); + } +} + +static void aEDSN_game_end_wait(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + f32 speed = designer->clean_speed; + aEv_designer_c* tmp_data_p = designer->tmp_save_p; + + if (chkTrigger(BUTTON_A)) { + tmp_data_p->button_count++; + + speed += 0.61f; + if (speed > 2.25f) { + speed = 2.25f; + } + } else { + speed -= 0.07f; + if (speed < 0.0f) { + speed = 0.0f; + } + } + + designer->clean_speed = speed; + + mPlib_Set_AnimeSpeedWashCar(speed); + designer->wash_time--; + if (designer->wash_time <= 0) { + tmp_data_p->result = 2; + aEDSN_setup_think_proc(designer, play, aEDSN_THINK_GAME_END_CALL); + } else if (tmp_data_p->button_count >= 100) { + tmp_data_p->result = designer->wash_time <= 360 ? 1 : 0; + aEDSN_setup_think_proc(designer, play, aEDSN_THINK_GAME_END_CALL); + } + + if (designer->npc_class.action.step == aNPC_ACTION_END_STEP && designer->npc_class.action.idx == aNPC_ACT_TURN) { + aEDSN_set_request_act(designer, 1, aNPC_ACT_WAIT, aNPC_ACT_TYPE_SEARCH, aNPC_ACT_OBJ_PLAYER, 0, 0); + } +} + +static void aEDSN_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)nactorx; + + (*designer->think_proc)(designer, play); +} + +static void aEDSN_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)nactorx; + + designer->npc_class.actor_class.status_data.weight = MASSTYPE_HEAVY; + designer->npc_class.condition_info.hide_request = FALSE; + + { + ACTOR* s_car_p = Actor_info_fgName_search(&play->actor_info, DESIGNER_CAR, ACTOR_PART_ITEM); + + if (s_car_p != NULL) { + designer->npc_class.actor_class.world.position.x = s_car_p->world.position.x + mFI_UT_WORLDSIZE_X_F; + designer->npc_class.actor_class.world.position.z = s_car_p->world.position.z + 2 * mFI_UT_WORLDSIZE_X_F; + } + } + + aEDSN_setup_think_proc(designer, play, aEDSN_THINK_TALK_START_WAIT); +} + +static void aEDSN_talk_start_wait_init(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + designer->npc_class.talk_info.melody_inst = designer->melody_save; + designer->npc_class.palActorIgnoreTimer = 0; + aEDSN_set_pl_talk_lock(designer, FALSE); +} + +static void aEDSN_game_start_call_wait_init(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + designer->npc_class.talk_info.melody_inst = 0; + aEDSN_set_request_act(designer, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_SEARCH, aNPC_ACT_OBJ_PLAYER, 0, 0); +} + +static void aEDSN_game_end_wait_init(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + aEv_designer_c* tmp_data_p = designer->tmp_save_p; + + designer->npc_class.talk_info.melody_inst = 0; + designer->wash_time = 1080; + designer->clean_speed = 0.0f; + tmp_data_p->button_count = 0; +} + +static void aEDSN_game_end_call_init(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play) { + aEDSN_game_start_call_wait_init(designer, play); + Camera2_change_priority(play, 0); + mDemo_Set_camera(CAMERA2_PROCESS_NORMAL); + designer->camera_flag = FALSE; + mPlib_Set_EndWashCar(); + designer->complete_flag = TRUE; +} + +typedef void (*aEDSN_THINK_INIT_PROC)(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play); + +typedef struct { + aEDSN_THINK_PROC think_proc; + aEDSN_THINK_INIT_PROC think_init_proc; + aNPC_TALK_REQUEST_PROC talk_request_proc; + u8 talk_idx; + u8 after_think_idx; +} aEDSN_setup_data_c; + +static void aEDSN_setup_think_proc(EV_DESIGNER_ACTOR* designer, GAME_PLAY* play, u8 think_idx) { + static aEDSN_setup_data_c dt_tbl[] = { + { + aEDSN_talk_start_wait, + aEDSN_talk_start_wait_init, + aEDSN_norm_talk_request, + 0, + aEDSN_THINK_GAME_START_CALL_WAIT, + }, + { + aEDSN_game_start_call_wait, + aEDSN_game_start_call_wait_init, + (aNPC_TALK_REQUEST_PROC)none_proc1, + 0, + aEDSN_THINK_GAME_START_CALL, + }, + { + (aEDSN_THINK_PROC)none_proc1, + (aEDSN_THINK_INIT_PROC)none_proc1, + aEDSN_force_talk_request, + 0, + aEDSN_THINK_GAME_END_WAIT, + }, + { + aEDSN_game_end_wait, + aEDSN_game_end_wait_init, + (aNPC_TALK_REQUEST_PROC)none_proc1, + 0, + aEDSN_THINK_GAME_END_CALL, + }, + { + (aEDSN_THINK_PROC)none_proc1, + aEDSN_game_end_call_init, + aEDSN_force_talk_request, + 1, + aEDSN_THINK_TALK_START_WAIT, + }, + }; + + aEDSN_setup_data_c* data_p = &dt_tbl[think_idx]; + + designer->think_idx = think_idx; + designer->think_proc = data_p->think_proc; + designer->npc_class.talk_info.talk_request_proc = data_p->talk_request_proc; + designer->talk_idx = data_p->talk_idx; + designer->next_think_idx = data_p->after_think_idx; + (*data_p->think_init_proc)(designer, play); +} + +static void aEDSN_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC think_proc[] = { aEDSN_think_init_proc, aEDSN_think_main_proc }; + + (*think_proc[type])(nactorx, play); +} + +static void aEDSN_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)nactorx; + + nactorx->think.think_proc = aEDSN_think_proc; + CLIP(npc_clip)->think_proc(nactorx, play, aNPC_THINK_SPECIAL, aNPC_THINK_TYPE_INIT); + + { + aEv_designer_c* tmp_data_p = (aEv_designer_c*)mEv_get_common_area(mEv_EVENT_DESIGNER, 0); + + if (tmp_data_p == NULL) { + tmp_data_p = (aEv_designer_c*)mEv_reserve_common_area(mEv_EVENT_DESIGNER, 0); + tmp_data_p->result = 2; + } + + designer->tmp_save_p = tmp_data_p; + } +} + +static void aEDSN_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (CLIP(npc_clip)->think_proc(nactorx, play, -1, aNPC_THINK_TYPE_CHK_INTERRUPT) == FALSE) { + CLIP(npc_clip)->think_proc(nactorx, play, -1, aNPC_THINK_TYPE_MAIN); + } +} + +static void aEDSN_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC sche_proc[] = { aEDSN_schedule_init_proc, aEDSN_schedule_main_proc }; + + (*sche_proc[type])(nactorx, play); +} diff --git a/src/actor/npc/event/ac_ev_designer_talk.c_inc b/src/actor/npc/event/ac_ev_designer_talk.c_inc new file mode 100644 index 00000000..9db7be70 --- /dev/null +++ b/src/actor/npc/event/ac_ev_designer_talk.c_inc @@ -0,0 +1,296 @@ +enum { + aEDSN_TALK_INVENTORY_CHECK, + aEDSN_TALK_CLOSE_UMB_END_WAIT, + aEDSN_TALK_CHECK_RESULT, + aEDSN_TALK_DEMO_START_WAIT, + aEDSN_TALK_DEMO_END_WAIT, + aEDSN_TALK_END_WAIT, + + aEDSN_TALK_NUM +}; + +static void aEDSN_set_pl_talk_lock(EV_DESIGNER_ACTOR* designer, u8 flag) { + if (designer->pl_talk_lock != flag) { + if (flag == TRUE) { + mPlib_Set_able_force_speak_label((ACTOR*)designer); + } else { + mPlib_Reset_able_force_speak_label(); + } + + designer->pl_talk_lock = flag; + } +} + +static int aEDSN_check_present(void) { + mEv_designer_c* ev_save_p = &Save_Get(event_save_data).special.event.designer; + PersonalID_c* pid = ev_save_p->pids; + int i; + + for (i = 0; i < mEv_DESGINER_NUM; i++) { + if (mPr_CheckCmpPersonalID(pid, &Now_Private->player_ID) == TRUE) { + return i; + } + + pid++; + } + + return -1; +} + +static int aEDSN_get_msg_no(EV_DESIGNER_ACTOR* designer, int idx) { + static int msg_no_0[27] = { + 0x0721, 0x0722, 0x0723, 0x0724, 0x0725, 0x0726, 0x0727, 0x0728, + 0x0729, 0x072A, 0x072B, 0x072C, 0x072D, 0x072E, 0x072F, 0x0730, + 0x0731, 0x0732, 0x0733, 0x0747, 0x0748, 0x0749, 0x074A, 0x074B, + 0x072B, 0x072C, 0x074C, + }; + + static int msg_no_1[27] = { + 0x0734, 0x0735, 0x0736, 0x0745, 0x0737, 0x0738, 0x0739, 0x0746, + 0x073A, 0x073B, 0x073C, 0x073D, 0x073E, 0x073F, 0x0740, 0x0741, + 0x0742, 0x0743, 0x0744, 0x0747, 0x0748, 0x0749, 0x074A, 0x074B, + 0x073C, 0x073D, 0x074C, + }; + + static int* msg_no[2] = {msg_no_0, msg_no_1}; + + return msg_no[designer->wear_flag][idx]; +} + +static void aEDSN_inventory_check_talk_proc(EV_DESIGNER_ACTOR* designer, GAME* game) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (mMsg_Check_MainNormalContinue(msg_p) == TRUE && order != 0) { + int talk_idx = aEDSN_TALK_END_WAIT; + + if (mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO) != -1) { + int msg_idx = 19; + + if (mPlib_Check_now_handin_item() && mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_TALK) { + msg_idx = 26; + talk_idx = aEDSN_TALK_CLOSE_UMB_END_WAIT; + } else { + mDemo_Set_talk_change_player(FALSE); + } + + mDemo_Set_talk_return_demo_wait(TRUE); + mMsg_Set_continue_msg_num(msg_p, aEDSN_get_msg_no(designer, msg_idx)); + mDemo_KeepCamera(CAMERA2_PROCESS_SIMPLE); + } else { + designer->next_think_idx = aEDSN_THINK_TALK_START_WAIT; + } + + aEDSN_change_talk_proc(designer, talk_idx); + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + } +} + +static void aEDSN_close_umb_end_wait_talk_proc(EV_DESIGNER_ACTOR* designer, GAME* game) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + if (mMsg_Check_MainNormalContinue(msg_p) == TRUE) { + mMsg_Set_LockContinue(msg_p); + if (mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_TALK) { + if (mPlib_Check_now_handin_item()) { + mPlib_request_main_talk_type1(game, mDemo_Get_talk_actor(), mDemo_Get_talk_turn(), TRUE); + } else { + mMsg_Unset_LockContinue(msg_p); + mDemo_Set_talk_change_player(FALSE); + aEDSN_change_talk_proc(designer, aEDSN_TALK_END_WAIT); + } + } + } +} + +static void aEDSN_check_result_talk_proc(EV_DESIGNER_ACTOR* designer, GAME* game) { + static int msg_idx[] = { 12, 14, 16 }; + static int next_talk_proc_idx[] = { aEDSN_TALK_DEMO_START_WAIT, aEDSN_TALK_DEMO_START_WAIT, aEDSN_TALK_END_WAIT }; + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + chase_angle(&designer->npc_class.actor_class.shape_info.rotation.y, designer->npc_class.actor_class.player_angle_y, 0x800); + if (mMsg_Check_MainNormalContinue(msg_p) == TRUE) { + mEv_designer_c* ev_save_p = &Save_Get(event_save_data).special.event.designer; + aEv_designer_c* tmp_save_p = designer->tmp_save_p; + mActor_name_t present = EMPTY_NO; + int result = tmp_save_p->result; + + switch (result) { + case 0: + mSP_SelectRandomItem_New(NULL, &present, 1, ev_save_p->gifted_cloths, ev_save_p->used, mSP_KIND_CLOTH, mSP_LISTTYPE_EVENT, FALSE); + break; + case 1: + mSP_SelectRandomItem_New(NULL, &present, 1, ev_save_p->gifted_cloths, ev_save_p->used, mSP_KIND_CLOTH, mSP_LISTTYPE_COMMON, FALSE); + break; + case 2: + mEv_set_status(mEv_EVENT_DESIGNER, mEv_STATUS_TALK); + mDemo_Set_talk_change_player(TRUE); + break; + } + + designer->present = present; + mEv_EventON(mEv_SPECL_DESIGNER_COMPLETE); + designer->npc_class.movement.mv_angl = designer->npc_class.actor_class.player_angle_y; + mMsg_Set_continue_msg_num(msg_p, aEDSN_get_msg_no(designer, msg_idx[result])); + aEDSN_change_talk_proc(designer, next_talk_proc_idx[result]); + } +} + +static void aEDSN_demo_start_wait_talk_proc(EV_DESIGNER_ACTOR* designer, GAME* game) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1); + + if (order == 2) { + aNPC_DEMO_GIVE_ITEM(designer->present, aHOI_REQUEST_PUTAWAY, TRUE); + mPr_SetFreePossessionItem(Now_Private, designer->present, mPr_ITEM_COND_NORMAL); + mMsg_REQUEST_MAIN_DISAPPEAR_WAIT_TYPE1(); + aEDSN_change_talk_proc(designer, aEDSN_TALK_DEMO_END_WAIT); + } +} + +static void aEDSN_demo_end_wait_talk_proc(EV_DESIGNER_ACTOR* designer, GAME* game) { + chase_angle(&designer->npc_class.actor_class.shape_info.rotation.y, designer->npc_class.actor_class.player_angle_y, 0x800); + if (aEDSN_check_present() == -1) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + if (mMsg_Check_main_wait(msg_p) == TRUE && CLIP(handOverItem_clip)->master_actor == NULL) { + mEv_designer_c* ev_save_p = &Save_Get(event_save_data).special.event.designer; + int idx = ev_save_p->used; + + mPr_CopyPersonalID(&ev_save_p->pids[idx], &Now_Private->player_ID); + ev_save_p->gifted_cloths[idx] = designer->present; + ev_save_p->used++; + mMsg_REQUEST_MAIN_APPEAR_WAIT_TYPE1(); + mDemo_Set_talk_change_player(TRUE); + aEDSN_change_talk_proc(designer, aEDSN_TALK_END_WAIT); + } + } +} + +static void aEDSN_talk_end_wait_talk_proc(EV_DESIGNER_ACTOR* designer, GAME* game) { + chase_angle(&designer->npc_class.actor_class.shape_info.rotation.y, designer->npc_class.actor_class.player_angle_y, 0x800); +} + +static void aEDSN_change_talk_proc(EV_DESIGNER_ACTOR* designer, int talk_proc_idx) { + static aEDSN_TALK_PROC talk_proc[] = { + // clang-format off + aEDSN_inventory_check_talk_proc, + aEDSN_close_umb_end_wait_talk_proc, + aEDSN_check_result_talk_proc, + aEDSN_demo_start_wait_talk_proc, + aEDSN_demo_end_wait_talk_proc, + aEDSN_talk_end_wait_talk_proc, + // clang-format on + }; + + designer->talk_proc = talk_proc[talk_proc_idx]; +} + +typedef struct designer_talk_req_info_s { + int msg_idx; + int cam_type; + aEDSN_TALK_PROC talk_proc; +} aEDSN_talk_request_info_c; + +static void aEDSN_set_force_talk_info(ACTOR* actorx) { + static aEDSN_talk_request_info_c dt_tbl[] = { + // clang-format off + { + 10, + CAMERA2_PROCESS_SIMPLE, + aEDSN_talk_end_wait_talk_proc, + }, + { + 25, + CAMERA2_PROCESS_TALK, + aEDSN_check_result_talk_proc, + }, + // clang-format on + }; + + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + int talk_idx = designer->talk_idx; + aEDSN_talk_request_info_c* data_p = &dt_tbl[talk_idx]; + + mDemo_Set_talk_change_player(FALSE); + mDemo_Set_msg_num(aEDSN_get_msg_no(designer, data_p->msg_idx)); + mDemo_Set_talk_turn(TRUE); + mDemo_Set_camera(data_p->cam_type); + + if (talk_idx == 0) { + mDemo_Set_talk_return_demo_wait(TRUE); + designer->camera_flag = TRUE; + } + + designer->talk_proc = data_p->talk_proc; +} + +static void aEDSN_force_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, aEDSN_set_force_talk_info); +} + +static void aEDSN_set_norm_talk_info(ACTOR* actorx) { + static int msg_start_idx[] = { 0, 4 }; + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + mEv_designer_c* ev_save_p = &Save_Get(event_save_data).special.event.designer; + int idx = aEDSN_check_present(); + int msg_idx; + int talk_proc_idx = aEDSN_TALK_END_WAIT; + + if (mSP_SearchItemCategoryPriority(Now_Private->cloth.item, mSP_KIND_CLOTH, mSP_LISTTYPE_EVENT, NULL) == TRUE) { + designer->wear_flag = TRUE; + } else { + designer->wear_flag = FALSE; + } + + if (designer->complete_flag == TRUE) { + msg_idx = 21 + RANDOM(3); + designer->next_think_idx = aEDSN_THINK_TALK_START_WAIT; + } else if (idx != -1) { + if (mSP_SearchItemCategoryPriority(ev_save_p->gifted_cloths[idx], mSP_KIND_CLOTH, mSP_LISTTYPE_EVENT, NULL) == TRUE) { + msg_idx = 17; + } else { + msg_idx = 18; + } + + designer->next_think_idx = aEDSN_THINK_TALK_START_WAIT; + } else { + if (mEv_CheckEvent(mEv_SPECL_DESIGNER_COMPLETE) == TRUE) { + msg_idx = 8; + } else { + msg_idx = msg_start_idx[Now_Private->gender == mPr_SEX_FEMALE] + RANDOM(4); + } + + designer->npc_class.palActorIgnoreTimer = -1; + talk_proc_idx = aEDSN_TALK_INVENTORY_CHECK; + aEDSN_set_pl_talk_lock(designer, TRUE); + } + + mDemo_Set_msg_num(aEDSN_get_msg_no(designer, msg_idx)); + aEDSN_change_talk_proc(designer, talk_proc_idx); +} + +static void aEDSN_norm_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_TALK, actorx, aEDSN_set_norm_talk_info); +} + +static int aEDSN_talk_init(ACTOR* actorx, GAME* game) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + + designer->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)none_proc1; + mDemo_Set_ListenAble(); + return TRUE; +} + +static int aEDSN_talk_end_chk(ACTOR* actorx, GAME* game) { + EV_DESIGNER_ACTOR* designer = (EV_DESIGNER_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int ret = FALSE; + + designer->talk_proc(designer, game); + if (mDemo_CAN_ACTOR_TALK(actorx)) { + aEDSN_setup_think_proc(designer, play, designer->next_think_idx); + ret = TRUE; + } + + return ret; +}