diff --git a/configure.py b/configure.py index 83e58bc7..8d54384d 100644 --- a/configure.py +++ b/configure.py @@ -1130,7 +1130,7 @@ config.libs = [ Object(Matching, "actor/npc/ac_npc_sendo.c"), Object(NonMatching, "actor/npc/ac_npc_shasho.c"), Object(Matching, "actor/npc/ac_npc_shop_master.c"), - Object(NonMatching, "actor/npc/ac_npc_shop_mastersp.c"), + Object(Matching, "actor/npc/ac_npc_shop_mastersp.c"), Object(NonMatching, "actor/npc/ac_npc_sleep_obaba.c"), Object(NonMatching, "actor/npc/ac_npc_soncho.c"), Object(NonMatching, "actor/npc/ac_npc_station_master.c"), diff --git a/include/ac_npc.h b/include/ac_npc.h index 222387bc..27138397 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -352,11 +352,13 @@ typedef struct npc_action_s { aNPC_ACTION_PROC act_proc; } aNPC_action_c; +#define aNPC_REQUEST_ARG_NUM 6 + typedef struct npc_request_s { u8 act_priority; u8 act_idx; u8 act_type; - u16 act_args[6]; + u16 act_args[aNPC_REQUEST_ARG_NUM]; u8 umb_flag; u8 _11; u8 head_priority; diff --git a/include/ac_npc_shop_mastersp.h b/include/ac_npc_shop_mastersp.h index e535b4c4..c24a98e1 100644 --- a/include/ac_npc_shop_mastersp.h +++ b/include/ac_npc_shop_mastersp.h @@ -3,11 +3,44 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" +#include "m_shop.h" +#include "m_player_lib.h" #ifdef __cplusplus extern "C" { #endif +#define aSHM_REQ_TICKET_NUM 5 + +#define aSHM_FIRST_PLACE_PERCENT 5 +#define aSHM_SECOND_PLACE_PERCENT (10 + aSHM_FIRST_PLACE_PERCENT) +#define aSHM_THIRD_PLACE_PERCENT (20 + aSHM_SECOND_PLACE_PERCENT) + +typedef struct npc_shop_mastersp_actor_s NPC_SHOP_MASTERSP_ACTOR; + +typedef void (*aSHM_THINK_PROC)(NPC_SHOP_MASTERSP_ACTOR*, GAME_PLAY*); +typedef void (*aSHM_TALK_PROC)(NPC_SHOP_MASTERSP_ACTOR*, GAME_PLAY*); + +struct npc_shop_mastersp_actor_s { + NPC_ACTOR npc_class; + int think_idx; + int next_think_idx; + int move_think_idx; + aSHM_THINK_PROC think_proc; + int talk_idx; + aSHM_TALK_PROC talk_proc; + s16 result; + s16 timer; + s16 root; + s16 root_idx; + s16 now_idx; + int month; + int ut[2]; + int melody_bak; + s16 base_pos[11][2]; +}; + extern ACTOR_PROFILE Npc_Shop_Mastersp_Profile; #ifdef __cplusplus @@ -15,4 +48,3 @@ extern ACTOR_PROFILE Npc_Shop_Mastersp_Profile; #endif #endif - diff --git a/include/audio_defs.h b/include/audio_defs.h index dfad42c4..f0ac21bc 100644 --- a/include/audio_defs.h +++ b/include/audio_defs.h @@ -111,6 +111,8 @@ typedef enum audio_sound_effects { NA_SE_STONECOIN_ROLL = 0x7D, NA_SE_STONECOIN_DRAG = 0x7E, + NA_SE_7F = 0x7F, + NA_SE_TRAIN_RIDE = 0x8D, NA_SE_GOKI_MOVE = 0xA8, diff --git a/include/m_demo.h b/include/m_demo.h index ed016798..357bbd8d 100644 --- a/include/m_demo.h +++ b/include/m_demo.h @@ -206,6 +206,8 @@ extern int mDemo_Check_ListenAble(); extern int mDemo_Check_DiffAngle_forTalk(s16 diff_angle); extern void mDemo_KeepCamera(int camera_type); +#define mDemo_CAN_ACTOR_TALK(actor) (!mDemo_Check(mDemo_TYPE_SPEAK, (actor)) && !mDemo_Check(mDemo_TYPE_TALK, (actor))) + #ifdef __cplusplus } #endif diff --git a/include/m_name_table.h b/include/m_name_table.h index f70b6937..ccb86e89 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -209,6 +209,9 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define TICKET_MONTH(n) (1 + (((n) >> 3) & 0xF)) #define TICKET_COUNT(n) (1 + ((n) & 7)) +#define TICKET_TO_MONTH(month) (((month) - 1) << 3) +#define TICKET_TO_COUNT(cnt) ((cnt) & 7) +#define TICKET_GET_ITEM(month, cnt) (ITM_TICKET_START | (((month) - 1) << 3) | ((cnt) & 7)) #define WISP_COUNT(n) (ITEM_IS_WISP(n) ? (1 + (n) - ITM_SPIRIT0) : 0) #define ITEM_IS_INSECT(n) ((n) >= ITM_INSECT_START && (n) < ITM_INSECT_END) diff --git a/src/actor/npc/ac_npc_shop_mastersp.c b/src/actor/npc/ac_npc_shop_mastersp.c new file mode 100644 index 00000000..51888536 --- /dev/null +++ b/src/actor/npc/ac_npc_shop_mastersp.c @@ -0,0 +1,135 @@ +#include "ac_npc_shop_mastersp.h" + +#include "m_common_data.h" +#include "libultra/libultra.h" +#include "m_item_name.h" +#include "m_msg.h" +#include "m_bgm.h" + +enum { + aSHM_WON_FIRST_PLACE, + aSHM_WON_SECOND_PLACE, + aSHM_WON_THIRD_PLACE, + aSHM_DIDNT_WIN, + + aSHM_WIN_NUM +}; + +enum { + aSHM_TALK_TALK_TRY, + aSHM_TALK_TALK_HAZURE, + aSHM_TALK_TALK_RETRY, + aSHM_TALK_STOP_PLAYER, + aSHM_TALK_GIVE_PLAYER, + aSHM_TALK_TALK_TAMAKESI, + aSHM_TALK_END_WAIT, + aSHM_TALK_SAY_GOODBYE, + aSHM_TALK_EXIT_WAIT, + + aSHM_TALK_NUM +}; + +enum { + aSHM_THINK_NORMAL_WAIT, + aSHM_THINK_NORMAL_WAIT2, + aSHM_THINK_NORMAL_WAIT3, + aSHM_THINK_NORMAL_TURN, + aSHM_THINK_4, + aSHM_THINK_5, + aSHM_THINK_WIN1, + aSHM_THINK_WIN2, + aSHM_THINK_WIN3, + aSHM_THINK_LOSE, + aSHM_THINK_10, + aSHM_THINK_11, + aSHM_THINK_12, + aSHM_THINK_MOVE, + aSHM_THINK_MOVE_TURN, + aSHM_THINK_FADE_OUT, + aSHM_THINK_MOVE_PLAYER, + aSHM_THINK_WAIT_PLAYER, + aSHM_THINK_WAIT_PLAYER2, + aSHM_THINK_WAIT_PLAYER3, + aSHM_THINK_WAIT_PLAYER4, + aSHM_THINK_HIROU, + aSHM_THINK_HAPPY_ACADEMY, + aSHM_THINK_HAPPY_ACADEMY2, + aSHM_THINK_HAPPY_ACADEMY3, + + aSHM_THINK_NUM +}; + +static void aSHM_actor_ct(ACTOR* actorx, GAME* game); +static void aSHM_actor_dt(ACTOR* actorx, GAME* game); +static void aSHM_actor_move(ACTOR* actorx, GAME* game); +static void aSHM_actor_init(ACTOR* actorx, GAME* game); +static void aSHM_actor_draw(ACTOR* actorx, GAME* game); +static void aSHM_actor_save(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Npc_Shop_Mastersp_Profile = { + mAc_PROFILE_NPC_SHOP_MASTERSP, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + SP_NPC_SHOP_MASTERSP, + ACTOR_OBJ_BANK_KEEP, + sizeof(NPC_SHOP_MASTERSP_ACTOR), + &aSHM_actor_ct, + &aSHM_actor_dt, + &aSHM_actor_init, + mActor_NONE_PROC1, + &aSHM_actor_save, +}; +// clang-format on + +static int aSHM_talk_init(ACTOR* actorx, GAME* game); +static int aSHM_talk_end_chk(ACTOR* actorx, GAME* game); + +static void aSHM_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type); +static int aSHM_change_talk_proc(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, int talk_proc_idx); +static void aSHM_setup_think_proc(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play, int think_idx); + +static void aSHM_set_base_position(ACTOR* actorx, GAME_PLAY* play); + +static void aSHM_actor_ct(ACTOR* actorx, GAME* game) { + // clang-format off + static aNPC_ct_data_c ct_data = { + &aSHM_actor_move, + &aSHM_actor_draw, + 5, + (aNPC_TALK_REQUEST_PROC)&none_proc1, + &aSHM_talk_init, + &aSHM_talk_end_chk, + 0, + }; + // clang-format on + + if (CLIP(npc_clip)->birth_check_proc(actorx, game) == TRUE) { + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)actorx; + + shop_mastersp->npc_class.schedule.schedule_proc = &aSHM_schedule_proc; + CLIP(npc_clip)->ct_proc(actorx, game, &ct_data); + aSHM_set_base_position(actorx, (GAME_PLAY*)game); + shop_mastersp->melody_bak = 0; + } +} + +static void aSHM_actor_save(ACTOR* actorx, GAME* game) { + mNpc_RenewalSetNpc(actorx); +} + +static void aSHM_actor_dt(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->dt_proc(actorx, game); +} + +static void aSHM_actor_init(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->init_proc(actorx, game); +} + +static void aSHM_actor_draw(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->draw_proc(actorx, game); +} + +#include "../src/actor/npc/ac_npc_shop_mastersp_move.c_inc" +#include "../src/actor/npc/ac_npc_shop_mastersp_talk.c_inc" +#include "../src/actor/npc/ac_npc_shop_mastersp_schedule.c_inc" diff --git a/src/actor/npc/ac_npc_shop_mastersp_move.c_inc b/src/actor/npc/ac_npc_shop_mastersp_move.c_inc new file mode 100644 index 00000000..8145e38a --- /dev/null +++ b/src/actor/npc/ac_npc_shop_mastersp_move.c_inc @@ -0,0 +1,123 @@ +static s16 aSHM_ftr_revise_x(mActor_name_t item) { + if (mRmTp_ItemNo2FtrSize(item) == mRmTp_FTRSIZE_1x1) { + return -(mFI_UT_WORLDSIZE_X / 2); + } + + return 0; +} + +static s16 aSHM_ftr_revise_z(mActor_name_t item) { + if (mRmTp_ItemNo2FtrSize(item) == mRmTp_FTRSIZE_2x2) { + return 0; + } + + return -mFI_UT_WORLDSIZE_Z; +} + +static void aSHM_set_base_position(ACTOR* actorx, GAME_PLAY* play) { + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)actorx; + int level = mSP_GetShopLevel(); + mActor_name_t* item_p = Save_Get(shop).lottery_items; + static s16 base_table_x[] = { 160, 240, 240, 240 }; + static s16 base_table_z[] = { 140, 140, 300, 300 }; + ACTOR* player = GET_PLAYER_ACTOR_ACTOR(play); + + shop_mastersp->base_pos[0][0] = base_table_x[level]; + shop_mastersp->base_pos[0][1] = base_table_z[level]; + + actorx->world.position.x = shop_mastersp->base_pos[0][0]; + actorx->world.position.z = shop_mastersp->base_pos[0][1]; + + shop_mastersp->base_pos[1][0] = base_table_x[level]; + shop_mastersp->base_pos[1][1] = base_table_z[level] - 2; + shop_mastersp->base_pos[1][0] += aSHM_ftr_revise_x(item_p[0]); + shop_mastersp->base_pos[1][1] += aSHM_ftr_revise_z(item_p[0]); + + shop_mastersp->base_pos[2][0] = base_table_x[level] + 80; + shop_mastersp->base_pos[2][1] = base_table_z[level] - 2; + shop_mastersp->base_pos[2][0] += aSHM_ftr_revise_x(item_p[1]); + shop_mastersp->base_pos[2][1] += aSHM_ftr_revise_z(item_p[1]); + + shop_mastersp->base_pos[3][0] = base_table_x[level] - 80; + shop_mastersp->base_pos[3][1] = base_table_z[level] - 2; + shop_mastersp->base_pos[3][0] += aSHM_ftr_revise_x(item_p[2]); + shop_mastersp->base_pos[3][1] += aSHM_ftr_revise_z(item_p[2]); + + shop_mastersp->base_pos[4][0] = shop_mastersp->base_pos[0][0] - 80; + shop_mastersp->base_pos[4][1] = shop_mastersp->base_pos[0][1]; + + shop_mastersp->base_pos[5][0] = shop_mastersp->base_pos[4][0]; + shop_mastersp->base_pos[5][1] = shop_mastersp->base_pos[4][1] + 80; + + shop_mastersp->base_pos[6][0] = shop_mastersp->base_pos[5][0] + 40; + shop_mastersp->base_pos[6][1] = shop_mastersp->base_pos[5][1]; + + shop_mastersp->base_pos[7][0] = shop_mastersp->base_pos[0][0] + 80; + shop_mastersp->base_pos[7][1] = shop_mastersp->base_pos[0][1]; + + shop_mastersp->base_pos[8][0] = shop_mastersp->base_pos[7][0]; + shop_mastersp->base_pos[8][1] = shop_mastersp->base_pos[7][1] + 80; + + shop_mastersp->base_pos[9][0] = shop_mastersp->base_pos[8][0] - 40; + shop_mastersp->base_pos[9][1] = shop_mastersp->base_pos[8][1]; + + shop_mastersp->base_pos[10][0] = player->world.position.x; + shop_mastersp->base_pos[10][1] = player->world.position.z - 60.0f; +} + +static void aSHM_set_avoid_pos(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp) { + static u8 root1[1] = { 1 }; + static u8 root2[3] = { 4, 5, 6 }; + static u8 root3[3] = { 5, 4, 0 }; + static u8 root4[2] = { 7, 2 }; + static u8 root5[2] = { 8, 9 }; + static u8 root6[3] = { 8, 7, 0 }; + static u8 root7[2] = { 4, 3 }; + static u8 root8[2] = { 5, 6 }; + static u8 root10[3] = { 7, 8, 10 }; + static u8* root_table[10] = { root1, root2, root3, root4, root5, root6, root7, root8, root3, root10 }; + + shop_mastersp->now_idx = root_table[shop_mastersp->root][shop_mastersp->root_idx]; +} + +static void aSHM_set_start_avoid_pos(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, s16 root) { + shop_mastersp->root = root; + shop_mastersp->root_idx = 0; + aSHM_set_avoid_pos(shop_mastersp); +} + +static int aSHM_set_next_avoid_pos(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp) { + static s16 root_max[] = { 1, 3, 3, 2, 2, 3, 2, 2, 3, 3 }; + + shop_mastersp->root_idx++; + if (shop_mastersp->root_idx < root_max[shop_mastersp->root]) { + aSHM_set_avoid_pos(shop_mastersp); + return FALSE; + } + + return TRUE; +} + +static int aSHM_set_request_act(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, u8 prio, u8 act_idx, u8 act_type, u16 act_obj, s16 pos_x, s16 pos_z) { + int ret = FALSE; + + if (prio >= shop_mastersp->npc_class.request.act_priority) { + u16 args[aNPC_REQUEST_ARG_NUM]; + + bzero(args, sizeof(args)); + args[0] = act_obj; + args[2] = pos_x; + args[3] = pos_z; + shop_mastersp->npc_class.request.act_priority = prio; + shop_mastersp->npc_class.request.act_idx = act_idx; + shop_mastersp->npc_class.request.act_type = act_type; + mem_copy((u8*)shop_mastersp->npc_class.request.act_args, (u8*)args, sizeof(args)); + ret = TRUE; + } + + return ret; +} + +static void aSHM_actor_move(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->move_proc(actorx, game); +} diff --git a/src/actor/npc/ac_npc_shop_mastersp_schedule.c_inc b/src/actor/npc/ac_npc_shop_mastersp_schedule.c_inc new file mode 100644 index 00000000..cb9b344a --- /dev/null +++ b/src/actor/npc/ac_npc_shop_mastersp_schedule.c_inc @@ -0,0 +1,303 @@ +static void aSHM_set_start_think(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + int think_idx; + ACTOR* actorx = (ACTOR*)shop_mastersp; + + if (!mLd_PlayerManKindCheck() && mEv_CheckEvent(mEv_SAVED_HRATALK_PLR0 + Common_Get(player_no)) == TRUE) { + think_idx = aSHM_THINK_HAPPY_ACADEMY; + } else { + actorx->talk_distance = 55.0f; + + if (check_null_lottery()) { + think_idx = aSHM_THINK_NORMAL_WAIT2; + } else if (ABS(actorx->player_angle_y) < 4000) { + actorx->talk_distance = 100.0f; + think_idx = aSHM_THINK_NORMAL_WAIT; + } else { + think_idx = aSHM_THINK_NORMAL_WAIT3; + } + } + + aSHM_setup_think_proc(shop_mastersp, play, think_idx); +} + +static void aSHM_normal_wait_common(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (player_go_away(play)) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_4); + } else if (player_buy(shop_mastersp, play)) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_5); + } +} + +static void aSHM_normal_wait(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)shop_mastersp; + + if (ABS(actorx->player_angle_y) > 4000) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_NORMAL_WAIT3); + actorx->talk_distance = 55.0f; + } + + aSHM_normal_wait_common(shop_mastersp, play); +} + +static void aSHM_normal_wait2(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)shop_mastersp; + + if (ABS(actorx->player_angle_y) > 4000) { + actorx->talk_distance = 55.0f; + } else { + actorx->talk_distance = 100.0f; + } + + aSHM_normal_wait_common(shop_mastersp, play); +} + +static void aSHM_normal_wait3(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)shop_mastersp; + + if (ABS(actorx->player_angle_y) < 4000) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_NORMAL_WAIT); + actorx->talk_distance = 100.0f; + } + + aSHM_normal_wait_common(shop_mastersp, play); +} + +static void aSHM_normal_turn(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)shop_mastersp; + + if (nactorx->action.idx == aNPC_ACT_TURN) { + aSHM_set_start_think(shop_mastersp, play); + } +} + +static void aSHM_move(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (shop_mastersp->npc_class.action.idx == aNPC_ACT_WALK2 || shop_mastersp->npc_class.action.idx == aNPC_ACT_WAIT) { + if (aSHM_set_next_avoid_pos(shop_mastersp)) { + aSHM_setup_think_proc(shop_mastersp, play, shop_mastersp->move_think_idx); + } else { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_MOVE); + } + } +} + +static void aSHM_move_turn(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (shop_mastersp->npc_class.action.idx == aNPC_ACT_TURN) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_MOVE); + } +} + +static void aSHM_move_player(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_DEMO_WALK) { + mPlib_request_main_demo_walk_type1((GAME*)play, shop_mastersp->base_pos[0][0], + shop_mastersp->base_pos[0][1] + 2 * mFI_UT_WORLDSIZE_Z, 2.0f, FALSE); + } else { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_WAIT_PLAYER); + } +} + +static void aSHM_wait_player(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_DEMO_WALK) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_WAIT_PLAYER2); + } +} + +static void aSHM_wait_player2(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + xyz_t pos; + ACTOR* actorx = (ACTOR*)shop_mastersp; + + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_ROTATE_OCTAGON) { + pos.x = shop_mastersp->base_pos[0][0]; + pos.y = actorx->world.position.y; + pos.z = shop_mastersp->base_pos[0][1] + 2 * mFI_UT_WORLDSIZE_Z - 2; + mPlib_request_main_rotate_octagon_type1((GAME*)play, &pos, DEG2SHORT_ANGLE2(180.0f)); + } else { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_WAIT_PLAYER3); + } +} + +static void aSHM_wait_player3(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (mPlib_Check_RotateOctagon()) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_WAIT_PLAYER4); + + if (CLIP(garagara_clip) != NULL) { + CLIP(garagara_clip)->garagara_anime_start_proc(shop_mastersp->result); + } + } +} + +static void aSHM_wait_player4(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (!mPlib_Check_RotateOctagon()) { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_WIN1 + shop_mastersp->result); + } +} + +static void aSHM_hirou(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + mActor_name_t* item_p = Save_Get(shop).lottery_items; + + if (shop_mastersp->timer == 10) { + aSHM_remove_gift(shop_mastersp, item_p[shop_mastersp->result]); + } + + if (shop_mastersp->timer > 0) { + shop_mastersp->timer--; + return; + } + + mFI_UtNumtoFGSet_common(RSV_SHOP_SOLD_FTR, shop_mastersp->ut[0], shop_mastersp->ut[1], FALSE); + aSHM_set_start_avoid_pos(shop_mastersp, shop_mastersp->root + 1); + shop_mastersp->move_think_idx = aSHM_THINK_10; + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_MOVE_TURN); +} + +static void aSHM_happy_academy3(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + GAME* game = (GAME*)play; + + if (mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_DEMO_WAIT) { + mPlib_request_main_wait_type3(game); + } else { + aSHM_setup_think_proc(shop_mastersp, play, aSHM_THINK_NORMAL_TURN); + } +} + +static void aSHM_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)nactorx; + + if (shop_mastersp->think_idx == aSHM_THINK_HAPPY_ACADEMY3) { + (*shop_mastersp->think_proc)(shop_mastersp, play); + } else if (shop_mastersp->think_idx == aSHM_THINK_NORMAL_WAIT || + shop_mastersp->think_idx == aSHM_THINK_NORMAL_WAIT2 || + shop_mastersp->think_idx == aSHM_THINK_NORMAL_WAIT3) { + (*shop_mastersp->think_proc)(shop_mastersp, play); + } else if (shop_mastersp->npc_class.action.step == aNPC_ACTION_END_STEP) { + (*shop_mastersp->think_proc)(shop_mastersp, play); + } else if (shop_mastersp->npc_class.action.idx == aNPC_ACT_WALK2) { + shop_mastersp->npc_class.movement.mv_add_angl = DEG2SHORT_ANGLE2(22.5f); + } +} + +static void aSHM_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)nactorx; + lbRTC_time_c rtc_time = Common_Get(time.rtc_time); + + shop_mastersp->npc_class.actor_class.status_data.weight = MASSTYPE_HEAVY; + shop_mastersp->npc_class.condition_info.hide_request = FALSE; + aSHM_set_start_think(shop_mastersp, play); + shop_mastersp->month = rtc_time.month; +} + +static void aSHM_normal_wait_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + aSHM_set_request_act(shop_mastersp, 4, aNPC_ACT_WAIT, aNPC_ACT_TYPE_SEARCH, aNPC_ACT_OBJ_PLAYER, 0, 0); +} + +static void aSHM_normal_turn_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)shop_mastersp; + + aSHM_set_request_act(shop_mastersp, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, + actorx->world.position.x, actorx->world.position.z + 10); +} + +static void aSHM_move_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + aSHM_set_request_act(shop_mastersp, 4, aNPC_ACT_WALK2, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, + shop_mastersp->base_pos[shop_mastersp->now_idx][0], + shop_mastersp->base_pos[shop_mastersp->now_idx][1]); +} + +static void aSHM_move_turn_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + aSHM_set_request_act(shop_mastersp, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, + shop_mastersp->base_pos[shop_mastersp->now_idx][0], + shop_mastersp->base_pos[shop_mastersp->now_idx][1]); +} + +static void aSHM_fade_out_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + // nothing +} + +static void aSHM_hirou_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + aSHM_set_request_act(shop_mastersp, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, + shop_mastersp->base_pos[shop_mastersp->now_idx][0], + shop_mastersp->base_pos[shop_mastersp->now_idx][1] - 10); + shop_mastersp->timer = 20; +} + +static void aSHM_happy_academy_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + shop_mastersp->move_think_idx = aSHM_THINK_HAPPY_ACADEMY2; + aSHM_set_start_avoid_pos(shop_mastersp, 9); +} + +static void aSHM_happy_academy2_init(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + mEv_EventOFF(mEv_SAVED_HRATALK_PLR0 + Common_Get(player_no)); + shop_mastersp->move_think_idx = aSHM_THINK_HAPPY_ACADEMY3; + aSHM_set_start_avoid_pos(shop_mastersp, 5); +} + +typedef struct { + aSHM_THINK_PROC think_proc; + aSHM_THINK_PROC think_init_proc; + aNPC_TALK_REQUEST_PROC talk_request_proc; + u8 talk_idx; + u8 next_think_idx; +} aSHM_think_data_c; + +static void aSHM_setup_think_proc(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play, int think_idx) { + // clang-format off + static aSHM_think_data_c dt_tbl[aSHM_THINK_NUM] = { + {aSHM_normal_wait, aSHM_normal_wait_init, aSHM_norm_talk_request, 0x00, aSHM_THINK_NORMAL_TURN}, + {aSHM_normal_wait2, aSHM_normal_wait_init, aSHM_norm_talk_request, 0x01, aSHM_THINK_NORMAL_TURN}, + {aSHM_normal_wait3, aSHM_normal_wait_init, aSHM_norm_talk_request, 0x02, aSHM_THINK_NORMAL_TURN}, + {aSHM_normal_turn, aSHM_normal_turn_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_NORMAL_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x00, aSHM_THINK_FADE_OUT}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x01, aSHM_THINK_NORMAL_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x02, aSHM_THINK_MOVE_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x03, aSHM_THINK_MOVE_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x04, aSHM_THINK_MOVE_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x05, aSHM_THINK_NORMAL_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x06, aSHM_THINK_MOVE_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x07, aSHM_THINK_NORMAL_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_normal_wait_init, aSHM_force_talk_request, 0x08, aSHM_THINK_NORMAL_TURN}, + {aSHM_move, aSHM_move_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_MOVE_TURN}, + {aSHM_move_turn, aSHM_move_turn_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_MOVE}, + {(aSHM_THINK_PROC)none_proc1, aSHM_fade_out_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_FADE_OUT}, + {aSHM_move_player, (aSHM_THINK_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_MOVE_PLAYER}, + {aSHM_wait_player, (aSHM_THINK_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_WAIT_PLAYER}, + {aSHM_wait_player2, (aSHM_THINK_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_WAIT_PLAYER2}, + {aSHM_wait_player3, (aSHM_THINK_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_WAIT_PLAYER3}, + {aSHM_wait_player4, (aSHM_THINK_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_WAIT_PLAYER4}, + {aSHM_hirou, aSHM_hirou_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_HIROU}, + {(aSHM_THINK_PROC)none_proc1, aSHM_happy_academy_init, aSHM_force_talk_request, 0x09, aSHM_THINK_MOVE_TURN}, + {(aSHM_THINK_PROC)none_proc1, aSHM_happy_academy2_init, aSHM_force_talk_request, 0x0A, aSHM_THINK_MOVE_TURN}, + {aSHM_happy_academy3, aSHM_normal_wait_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aSHM_THINK_HAPPY_ACADEMY3}, + }; + // clang-format on + + aSHM_think_data_c* data_p = &dt_tbl[think_idx]; + + shop_mastersp->think_idx = think_idx; + shop_mastersp->think_proc = data_p->think_proc; + shop_mastersp->npc_class.talk_info.talk_request_proc = data_p->talk_request_proc; + shop_mastersp->talk_idx = data_p->talk_idx; + shop_mastersp->next_think_idx = data_p->next_think_idx; + (*data_p->think_init_proc)(shop_mastersp, play); +} + +static void aSHM_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC think_proc[] = { aSHM_think_init_proc, aSHM_think_main_proc }; + + (*think_proc[type])(nactorx, play); +} + +static void aSHM_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->think.think_proc = aSHM_think_proc; + CLIP(npc_clip)->think_proc(nactorx, play, aNPC_THINK_IN_BLOCK, 0); +} + +static void aSHM_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (!CLIP(npc_clip)->think_proc(nactorx, play, -1, 1)) { + CLIP(npc_clip)->think_proc(nactorx, play, -1, 2); + } +} + +static void aSHM_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC sche_proc[] = { aSHM_schedule_init_proc, aSHM_schedule_main_proc }; + + (*sche_proc[type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc_shop_mastersp_talk.c_inc b/src/actor/npc/ac_npc_shop_mastersp_talk.c_inc new file mode 100644 index 00000000..0119c960 --- /dev/null +++ b/src/actor/npc/ac_npc_shop_mastersp_talk.c_inc @@ -0,0 +1,421 @@ +static int player_go_away(GAME_PLAY* play) { + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + + if (playerx != NULL && CLIP(shop_design_clip) != NULL) { + PLAYER_ACTOR* player = (PLAYER_ACTOR*)playerx; + mActor_name_t front_item = player->item_in_front; + + if (front_item == EXIT_DOOR1) { + return TRUE; + } + } + + return FALSE; +} + +static int player_buy(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + int ux; + int uz; + mActor_name_t item; + + if (shop_mastersp->timer > 0) { + shop_mastersp->timer--; + return FALSE; + } + + if (playerx != NULL) { + PLAYER_ACTOR* player = (PLAYER_ACTOR*)playerx; + + if (player->a_btn_pressed == TRUE) { + mFI_Wpos2UtNum(&ux, &uz, player->forward_ut_pos); + item = CLIP(shop_design_clip)->unitNum2ItemNo_proc(ux, uz); + + if (item != EMPTY_NO && item != RSV_SHOP_SOLD_FTR && item != RSV_NO) { + shop_mastersp->timer = 10; + return TRUE; + } + } + } + + return FALSE; +} + +static int check_null_lottery(void) { + mActor_name_t* item_p = Save_Get(shop).lottery_items; + int i; + + for (i = 0; i < mSP_LOTTERY_ITEM_COUNT; i++) { + if (item_p[i] != EMPTY_NO && item_p[i] != RSV_SHOP_SOLD_FTR) { + return FALSE; + } + } + + return TRUE; +} + +static int search_lottery_ticket(int idx, int month) { + mActor_name_t item = Now_Private->inventory.pockets[idx]; + + if (NowPrivate_GetItemCond(idx) == mPr_ITEM_COND_NORMAL && ITEM_NAME_GET_TYPE(item) == NAME_TYPE_ITEM1 && + ITEM_NAME_GET_CAT(item - ITEM1_NO_START) == ITEM1_CAT_TICKET && TICKET_MONTH(item) == month) { + return TICKET_COUNT(item); + } + + return 0; +} + +static int check_lottery_ticket(int month) { + int i; + int count = 0; + + for (i = 0; i < mPr_POCKETS_SLOT_COUNT && count < aSHM_REQ_TICKET_NUM; i++) { + count += search_lottery_ticket(i, month); + } + + return count >= aSHM_REQ_TICKET_NUM; +} + +static void uketori_lottery_ticket_amari(int idx, int count, int month) { + mActor_name_t item = Now_Private->inventory.pockets[idx]; + + mPr_SetPossessionItem(Now_Private, idx, ITM_TICKET_START | TICKET_TO_MONTH(month) | (TICKET_TO_COUNT(item) - count), + mPr_ITEM_COND_NORMAL); +} + +static void uketori_lottery_ticket(int month) { + int i; + int count; + int req = aSHM_REQ_TICKET_NUM; + + for (i = 0; i < mPr_POCKETS_SLOT_COUNT && req > 0; i++) { + count = search_lottery_ticket(i, month); + if (count != 0) { + if (count <= req) { + mPr_SetPossessionItem(Now_Private, i, EMPTY_NO, mPr_ITEM_COND_NORMAL); + } else { + uketori_lottery_ticket_amari(i, req, month); + } + + req -= count; + } + } +} + +static void aSHM_get_Fgitem_pos(mActor_name_t item, int* ux, int* uz) { + mActor_name_t* fg_p = mFI_BkNumtoUtFGTop(0, 0); + int i; + + for (i = 0; i < UT_TOTAL_NUM; i++) { + if (item == *fg_p) { + *ux = i % UT_X_NUM; + *uz = i / UT_X_NUM; + break; + } + + fg_p++; + } +} + +static void aSHM_remove_gift(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, mActor_name_t item) { + int ux; + int uz; + int ftrID; + + aSHM_get_Fgitem_pos(item, &ux, &uz); + + if (aMR_CLIP != NULL && aMR_CLIP->unitNum2ftrItemNoftrId_proc(NULL, &ftrID, ux, uz, mCoBG_LAYER0)) { + aMR_CLIP->ftrId2extinguishFtr_proc(ftrID); + } + + shop_mastersp->ut[0] = ux; + shop_mastersp->ut[1] = uz; +} + +static int to_atari(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp) { + u8 name_str[mIN_ITEM_NAME_LEN]; + mActor_name_t* item_p = Save_Get(shop).lottery_items; + + if (item_p[shop_mastersp->result] == RSV_SHOP_SOLD_FTR || item_p[shop_mastersp->result] == EMPTY_NO) { + return FALSE; + } + + mIN_copy_name_str(name_str, item_p[shop_mastersp->result]); + mMsg_SET_ITEM_STR_ART(mMsg_FREE_STR0, name_str, mIN_ITEM_NAME_LEN, item_p[shop_mastersp->result]); + mPr_SetFreePossessionItem(Now_Private, item_p[shop_mastersp->result], mPr_ITEM_COND_PRESENT); + aSHM_set_start_avoid_pos(shop_mastersp, shop_mastersp->result * 3); + shop_mastersp->move_think_idx = aSHM_THINK_HIROU; + return TRUE; +} + +static void fukubiki_before_process(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp) { + int rng = RANDOM(100); + + uketori_lottery_ticket(shop_mastersp->month); + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_STOP_PLAYER); + shop_mastersp->next_think_idx = aSHM_THINK_MOVE_PLAYER; + + if (rng < aSHM_FIRST_PLACE_PERCENT) { + shop_mastersp->result = aSHM_WON_FIRST_PLACE; + } else if (rng < aSHM_SECOND_PLACE_PERCENT) { + shop_mastersp->result = aSHM_WON_SECOND_PLACE; + } else if (rng < aSHM_THIRD_PLACE_PERCENT) { + shop_mastersp->result = aSHM_WON_THIRD_PLACE; + } else { + shop_mastersp->result = aSHM_DIDNT_WIN; + } + + // If the prize was already won then we change to didn't win + if (shop_mastersp->result != aSHM_DIDNT_WIN && !to_atari(shop_mastersp)) { + shop_mastersp->result = aSHM_DIDNT_WIN; + } +} + +static void aSHM_talk_try(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (mMsg_CHECK_MAINNORMALCONTINUE()) { + shop_mastersp->result = mChoice_GET_CHOSENUM(); + + switch (shop_mastersp->result) { + case mChoice_CHOICE0: + if (check_lottery_ticket(shop_mastersp->month)) { + mMsg_SET_CONTINUE_MSG_NUM(0x10D4); + fukubiki_before_process(shop_mastersp); + } else { + mMsg_SET_CONTINUE_MSG_NUM(0x10D3); + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_END_WAIT); + } + break; + case mChoice_CHOICE1: + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_END_WAIT); + break; + } + } +} + +static void aSHM_talk_hazure(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order == 3) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + if (check_lottery_ticket(shop_mastersp->month)) { + mMsg_SET_CONTINUE_MSG_NUM(0x10D7); + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_TALK_RETRY); + } else { + mMsg_SET_CONTINUE_MSG_NUM(0x10D6); + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_TALK_TAMAKESI); + } + } +} + +static void aSHM_talk_retry(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order == 2) { + if (CLIP(garagara_clip) != NULL) { + CLIP(garagara_clip)->delete_ball_proc(); + } + + shop_mastersp->result = mChoice_GET_CHOSENUM(); + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + switch (shop_mastersp->result) { + case mChoice_CHOICE0: + fukubiki_before_process(shop_mastersp); + break; + case mChoice_CHOICE1: + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_END_WAIT); + break; + } + } +} + +static void aSHM_stop_player(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)shop_mastersp; + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + + if (order == 1) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + sAdo_OngenTrgStart(NA_SE_7F, &actorx->world.position); + } + + if (!mDemo_Check(mDemo_TYPE_TALK, actorx) && !mDemo_Check(mDemo_TYPE_SPEAK, actorx)) { + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_DEMO_WAIT) { + mPlib_request_main_demo_wait_type1((GAME*)play, FALSE, NULL); + } else { + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_END_WAIT); + } + } +} + +static void aSHM_give_player(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + mActor_name_t* item_p = Save_Get(shop).lottery_items; + + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 2); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, item_p[shop_mastersp->result]); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, aHOI_REQUEST_PUTAWAY); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, FALSE); + + item_p[shop_mastersp->result] = RSV_SHOP_SOLD_FTR; + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_STOP_PLAYER); + aSHM_set_start_avoid_pos(shop_mastersp, shop_mastersp->root + 1); + + if (check_null_lottery() || !check_lottery_ticket(shop_mastersp->month)) { + shop_mastersp->move_think_idx = aSHM_THINK_11; + } else { + shop_mastersp->move_think_idx = aSHM_THINK_12; + } +} + +static void aSHM_talk_tamakesi(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)shop_mastersp; + + if (!mDemo_Check(mDemo_TYPE_SPEAK, actorx) && !mDemo_Check(mDemo_TYPE_TALK, actorx)) { + if (CLIP(garagara_clip) != NULL) { + CLIP(garagara_clip)->delete_ball_proc(); + } + } +} + +static void aSHM_say_goodbye(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + if (mMsg_Check_idling_now(msg_p) == TRUE) { + mMsg_request_main_disappear_wait_type1(msg_p); + aSHM_change_talk_proc(shop_mastersp, aSHM_TALK_EXIT_WAIT); + } +} + +static void aSHM_exit_wait(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, GAME_PLAY* play) { + if (mMsg_CHECK_MAIN_WAIT() == TRUE) { + goto_other_scene(play, Common_GetPointer(structure_exit_door_data), TRUE); + + if (play->fb_wipe_mode == 0) { + mBGMPsComp_scene_mode(14); + mBGMPsComp_volume_talk_end(); + mBGMPsComp_make_ps_wipe(0x195); + } + } +} + +static int aSHM_change_talk_proc(NPC_SHOP_MASTERSP_ACTOR* shop_mastersp, int talk_proc) { + // clang-format off + static aSHM_TALK_PROC proc[aSHM_TALK_NUM] = { + &aSHM_talk_try, + &aSHM_talk_hazure, + &aSHM_talk_retry, + &aSHM_stop_player, + &aSHM_give_player, + &aSHM_talk_tamakesi, + (aSHM_TALK_PROC)&none_proc1, + &aSHM_say_goodbye, + &aSHM_exit_wait, + }; + // clang-format on + + int ret = TRUE; + + shop_mastersp->talk_proc = proc[talk_proc]; + + if (talk_proc == aSHM_TALK_STOP_PLAYER) { + mDemo_Set_talk_return_demo_wait(TRUE); + } + + if (talk_proc == aSHM_TALK_SAY_GOODBYE) { + mMsg_SET_IDLING_REQ(); + } + + return ret; +} + +typedef struct { + int msg_no; + int talk_proc; + u8 turn; + u8 cam_type; +} aSHM_talk_data_c; + +static void aSHM_set_force_talk_info(ACTOR* actorx) { + // clang-format off + static aSHM_talk_data_c dt_tbl[] = { + {0x109E, aSHM_TALK_SAY_GOODBYE, FALSE, CAMERA2_PROCESS_NORMAL}, + {0x10E0, aSHM_TALK_END_WAIT, TRUE, CAMERA2_PROCESS_NORMAL}, + {0x10D9, aSHM_TALK_STOP_PLAYER, TRUE, CAMERA2_PROCESS_TALK}, + {0x10DA, aSHM_TALK_STOP_PLAYER, TRUE, CAMERA2_PROCESS_TALK}, + {0x10DB, aSHM_TALK_STOP_PLAYER, TRUE, CAMERA2_PROCESS_TALK}, + {0x10D5, aSHM_TALK_TALK_HAZURE, TRUE, CAMERA2_PROCESS_TALK}, + {0x10E3, aSHM_TALK_GIVE_PLAYER, TRUE, CAMERA2_PROCESS_TALK}, + {0x10DC, aSHM_TALK_TALK_TAMAKESI, TRUE, CAMERA2_PROCESS_TALK}, + {0x10DD, aSHM_TALK_TALK_RETRY, TRUE, CAMERA2_PROCESS_TALK}, + {0x10E6, aSHM_TALK_STOP_PLAYER, TRUE, CAMERA2_PROCESS_NORMAL}, + {0x082A, aSHM_TALK_STOP_PLAYER, TRUE, CAMERA2_PROCESS_TALK}, + }; + // clang-format on + + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)actorx; + aSHM_talk_data_c* data_p = &dt_tbl[shop_mastersp->talk_idx]; + + mDemo_Set_msg_num(data_p->msg_no); + mDemo_Set_talk_turn(data_p->turn); + mDemo_Set_camera(data_p->cam_type); + aSHM_change_talk_proc(shop_mastersp, data_p->talk_proc); + + if (shop_mastersp->talk_idx != 0 && shop_mastersp->talk_idx != 1) { + if (shop_mastersp->npc_class.talk_info.melody_inst != 0) { + shop_mastersp->melody_bak = shop_mastersp->npc_class.talk_info.melody_inst; + } + + shop_mastersp->npc_class.talk_info.melody_inst = 0; + } +} + +static void aSHM_force_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aSHM_set_force_talk_info); +} + +static void aSHM_set_norm_talk_info(ACTOR* actorx) { + // clang-format off + static aSHM_talk_data_c dt_tbl[] = { + {0x10D1, aSHM_TALK_TALK_TRY, TRUE, CAMERA2_PROCESS_TALK}, + {0x10DF, aSHM_TALK_END_WAIT, TRUE, CAMERA2_PROCESS_TALK}, + {0x10E4, aSHM_TALK_END_WAIT, TRUE, CAMERA2_PROCESS_TALK}, + }; + // clang-format on + + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)actorx; + aSHM_talk_data_c* data_p = &dt_tbl[shop_mastersp->talk_idx]; + + mDemo_Set_msg_num(data_p->msg_no); + mDemo_Set_talk_turn(data_p->turn); + mDemo_Set_camera(data_p->cam_type); + aSHM_change_talk_proc(shop_mastersp, data_p->talk_proc); +} + +static void aSHM_norm_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_TALK, actorx, &aSHM_set_norm_talk_info); +} + +static int aSHM_talk_init(ACTOR* actorx, GAME* game) { + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)actorx; + + shop_mastersp->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1; + mDemo_Set_ListenAble(); + mDemo_Start(actorx); + return TRUE; +} + +static int aSHM_talk_end_chk(ACTOR* actorx, GAME* game) { + NPC_SHOP_MASTERSP_ACTOR* shop_mastersp = (NPC_SHOP_MASTERSP_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int ret = FALSE; + + (*shop_mastersp->talk_proc)(shop_mastersp, play); + if (mDemo_CAN_ACTOR_TALK(actorx)) { + aSHM_setup_think_proc(shop_mastersp, play, shop_mastersp->next_think_idx); + ret = TRUE; + + if (shop_mastersp->melody_bak != 0) { + shop_mastersp->npc_class.talk_info.melody_inst = shop_mastersp->melody_bak; + } + } + + return ret; +}