diff --git a/configure.py b/configure.py index 4d7b924f..9bad599d 100644 --- a/configure.py +++ b/configure.py @@ -968,7 +968,7 @@ config.libs = [ Object(NonMatching, "actor/ac_gyoei.c"), Object(Matching, "actor/ac_handOverItem.c"), Object(Matching, "actor/ac_haniwa.c"), - Object(NonMatching, "actor/ac_hatumode_control.c"), + Object(Matching, "actor/ac_hatumode_control.c"), Object(NonMatching, "actor/ac_house.c"), Object(Matching, "actor/ac_house_clock.c"), Object(NonMatching, "actor/ac_house_goki.c"), @@ -1086,7 +1086,7 @@ config.libs = [ Object(NonMatching, "actor/npc/ac_hanami_npc1.c"), Object(NonMatching, "actor/npc/ac_harvest_npc0.c"), Object(NonMatching, "actor/npc/ac_harvest_npc1.c"), - Object(NonMatching, "actor/npc/ac_hatumode_npc0.c"), + Object(Matching, "actor/npc/ac_hatumode_npc0.c"), Object(NonMatching, "actor/npc/ac_kamakura_npc0.c"), Object(NonMatching, "actor/npc/ac_normal_npc.c"), Object(NonMatching, "actor/npc/ac_npc.c"), diff --git a/include/ac_hatumode_control.h b/include/ac_hatumode_control.h index 2fafcd31..ed7a6714 100644 --- a/include/ac_hatumode_control.h +++ b/include/ac_hatumode_control.h @@ -8,6 +8,38 @@ extern "C" { #endif +typedef struct hatumode_event_save_s { + u16 state; + u16 flags0; + u16 flags1; + s16 yashiro_pos[3]; + u8 cur_npc_idx; +} aEv_hatumode_save_c; + +typedef void (*aHTMD_TALK_INFO_PROC)(ACTOR*, int); +typedef int (*aHTMD_THINK_INIT_PROC)(ACTOR*, GAME_PLAY*); +typedef int (*aHTMD_SET_START_PROC)(ACTOR*); +typedef int (*aHTMD_PLAYER_MOVE_PROC)(GAME_PLAY*, int); +typedef int (*aHTMD_LOOK_PLAYER_PROC)(ACTOR*); + +typedef struct hatumode_ctrl_clip_s { + aHTMD_TALK_INFO_PROC talk_info_proc; + aHTMD_THINK_INIT_PROC think_init_proc; + aHTMD_SET_START_PROC set_start_proc; + aHTMD_PLAYER_MOVE_PROC player_move_proc; + aHTMD_LOOK_PLAYER_PROC look_player_proc; +} aHTMD_clip_c; + +typedef struct hatumode_ctrl_actor_s HATUMODE_CONTROL_ACTOR; + +typedef void (*aHTC_MOVE_PROC)(HATUMODE_CONTROL_ACTOR*, GAME_PLAY*); + +struct hatumode_ctrl_actor_s { + ACTOR actor_class; + aHTMD_clip_c clip; + aHTC_MOVE_PROC move_proc; +}; + extern ACTOR_PROFILE Hatumode_Control_Profile; #ifdef __cplusplus @@ -15,4 +47,3 @@ extern ACTOR_PROFILE Hatumode_Control_Profile; #endif #endif - diff --git a/include/ac_hatumode_npc0.h b/include/ac_hatumode_npc0.h index 4cf964b1..f77f21dc 100644 --- a/include/ac_hatumode_npc0.h +++ b/include/ac_hatumode_npc0.h @@ -3,11 +3,77 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +#define aHN0_TALK_REQ_NONE 0 +#define aHN0_TALK_REQ_NORM 1 +#define aHN0_TALK_REQ_FORCE 2 + +enum { + aHN0_THINK_INIT_NONE, + aHN0_THINK_INIT_NORMAL_WAIT, + aHN0_THINK_INIT_MOVE, + aHN0_THINK_INIT_TURN_F, + aHN0_THINK_INIT_SAISEN, + aHN0_THINK_INIT_OMAIRI_AF, + aHN0_THINK_INIT_NEXT_POS, + aHN0_THINK_INIT_TURN_MOVE, + aHN0_THINK_INIT_MOVE_BF, + aHN0_THINK_INIT_TURN_AISATU, + aHN0_THINK_INIT_AISATU, + aHN0_THINK_INIT_AISATU2, + aHN0_THINK_INIT_HAIGO, + + aHN0_THINK_INIT_NUM +}; + +enum { + aHN0_THINK_PROC_NONE, + aHN0_THINK_PROC_BIRTH, + aHN0_THINK_PROC_READY1, + aHN0_THINK_PROC_READY2, + aHN0_THINK_PROC_TURN_NEXT, + aHN0_THINK_PROC_FLAG2_WAIT, + aHN0_THINK_PROC_ANIME_WAIT, + aHN0_THINK_PROC_ANIME_WAIT_SAISEN, + aHN0_THINK_PROC_TIMER_WAIT, + aHN0_THINK_PROC_MOVE_WAIT, + aHN0_THINK_PROC_MOVE_BF, + aHN0_THINK_PROC_AISATU_WAIT, + aHN0_THINK_PROC_AISATU2_WAIT, + aHN0_THINK_PROC_TO_OMAIRI, + aHN0_THINK_PROC_PLAYER_MOVE, + aHN0_THINK_PROC_PLAYER_WAIT, + aHN0_THINK_PROC_KASASIMAI, + aHN0_THINK_PROC_SANPAI_WAIT, + + aHN0_THINK_PROC_NUM +}; + +typedef struct hatumode_npc0_actor_s HATUMODE_NPC0_ACTOR; + +typedef void (*aHN0_TALK_PROC)(HATUMODE_NPC0_ACTOR*, GAME_PLAY*); + +struct hatumode_npc0_actor_s { + NPC_ACTOR npc_class; + aHN0_TALK_PROC talk_proc; + int base_msg; + s16 timer; + s16 pos[2]; + u8 think_idx; + u8 next_think_idx; + u8 move_think_idx; + u8 talk_idx; + u8 think_proc_idx; + u8 think_change_flag; + u8 root; + u8 player; +}; + extern ACTOR_PROFILE Hatumode_Npc0_Profile; #ifdef __cplusplus @@ -15,4 +81,3 @@ extern ACTOR_PROFILE Hatumode_Npc0_Profile; #endif #endif - diff --git a/include/ac_npc.h b/include/ac_npc.h index 3a6d7361..58190947 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -123,6 +123,13 @@ enum { aNPC_THINK_TYPE_NUM }; +enum { + aNPC_THINK_PROC_INIT, + aNPC_THINK_PROC_MAIN, + + aNPC_THINK_PROC_NUM +}; + typedef void (*aNPC_TALK_REQUEST_PROC)(ACTOR*, GAME*); typedef int (*aNPC_TALK_INIT_PROC)(ACTOR*, GAME*); typedef int (*aNPC_TALK_END_CHECK_PROC)(ACTOR*, GAME*); @@ -152,6 +159,7 @@ typedef void (*aNPC_MOVE_PROC)(ACTOR*, GAME*); typedef void (*aNPC_MOVE_BEFORE_PROC)(ACTOR*, GAME*); typedef void (*aNPC_MOVE_AFTER_PROC)(ACTOR*, GAME*); typedef void (*aNPC_DRAW_PROC)(ACTOR*, GAME*); +typedef void (*aNPC_SET_DST_POS_PROC)(NPC_ACTOR*, f32, f32); typedef void (*aNPC_REBUILD_DMA_PROC)(); typedef void (*aNPC_TALK_DEMO_PROC)(ACTOR*); @@ -186,7 +194,7 @@ struct ac_npc_clip_s { /* 0x110 */ aNPC_TALK_DEMO_PROC talk_demo_proc; /* 0x114 */ aNPC_ANIMATION_INIT_PROC animation_init_proc; /* 0x118 */ aNPC_CHG_SCHEDULE_PROC chg_schedule_proc; - /* 0x11C */ void* _11C; + /* 0x11C */ aNPC_SET_DST_POS_PROC set_dst_pos_proc; /* 0x120 */ aNPC_CLIP_THINK_PROC think_proc; /* 0x124 */ aNPC_FORCE_CALL_REQ_PROC force_call_req_proc; /* 0x128 */ void* _128; @@ -514,6 +522,13 @@ enum { aNPC_SCHEDULE_TYPE_NUM }; +enum { + aNPC_SCHEDULE_PROC_INIT, + aNPC_SCHEDULE_PROC_MAIN, + + aNPC_SCHEDULE_PROC_NUM +}; + struct npc_actor_s { ACTOR actor_class; s_xyz _174; diff --git a/include/m_clip.h b/include/m_clip.h index d1bee711..3d47cda9 100644 --- a/include/m_clip.h +++ b/include/m_clip.h @@ -32,6 +32,7 @@ #include "ac_broker_design.h" #include "ac_garagara.h" #include "ac_turi_clip.h" +#include "ac_hatumode_control.h" #ifdef __cplusplus extern "C" { @@ -83,7 +84,7 @@ typedef struct clip_s { /* 0x0B8 */ aShopUmbrella_Clip_c* shop_umbrella_clip; /* 0x0BC */ aAR_Clip_c* arrange_room_clip; /* 0x0C0 */ aGRGR_clip_c* garagara_clip; - /* 0x0C4 */ void* _0C4; + /* 0x0C4 */ aHTMD_clip_c* hatumode_clip; /* 0x0C8 */ void* shrine_clip; /* 0x0CC */ void* _0CC; /* 0x0D0 */ void* _0D0; diff --git a/src/actor/ac_hatumode_clip_move.c_inc b/src/actor/ac_hatumode_clip_move.c_inc new file mode 100644 index 00000000..86b9c165 --- /dev/null +++ b/src/actor/ac_hatumode_clip_move.c_inc @@ -0,0 +1,187 @@ +static int aHN0_set_request_act(HATUMODE_NPC0_ACTOR* hatumode_npc0, u8 prio, u8 idx, u8 type, u16 obj, s16 move_x, s16 move_z) { + int res = FALSE; + + if (prio >= hatumode_npc0->npc_class.request.act_priority) { + u16 args[6]; + + bzero(args, sizeof(args)); + args[0] = obj; + args[2] = move_x; + args[3] = move_z; + hatumode_npc0->npc_class.request.act_priority = prio; + hatumode_npc0->npc_class.request.act_idx = idx; + hatumode_npc0->npc_class.request.act_type = type; + mem_copy((u8*)hatumode_npc0->npc_class.request.act_args, (u8*)args, sizeof(args)); + res = TRUE; + } + + return res; +} + +static int aHN0_make_msg(HATUMODE_NPC0_ACTOR* hatumode_npc0) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + int idx = (4 + (hatumode_npc0->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0) - hatumode_p->cur_npc_idx) & 3; + + switch (idx) { + case 1: + return hatumode_npc0->base_msg + 3 + RANDOM(3); + case 2: + return hatumode_npc0->base_msg + 6 + RANDOM(3); + case 3: + return hatumode_npc0->base_msg + 9 + RANDOM(3); + default: + return hatumode_npc0->base_msg + 12 + RANDOM(3); + } +} + + +enum { + aHN0_TALK_WAIT, + aHN0_TALK_STOP_PLAYER, + aHN0_TALK_SAISEN_SURU, + + aHN0_TALK_NUM +}; + +static int aHN0_change_talk_proc(HATUMODE_NPC0_ACTOR* hatumode_npc0, int talk_idx); + +static void aHN0_talk_stop_player(HATUMODE_NPC0_ACTOR* hatumode_npc0, GAME_PLAY* play) { + if (!mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)hatumode_npc0) && !mDemo_Check(mDemo_TYPE_SPEAK, (ACTOR*)hatumode_npc0)) { + aHN0_change_talk_proc(hatumode_npc0, aHN0_TALK_WAIT); + } +} + +static void aHN0_talk_saisen_suru(HATUMODE_NPC0_ACTOR* hatumode_npc0, GAME_PLAY* play) { + if (mMsg_CHECK_MAINNORMALCONTINUE()) { + if (mChoice_GET_CHOSENUM() == mChoice_CHOICE0) { + aHN0_change_talk_proc(hatumode_npc0, aHN0_TALK_STOP_PLAYER); + mMsg_SET_CONTINUE_MSG_NUM(hatumode_npc0->base_msg + 1); + hatumode_npc0->next_think_idx = 0x22; + hatumode_npc0->player = 0; + mDemo_Set_talk_return_demo_wait(TRUE); + } else { + aHN0_change_talk_proc(hatumode_npc0, aHN0_TALK_WAIT); + mMsg_SET_CONTINUE_MSG_NUM(hatumode_npc0->base_msg + 2); + } + } +} + +static int aHN0_change_talk_proc(HATUMODE_NPC0_ACTOR* hatumode_npc0, int talk_idx) { + // clang-format off + static aHN0_TALK_PROC proc[] = { + (aHN0_TALK_PROC)&none_proc1, + &aHN0_talk_stop_player, + &aHN0_talk_saisen_suru, + }; + // clang-format on + + hatumode_npc0->talk_proc = proc[talk_idx]; + return TRUE; +} + +typedef struct { + u8 change_msg; + u8 talk_idx; +} aHN0_talk_info_c; + +static void aHTC_clip_talk_info(ACTOR* actorx, int type) { + // clang-format off + static aHN0_talk_info_c dt_tbl0[] = { + { 1, aHN0_TALK_WAIT }, + { 0, aHN0_TALK_WAIT }, + }; + // clang-format on + + // clang-format off + static aHN0_talk_info_c dt_tbl1[] = { + { 0, aHN0_TALK_SAISEN_SURU }, + { 0, aHN0_TALK_SAISEN_SURU }, + { 2, aHN0_TALK_WAIT }, + { 2, aHN0_TALK_WAIT }, + }; + // clang-format on + + HATUMODE_NPC0_ACTOR* hatumode_npc0 = (HATUMODE_NPC0_ACTOR*)actorx; + aHN0_talk_info_c* data_p; + + if (type != 0) { + data_p = &dt_tbl1[hatumode_npc0->talk_idx]; + } else { + data_p = &dt_tbl0[hatumode_npc0->talk_idx]; + } + + switch (data_p->change_msg) { + case 0: + mDemo_Set_msg_num(hatumode_npc0->base_msg); + break; + case 1: + mDemo_Set_msg_num(hatumode_npc0->base_msg + 15 + RANDOM(3)); + break; + case 2: + mDemo_Set_msg_num(aHN0_make_msg(hatumode_npc0)); + break; + } + + mDemo_Set_talk_turn(TRUE); + mDemo_Set_camera(CAMERA2_PROCESS_TALK); + aHN0_change_talk_proc(hatumode_npc0, data_p->talk_idx); +} + +static int aHTMD_clip_set_start(ACTOR* actorx) { + int idx = actorx->npc_id - SP_NPC_EV_HATUMODE_0; + static s16 table_x[] = { 20, 40, -40, 40, -40 }; + static s16 table_z[] = { -10, 40, 40, 0, 0 }; + static u8 table_root[] = { 0, 4, 9, 3, 8 }; + + actorx->world.position.x += (f32)table_x[idx]; + actorx->world.position.z += (f32)table_z[idx]; + return table_root[idx]; +} + +static u8 aHTMD_next_position(u8 root, s16* pos) { + static s16 aHN0_posX[] = { 20, 0, 40, 0, 40, -60, -60, 100, 100 }; + static s16 aHN0_posZ[] = { 75, 160, 160, 200, 200, 75, 200, 75, 200 }; + static u8 aHN0_root[] = { 0, 5, 6, 3, 1, 0, 7, 8, 4, 2 }; + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + root++; + if (root == 10) { + root = 5; + } else if (root == 5) { + root = 0; + } + + pos[0] = hatumode_p->yashiro_pos[0] + aHN0_posX[aHN0_root[root]]; + pos[1] = hatumode_p->yashiro_pos[1] + aHN0_posZ[aHN0_root[root]]; + return root; +} + +static int aHTMD_clip_player_move(GAME_PLAY* play, int root) { + static s16 aHN0_posX[] = { 20, 20, -80, 120 }; + static s16 aHN0_posZ[] = { 120, 85, 85, 85 }; + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_DEMO_WALK) { + mPlib_request_main_demo_walk_type1((GAME*)play, hatumode_p->yashiro_pos[0] + aHN0_posX[root], hatumode_p->yashiro_pos[1] + aHN0_posZ[root], 2.0f, FALSE); + return FALSE; + } + + return TRUE; +} + +static int aHTMD_clip_look_player(ACTOR* actorx) { + HATUMODE_NPC0_ACTOR* hatumode_npc0 = (HATUMODE_NPC0_ACTOR*)actorx; + + if (hatumode_npc0->npc_class.action.step == aNPC_ACTION_END_STEP || hatumode_npc0->npc_class.action.idx == aNPC_ACT_WAIT) { + s16 d_ang = actorx->player_angle_y - actorx->shape_info.rotation.y; + u8 act_idx = aNPC_ACT_TURN; + + if (ABS(d_ang) < DEG2SHORT_ANGLE2(67.5f)) { + act_idx = aNPC_ACT_WAIT; + } + + aHN0_set_request_act(hatumode_npc0, 4, act_idx, aNPC_ACT_TYPE_SEARCH, aNPC_ACT_OBJ_PLAYER, 0, 0); + } + + return FALSE; +} diff --git a/src/actor/ac_hatumode_clip_think.c_inc b/src/actor/ac_hatumode_clip_think.c_inc new file mode 100644 index 00000000..878c7088 --- /dev/null +++ b/src/actor/ac_hatumode_clip_think.c_inc @@ -0,0 +1,220 @@ +static void aHN0_aisatu_local(HATUMODE_NPC0_ACTOR* hatumode_npc) { + switch (mNpc_GetNpcLooks((ACTOR*)hatumode_npc)) { + case mNpc_LOOKS_KO_GIRL: + case mNpc_LOOKS_SPORT_MAN: + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_AISATU1, FALSE); + break; + case mNpc_LOOKS_GIRL: + case mNpc_LOOKS_BOY: + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_AISATU2, FALSE); + break; + case mNpc_LOOKS_GRIM_MAN: + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_AISATU3, FALSE); + break; + case mNpc_LOOKS_NANIWA_LADY: + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_AISATU4, FALSE); + break; + } +} + +static void aHN0_normal_wait_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aHN0_set_request_act(hatumode_npc, 4, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_ACT_OBJ_DEFAULT, 0, 0); +} + +static void aHN0_move_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aHN0_set_request_act(hatumode_npc, 4, aNPC_ACT_WALK2, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, hatumode_npc->pos[0], hatumode_npc->pos[1]); + hatumode_npc->timer = 20; + hatumode_npc->npc_class.actor_class.status_data.weight = MASSTYPE_HEAVY; +} + +static void aHN0_turn_f_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)hatumode_npc; + + aHN0_set_request_act(hatumode_npc, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actorx->world.position.x, actorx->world.position.z - 10.0f); +} + +static void aHN0_saisen_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + switch (hatumode_npc->think_idx) { + case 4: + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_SAISEN1, FALSE); + break; + case 5: + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_OMAIRI1, FALSE); + if (aSHR_GET_CLIP() != NULL) { + aSHR_GET_CLIP()->anime_play_proc(); + } + break; + } + + hatumode_npc->npc_class.draw.main_animation.keyframe.frame_control.mode = cKF_FRAMECONTROL_STOP; +} + +static void aHN0_omairi_af_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aHN0_normal_wait_init(hatumode_npc, play); + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_WAIT1, FALSE); + hatumode_npc->timer = 120; +} + +static void aHN0_turn_move_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aHN0_set_request_act(hatumode_npc, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, hatumode_npc->pos[0], hatumode_npc->pos[1]); +} + +static void aHN0_next_pos_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + aHN0_normal_wait_init(hatumode_npc, play); + hatumode_npc->root = aHTMD_next_position(hatumode_npc->root, hatumode_npc->pos); + hatumode_npc->timer = 0; + + switch (hatumode_npc->think_idx) { + case 10: + hatumode_p->flags1 |= (0x10 << ((hatumode_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0) & 1)); + break; + case 29: + hatumode_p->flags1 |= (0x04 << ((hatumode_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0) & 1)); + break; + case 24: + hatumode_p->flags1 |= (0x01 << ((hatumode_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0) & 1)); + break; + } +} + +static void aHN0_move_bf_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aHN0_normal_wait_init(hatumode_npc, play); + CLIP(npc_clip)->animation_init_proc((ACTOR*)hatumode_npc, aNPC_ANIM_WAIT1, FALSE); +} + +static void aHN0_turn_aisatu_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)hatumode_npc; + f32 x; + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if ((hatumode_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0) & 1) { + x = 10.0f; + } else { + x = -10.0f; + } + + aHN0_set_request_act(hatumode_npc, 4, aNPC_ACT_TURN, aNPC_ACT_TYPE_TO_POINT, aNPC_ACT_OBJ_DEFAULT, actorx->world.position.x + x, actorx->world.position.z); + hatumode_p->flags0 |= 0x1000; +} + +static void aHN0_aisatu_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + aHN0_aisatu_local(hatumode_npc); + hatumode_p->flags0 &= ~(0x2000 | 0x1000); +} + +static void aHN0_aisatu2_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + aHN0_aisatu_local(hatumode_npc); + hatumode_p->flags0 |= 0x2000; +} + +static void aHN0_haigo_init(HATUMODE_NPC0_ACTOR* hatumode_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + hatumode_npc->pos[0] = 20 + hatumode_p->yashiro_pos[0]; + hatumode_npc->pos[1] = 115 + hatumode_p->yashiro_pos[1]; + aHN0_turn_move_init(hatumode_npc, play); +} + +typedef struct { + u8 think_proc_idx; + u8 think_init; + u8 talk_req; + u8 talk_idx; + u8 next_think_idx; +} aHN0_think_data_c; + +// clang-format off +// TODO: enum for the various think idx values & enum/definitions for the talk idx type +static aHN0_think_data_c dt_tbl[] = { + { aHN0_THINK_PROC_READY1, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x00 }, + { aHN0_THINK_PROC_READY2, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x01 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_F, aHN0_TALK_REQ_NONE, 0x00, 0x02 }, + { aHN0_THINK_PROC_FLAG2_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NORM, 0x00, 0x02 }, + { aHN0_THINK_PROC_ANIME_WAIT_SAISEN, aHN0_THINK_INIT_SAISEN, aHN0_TALK_REQ_NONE, 0x00, 0x04 }, + { aHN0_THINK_PROC_ANIME_WAIT, aHN0_THINK_INIT_SAISEN, aHN0_TALK_REQ_NONE, 0x00, 0x05 }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_OMAIRI_AF, aHN0_TALK_REQ_NORM, 0x01, 0x07 }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_NEXT_POS, aHN0_TALK_REQ_NONE, 0x00, 0x07 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x08 }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x08 }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_NEXT_POS, aHN0_TALK_REQ_NONE, 0x00, 0x0A }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x0B }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x0C }, + { aHN0_THINK_PROC_FLAG2_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x0D }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_NEXT_POS, aHN0_TALK_REQ_NONE, 0x00, 0x0E }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x0F }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x0F }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_AISATU, aHN0_TALK_REQ_NONE, 0x00, 0x11 }, + { aHN0_THINK_PROC_AISATU_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x12 }, + { aHN0_THINK_PROC_ANIME_WAIT, aHN0_THINK_INIT_AISATU, aHN0_TALK_REQ_NONE, 0x00, 0x13 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_F, aHN0_TALK_REQ_NONE, 0x00, 0x14 }, + { aHN0_THINK_PROC_AISATU2_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NORM, 0x02, 0x14 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_AISATU, aHN0_TALK_REQ_NONE, 0x00, 0x16 }, + { aHN0_THINK_PROC_ANIME_WAIT, aHN0_THINK_INIT_AISATU2, aHN0_TALK_REQ_NONE, 0x00, 0x17 }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_NEXT_POS, aHN0_TALK_REQ_NONE, 0x00, 0x18 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x19 }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x19 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_F, aHN0_TALK_REQ_NONE, 0x00, 0x1B }, + { aHN0_THINK_PROC_FLAG2_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NORM, 0x03, 0x1B }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_NEXT_POS, aHN0_TALK_REQ_NONE, 0x00, 0x1D }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x1E }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x1E }, + { aHN0_THINK_PROC_TO_OMAIRI, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x20 }, + { aHN0_THINK_PROC_MOVE_BF, aHN0_THINK_INIT_MOVE_BF, aHN0_TALK_REQ_NONE, 0x00, 0x21 }, + { aHN0_THINK_PROC_PLAYER_MOVE, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x22 }, + { aHN0_THINK_PROC_PLAYER_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x23 }, + { aHN0_THINK_PROC_TIMER_WAIT, aHN0_THINK_INIT_NEXT_POS, aHN0_TALK_REQ_NONE, 0x00, 0x24 }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_TURN_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x25 }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x26 }, + { aHN0_THINK_PROC_PLAYER_MOVE, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x27 }, + { aHN0_THINK_PROC_PLAYER_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x28 }, + { aHN0_THINK_PROC_KASASIMAI, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x29 }, + { aHN0_THINK_PROC_SANPAI_WAIT, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_NONE, 0x00, 0x2A }, + { aHN0_THINK_PROC_TURN_NEXT, aHN0_THINK_INIT_HAIGO, aHN0_TALK_REQ_NONE, 0x00, 0x2B }, + { aHN0_THINK_PROC_MOVE_WAIT, aHN0_THINK_INIT_MOVE, aHN0_TALK_REQ_NONE, 0x00, 0x2C }, + { aHN0_THINK_PROC_NONE, aHN0_THINK_INIT_NORMAL_WAIT, aHN0_TALK_REQ_FORCE, 0x00, 0x1D }, +}; +// clang-format on + +typedef void (*aHN0_THINK_INIT_PROC)(HATUMODE_NPC0_ACTOR*, GAME_PLAY*); + +// clang-format off +static aHN0_THINK_INIT_PROC init_table[] = { + (aHN0_THINK_INIT_PROC)&none_proc1, + &aHN0_normal_wait_init, + &aHN0_move_init, + &aHN0_turn_f_init, + &aHN0_saisen_init, + &aHN0_omairi_af_init, + &aHN0_next_pos_init, + &aHN0_turn_move_init, + &aHN0_move_bf_init, + &aHN0_turn_aisatu_init, + &aHN0_aisatu_init, + &aHN0_aisatu2_init, + &aHN0_haigo_init, +}; +// clang-format on + +static int aHTMD_clip_think_init(ACTOR* actorx, GAME_PLAY* play) { + HATUMODE_NPC0_ACTOR* hatumode_npc = (HATUMODE_NPC0_ACTOR*)actorx; + aHN0_think_data_c* data_p = &dt_tbl[hatumode_npc->think_idx]; + + hatumode_npc->think_proc_idx = data_p->think_proc_idx; + hatumode_npc->talk_idx = data_p->talk_idx; + hatumode_npc->next_think_idx = data_p->next_think_idx; + (*init_table[data_p->think_init])(hatumode_npc, play); + + if (data_p->talk_req == aHN0_TALK_REQ_NONE) { + hatumode_npc->npc_class.head.lock_flag = TRUE; + } else { + hatumode_npc->npc_class.head.lock_flag = FALSE; + } + + return data_p->talk_req; +} diff --git a/src/actor/ac_hatumode_control.c b/src/actor/ac_hatumode_control.c new file mode 100644 index 00000000..e1572a53 --- /dev/null +++ b/src/actor/ac_hatumode_control.c @@ -0,0 +1,64 @@ +#include "ac_hatumode_control.h" + +#include "m_common_data.h" +#include "ac_hatumode_npc0.h" +#include "m_msg.h" +#include "m_player_lib.h" +#include "ac_shrine.h" +#include "libultra/libultra.h" + +static void aHTC_actor_ct(ACTOR* actorx, GAME* game); +static void aHTC_actor_dt(ACTOR* actorx, GAME* game); +static void aHTC_actor_move(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Hatumode_Control_Profile = { + mAc_PROFILE_HATUMODE_CONTROL, + ACTOR_PART_CONTROL, + ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(HATUMODE_CONTROL_ACTOR), + &aHTC_actor_ct, + &aHTC_actor_dt, + &aHTC_actor_move, + mActor_NONE_PROC1, + NULL, +}; +// clang-format on + +static void aHTC_setup_move_proc(HATUMODE_CONTROL_ACTOR* hatumode_control, s16 move_proc_idx); + +#include "../src/actor/ac_hatumode_control_move.c_inc" +#include "../src/actor/ac_hatumode_clip_move.c_inc" +#include "../src/actor/ac_hatumode_clip_think.c_inc" + +static void aHTC_clip_talk_info(ACTOR*, int); +static int aHTMD_clip_think_init(ACTOR*, GAME_PLAY*); +static int aHTMD_clip_set_start(ACTOR*); +static int aHTMD_clip_player_move(GAME_PLAY*, int); +static int aHTMD_clip_look_player(ACTOR*); + + +static void aHTC_actor_ct(ACTOR* actorx, GAME* game) { + HATUMODE_CONTROL_ACTOR* hatumode_control = (HATUMODE_CONTROL_ACTOR*)actorx; + + hatumode_control->clip.talk_info_proc = &aHTC_clip_talk_info; + hatumode_control->clip.think_init_proc = &aHTMD_clip_think_init; + hatumode_control->clip.set_start_proc = &aHTMD_clip_set_start; + hatumode_control->clip.player_move_proc = &aHTMD_clip_player_move; + hatumode_control->clip.look_player_proc = &aHTMD_clip_look_player; + CLIP(hatumode_clip) = &hatumode_control->clip; + aHTC_setup_move_proc(hatumode_control, 0); +} + +static void aHTC_actor_dt(ACTOR* actorx, GAME* game) { + CLIP(hatumode_clip) = NULL; + mEv_actor_dying_message(mEv_EVENT_NEW_YEARS_DAY, actorx); +} + +static void aHTC_actor_move(ACTOR* actorx, GAME* game) { + HATUMODE_CONTROL_ACTOR* hatumode_control = (HATUMODE_CONTROL_ACTOR*)actorx; + + (*hatumode_control->move_proc)(hatumode_control, (GAME_PLAY*)game); +} diff --git a/src/actor/ac_hatumode_control_move.c_inc b/src/actor/ac_hatumode_control_move.c_inc new file mode 100644 index 00000000..e74e00af --- /dev/null +++ b/src/actor/ac_hatumode_control_move.c_inc @@ -0,0 +1,131 @@ +static void aHTC_ready(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (hatumode_p != NULL && hatumode_p->state == 1) { + hatumode_control->actor_class.world.position.x = 20 + hatumode_p->yashiro_pos[0]; + hatumode_control->actor_class.world.position.z = 40 + hatumode_p->yashiro_pos[1]; + hatumode_control->actor_class.world.position.y = hatumode_p->yashiro_pos[2]; + aHTC_setup_move_proc(hatumode_control, 1); + } +} + +static void aHTC_wait(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (hatumode_p->flags0 & 0x8000) { + aHTC_setup_move_proc(hatumode_control, 2); + } +} + +static void aHTC_set_talk_info_local(ACTOR* actorx) { + rgba_t window_color; + + mDemo_Set_camera(CAMERA2_PROCESS_NORMAL); + mDemo_Set_talk_display_name(FALSE); + mDemo_Set_ListenAble(); + window_color.r = 255; + window_color.g = 60; + window_color.b = 40; + window_color.a = 255; + mDemo_Set_talk_window_color(&window_color); +} + +static void aHTC_request(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)hatumode_control; + + if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == TRUE) { + if (mSP_money_check(50)) { + aHTC_setup_move_proc(hatumode_control, 3); + mDemo_Set_msg_num(0x112C); + } else { + aHTC_setup_move_proc(hatumode_control, 4); + mDemo_Set_msg_num(0x112E); + } + } else { + if (mDemo_Get_talk_actor() == NULL) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aHTC_set_talk_info_local); + } + } +} + +static void aHTC_select(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + if (mMsg_CHECK_MAINNORMALCONTINUE()) { + if (mChoice_GET_CHOSENUM() == mChoice_CHOICE0) { + aHTC_setup_move_proc(hatumode_control, 7); + mMsg_SET_CONTINUE_MSG_NUM(0x112D); + } else { + aHTC_setup_move_proc(hatumode_control, 4); + mMsg_SET_CONTINUE_MSG_NUM(0x112E); + } + } +} + +static void aHTC_nomoney(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + if (!mDemo_Check(mDemo_TYPE_SPEAK, (ACTOR*)hatumode_control)) { + aHTC_setup_move_proc(hatumode_control, 5); + } +} + +static void aHTC_inori(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + xyz_t pos; + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + pos.x = 20 + hatumode_p->yashiro_pos[0]; + pos.y = hatumode_p->yashiro_pos[2]; + pos.z = 85 + hatumode_p->yashiro_pos[1]; + + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_PRAY) { + mPlib_request_main_pray_type1((GAME*)play, &pos, DEG2SHORT_ANGLE2(180.0f)); + } else { + aHTC_setup_move_proc(hatumode_control, 6); + } +} + +static void aHTC_inori_end(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_WAIT) { + aHTC_setup_move_proc(hatumode_control, 1); + hatumode_p->flags0 &= ~0x8000; + } +} + +static void aHTC_pay(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + if (!mDemo_Check(mDemo_TYPE_SPEAK, (ACTOR*)hatumode_control)) { + aHTC_setup_move_proc(hatumode_control, 8); + mSP_get_sell_price(50); + } +} + +static void aHTC_saisen(HATUMODE_CONTROL_ACTOR* hatumode_control, GAME_PLAY* play) { + xyz_t pos; + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + pos.x = 20 + hatumode_p->yashiro_pos[0]; + pos.y = hatumode_p->yashiro_pos[2]; + pos.z = 85 + hatumode_p->yashiro_pos[1]; + + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_THROW_MONEY) { + mPlib_request_main_throw_money_type1((GAME*)play, &pos, DEG2SHORT_ANGLE2(180.0f)); + } else { + aHTC_setup_move_proc(hatumode_control, 6); + } +} + +static void aHTC_setup_move_proc(HATUMODE_CONTROL_ACTOR* hatumode_control, s16 move_proc_idx) { + // clang-format off + static aHTC_MOVE_PROC process[] = { + &aHTC_ready, + &aHTC_wait, + &aHTC_request, + &aHTC_select, + &aHTC_nomoney, + &aHTC_inori, + &aHTC_inori_end, + &aHTC_pay, + &aHTC_saisen, + }; + // clang-format on + + hatumode_control->move_proc = process[move_proc_idx]; +} diff --git a/src/actor/npc/ac_hatumode_npc0.c b/src/actor/npc/ac_hatumode_npc0.c new file mode 100644 index 00000000..06bf0f4c --- /dev/null +++ b/src/actor/npc/ac_hatumode_npc0.c @@ -0,0 +1,118 @@ +#include "ac_hatumode_npc0.h" + +#include "m_common_data.h" +#include "m_player_lib.h" + +static void aHN0_actor_ct(ACTOR* actorx, GAME* game); +static void aHN0_actor_dt(ACTOR* actorx, GAME* game); +static void aHN0_actor_move(ACTOR* actorx, GAME* game); +static void aHN0_actor_draw(ACTOR* actorx, GAME* game); +static void aHN0_actor_save(ACTOR* actorx, GAME* game); +static void aHN0_actor_init(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Hatumode_Npc0_Profile = { + mAc_PROFILE_HATUMODE_NPC0, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + SP_NPC_EV_HATUMODE_0, + ACTOR_OBJ_BANK_KEEP, + sizeof(HATUMODE_NPC0_ACTOR), + &aHN0_actor_ct, + &aHN0_actor_dt, + &aHN0_actor_init, + mActor_NONE_PROC1, + &aHN0_actor_save +}; +// clang-format on + +static void aHN0_talk_request(ACTOR* actorx, GAME* game); +static int aHN0_talk_init(ACTOR* actorx, GAME* game); +static int aHN0_talk_end_chk(ACTOR* actorx, GAME* game); + +static void aHN0_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type); +static void aEv_init_hatumode_save_area(void); +static void aHN0_setup_think_proc(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play, u8 think_idx); + +static void aHN0_actor_ct(ACTOR* actorx, GAME* game) { + // clang-format off + static aNPC_ct_data_c ct_data = { + &aHN0_actor_move, + &aHN0_actor_draw, + 5, + (aNPC_TALK_REQUEST_PROC)&none_proc1, + &aHN0_talk_init, + &aHN0_talk_end_chk, + 0, + }; + // clang-format on + + // clang-format off + static int base_msg_table[] = { + 0x1DFF, + 0x1E11, + 0x1DED, + 0x1E23, + 0x1E35, + 0x1E47, + }; + // clang-format on + + if (CLIP(npc_clip)->birth_check_proc(actorx, game) == TRUE) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)actorx; + + h_npc->npc_class.schedule.schedule_proc = &aHN0_schedule_proc; + CLIP(npc_clip)->ct_proc(actorx, game, &ct_data); + h_npc->npc_class.palActorIgnoreTimer = -1; + h_npc->think_change_flag = FALSE; + h_npc->base_msg = base_msg_table[mNpc_GetNpcLooks(actorx)]; + + if (actorx->npc_id == SP_NPC_EV_HATUMODE_0) { + aEv_init_hatumode_save_area(); + actorx->cull_radius = 800.0f; + } + + h_npc->npc_class.collision.priority = 0; + actorx->world.position.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(actorx->world.position, 0.0f); + actorx->position_speed.y = 0.0f; + actorx->gravity = 0.0f; + actorx->max_velocity_y = 0.0f; + h_npc->npc_class.collision.pipe.attribute.pipe.radius = 20; + } +} + +static void aHN0_actor_save(ACTOR* actorx, GAME* game) { + mNpc_RenewalSetNpc(actorx); +} + +static void aHN0_actor_dt(ACTOR* actorx, GAME* game) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + CLIP(npc_clip)->dt_proc(actorx, game); + if (actorx->npc_id == SP_NPC_EV_HATUMODE_0) { + hatumode_p->flags0 = 0x01; + hatumode_p->state = 2; + } +} + +static void aHN0_actor_init(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->init_proc(actorx, game); +} + +static void aHN0_actor_move(ACTOR* actorx, GAME* game) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + CLIP(npc_clip)->move_proc(actorx, game); + ((NPC_ACTOR*)actorx)->collision.pipe.attribute.pipe.radius = 20; + if (hatumode_p != NULL && actorx->npc_id != SP_NPC_EV_HATUMODE_0 && hatumode_p->state == 2 && (hatumode_p->flags0 & (1 << (actorx->npc_id - SP_NPC_EV_HATUMODE_0))) == 0) { + hatumode_p->flags0 |= (1 << (actorx->npc_id - SP_NPC_EV_HATUMODE_0)); + Actor_delete(actorx); + } +} + +static void aHN0_actor_draw(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->draw_proc(actorx, game); +} + +#include "../src/actor/npc/ac_hatumode_npc0_talk.c_inc" +#include "../src/actor/npc/ac_hatumode_npc0_schedule.c_inc" diff --git a/src/actor/npc/ac_hatumode_npc0_schedule.c_inc b/src/actor/npc/ac_hatumode_npc0_schedule.c_inc new file mode 100644 index 00000000..205fdd76 --- /dev/null +++ b/src/actor/npc/ac_hatumode_npc0_schedule.c_inc @@ -0,0 +1,292 @@ +static int aHN0_flag2_wait_check(HATUMODE_NPC0_ACTOR* h_npc) { + u16 bit; + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + bit = 0; + switch (h_npc->think_idx) { + case 3: + bit = 0x01 << ((((ACTOR*)h_npc)->npc_id - SP_NPC_EV_HATUMODE_0) & 1); + break; + case 13: + bit = 0x04 << (((((ACTOR*)h_npc)->npc_id - SP_NPC_EV_HATUMODE_0) & 1) ^ 1); + break; + case 28: + bit = 0x10 << (((((ACTOR*)h_npc)->npc_id - SP_NPC_EV_HATUMODE_0) & 1) ^ 1); + break; + } + + if (hatumode_p->flags1 & bit) { + hatumode_p->flags1 &= ~bit; + return TRUE; + } + + return FALSE; +} + +static void aHN0_birth(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (CLIP(hatumode_clip) != NULL) { + aHN0_set_start_position(h_npc); + if (h_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0 == 0) { + aHN0_setup_think_proc(h_npc, play, 0); + } else { + aHN0_setup_think_proc(h_npc, play, 1); + } + } else { + h_npc->think_proc_idx = aHN0_THINK_PROC_BIRTH; + } +} + +static void aHN0_ready1(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (hatumode_p->state == 1 || mFI_SetOyasiroPos(hatumode_p->yashiro_pos)) { + hatumode_p->state = 1; + hatumode_p->cur_npc_idx = 0; + h_npc->root = 5; + aHN0_setup_think_proc(h_npc, play, 4); + } +} + +static void aHN0_ready2(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + static u8 root_table[] = { 5, 4, 9, 3 }; + static u8 proc_idx_table[] = { 4, 27, 27, 20 }; + int idx = h_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0; + + if (hatumode_p != NULL && hatumode_p->state == 1) { + h_npc->npc_class.actor_class.state_bitfield |= ACTOR_STATE_NO_MOVE_WHILE_CULLED; + h_npc->root = root_table[idx]; + aHN0_setup_think_proc(h_npc, play, proc_idx_table[idx]); + } +} + +static void aHN0_turn_next(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (h_npc->npc_class.action.idx == aNPC_ACT_TURN) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } +} + +static void aHN0_flag2_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (aHN0_flag2_wait_check(h_npc)) { + if (h_npc->think_idx == 28 && (hatumode_p->flags0 & 0x4000) != 0) { + hatumode_p->flags0 &= ~0x4000; + aHN0_setup_think_proc(h_npc, play, 43); + } else { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } + } +} + +static void aHN0_anime_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (cKF_FrameControl_stop_proc(&h_npc->npc_class.draw.main_animation.keyframe.frame_control) == cKF_STATE_STOPPED) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } +} + +static void aHN0_anime_wait_saisen(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (cKF_FrameControl_stop_proc(&h_npc->npc_class.draw.main_animation.keyframe.frame_control) == cKF_STATE_STOPPED) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } else if (cKF_FrameControl_passCheck_now(&h_npc->npc_class.draw.main_animation.keyframe.frame_control, 33.0f) == TRUE) { + ACTOR* actorx = (ACTOR*)h_npc; + + eEC_CLIP->effect_make_proc(eEC_EFFECT_COIN, actorx->world.position, 1, actorx->shape_info.rotation.y, (GAME*)play, actorx->npc_id, 0, 0); + } +} + +static void aHN0_timer_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (h_npc->timer > 0) { + h_npc->timer--; + } else { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } +} + +static void aHN0_move_bf(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (!h_npc->npc_class.collision.turn_flag) { + aHN0_setup_think_proc(h_npc, play, h_npc->move_think_idx); + } + + CLIP(npc_clip)->set_dst_pos_proc(&h_npc->npc_class, h_npc->pos[0], h_npc->pos[1]); +} + +static void aHN0_move_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (h_npc->npc_class.action.idx == aNPC_ACT_WALK2) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + h_npc->npc_class.actor_class.status_data.weight = MASSTYPE_IMMOVABLE; + } else if ((s16)h_npc->npc_class.movement.target_pos_x != h_npc->pos[0] || (s16)h_npc->npc_class.movement.target_pos_z != h_npc->pos[1]) { + h_npc->move_think_idx = h_npc->think_idx - 1; + aHN0_setup_think_proc(h_npc, play, 33); + } +} + +static void aHN0_aisatu_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (hatumode_p->flags0 & 0x2000) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } +} + +static void aHN0_aisatu2_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (hatumode_p->flags0 & 0x1000) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } +} + +static void aHN0_to_omairi(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + hatumode_p->cur_npc_idx = h_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0; + aHN0_setup_think_proc(h_npc, play, 2); +} + +static void aHN0_player_move(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + if (CLIP(hatumode_clip)->player_move_proc(play, h_npc->player)) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + h_npc->player++; + } +} + +static void aHN0_player_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + CLIP(hatumode_clip)->look_player_proc((ACTOR*)h_npc); + if (mPlib_get_player_actor_main_index((GAME*)play) != mPlayer_INDEX_DEMO_WALK) { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + } +} + +static void aHN0_kasasimai(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_WAIT) { + if (mPlib_Check_now_handin_item()) { + mPlib_request_main_demo_wait_type1((GAME*)play, TRUE, NULL); + } else { + aHN0_setup_think_proc(h_npc, play, ++h_npc->think_idx); + hatumode_p->flags0 |= 0x8000; + } + } +} + +static void aHN0_sanpai_wait(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if ((hatumode_p->flags0 & 0x8000) == 0) { + hatumode_p->flags0 |= 0x4000; + hatumode_p->flags1 &= ~(1 << ((h_npc->npc_class.actor_class.npc_id - SP_NPC_EV_HATUMODE_0) & 1)); + aHN0_setup_think_proc(h_npc, play, 10); + } +} + +typedef void (*aHN0_THINK_PROC)(HATUMODE_NPC0_ACTOR*, GAME_PLAY*); + +// clang-format off +static aHN0_THINK_PROC proc_table[] = { + (aHN0_THINK_PROC)&none_proc1, + &aHN0_birth, + &aHN0_ready1, + &aHN0_ready2, + &aHN0_turn_next, + &aHN0_flag2_wait, + &aHN0_anime_wait, + &aHN0_anime_wait_saisen, + &aHN0_timer_wait, + &aHN0_move_wait, + &aHN0_move_bf, + &aHN0_aisatu_wait, + &aHN0_aisatu2_wait, + &aHN0_to_omairi, + &aHN0_player_move, + &aHN0_player_wait, + &aHN0_kasasimai, + &aHN0_sanpai_wait, +}; +// clang-format on + +static void aHN0_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)nactorx; + + if (mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)nactorx) != TRUE) { + if (h_npc->npc_class.action.step == aNPC_ACTION_END_STEP) { + h_npc->npc_class.condition_info.demo_flg = aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_MOVE_Y | aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK; + } + + if (h_npc->npc_class.action.step == aNPC_ACTION_END_STEP || h_npc->npc_class.action.idx == aNPC_ACT_WAIT) { + (*proc_table[h_npc->think_proc_idx])(h_npc, play); + } + } +} + +static void aHN0_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)nactorx; + + aHN0_birth(h_npc, play); + nactorx->actor_class.status_data.weight = MASSTYPE_IMMOVABLE; + nactorx->condition_info.hide_request = FALSE; + nactorx->think.interrupt_flags = 0; + nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_MOVE_Y | aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK; +} + +static void aHN0_setup_think_proc(HATUMODE_NPC0_ACTOR* h_npc, GAME_PLAY* play, u8 think_idx) { + // clang-format off + static aNPC_TALK_REQUEST_PROC talk_request_table[] = { + (aNPC_TALK_REQUEST_PROC)&none_proc1, + &aHN0_norm_talk_request, + &aHN0_force_talk_request, + }; + // clang-format on + + h_npc->think_idx = think_idx; + if (CLIP(hatumode_clip) != NULL) { + h_npc->npc_class.talk_info.talk_request_proc = talk_request_table[CLIP(hatumode_clip)->think_init_proc((ACTOR*)h_npc, play)]; + } else { + h_npc->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1; + h_npc->think_proc_idx = aHN0_THINK_PROC_BIRTH; + } + + h_npc->think_change_flag = TRUE; +} + +static void aHN0_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + switch (proc_type) { + case aNPC_THINK_PROC_INIT: + aHN0_think_init_proc(nactorx, play); + break; + case aNPC_THINK_PROC_MAIN: + aHN0_think_main_proc(nactorx, play); + break; + } +} + +static void aHN0_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->think.think_proc = &aHN0_think_proc; + CLIP(npc_clip)->think_proc(nactorx, play, aNPC_THINK_SPECIAL, FALSE); + +} + +static void aHN0_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)nactorx; + + if (!CLIP(npc_clip)->think_proc(nactorx, play, -1, 1)) { + CLIP(npc_clip)->think_proc(nactorx, play, -1, 2); + } else { + if (nactorx->collision.turn_flag == TRUE && h_npc->think_proc_idx == aHN0_THINK_PROC_MOVE_WAIT) { + h_npc->move_think_idx = h_npc->think_idx - 1; + aHN0_setup_think_proc(h_npc, play, 33); + } + } +} + +static void aHN0_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + switch (proc_type) { + case aNPC_SCHEDULE_PROC_INIT: + aHN0_schedule_init_proc(nactorx, play); + break; + case aNPC_SCHEDULE_PROC_MAIN: + aHN0_schedule_main_proc(nactorx, play); + break; + } +} diff --git a/src/actor/npc/ac_hatumode_npc0_talk.c_inc b/src/actor/npc/ac_hatumode_npc0_talk.c_inc new file mode 100644 index 00000000..b774565e --- /dev/null +++ b/src/actor/npc/ac_hatumode_npc0_talk.c_inc @@ -0,0 +1,81 @@ +static void aEv_init_hatumode_save_area(void) { + aEv_hatumode_save_c* hatumode_p = (aEv_hatumode_save_c*)mEv_get_save_area(1, 7); + + if (hatumode_p == NULL) { + hatumode_p = (aEv_hatumode_save_c*)mEv_reserve_save_area(1, 7); + hatumode_p->state = 0; + } else { + hatumode_p->state = 1; + } + + hatumode_p->flags0 = 0; + hatumode_p->flags1 = 0; +} + +static int aHN0_set_start_position(HATUMODE_NPC0_ACTOR* h_npc) { + ACTOR* actorx = (ACTOR*)h_npc; + + if (CLIP(hatumode_clip) == NULL) { + return FALSE; + } + + h_npc->root = CLIP(hatumode_clip)->set_start_proc(actorx); + actorx->shape_info.rotation.y = DEG2SHORT_ANGLE2(180.0f); + actorx->world.angle.y = DEG2SHORT_ANGLE2(180.0f); + h_npc->npc_class.movement.mv_angl = actorx->world.angle.y; + return TRUE; +} + +static void aHN0_set_force_talk_info(ACTOR* actorx) { + if (CLIP(hatumode_clip) != NULL) { + CLIP(hatumode_clip)->talk_info_proc(actorx, 0); + } +} + +static void aHN0_force_talk_request(ACTOR* actorx, GAME* game) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)actorx; + + if (!h_npc->think_change_flag) { + mDemo_Request(mDemo_TYPE_SPEAK, actorx, &aHN0_set_force_talk_info); + } else { + h_npc->think_change_flag = FALSE; + } +} + +static void aHN0_set_norm_talk_info(ACTOR* actorx) { + if (CLIP(hatumode_clip) != NULL) { + CLIP(hatumode_clip)->talk_info_proc(actorx, 1); + } +} + +static void aHN0_norm_talk_request(ACTOR* actorx, GAME* game) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)actorx; + + if (!h_npc->think_change_flag) { + mDemo_Request(mDemo_TYPE_TALK, actorx, &aHN0_set_norm_talk_info); + } else { + h_npc->think_change_flag = FALSE; + } +} + +static int aHN0_talk_init(ACTOR* actorx, GAME* game) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)actorx; + + h_npc->npc_class.talk_info.talk_request_proc = (aNPC_TALK_REQUEST_PROC)&none_proc1; + mDemo_Set_ListenAble(); + mDemo_Start(actorx); + return TRUE; +} + +static int aHN0_talk_end_chk(ACTOR* actorx, GAME* game) { + HATUMODE_NPC0_ACTOR* h_npc = (HATUMODE_NPC0_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + int res = FALSE; + + (*h_npc->talk_proc)(h_npc, play); + if (!mDemo_Check(mDemo_TYPE_SPEAK, actorx) && !mDemo_Check(mDemo_TYPE_TALK, actorx)) { + aHN0_setup_think_proc(h_npc, play, h_npc->next_think_idx); + res = TRUE; + } + return res; +}