From 526b5af4a9cd836280dc1ac13fe9be15bdc5db75 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Mon, 12 May 2025 01:57:57 -0400 Subject: [PATCH] Implement & link ac_present_npc --- configure.py | 2 +- include/ac_present_demo.h | 23 +- include/ac_present_npc.h | 22 +- include/m_common_data.h | 2 +- src/actor/ac_present_demo.c | 9 - src/actor/npc/ac_present_npc.c | 104 +++++ src/actor/npc/ac_present_npc_schedule.c_inc | 402 ++++++++++++++++++++ 7 files changed, 544 insertions(+), 20 deletions(-) create mode 100644 src/actor/npc/ac_present_npc.c create mode 100644 src/actor/npc/ac_present_npc_schedule.c_inc diff --git a/configure.py b/configure.py index 207a14e8..8e334b20 100644 --- a/configure.py +++ b/configure.py @@ -1145,7 +1145,7 @@ config.libs = [ Object(NonMatching, "actor/npc/ac_npc_station_master.c"), Object(Matching, "actor/npc/ac_npc_super_master.c"), Object(Matching, "actor/npc/ac_npc_totakeke.c"), - Object(NonMatching, "actor/npc/ac_present_npc.c"), + Object(Matching, "actor/npc/ac_present_npc.c"), Object(NonMatching, "actor/npc/ac_taisou_npc0.c"), Object(NonMatching, "actor/npc/ac_tamaire_npc0.c"), Object(NonMatching, "actor/npc/ac_tamaire_npc1.c"), diff --git a/include/ac_present_demo.h b/include/ac_present_demo.h index acc405da..9f64fdaf 100644 --- a/include/ac_present_demo.h +++ b/include/ac_present_demo.h @@ -20,18 +20,27 @@ enum { aPRD_TYPE_NUM }; +enum { + aPRD_ACTION_FIRST_SET, + aPRD_ACTION_PL_COME_OUT_WAIT, + aPRD_ACTION_PRESENT_WAIT, + aPRD_ACTION_RETIRE_NPC_WAIT, + + aPRD_ACTION_NUM +}; + typedef struct present_demo_actor_s PRESENT_DEMO_ACTOR; typedef void (*aPRD_ACTION_PROC)(PRESENT_DEMO_ACTOR* present_demo, GAME* game); struct present_demo_actor_s { - ACTOR actor_class; - int action; - aPRD_ACTION_PROC action_proc; - ACTOR* world_actor; - int _180; - int type; - mActor_name_t present; + /* 0x000 */ ACTOR actor_class; + /* 0x174 */ int action; + /* 0x178 */ aPRD_ACTION_PROC action_proc; + /* 0x17C */ ACTOR* world_actor; + /* 0x180 */ int _180; + /* 0x184 */ int type; + /* 0x188 */ mActor_name_t present; }; extern ACTOR_PROFILE Present_Demo_Profile; diff --git a/include/ac_present_npc.h b/include/ac_present_npc.h index 30187489..0e1ca469 100644 --- a/include/ac_present_npc.h +++ b/include/ac_present_npc.h @@ -2,12 +2,31 @@ #define AC_PRESENT_NPC_H #include "types.h" -#include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +#define aPST_PRESENT_TYPE_GOLDEN_ROD (1 << 0) +#define aPST_PRESENT_TYPE_GOLDEN_NET (1 << 1) + +typedef struct present_npc_actor_s PRESENT_NPC_ACTOR; + +typedef void (*aPST_THINK_PROC)(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play); +typedef void (*aPST_TALK_PROC)(PRESENT_NPC_ACTOR* actor); + +struct present_npc_actor_s { + NPC_ACTOR npc_class; + int think_idx; + int next_think_idx; + aPST_THINK_PROC think_proc; + int talk_type; + aPST_TALK_PROC talk_proc; + u8 _9A8; + u8 umbrella_flag; +}; + extern ACTOR_PROFILE Present_Npc_Profile; #ifdef __cplusplus @@ -15,4 +34,3 @@ extern ACTOR_PROFILE Present_Npc_Profile; #endif #endif - diff --git a/include/m_common_data.h b/include/m_common_data.h index 856a239d..03ff2f4c 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -164,7 +164,7 @@ typedef struct Save_s { /* 0x024186 */ lbRTC_day_t rainbow_day; /* 0x024187 */ u8 rainbow_reserved; /* 0x024188 */ u8 _24188; - /* 0x024189 */ u8 _24189; + /* 0x024189 */ u8 first_present; /* 0x02418A */ u8 town_day; /* 0x02418B */ u8 _2418B[0x24198 - 0x2418B]; /* 0x024198 */ OSTime travel_hard_time; diff --git a/src/actor/ac_present_demo.c b/src/actor/ac_present_demo.c index b379da37..6d87292b 100644 --- a/src/actor/ac_present_demo.c +++ b/src/actor/ac_present_demo.c @@ -5,15 +5,6 @@ #include "m_soncho.h" #include "m_player_lib.h" -enum { - aPRD_ACTION_FIRST_SET, - aPRD_ACTION_PL_COME_OUT_WAIT, - aPRD_ACTION_PRESENT_WAIT, - aPRD_ACTION_RETIRE_NPC_WAIT, - - aPRD_ACTION_NUM -}; - static void aPRD_actor_ct(ACTOR* actorx, GAME* game); static void aPRD_actor_dt(ACTOR* actorx, GAME* game); static void aPRD_actor_move(ACTOR* actorx, GAME* game); diff --git a/src/actor/npc/ac_present_npc.c b/src/actor/npc/ac_present_npc.c new file mode 100644 index 00000000..2a6a7ab6 --- /dev/null +++ b/src/actor/npc/ac_present_npc.c @@ -0,0 +1,104 @@ +#include "ac_present_npc.h" + +#include "m_common_data.h" +#include "ac_present_demo.h" +#include "libultra/libultra.h" +#include "m_msg.h" +#include "m_soncho.h" +#include "m_house.h" + +enum { + aPST_TALK_PRESENT_SEND_START_WAIT, + aPST_TALK_PRESENT_SEND_END_WAIT, + aPST_TALK_END_WAIT, + + aPST_TALK_NUM +}; + +enum { + aPST_THINK_WAIT, + aPST_THINK_TALK, + aPST_THINK_EXIT_TURN, + aPST_THINK_EXIT, + + aPST_THINK_NUM +}; + +static void aPST_actor_ct(ACTOR* actorx, GAME* game); +static void aPST_actor_draw(ACTOR* actorx, GAME* game); +static void aPST_actor_dt(ACTOR* actorx, GAME* game); +static void aPST_actor_init(ACTOR* actorx, GAME* game); +static void aPST_actor_move(ACTOR* actorx, GAME* game); +static void aPST_actor_save(ACTOR* actorx, GAME* game); + +ACTOR_PROFILE Present_Npc_Profile = { + // clang-format off + mAc_PROFILE_PRESENT_NPC, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(PRESENT_NPC_ACTOR), + aPST_actor_ct, + aPST_actor_dt, + aPST_actor_init, + mActor_NONE_PROC1, + aPST_actor_save, + // clang-format on +}; + +static int aPST_talk_end_chk(ACTOR* actorx, GAME* game); +static int aPST_talk_init(ACTOR* actorx, GAME* game); + +static void aPST_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type); +static void aPST_change_talk_proc(PRESENT_NPC_ACTOR* actor, int type); +static void aPST_setup_think_proc(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play, int type); + +static void aPST_actor_ct(ACTOR* actorx, GAME* game) { + static aNPC_ct_data_c ct_data = { + // clang-format off + aPST_actor_move, + aPST_actor_draw, + aNPC_CT_SCHED_TYPE_SPECIAL, + NULL, + aPST_talk_init, + aPST_talk_end_chk, + 0, + // clang-format on + }; + + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)actorx; + + if (NPC_CLIP->birth_check_proc(actorx, game) == TRUE) { + actor->npc_class.schedule.schedule_proc = aPST_schedule_proc; + NPC_CLIP->ct_proc(actorx, game, &ct_data); + } +} + +static void aPST_actor_dt(ACTOR* actorx, GAME* game) { + NPC_CLIP->dt_proc(actorx, game); + + if (CLIP(demo_clip2) != NULL && CLIP(demo_clip2)->type == mDemo_CLIP_TYPE_PRESENT_DEMO) { + ACTOR* demo_actorx = (ACTOR*)CLIP(demo_clip2)->demo_class; + + if (demo_actorx != NULL) { + PRESENT_DEMO_ACTOR* present_demo = (PRESENT_DEMO_ACTOR*)demo_actorx; + + present_demo->world_actor = NULL; + } + } +} + +static void aPST_actor_save(ACTOR* actorx, GAME* game) { + NPC_CLIP->save_proc(actorx, game); +} + +static void aPST_actor_init(ACTOR* actorx, GAME* game) { + NPC_CLIP->init_proc(actorx, game); +} + +static void aPST_actor_draw(ACTOR* actorx, GAME* game) { + NPC_CLIP->draw_proc(actorx, game); +} + +#include "../src/actor/npc/ac_present_npc_schedule.c_inc" diff --git a/src/actor/npc/ac_present_npc_schedule.c_inc b/src/actor/npc/ac_present_npc_schedule.c_inc new file mode 100644 index 00000000..f9dd873d --- /dev/null +++ b/src/actor/npc/ac_present_npc_schedule.c_inc @@ -0,0 +1,402 @@ +static int aPST_set_request_act(PRESENT_NPC_ACTOR* actor, u8 prio, u8 idx, u8 type, u16 obj, s16 move_x, s16 move_z) { + int res = FALSE; + + if (prio >= actor->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; + actor->npc_class.request.act_priority = prio; + actor->npc_class.request.act_idx = idx; + actor->npc_class.request.act_type = type; + mem_copy((u8*)actor->npc_class.request.act_args, (u8*)args, sizeof(args)); + res = TRUE; + } + + return res; +} + +static void aPST_make_umbrella(ACTOR* actorx, GAME* game) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)actorx; + + if (actor->npc_class.right_hand.item_actor_p == NULL) { + ACTOR* tool_actor = CLIP(tools_clip)->aTOL_birth_proc(actor->npc_class.right_hand.umbrella_type, aTOL_ACTION_S_TAKEOUT, (ACTOR*)actor, game, -1, NULL); + + if (tool_actor != NULL) { + actor->npc_class.right_hand.item_actor_p = tool_actor; + actor->npc_class.draw.sub_anim_type = aNPC_SUB_ANIM_UMBRELLA; + NPC_CLIP->animation_init_proc((ACTOR*)actor, aNPC_ANIM_WAIT1, FALSE); + } + } +} + +static void aPST_actor_move(ACTOR* actorx, GAME* game) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)actorx; + + NPC_CLIP->move_proc(actorx, game); + if (actor->umbrella_flag == TRUE) { + aPST_make_umbrella(actorx, game); + } +} + +static int aPST_check_first_present(u8 present_type) { + int ret = FALSE; + + if ((Save_Get(first_present) & present_type) == 0) { + Save_Get(first_present) |= present_type; + ret = TRUE; + } + + return ret; +} + +static void aPST_present_send_start_wait_talk_proc(PRESENT_NPC_ACTOR* actor) { + int order = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 1); + + if (order == 2) { + ACTOR* demo_actorx; + mActor_name_t item = ITM_PAPER00; + u16 present = FALSE; + u32 item_cond = mPr_ITEM_COND_NORMAL; + + if (CLIP(demo_clip2) != NULL && CLIP(demo_clip2)->type == mDemo_CLIP_TYPE_PRESENT_DEMO) { + demo_actorx = (ACTOR*)CLIP(demo_clip2)->demo_class; + + if (demo_actorx != NULL) { + PRESENT_DEMO_ACTOR* demo_actor = (PRESENT_DEMO_ACTOR*)demo_actorx; + + item = demo_actor->present; + if (demo_actor->type == aPRD_TYPE_SONCHO_VACATION0_CONTRIBUTED || demo_actor->type == aPRD_TYPE_SONCHO_VACATION1_CONTRIBUTED) { + u8 item_name[mIN_ITEM_NAME_LEN]; + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + mIN_copy_name_str(item_name, item); + mMsg_Set_item_str_art(msg_p, mMsg_ITEM_STR0, item_name, sizeof(item_name), mIN_get_item_article(item)); + } + + switch (demo_actor->type) { + case aPRD_TYPE_GOLDEN_ROD: + case aPRD_TYPE_GOLDEN_NET: + present = FALSE; + item_cond = mPr_ITEM_COND_NORMAL; + break; + default: + present = TRUE; + item_cond = mPr_ITEM_COND_PRESENT; + break; + } + } + } + + aNPC_DEMO_GIVE_ITEM(item, aHOI_REQUEST_PUTAWAY, present); + mPr_SetFreePossessionItem(Now_Private, item, item_cond); + mMsg_SET_LOCKCONTINUE(); + aPST_change_talk_proc(actor, aPST_TALK_PRESENT_SEND_START_WAIT); + } +} + +static void aPST_present_send_end_wait_talk_proc(PRESENT_NPC_ACTOR* actor) { + if (aHOI_CLIP->master_actor == NULL) { + mMsg_UNSET_LOCKCONTINUE(); + aPST_change_talk_proc(actor, aPST_TALK_END_WAIT); + } +} + +static void aPST_change_talk_proc(PRESENT_NPC_ACTOR* actor, int type) { + static aPST_TALK_PROC talk_proc[] = { + // clang-format off + aPST_present_send_start_wait_talk_proc, + aPST_present_send_end_wait_talk_proc, + (aPST_TALK_PROC)none_proc1, + // clang-format on + }; + + actor->talk_proc = talk_proc[type]; +} + +static void aPST_set_talk_info(ACTOR* actorx) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)actorx; + ACTOR* demo_actorx; + int looks = mNpc_GetNpcLooks(actorx); + int msg_no = 0x319F; + aPST_TALK_PROC talk_proc = aPST_present_send_start_wait_talk_proc; + + if (CLIP(demo_clip2) != NULL && CLIP(demo_clip2)->type == mDemo_CLIP_TYPE_PRESENT_DEMO) { + demo_actorx = (ACTOR*)CLIP(demo_clip2)->demo_class; + + if (demo_actorx != NULL) { + PRESENT_DEMO_ACTOR* demo_actor = (PRESENT_DEMO_ACTOR*)demo_actorx; + + switch (demo_actor->type) { + case aPRD_TYPE_BIRTHDAY: + msg_no = 0x319F + looks * 6 + RANDOM(3); + break; + case aPRD_TYPE_GOLDEN_ROD: + if (aPST_check_first_present(aPST_PRESENT_TYPE_GOLDEN_ROD) == TRUE) { + msg_no = 0x31C3; + } else { + msg_no = 0x31C7; + } + break; + case aPRD_TYPE_GOLDEN_NET: + if (aPST_check_first_present(aPST_PRESENT_TYPE_GOLDEN_NET) == TRUE) { + msg_no = 0x31C5; + } else { + msg_no = 0x31C9; + } + break; + case aPRD_TYPE_SONCHO_VACATION0_CONTRIBUTED: + if (mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO) == -1) { + msg_no = 0x33FF; + talk_proc = (aPST_TALK_PROC)none_proc1; + } else { + msg_no = 0x33FD; + mSC_LightHouse_Event_Clear(-1); + } + break; + case aPRD_TYPE_SONCHO_VACATION1_CONTRIBUTED: + if (mPr_GetPossessionItemIdx(Now_Private, EMPTY_NO) == -1) { + msg_no = 0x3416; + talk_proc = (aPST_TALK_PROC)none_proc1; + } else { + msg_no = 0x3414; + mSC_LightHouse_Event_Clear(-1); + } + break; + case aPRD_TYPE_SONCHO_VACATION0_STARTED: + msg_no = 0x3400; + talk_proc = (aPST_TALK_PROC)none_proc1; + mSC_LightHouse_Event_Clear(-1); + break; + case aPRD_TYPE_SONCHO_VACATION1_STARTED: + msg_no = 0x3417; + talk_proc = (aPST_TALK_PROC)none_proc1; + mSC_LightHouse_Event_Clear(-1); + break; + } + } + } + + mDemo_Set_msg_num(msg_no); + actor->_9A8 = 0; + actor->talk_proc = talk_proc; +} + +static void aPST_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, aPST_set_talk_info); +} + +static int aPST_talk_init(ACTOR* actorx, GAME* game) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)actorx; + + actor->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)none_proc1; + mDemo_Set_ListenAble(); + return TRUE; +} + +static int aPST_talk_end_chk(ACTOR* actorx, GAME* game) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int ret = FALSE; + + (*actor->talk_proc)(actor); + if (!mDemo_Check(mDemo_TYPE_SPEAK, actorx)) { + aPST_setup_think_proc(actor, play, actor->next_think_idx); + ret = TRUE; + } + + return ret; +} + +static void aPST_wait(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play) { + ACTOR* demo_actorx; + + if (CLIP(demo_clip2) != NULL && CLIP(demo_clip2)->type == mDemo_CLIP_TYPE_PRESENT_DEMO) { + demo_actorx = (ACTOR*)CLIP(demo_clip2)->demo_class; + + if (demo_actorx != NULL) { + PRESENT_DEMO_ACTOR* demo_actor = (PRESENT_DEMO_ACTOR*)demo_actorx; + + if (demo_actor->action != aPRD_ACTION_PL_COME_OUT_WAIT) { + aPST_setup_think_proc(actor, play, aPST_THINK_TALK); + } + } + } +} + +static void aPST_exit_turn(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play) { + if (actor->npc_class.action.step == aNPC_ACTION_END_STEP && actor->npc_class.action.idx == aNPC_ACT_TURN) { + aPST_setup_think_proc(actor, play, aPST_THINK_EXIT); + } +} + +static void aPST_exit(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play) { + static s16 moveX[] = { 2240, 2240, 2240, 2240 }; + static s16 moveZ[] = { 1900, 1980, 1300, 1220 }; + + ACTOR* demo_actorx; + + if (actor->npc_class.action.step == aNPC_ACTION_END_STEP) { + f32 z = actor->npc_class.actor_class.world.position.z; + int move_idx; + + if (z <= 1540.0f) { + if (z <= 1220.0f) { + move_idx = -1; + } else if (z <= 1300.0f) { + move_idx = 3; + } else { + move_idx = 2; + } + } else { + if (z >= 1980.0f) { + move_idx = -1; + } else if (z >= 1900.0f) { + move_idx = 1; + } else { + move_idx = 0; + } + } + + if (move_idx == -1) { + if (CLIP(demo_clip2) != NULL && CLIP(demo_clip2)->type == mDemo_CLIP_TYPE_PRESENT_DEMO) { + demo_actorx = (ACTOR*)CLIP(demo_clip2)->demo_class; + + if (demo_actorx != NULL) { + PRESENT_DEMO_ACTOR* demo_actor = (PRESENT_DEMO_ACTOR*)demo_actorx; + + demo_actor->world_actor = NULL; + Actor_delete((ACTOR*)actor); + play->submenu.start_refuse = FALSE; + } + } + } else { + aPST_set_request_act(actor, 4, aNPC_ACT_RUN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, moveX[move_idx], moveZ[move_idx]); + } + } +} + +static void aPST_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)nactorx; + + (*actor->think_proc)(actor, play); +} + +static void aPST_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)nactorx; + + aPST_setup_think_proc(actor, play, aPST_THINK_WAIT); +} + +static void aPST_exit_turn_init(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play) { + static s16 moveX[] = { 2240, 2240 }; + static s16 moveZ[] = { 1900, 1300 }; + + ACTOR* demo_actorx; + int move_idx = 0; + + if (actor->npc_class.actor_class.world.position.z <= 1540.0f) { + move_idx = 1; + } + + aPST_set_request_act(actor, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, moveX[move_idx], moveZ[move_idx]); + + if (CLIP(demo_clip2) != NULL && CLIP(demo_clip2)->type == mDemo_CLIP_TYPE_PRESENT_DEMO) { + demo_actorx = (ACTOR*)CLIP(demo_clip2)->demo_class; + + if (demo_actorx != NULL) { + PRESENT_DEMO_ACTOR* demo_actor = (PRESENT_DEMO_ACTOR*)demo_actorx; + + demo_actor->_180 = 1; + } + } +} + +typedef void (*aPST_THINK_INIT_PROC)(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play); + +typedef struct { + aPST_THINK_PROC think_proc; + aPST_THINK_INIT_PROC init_proc; + aNPC_TALK_REQUEST_PROC talk_request_proc; + u8 talk_type; + u8 next_think_idx; +} aPST_think_data_c; + +static void aPST_setup_think_proc(PRESENT_NPC_ACTOR* actor, GAME_PLAY* play, int type) { + static aPST_think_data_c dt_tbl[] = { + // clang-format off + { aPST_wait, (aPST_THINK_INIT_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aPST_THINK_WAIT }, + { (aPST_THINK_PROC)none_proc1, (aPST_THINK_INIT_PROC)none_proc1, aPST_talk_request, 0x00, aPST_THINK_EXIT_TURN }, + { aPST_exit_turn, aPST_exit_turn_init, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aPST_THINK_EXIT_TURN }, + { aPST_exit, (aPST_THINK_INIT_PROC)none_proc1, (aNPC_TALK_REQUEST_PROC)none_proc1, 0x00, aPST_THINK_EXIT }, + // clang-format on + }; + + aPST_think_data_c* data_p = &dt_tbl[type]; + + actor->think_idx = type; + actor->think_proc = data_p->think_proc; + actor->npc_class.talk_info.talk_request_proc = data_p->talk_request_proc; + actor->talk_type = data_p->talk_type; + actor->next_think_idx = data_p->next_think_idx; + (*data_p->init_proc)(actor, play); +} + +static void aPST_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC think_proc[] = { aPST_think_init_proc, aPST_think_main_proc }; + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)nactorx; + + (*think_proc[type])(nactorx, play); +} + +typedef struct { + float pos_x; + float pos_z; + s16 angle_y; +} aPST_set_data_c; + +static void aPST_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + static aPST_set_data_c set_data[] = { + // clang-format off + {2180.0f, 1540.0f, DEG2SHORT_ANGLE2(-135.0f)}, + {2300.0f, 1540.0f, DEG2SHORT_ANGLE2( 135.0f)}, + {2180.0f, 1820.0f, DEG2SHORT_ANGLE2(-135.0f)}, + {2300.0f, 1820.0f, DEG2SHORT_ANGLE2( 135.0f)}, + // clang-format on + }; + + PRESENT_NPC_ACTOR* actor = (PRESENT_NPC_ACTOR*)nactorx; + aPST_set_data_c* set_data_p; + + nactorx->think.think_proc = aPST_think_proc; + NPC_CLIP->think_proc(nactorx, play, aNPC_THINK_SPECIAL, aNPC_THINK_TYPE_INIT); + nactorx->collision.check_kind = aNPC_BG_CHECK_TYPE_NORMAL; + nactorx->draw.main_animation.keyframe.morph_counter = 0.0f; + nactorx->actor_class.status_data.weight = MASSTYPE_IMMOVABLE; + nactorx->condition_info.hide_request = FALSE; + + set_data_p = &set_data[mHS_get_arrange_idx(Common_Get(player_no))]; + nactorx->actor_class.world.position.x = set_data_p->pos_x; + nactorx->actor_class.world.position.z = set_data_p->pos_z; + nactorx->actor_class.shape_info.rotation.y = set_data_p->angle_y; + nactorx->actor_class.world.angle.y = set_data_p->angle_y; + nactorx->movement.mv_angl = set_data_p->angle_y; + + if (nactorx->npc_info.animal != NULL && Common_Get(weather) == mEnv_WEATHER_RAIN) { + actor->umbrella_flag = TRUE; + } +} + +static void aPST_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (NPC_CLIP->think_proc(nactorx, play, -1, aNPC_THINK_TYPE_CHK_INTERRUPT) == FALSE) { + NPC_CLIP->think_proc(nactorx, play, -1, aNPC_THINK_TYPE_MAIN); + } +} + +static void aPST_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC sche_proc[] = { aPST_schedule_init_proc, aPST_schedule_main_proc }; + + (*sche_proc[type])(nactorx, play); +}