From 1310657ac25d4c0d5aa9ebc38f48e6a6b254925c Mon Sep 17 00:00:00 2001 From: Vi Date: Thu, 15 May 2025 20:57:04 -0500 Subject: [PATCH] Implement and link ac_halloween_npc.c --- configure.py | 2 +- include/ac_halloween_npc.h | 34 ++ src/actor/npc/ac_halloween_npc.c | 129 ++++++++ src/actor/npc/ac_halloween_npc_move.c_inc | 22 ++ src/actor/npc/ac_halloween_npc_schedule.c_inc | 120 +++++++ src/actor/npc/ac_halloween_npc_talk.c_inc | 301 ++++++++++++++++++ 6 files changed, 607 insertions(+), 1 deletion(-) create mode 100644 src/actor/npc/ac_halloween_npc.c create mode 100644 src/actor/npc/ac_halloween_npc_move.c_inc create mode 100644 src/actor/npc/ac_halloween_npc_schedule.c_inc create mode 100644 src/actor/npc/ac_halloween_npc_talk.c_inc diff --git a/configure.py b/configure.py index 5bb3e5dc..a10438e7 100644 --- a/configure.py +++ b/configure.py @@ -1098,7 +1098,7 @@ config.libs = [ Object(NonMatching, "actor/npc/ac_countdown_npc1.c"), Object(Matching, "actor/npc/ac_go_home_npc.c"), Object(NonMatching, "actor/npc/ac_groundhog_npc0.c"), - Object(NonMatching, "actor/npc/ac_halloween_npc.c"), + Object(Matching, "actor/npc/ac_halloween_npc.c"), Object(NonMatching, "actor/npc/ac_hanabi_npc0.c"), Object(NonMatching, "actor/npc/ac_hanabi_npc1.c"), Object(NonMatching, "actor/npc/ac_hanami_npc0.c"), diff --git a/include/ac_halloween_npc.h b/include/ac_halloween_npc.h index 3cd4291d..b7484a48 100644 --- a/include/ac_halloween_npc.h +++ b/include/ac_halloween_npc.h @@ -3,11 +3,45 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +typedef struct halloween_npc_s NPC_HALLOWEEN_ACTOR; + +typedef void (*aHWN_TALK_PROC)(NPC_HALLOWEEN_ACTOR*, GAME_PLAY*); +// has to be _P because a function is already defined as aHWN_think_proc +typedef void (*aHWN_THINK_PROC_P)(NPC_ACTOR*, GAME_PLAY*); +/* sizeof(halloween_npc_s) == 0x9AC*/ +struct halloween_npc_s { + /* 0x000 */ NPC_ACTOR npc_class; + /* 0x994 */ int dt_tbl_idx; + /* 0x998 */ aHWN_THINK_PROC_P think_proc; + /* 0x99C */ int _99C; + /* 0x9A0 */ aHWN_TALK_PROC talk_proc; + /* 0x9A4 */ mActor_name_t item; + /* 0x9A8 */ BOOL _9A0; +}; +enum { + aHWN_TALK_FIRST_CALL_TALK_PROC, // 0 + aHWN_TALK_TRICK_OR_TREAT_TALK_PROC, // 1 + aHWN_TALK_MENU_OPEN_WAIT_TALK_PROC, // 2 + aHWN_TALK_MENU_CLOSE_WAIT_TALK_PROC, // 3 + aHWN_TALK_GET_OTHER_ITEM_WAIT_TALK_PROC, // 4 + aHWN_TALK_RECEIVE_TOOL_ITEM_START_WAIT_TALK_PROC, // 5 + aHWN_TALK_RECEIVE_TOOL_ITEM_END_WAIT_TALK_PROC, // 6 + aHWN_TALK_TRICK_TIMING_WAIT_TALK_PROC, // 7 + aHWN_TALK_TRICK_CHG_CLOTH_TALK_PROC, // 8 + aHWN_TALK_TRICK_CHG_CLOTH_END_WAIT_TALK_PROC, // 9 + aHWN_TALK_GET_AME_WAIT_TALK_PROC, // 10 + aHWN_TALK_GET_AME_TALK_PROC, // 11 + aHWN_TALK_PL_DEMO_CODE_END_WAIT_TALK_PROC, // 12 + aHWN_TALK_NONE_PROC1, // 13 +}; + + extern ACTOR_PROFILE Halloween_Npc_Profile; #ifdef __cplusplus diff --git a/src/actor/npc/ac_halloween_npc.c b/src/actor/npc/ac_halloween_npc.c new file mode 100644 index 00000000..e3866fe8 --- /dev/null +++ b/src/actor/npc/ac_halloween_npc.c @@ -0,0 +1,129 @@ +#include "ac_halloween_npc.h" + +#include "ac_npc.h" +#include "ac_npc_h.h" +#include "dolphin/os/OSRtc.h" +#include "libc64/qrand.h" +#include "libultra/libultra.h" +#include "m_actor_type.h" +#include "m_bgm.h" +#include "m_card.h" +#include "m_choice.h" +#include "m_common_data.h" +#include "m_config.h" +#include "m_demo.h" +#include "m_lib.h" +#include "m_msg.h" +#include "m_npc.h" +#include "m_play.h" +#include "m_play_h.h" +#include "m_player.h" +#include "m_player_lib.h" +#include "m_room_type.h" +#include "m_soncho.h" +#include "m_vibctl.h" +#include "types.h" + +static void aHWN_actor_ct(ACTOR* actorx, GAME* game); +static void aHWN_actor_dt(ACTOR* actorx, GAME* game); +static void aHWN_actor_save(ACTOR* actorx, GAME* game); +static void aHWN_actor_init(ACTOR* actorx, GAME* game); +static void aHWN_actor_draw(ACTOR* actorx, GAME* game); + +static BOOL aHWN_set_request_act(NPC_HALLOWEEN_ACTOR* actorx, u8 prio, u8 idx, u8 type, u16 obj, s16 move_x, + s16 move_z); +static void aHWN_actor_move(ACTOR* actorx, GAME* game); + +static int aHWN_get_trick_type(); +static void aHWN_restart_msg_win(NPC_HALLOWEEN_ACTOR* actorx, int msg_idx); +static void aHWN_first_call_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_trick_or_treat_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_menu_open_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_menu_close_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_get_other_item_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_receive_tool_item_start_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_receive_tool_item_end_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_trick_timing_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_trick_chg_cloth_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_trick_chg_cloth_end_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_get_ame_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_get_ame_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_pl_demo_code_end_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_change_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, int talk_proc_idx); +static void aHWN_set_force_talk_info(ACTOR* actorx); +static void aHWN_force_talk_request(ACTOR* actorx, GAME* game); +static void aHWN_set_norm_talk_info(NPC_HALLOWEEN_ACTOR* actorx); +static void aHWN_norm_talk_request(NPC_HALLOWEEN_ACTOR* actorx); +static int aHWN_talk_init(); +static BOOL aHWN_talk_end_chk(ACTOR* actorx, GAME* game); + +static void aHWN_approach(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_approach_wait(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* playe); +static void aHWN_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_approach_init(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_approach_wait_init(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_setup_think_proc(ACTOR* actorx, GAME* game, int dt_tbl_idx); +static void aHWN_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_proc_idx); +static void aHWN_schedule_think_init(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aHWN_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sche_proc_idx); + +// clang-format off +ACTOR_PROFILE Halloween_Npc_Profile = { + mAc_PROFILE_HALLOWEEN_NPC, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + 0, + ACTOR_OBJ_BANK_KEEP, + sizeof(NPC_HALLOWEEN_ACTOR), + aHWN_actor_ct, + aHWN_actor_dt, + aHWN_actor_init, + mActor_NONE_PROC1, + aHWN_actor_save, +}; +// clang-format on + +static void aHWN_actor_ct(ACTOR* actorx, GAME* game) { + // clang-format off + static aNPC_ct_data_c ct_data = { + &aHWN_actor_move, + &aHWN_actor_draw, + aNPC_CT_SCHED_TYPE_SPECIAL, + &aHWN_force_talk_request, + &aHWN_talk_init, + &aHWN_talk_end_chk, + 0, + }; + // clang-format on + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + if (NPC_CLIP->birth_check_proc(actorx, game) == TRUE) { + hwn_actor->npc_class.schedule.schedule_proc = &aHWN_schedule_proc; + NPC_CLIP->ct_proc(actorx, game, &ct_data); + hwn_actor->npc_class.palActorIgnoreTimer = -1; + } +} + +static void aHWN_actor_dt(ACTOR* actorx, GAME* game) { + NPC_CLIP->dt_proc(actorx, game); +} + +static void aHWN_actor_save(ACTOR* actorx, GAME* game) { + NPC_CLIP->save_proc(actorx, game); +} + +static void aHWN_actor_init(ACTOR* actorx, GAME* game) { + NPC_CLIP->init_proc(actorx, game); +} + +static void aHWN_actor_draw(ACTOR* actorx, GAME* game) { + NPC_CLIP->draw_proc(actorx, game); +} + +#include "../src/actor/npc/ac_halloween_npc_move.c_inc" + +#include "../src/actor/npc/ac_halloween_npc_talk.c_inc" + +#include "../src/actor/npc/ac_halloween_npc_schedule.c_inc" diff --git a/src/actor/npc/ac_halloween_npc_move.c_inc b/src/actor/npc/ac_halloween_npc_move.c_inc new file mode 100644 index 00000000..ea1af053 --- /dev/null +++ b/src/actor/npc/ac_halloween_npc_move.c_inc @@ -0,0 +1,22 @@ +static BOOL aHWN_set_request_act(NPC_HALLOWEEN_ACTOR* actorx, u8 prio, u8 idx, u8 type, u16 obj, s16 move_x, + s16 move_z) { + BOOL res = FALSE; + if (prio >= actorx->npc_class.request.act_priority) { + u16 args[aNPC_REQUEST_ARG_NUM]; + bzero(args, sizeof(args)); + args[0] = obj; + args[2] = move_x; + args[3] = move_z; + args[5] = 70; + actorx->npc_class.request.act_priority = prio; + actorx->npc_class.request.act_idx = idx; + actorx->npc_class.request.act_type = type; + mem_copy((u8*)actorx->npc_class.request.act_args, (u8*)args, sizeof(args)); + res = TRUE; + } + return res; +} + +static void aHWN_actor_move(ACTOR* actorx, GAME* game) { + NPC_CLIP->move_proc(actorx, game); +} diff --git a/src/actor/npc/ac_halloween_npc_schedule.c_inc b/src/actor/npc/ac_halloween_npc_schedule.c_inc new file mode 100644 index 00000000..845ca6e1 --- /dev/null +++ b/src/actor/npc/ac_halloween_npc_schedule.c_inc @@ -0,0 +1,120 @@ +static void aHWN_approach(NPC_ACTOR* actorx, GAME_PLAY* play) { + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + ACTOR* talk_actor = mDemo_Get_talk_actor(); + if ((talk_actor != NULL && talk_actor != &actorx->actor_class) || + (hwn_actor->npc_class.actor_class.block_x != play->block_table.block_x || + hwn_actor->npc_class.actor_class.block_z != play->block_table.block_z)) { + aHWN_setup_think_proc(&actorx->actor_class, &play->game, 1); + } else if (hwn_actor->npc_class.action.step == aNPC_ACTION_END_STEP) { + aHWN_setup_think_proc(&actorx->actor_class, &play->game, 0); + } +} + +static void aHWN_approach_wait(NPC_ACTOR* actorx, GAME_PLAY* play) { + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + if (((mDemo_Get_talk_actor() == 0) && (hwn_actor->npc_class.actor_class.block_x == (play->block_table).block_x)) && + (hwn_actor->npc_class.actor_class.block_z == (play->block_table).block_z)) { + aHWN_setup_think_proc(&actorx->actor_class, &play->game, 0); + } else if (hwn_actor->npc_class.action.step == aNPC_ACTION_END_STEP) { + aHWN_setup_think_proc(&actorx->actor_class, &play->game, 1); + } +} + +static void aHWN_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + hwn_actor->think_proc(actorx, play); +} + +static void aHWN_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + aHWN_setup_think_proc(&actorx->actor_class, &play->game, 0); + hwn_actor->npc_class.condition_info.hide_request = 0; + hwn_actor->npc_class.think.interrupt_flags = aNPC_THINK_INTERRUPT_ENTRANCE | aNPC_THINK_INTERRUPT_OBSTACLE; + hwn_actor->npc_class.condition_info.demo_flg = aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV; +} + +static void aHWN_approach_init(NPC_ACTOR* actorx, GAME_PLAY* play) { + aHWN_set_request_act((NPC_HALLOWEEN_ACTOR*)actorx, 4, aNPC_ACT_RUN, aNPC_ACT_TYPE_SEARCH, aNPC_ACT_OBJ_PLAYER, 0, + 0); +} + +static void aHWN_approach_wait_init(NPC_ACTOR* actorx, GAME_PLAY* play) { + aHWN_set_request_act((NPC_HALLOWEEN_ACTOR*)actorx, 4, aNPC_ACT_WAIT, aNPC_ACT_TYPE_SEARCH, aNPC_ACT_OBJ_PLAYER, 0, + 0); +} + +typedef struct { + aHWN_THINK_PROC_P approach_proc; + aHWN_THINK_PROC_P approach_init_proc; + aNPC_TALK_REQUEST_PROC talk_request_proc; + u8 unk; +} aHWN_talk_data_c; + +static void aHWN_setup_think_proc(ACTOR* actorx, GAME* game, int dt_tbl_idx) { + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + aHWN_talk_data_c* data; + // clang-format off + static aHWN_talk_data_c dt_tbl[] = { + { &aHWN_approach, &aHWN_approach_init, &aHWN_force_talk_request, 0 }, + { &aHWN_approach_wait, &aHWN_approach_wait_init, (aNPC_TALK_REQUEST_PROC)&none_proc1, 0 }, + }; + // clang-format on + + hwn_actor->dt_tbl_idx = dt_tbl_idx; + data = &dt_tbl[dt_tbl_idx]; + hwn_actor->think_proc = data->approach_proc; + hwn_actor->npc_class.talk_info.talk_request_proc = data->talk_request_proc; + hwn_actor->_99C = data->unk; + data->approach_init_proc((NPC_ACTOR*)actorx, (GAME_PLAY*)game); +} + +static void aHWN_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_proc_idx) { + static aHWN_THINK_PROC_P think_proc[] = { aHWN_think_init_proc, aHWN_think_main_proc }; + think_proc[think_proc_idx](actorx, play); +} + +static void aHWN_schedule_think_init(NPC_ACTOR* actorx, GAME_PLAY* play) { + static int think_idx[] = { 5, 9, 1 }; + NPC_CLIP->think_proc(actorx, play, think_idx[actorx->schedule.step], 0); +} + +static void aHWN_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + int step = 1; + actorx->think.think_proc = aHWN_think_proc; + if (actorx->npc_info.animal->is_home == TRUE) { + step = 0; + } + actorx->schedule.step = step; + aHWN_schedule_think_init(actorx, play); +} + +static void aHWN_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + if (actorx->think.end_flag == TRUE) { + if (actorx->schedule.step != 2) { + actorx->schedule.step += 1; + } + aHWN_schedule_think_init(actorx, play); + } else if (hwn_actor->_9A0 == TRUE) { + if (NPC_CLIP->think_proc(actorx, play, -1, 1) == 0) { + if (actorx->action.step == aNPC_ACTION_END_STEP) { + hwn_actor->_9A0 = FALSE; + aHWN_schedule_think_init(actorx, play); + } + } else { + actorx->request.act_priority = 4; + } + } else { + if (NPC_CLIP->think_proc(actorx, play, -1, 1) == 0) { + NPC_CLIP->think_proc(actorx, play, -1, 2); + } else { + actorx->request.act_priority = 4; + hwn_actor->_9A0 = TRUE; + } + } +} + +static void aHWN_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sche_proc_idx) { + static aNPC_SUB_PROC sche_proc[] = { aHWN_schedule_init_proc, aHWN_schedule_main_proc }; + sche_proc[sche_proc_idx](actorx, play); +} diff --git a/src/actor/npc/ac_halloween_npc_talk.c_inc b/src/actor/npc/ac_halloween_npc_talk.c_inc new file mode 100644 index 00000000..297dfbf4 --- /dev/null +++ b/src/actor/npc/ac_halloween_npc_talk.c_inc @@ -0,0 +1,301 @@ +static int aHWN_get_trick_type(void) { + int count = 0; + int idx[mPr_POCKETS_SLOT_COUNT]; + mActor_name_t* pockets_p = Now_Private->inventory.pockets; + int i; + int ret = 0; // trick type enum/define + + for (i = 0; i < mPr_POCKETS_SLOT_COUNT; i++) { + switch (ITEM_NAME_GET_TYPE(*pockets_p)) { + case NAME_TYPE_FTR0: + case NAME_TYPE_FTR1: + if ((NowPrivate_GetItemCond(i) & mPr_ITEM_COND_QUEST) == 0) { + int ftr_idx = mRmTp_FtrItemNo2FtrIdx(*pockets_p); + + // check furniture is not jack-o'-lantern nor jack-in-the-box + if (ftr_idx != 0x127 && ftr_idx != 0x131) { + idx[count++] = i; + } + } + break; + case NAME_TYPE_ITEM1: + if (ITEM_NAME_GET_CAT(*pockets_p) != ITEM1_CAT_TOOL && + (NowPrivate_GetItemCond(i) & mPr_ITEM_COND_QUEST) == 0) { + idx[count++] = i; + } + break; + } + + pockets_p++; + } + + if (count > 0 && RANDOM_F(1.0f) < 0.5f) { + mActor_name_t new_item; + + mSP_SelectRandomItem_New(NULL, &new_item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_HALLOWEEN2, FALSE); + mPr_SetPossessionItem(Now_Private, idx[RANDOM(count)], new_item, mPr_ITEM_COND_NORMAL); + mDemo_Set_OrderValue(mDemo_ORDER_PLAYER, 0, 0xFD); // play trick animation + ret = 1; + } + + return ret; +} + +static void aHWN_restart_msg_win(NPC_HALLOWEEN_ACTOR* actorx, int msg_idx) { + int msg_data; + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + int look = mNpc_GetLooks(actorx->npc_class.npc_info.event->npc_id); + mMsg_request_main_appear_wait_type1(msg_p); + mMsg_ChangeMsgData(msg_p, ((look & 0xFF) * 6 + msg_idx)); + mMsg_Set_ForceNext(msg_p); + mMsg_Unset_LockContinue(msg_p); +} + +static void aHWN_first_call_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int look = mNpc_GetLooks(actorx->npc_class.npc_info.event->npc_id); + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + mMsg_Set_continue_msg_num(msg_p, ((look & 0xFF) * 6) + 0x98b); + aHWN_change_talk_proc(actorx, aHWN_TALK_TRICK_OR_TREAT_TALK_PROC); +} + +static void aHWN_trick_or_treat_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int talk_proc_idx; + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + int order_value = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + if (order_value && mMsg_Check_MainNormalContinue(msg_p) == TRUE) { + if (mChoice_GET_CHOSENUM() == 0) { + mMsg_request_main_disappear_wait_type1(msg_p); + talk_proc_idx = aHWN_TALK_MENU_OPEN_WAIT_TALK_PROC; + } else { + talk_proc_idx = aHWN_TALK_TRICK_TIMING_WAIT_TALK_PROC; + } + aHWN_change_talk_proc(actorx, talk_proc_idx); + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + } +} + +static void aHWN_menu_open_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + if (mMsg_Check_main_wait(msg_p) == TRUE) { + mSM_open_submenu(&play->submenu, mSM_OVL_INVENTORY, 6, 0); + mMsg_Set_LockContinue(msg_p); + aHWN_change_talk_proc(actorx, aHWN_TALK_MENU_CLOSE_WAIT_TALK_PROC); + } +} + +static void aHWN_menu_close_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actor, GAME_PLAY* play) { + Submenu_Item_c* item_p; + int talk_proc_idx; + BOOL shouldSetPosessionItem; + mActor_name_t item; + + if (play->submenu.open_flag == FALSE) { + item_p = play->submenu.item_p; + shouldSetPosessionItem = TRUE; + item = item_p->item; + actor->item = item; + if (item == EMPTY_NO) { + talk_proc_idx = aHWN_TALK_TRICK_TIMING_WAIT_TALK_PROC; + aHWN_restart_msg_win(actor, 0x98c); + shouldSetPosessionItem = FALSE; + } else if (item != ITM_FOOD_CANDY) { + if ((item >= ITM_NET && item <= ITM_ROD) || (item >= ITM_GOLDEN_NET && item <= ITM_GOLDEN_ROD)) { + shouldSetPosessionItem = FALSE; + } + talk_proc_idx = aHWN_TALK_GET_OTHER_ITEM_WAIT_TALK_PROC; + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 3); + } else { + talk_proc_idx = aHWN_TALK_GET_AME_WAIT_TALK_PROC; + aHWN_restart_msg_win(actor, 0x98f); + } + if (shouldSetPosessionItem == TRUE) { + mPr_SetPossessionItem(Now_Private, item_p->slot_no, 0, 0); + } + aHWN_change_talk_proc(actor, talk_proc_idx); + } +} + +static void aHWN_get_other_item_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + mActor_name_t item; + int talk_proc_idx; + int msg_idx; + if (CLIP(handOverItem_clip)->master_actor == 0) { + item = actorx->item; + talk_proc_idx = aHWN_TALK_TRICK_TIMING_WAIT_TALK_PROC; + msg_idx = 0x98e; + if ((item >= ITM_NET && item <= ITM_ROD) || (item >= ITM_GOLDEN_NET && item <= ITM_GOLDEN_ROD)) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 1, 0); + msg_idx = 0x990; + talk_proc_idx = aHWN_TALK_RECEIVE_TOOL_ITEM_START_WAIT_TALK_PROC; + } + aHWN_restart_msg_win(actorx, msg_idx); + aHWN_change_talk_proc(actorx, talk_proc_idx); + } +} + +static void aHWN_receive_tool_item_start_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int OrderValue = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1); + if (OrderValue == 2) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 0, actorx->item); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 1, 7); + mDemo_Set_OrderValue(mDemo_ORDER_NPC1, 2, 0); + mMsg_SET_LOCKCONTINUE(); + aHWN_change_talk_proc(actorx, aHWN_TALK_RECEIVE_TOOL_ITEM_END_WAIT_TALK_PROC); + } +} + +static void aHWN_receive_tool_item_end_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int OrderValue = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1); + if ((OrderValue == 0) && (CLIP(handOverItem_clip)->master_actor == 0)) { + mMsg_UNSET_LOCKCONTINUE(); + aHWN_change_talk_proc(actorx, aHWN_TALK_TRICK_TIMING_WAIT_TALK_PROC); + } +} + +static void aHWN_trick_timing_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int trick_type; + int talk_proc_idx; + int OrderValue = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 9); + mMsg_Window_c* msg_p; + if (OrderValue != 0) { + msg_p = mMsg_Get_base_window_p(); + trick_type = aHWN_get_trick_type(); + talk_proc_idx = aHWN_TALK_PL_DEMO_CODE_END_WAIT_TALK_PROC; + if (trick_type == 0) { + talk_proc_idx = aHWN_TALK_TRICK_CHG_CLOTH_TALK_PROC; + } + mMsg_Set_LockContinue(msg_p); + aHWN_change_talk_proc(actorx, talk_proc_idx); + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 9, 0); + } +} + +static void aHWN_trick_chg_cloth_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int player_actor_main_index = mPlib_get_player_actor_main_index(&play->game); + if (player_actor_main_index == mPlayer_INDEX_CHANGE_CLOTH) { + aHWN_change_talk_proc(actorx, aHWN_TALK_TRICK_CHG_CLOTH_END_WAIT_TALK_PROC); + } else { + mPlib_request_main_change_cloth_forNPC_type1(&play->game, ITM_CLOTH017, 0x11, 0); + } +} + +static void aHWN_trick_chg_cloth_end_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + mMsg_Window_c* msg_p; + int looks; + int player_actor_main_index = mPlib_get_player_actor_main_index(&play->game); + if (player_actor_main_index != mPlayer_INDEX_CHANGE_CLOTH) { + msg_p = mMsg_Get_base_window_p(); + looks = mNpc_GetLooks(actorx->npc_class.npc_info.event->npc_id); + mMsg_Unset_LockContinue(msg_p); + mMsg_Set_ForceNext(msg_p); + mMsg_ChangeMsgData(msg_p, (looks * 6 + 0x98d)); + aHWN_change_talk_proc(actorx, aHWN_TALK_NONE_PROC1); + } +} + +static void aHWN_get_ame_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + int OrderValue = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1); + if ((OrderValue == 3) && (CLIP(handOverItem_clip)->master_actor != 0)) { + mMsg_SET_LOCKCONTINUE(); + aHWN_change_talk_proc(actorx, aHWN_TALK_GET_AME_TALK_PROC); + } +} + +static void aHWN_get_ame_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + if (CLIP(handOverItem_clip)->master_actor == 0) { + mMsg_UNSET_LOCKCONTINUE(); + aHWN_change_talk_proc(actorx, aHWN_TALK_NONE_PROC1); + } +} + +static void aHWN_pl_demo_code_end_wait_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, GAME_PLAY* play) { + mMsg_Window_c* msg_p; + int look; + int OrderValue = mDemo_Get_OrderValue(mDemo_ORDER_PLAYER, 0); + if (OrderValue == 0) { + msg_p = mMsg_Get_base_window_p(); + look = mNpc_GetLooks(actorx->npc_class.npc_info.event->npc_id); + mMsg_Unset_LockContinue(msg_p); + mMsg_Set_ForceNext(msg_p); + mMsg_ChangeMsgData(msg_p, ((look & 0xFF) * 6 + 0x98d)); + aHWN_change_talk_proc(actorx, aHWN_TALK_NONE_PROC1); + } +} + +static void aHWN_change_talk_proc(NPC_HALLOWEEN_ACTOR* actorx, int talk_proc_idx) { + // clang-format off + static aHWN_TALK_PROC talk_proc[] = { + &aHWN_first_call_talk_proc, + &aHWN_trick_or_treat_talk_proc, + &aHWN_menu_open_wait_talk_proc, + &aHWN_menu_close_wait_talk_proc, + &aHWN_get_other_item_wait_talk_proc, + &aHWN_receive_tool_item_start_wait_talk_proc, + &aHWN_receive_tool_item_end_wait_talk_proc, + &aHWN_trick_timing_wait_talk_proc, + &aHWN_trick_chg_cloth_talk_proc, + &aHWN_trick_chg_cloth_end_wait_talk_proc, + &aHWN_get_ame_wait_talk_proc, + &aHWN_get_ame_talk_proc, + &aHWN_pl_demo_code_end_wait_talk_proc, + (aHWN_TALK_PROC)&none_proc1, + }; + // clang-format on + actorx->talk_proc = talk_proc[talk_proc_idx]; +} + +static void aHWN_set_force_talk_info(ACTOR* actorx) { + mDemo_Set_msg_num(0x98a); + mDemo_Set_talk_turn(1); + aHWN_change_talk_proc((NPC_HALLOWEEN_ACTOR*)actorx, aHWN_TALK_FIRST_CALL_TALK_PROC); +} + +static void aHWN_force_talk_request(ACTOR* actorx, GAME* game) { + int bx; + int bz; + ACTOR* player_actorx = GET_PLAYER_ACTOR_ACTOR((GAME_PLAY*)game); + if (player_actorx != NULL) { + if (!mFI_Wpos2BlockNum(&bx, &bz, player_actorx->world.position)) { + bx = 0; + bz = 0; + } + } else { + bx = 0; + bz = 0; + } + if (actorx->player_distance_xz < 70.0f) { + if ((ABS(actorx->player_distance_y) < 20.0f) && (actorx->block_x == bx) && (actorx->block_z == bz)) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, aHWN_set_force_talk_info); + } + } +} + +static void aHWN_set_norm_talk_info(NPC_HALLOWEEN_ACTOR* actorx) { + int looks = mNpc_GetLooks(actorx->npc_class.npc_info.event->npc_id); + mDemo_Set_msg_num((looks & 0xFF) + 0x9af); + aHWN_change_talk_proc(actorx, aHWN_TALK_NONE_PROC1); +} + +static void aHWN_norm_talk_request(NPC_HALLOWEEN_ACTOR* actorx) { + mDemo_Request(mDemo_TYPE_TALK, &actorx->npc_class.actor_class, (mDemo_REQUEST_PROC)aHWN_set_norm_talk_info); +} + +static int aHWN_talk_init() { + mDemo_Set_ListenAble(); + return 1; +} + +static BOOL aHWN_talk_end_chk(ACTOR* actorx, GAME* game) { + BOOL res = FALSE; + NPC_HALLOWEEN_ACTOR* hwn_actor = (NPC_HALLOWEEN_ACTOR*)actorx; + hwn_actor->talk_proc((NPC_HALLOWEEN_ACTOR*)actorx, (GAME_PLAY*)game); + if ((mDemo_Check(mDemo_TYPE_SPEAK, &hwn_actor->npc_class.actor_class) == FALSE) && + (mDemo_Check(mDemo_TYPE_TALK, &hwn_actor->npc_class.actor_class) == FALSE)) { + if (hwn_actor->npc_class.schedule.step == 1) { + hwn_actor->npc_class.think.end_flag = TRUE; + } + res = TRUE; + hwn_actor->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)aHWN_norm_talk_request; + } + return res; +}