From eb3ce7a2e85290424a543bd2387312f55664dc02 Mon Sep 17 00:00:00 2001 From: Vi Date: Sun, 8 Jun 2025 14:28:15 -0500 Subject: [PATCH] implement and link both ac_tukumi_npc's --- configure.py | 4 +- include/ac_tukimi_npc0.h | 7 + include/ac_tukimi_npc1.h | 8 + src/actor/npc/ac_tukimi_npc0.c | 119 +++++++++++++++ src/actor/npc/ac_tukimi_npc0_anime.c_inc | 4 + src/actor/npc/ac_tukimi_npc0_talk.c_inc | 149 +++++++++++++++++++ src/actor/npc/ac_tukimi_npc1.c | 120 +++++++++++++++ src/actor/npc/ac_tukimi_npc1_anime.c_inc | 4 + src/actor/npc/ac_tukimi_npc1_talk.c_inc | 181 +++++++++++++++++++++++ 9 files changed, 594 insertions(+), 2 deletions(-) create mode 100644 src/actor/npc/ac_tukimi_npc0.c create mode 100644 src/actor/npc/ac_tukimi_npc0_anime.c_inc create mode 100644 src/actor/npc/ac_tukimi_npc0_talk.c_inc create mode 100644 src/actor/npc/ac_tukimi_npc1.c create mode 100644 src/actor/npc/ac_tukimi_npc1_anime.c_inc create mode 100644 src/actor/npc/ac_tukimi_npc1_talk.c_inc diff --git a/configure.py b/configure.py index cd271140..88c930f3 100644 --- a/configure.py +++ b/configure.py @@ -1151,8 +1151,8 @@ config.libs = [ Object(NonMatching, "actor/npc/ac_tamaire_npc1.c"), Object(NonMatching, "actor/npc/ac_tokyoso_npc0.c"), Object(NonMatching, "actor/npc/ac_tokyoso_npc1.c"), - Object(NonMatching, "actor/npc/ac_tukimi_npc0.c"), - Object(NonMatching, "actor/npc/ac_tukimi_npc1.c"), + Object(Matching, "actor/npc/ac_tukimi_npc0.c"), + Object(Matching, "actor/npc/ac_tukimi_npc1.c"), Object(NonMatching, "actor/npc/ac_tunahiki_npc0.c"), Object(NonMatching, "actor/npc/ac_tunahiki_npc1.c"), Object(Matching, "actor/npc/ac_turi_npc0.c"), diff --git a/include/ac_tukimi_npc0.h b/include/ac_tukimi_npc0.h index 0077d798..893b51ae 100644 --- a/include/ac_tukimi_npc0.h +++ b/include/ac_tukimi_npc0.h @@ -3,13 +3,20 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +typedef struct tukimi_npc0_s TUKIMI_NPC0_ACTOR; extern ACTOR_PROFILE Tukimi_Npc0_Profile; +/* sizeof(tukimi_npc0_s) == 0x994 */ +struct tukimi_npc0_s { + /* 0x000 */ NPC_ACTOR npc_class; +}; + #ifdef __cplusplus } #endif diff --git a/include/ac_tukimi_npc1.h b/include/ac_tukimi_npc1.h index 408f090a..f5376c31 100644 --- a/include/ac_tukimi_npc1.h +++ b/include/ac_tukimi_npc1.h @@ -3,13 +3,21 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { #endif +typedef struct tukimi_npc1_s TUKIMI_NPC1_ACTOR; extern ACTOR_PROFILE Tukimi_Npc1_Profile; +/* sizeof(tukimi_npc1_s) == 0x998 */ +struct tukimi_npc1_s { + /* 0x000 */ NPC_ACTOR npc_class; + /* 0x994 */ int npcIdx; +}; + #ifdef __cplusplus } #endif diff --git a/src/actor/npc/ac_tukimi_npc0.c b/src/actor/npc/ac_tukimi_npc0.c new file mode 100644 index 00000000..6f93a22a --- /dev/null +++ b/src/actor/npc/ac_tukimi_npc0.c @@ -0,0 +1,119 @@ +#include "ac_tukimi_npc0.h" + +#include "ac_npc.h" +#include "ac_npc_h.h" +#include "ac_quest_manager.h" +#include "audio.h" +#include "dolphin/os/OSRtc.h" +#include "game.h" +#include "libc64/qrand.h" +#include "libultra/libultra.h" +#include "m_actor.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_event.h" +#include "m_field_info.h" +#include "m_land.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_lib.h" +#include "m_private.h" +#include "m_quest.h" +#include "m_soncho.h" +#include "m_submenu.h" +#include "m_vibctl.h" +#include "sys_math.h" +#include "types.h" + +static void aTM0_actor_ct(ACTOR* actorx, GAME* game); +static void aTM0_actor_save(ACTOR* actorx, GAME* game); +static void aTM0_actor_dt(ACTOR* actorx, GAME* game); +static void aTM0_actor_init(ACTOR* actorx, GAME* game); +static void aTM0_actor_move(ACTOR* actorx, GAME* game); +static void aTM0_actor_draw(ACTOR* actorx, GAME* game); + +static void aTM0_set_animation(ACTOR* actorx, GAME* game); + +static void aTM0_set_request_act(NPC_ACTOR* actorx); +static void aTM0_act_chg_data_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM0_act_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM0_act_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int act_idx); +static void aTM0_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM0_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM0_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_idx); +static void aTM0_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM0_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM0_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sche_proc_idx); +static void aTM0_set_talk_info(ACTOR* actorx); +static void aTM0_talk_request(ACTOR* actorx, GAME* game); +static int aTM0_talk_init(ACTOR* actorx, GAME* game); +static int aTM0_talk_end_chk(ACTOR* actorx, GAME* game); + + +// clang-format off +ACTOR_PROFILE Tukimi_Npc0_Profile = { + mAc_PROFILE_TUKIMI_NPC0, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(TUKIMI_NPC0_ACTOR), + aTM0_actor_ct, + aTM0_actor_dt, + aTM0_actor_init, + mActor_NONE_PROC1, + aTM0_actor_save, +}; +// clang-format on + +static void aTM0_actor_ct(ACTOR* actorx, GAME* game) { + // clang-format off + static aNPC_ct_data_c ct_data = { + &aTM0_actor_move, + &aTM0_actor_draw, + aNPC_CT_SCHED_TYPE_SPECIAL, + &aTM0_talk_request, + &aTM0_talk_init, + &aTM0_talk_end_chk, + 0, + }; + // clang-format on + + TUKIMI_NPC0_ACTOR* tukimi_npc0_actor = (TUKIMI_NPC0_ACTOR*)actorx; + if (NPC_CLIP->birth_check_proc(actorx, game) == TRUE) { + tukimi_npc0_actor->npc_class.schedule.schedule_proc = aTM0_schedule_proc; + NPC_CLIP->ct_proc(actorx, game, &ct_data); + } +} + +static void aTM0_actor_save(ACTOR* actorx, GAME* game) { + NPC_CLIP->save_proc(actorx, game); +} + +static void aTM0_actor_dt(ACTOR* actorx, GAME* game) { + NPC_CLIP->dt_proc(actorx, game); +} + +static void aTM0_actor_init(ACTOR* actorx, GAME* game) { + NPC_CLIP->init_proc(actorx, game); +} + +static void aTM0_actor_move(ACTOR* actorx, GAME* game) { + NPC_CLIP->move_proc(actorx, game); +} + +static void aTM0_actor_draw(ACTOR* actorx, GAME* game) { + NPC_CLIP->draw_proc(actorx, game); +} + +#include "../src/actor/npc/ac_tukimi_npc0_anime.c_inc" + +#include "../src/actor/npc/ac_tukimi_npc0_talk.c_inc" diff --git a/src/actor/npc/ac_tukimi_npc0_anime.c_inc b/src/actor/npc/ac_tukimi_npc0_anime.c_inc new file mode 100644 index 00000000..3335f559 --- /dev/null +++ b/src/actor/npc/ac_tukimi_npc0_anime.c_inc @@ -0,0 +1,4 @@ + +static void aTM0_set_animation(ACTOR* actorx, GAME* game) { + NPC_CLIP->animation_init_proc(actorx, aNPC_ANIM_SANBASI1, FALSE); +} diff --git a/src/actor/npc/ac_tukimi_npc0_talk.c_inc b/src/actor/npc/ac_tukimi_npc0_talk.c_inc new file mode 100644 index 00000000..dfd51fdd --- /dev/null +++ b/src/actor/npc/ac_tukimi_npc0_talk.c_inc @@ -0,0 +1,149 @@ +static void aTM0_set_request_act(NPC_ACTOR* actorx) { + actorx->request.act_priority = 4; + actorx->request.act_idx = aNPC_ACT_SPECIAL; + actorx->request.act_type = aNPC_ACT_TYPE_SEARCH; +} + +static void aTM0_act_chg_data_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + actorx->action.act_obj = aNPC_ACT_OBJ_PLAYER; +} + +static void aTM0_act_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + actorx->action.step = 0; + aTM0_set_animation(&actorx->actor_class, &play->game); +} + +static void aTM0_act_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int act_idx) { + // clang-format off + static aNPC_SUB_PROC act_proc[] = { + &aTM0_act_init_proc, + &aTM0_act_chg_data_proc, + (aNPC_SUB_PROC)&none_proc1 + }; + // clang-format on + act_proc[act_idx](actorx, play); +} + +static void aTM0_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + if (actorx->action.step == aNPC_ACTION_END_STEP) { + if (actorx->action.idx == aNPC_ACT_SPECIAL) { + actorx->action.step = 0; + aTM0_set_animation(&actorx->actor_class, &play->game); + } + actorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | 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; + aTM0_set_request_act(actorx); + } +} + +static void aTM0_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + actorx->think.interrupt_flags = 0; + actorx->action.act_proc = &aTM0_act_proc; + aTM0_set_request_act(actorx); +} + +static void aTM0_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_idx) { + // clang-format off + static aNPC_SUB_PROC think_proc[] = { + &aTM0_think_init_proc, + &aTM0_think_main_proc, + }; + // clang-format on + think_proc[think_idx](actorx, play); +} + +static void aTM0_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + int puleIdx; + s16 ang; + static s16 def_angle[] = {0xA000, 0x2000, 0x6000, 0xE000, 0xE000, 0x2000, 0xA000, 0}; + static f32 def_posX[] = {1.0f, 39.0f, 39.0f, 1.0f, 1.0f, 39.0f, 1.0f}; + static f32 def_posZ[] = {1.0f, 39.0f, 1.0f, 39.0f, 39.0f, 39.0f, 1.0f}; + actorx->think.think_proc = &aTM0_think_proc; + actorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | 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; + actorx->collision.check_kind = aNPC_BG_CHECK_TYPE_ONLY_GROUND; + actorx->condition_info.hide_request = FALSE; + actorx->palActorIgnoreTimer = -1; + actorx->talk_info.turn = aNPC_TALK_TURN_HEAD; + actorx->talk_info.default_animation = aNPC_ANIM_SANBASI1; + actorx->actor_class.status_data.weight = MASSTYPE_HEAVY; + + puleIdx = mFI_GetPuleIdx(); + ang = def_angle[puleIdx]; + actorx->actor_class.shape_info.rotation.y = ang; + actorx->actor_class.world.angle.y = ang; + actorx->movement.mv_angl = ang; + + actorx->actor_class.world.position.x += def_posX[puleIdx]; + actorx->actor_class.world.position.z += def_posZ[puleIdx]; + NPC_CLIP->think_proc(actorx, play, 9, FALSE); +} + +static void aTM0_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + s16 yRot; + f32 trigVal; + if (NPC_CLIP->think_proc(actorx, play, -1, 1) == FALSE) { + NPC_CLIP->think_proc(actorx, play, -1, 2); + } + if (actorx->action.idx == aNPC_ACT_SPECIAL) { + yRot = actorx->actor_class.shape_info.rotation.y; + actorx->request.head_pos.x = actorx->actor_class.eye.position.x + sin_s(yRot) * 40.0f; + actorx->request.head_pos.y = actorx->actor_class.eye.position.y - 30.0f; + actorx->request.head_pos.z = actorx->actor_class.eye.position.z + cos_s(yRot) * 40.0f; + actorx->request.head_priority = 3; + actorx->request.head_type = 2; + } +} + +static void aTM0_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sche_proc_idx) { + // clang-format off + static aNPC_SUB_PROC sche_proc[] = { + &aTM0_schedule_init_proc, + &aTM0_schedule_main_proc, + }; + // clang-format on + sche_proc[sche_proc_idx](actorx, play); +} + +static void aTM0_set_talk_info(ACTOR* actorx) { + static int msg_base[mNpc_LOOKS_NUM] = {0x1EB0, 0x1EBF, 0x1EA1, 0x1ECE, 0x1EDD, 0x1EEC}; + static int msg_base2[mNpc_LOOKS_NUM] = {0x3F46, 0x3F55, 0x3F37, 0x3F64, 0x3F73, 0x3F82}; + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + u8 worldName[LAND_NAME_SIZE]; + mNpc_EventNpc_c* eventNpc; + ACTOR* actorRet; + int looks; + int* msg; + int i; + looks = mNpc_GetNpcLooks(actorx); + msg = msg_base; + + for (i = 0; i < mNpc_EVENT_NPC_NUM; i++) { + eventNpc = mNpc_GetSameEventNpc(i + SP_NPC_EV_TUKIMI_0); + if (eventNpc != NULL) { + actorRet = Actor_info_fgName_search(&((GAME_PLAY*)gamePT)->actor_info,eventNpc->event_id, ACTOR_PART_NPC); + mNpc_GetNpcWorldName(worldName, actorRet); + mMsg_Set_free_str(msg_p, i + mMsg_FREE_STR1, worldName, LAND_NAME_SIZE); + } + } + if (mEv_check_status(mEv_EVENT_METEOR_SHOWER, mEv_STATUS_ACTIVE) == TRUE) { + msg = msg_base2; + } + mDemo_Set_msg_num(msg[looks] + RANDOM(3)); +} + +static void aTM0_talk_request(ACTOR* actorx, GAME* game) { + mDemo_Request(mDemo_TYPE_TALK, actorx, aTM0_set_talk_info); +} + +static int aTM0_talk_init(ACTOR* actorx, GAME* game) { + mDemo_Set_ListenAble(); + return TRUE; +} + +static int aTM0_talk_end_chk(ACTOR* actorx, GAME* game) { + BOOL res = FALSE; + int demoCheck = mDemo_Check(mDemo_TYPE_TALK, actorx); + if (demoCheck == FALSE){ + res = TRUE; + } + return res; +} \ No newline at end of file diff --git a/src/actor/npc/ac_tukimi_npc1.c b/src/actor/npc/ac_tukimi_npc1.c new file mode 100644 index 00000000..861ef385 --- /dev/null +++ b/src/actor/npc/ac_tukimi_npc1.c @@ -0,0 +1,120 @@ +#include "ac_tukimi_npc1.h" + +#include "ac_npc.h" +#include "ac_npc_h.h" +#include "ac_quest_manager.h" +#include "audio.h" +#include "dolphin/os/OSRtc.h" +#include "game.h" +#include "libc64/qrand.h" +#include "libultra/libultra.h" +#include "m_actor.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_event.h" +#include "m_field_info.h" +#include "m_land.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_lib.h" +#include "m_private.h" +#include "m_quest.h" +#include "m_soncho.h" +#include "m_submenu.h" +#include "m_vibctl.h" +#include "sys_math.h" +#include "types.h" + +static void aTM1_actor_ct(ACTOR* actorx, GAME* game); +static void aTM1_actor_save(ACTOR* actorx, GAME* game); +static void aTM1_actor_dt(ACTOR* actorx, GAME* game); +static void aTM1_actor_init(ACTOR* actorx, GAME* game); +static void aTM1_actor_move(ACTOR* actorx, GAME* game); +static void aTM1_actor_draw(ACTOR* actorx, GAME* game); + +static void aTM1_set_animation(ACTOR* actorx, int anime_idx); + +static void aTM1_set_request_act(NPC_ACTOR* actorx); +static void aTM1_act_chg_data_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM1_act_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM1_act_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int act_idx); +static void aTM1_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM1_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM1_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_idx); +static void aTM1_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM1_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play); +static void aTM1_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sche_proc_idx); +static void aTM1_set_talk_info(ACTOR* actorx); +static void aTM1_set_talk_info2(ACTOR* actorx); +static void aTM1_talk_request(ACTOR* actorx, GAME* game); +static int aTM1_talk_init(ACTOR* actorx, GAME* game); +static int aTM1_talk_end_chk(ACTOR* actorx, GAME* game); + + +// clang-format off +ACTOR_PROFILE Tukimi_Npc1_Profile = { + mAc_PROFILE_TUKIMI_NPC1, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(TUKIMI_NPC1_ACTOR), + aTM1_actor_ct, + aTM1_actor_dt, + aTM1_actor_init, + mActor_NONE_PROC1, + aTM1_actor_save, +}; +// clang-format on + +static void aTM1_actor_ct(ACTOR* actorx, GAME* game) { + // clang-format off + static aNPC_ct_data_c ct_data = { + &aTM1_actor_move, + &aTM1_actor_draw, + aNPC_CT_SCHED_TYPE_SPECIAL, + &aTM1_talk_request, + &aTM1_talk_init, + &aTM1_talk_end_chk, + 0, + }; + // clang-format on + + TUKIMI_NPC1_ACTOR* tukimi_npc0_actor = (TUKIMI_NPC1_ACTOR*)actorx; + if (NPC_CLIP->birth_check_proc(actorx, game) == TRUE) { + tukimi_npc0_actor->npc_class.schedule.schedule_proc = aTM1_schedule_proc; + NPC_CLIP->ct_proc(actorx, game, &ct_data); + } +} + +static void aTM1_actor_save(ACTOR* actorx, GAME* game) { + NPC_CLIP->save_proc(actorx, game); +} + +static void aTM1_actor_dt(ACTOR* actorx, GAME* game) { + NPC_CLIP->dt_proc(actorx, game); +} + +static void aTM1_actor_init(ACTOR* actorx, GAME* game) { + NPC_CLIP->init_proc(actorx, game); +} + +static void aTM1_actor_move(ACTOR* actorx, GAME* game) { + NPC_CLIP->move_proc(actorx, game); +} + +static void aTM1_actor_draw(ACTOR* actorx, GAME* game) { + NPC_CLIP->draw_proc(actorx, game); +} + +#include "../src/actor/npc/ac_tukimi_npc1_anime.c_inc" + +#include "../src/actor/npc/ac_tukimi_npc1_talk.c_inc" diff --git a/src/actor/npc/ac_tukimi_npc1_anime.c_inc b/src/actor/npc/ac_tukimi_npc1_anime.c_inc new file mode 100644 index 00000000..9d4641f1 --- /dev/null +++ b/src/actor/npc/ac_tukimi_npc1_anime.c_inc @@ -0,0 +1,4 @@ +static void aTM1_set_animation(ACTOR* actorx, int anime_idx) { + static int animeSeqNo[] = {aNPC_ANIM_WAIT1, aNPC_ANIM_KUISINBO1}; + NPC_CLIP->animation_init_proc(actorx, animeSeqNo[anime_idx], FALSE); +} diff --git a/src/actor/npc/ac_tukimi_npc1_talk.c_inc b/src/actor/npc/ac_tukimi_npc1_talk.c_inc new file mode 100644 index 00000000..7e734cb3 --- /dev/null +++ b/src/actor/npc/ac_tukimi_npc1_talk.c_inc @@ -0,0 +1,181 @@ +static void aTM1_set_request_act(NPC_ACTOR* actorx) { + actorx->request.act_priority = 4; + actorx->request.act_idx = aNPC_ACT_SPECIAL; + actorx->request.act_type = aNPC_ACT_TYPE_SEARCH; +} + +static void aTM1_act_chg_data_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + actorx->action.act_obj = aNPC_ACT_OBJ_PLAYER; +} + +static void aTM1_act_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + int unk = ((TUKIMI_NPC1_ACTOR*)actorx)->npcIdx == 4; + actorx->action.step = 0; + aTM1_set_animation(&actorx->actor_class, unk); +} + +static void aTM1_act_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int act_idx) { + // clang-format off + static aNPC_SUB_PROC act_proc[] = { + &aTM1_act_init_proc, + &aTM1_act_chg_data_proc, + (aNPC_SUB_PROC)&none_proc1 + }; + // clang-format on + act_proc[act_idx](actorx, play); +} + +void aTM1_think_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + int npc_idx; + if (actorx->action.step == aNPC_ACTION_END_STEP) { + if (actorx->action.idx == aNPC_ACT_SPECIAL) { + npc_idx = ((TUKIMI_NPC1_ACTOR*)actorx)->npcIdx==4; + actorx->action.step = 0; + aTM1_set_animation(&actorx->actor_class, npc_idx); + } + actorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | 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; + aTM1_set_request_act(actorx); + } +} + +static void aTM1_think_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + actorx->think.interrupt_flags = 0; + actorx->action.act_proc = &aTM1_act_proc; + aTM1_set_request_act(actorx); +} + +static void aTM1_think_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int think_idx) { + // clang-format off + static aNPC_SUB_PROC think_proc[] = { + &aTM1_think_init_proc, + &aTM1_think_main_proc, + }; + // clang-format on + think_proc[think_idx](actorx, play); +} + +static void aTM1_schedule_init_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + TUKIMI_NPC1_ACTOR* tukimi_actor = (TUKIMI_NPC1_ACTOR*)actorx; + int puleIdx; + int npcIdx; + s16 ang; + static s16 def_angle[][7] = {0xC000, 0x4000, 0xA000, 0x8000, 0xE000, 0xC000, 0x2000, 0x2000, 0xA000, 0xE000, 0x2000, 0xE000, 0xE000, 0xC000, 0x2000, 0xA000, 0xE000, 0x2000, 0xE000, 0xE000, 0xC000, 0xE000, 0xE000, 0, 0, 0x2000, 0x6000, 0xE000, 0, 0, 0, 0, 0, 0, 0}; + actorx->think.think_proc = &aTM1_think_proc; + actorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | 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; + actorx->collision.check_kind = aNPC_BG_CHECK_TYPE_NONE; + actorx->condition_info.hide_request = FALSE; + actorx->palActorIgnoreTimer = -1; + + if (actorx->actor_class.npc_id == SP_NPC_EV_TUKIMI_4) { + actorx->talk_info.turn = aNPC_TALK_TURN_NONE; + actorx->talk_info.default_animation = aNPC_ANIM_KUISINBO1; + } else { + actorx->talk_info.turn = aNPC_TALK_TURN_HEAD; + actorx->talk_info.default_animation = aNPC_ANIM_SITDOWN_WAIT1; + } + + actorx->actor_class.status_data.weight = MASSTYPE_HEAVY; + + puleIdx = mFI_GetPuleIdx(); + npcIdx = actorx->actor_class.npc_id - SP_NPC_EV_TUKIMI_0; + ang = def_angle[npcIdx][puleIdx]; + actorx->actor_class.shape_info.rotation.y = ang; + actorx->actor_class.world.angle.y = ang; + actorx->movement.mv_angl = ang; + + tukimi_actor->npcIdx = npcIdx; + NPC_CLIP->think_proc(actorx, play, 9, FALSE); +} + +static void aTM1_schedule_main_proc(NPC_ACTOR* actorx, GAME_PLAY* play) { + s16 yRot; + if (NPC_CLIP->think_proc(actorx, play, -1, 1) == FALSE) { + NPC_CLIP->think_proc(actorx, play, -1, 2); + } + if ((((TUKIMI_NPC1_ACTOR*)actorx)->npcIdx != 4) && (actorx->action.idx == aNPC_ACT_SPECIAL)) { + yRot = actorx->actor_class.shape_info.rotation.y; + actorx->request.head_pos.x = actorx->actor_class.eye.position.x + sin_s(yRot) * 40.0f; + actorx->request.head_pos.y = actorx->actor_class.eye.position.y + 30.0f; + actorx->request.head_pos.z = actorx->actor_class.eye.position.z + cos_s(yRot) * 40.0f; + actorx->request.head_priority = 3; + actorx->request.head_type = 2; + } +} + +static void aTM1_schedule_proc(NPC_ACTOR* actorx, GAME_PLAY* play, int sche_proc_idx) { + // clang-format off + static aNPC_SUB_PROC sche_proc[] = { + &aTM1_schedule_init_proc, + &aTM1_schedule_main_proc, + }; + // clang-format on + sche_proc[sche_proc_idx](actorx, play); +} + +static void aTM1_set_talk_info(ACTOR* actorx) { + static int msg_base[mNpc_LOOKS_NUM] = {0x1EB0, 0x1EBF, 0x1EA1, 0x1ECE, 0x1EDD, 0x1EEC}; + static int msg_base2[mNpc_LOOKS_NUM] = {0x3F46, 0x3F55, 0x3F37, 0x3F64, 0x3F73, 0x3F82}; + + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + u8 worldName[LAND_NAME_SIZE]; + mNpc_EventNpc_c* eventNpc; + ACTOR* actorRet; + int npcIdx; + int* msg; + int looks; + int i; + looks = mNpc_GetNpcLooks(actorx); + npcIdx = ((TUKIMI_NPC1_ACTOR*)actorx)->npcIdx; + msg = msg_base; + + for (i = 0; i < mNpc_EVENT_NPC_NUM; i++) { + eventNpc = mNpc_GetSameEventNpc(i + SP_NPC_EV_TUKIMI_0); + if (eventNpc != NULL) { + actorRet = Actor_info_fgName_search(&((GAME_PLAY*)gamePT)->actor_info,eventNpc->event_id, ACTOR_PART_NPC); + mNpc_GetNpcWorldName(worldName, actorRet); + mMsg_Set_free_str(msg_p, i + mMsg_FREE_STR1, worldName, LAND_NAME_SIZE); + } + } + if (mEv_check_status(mEv_EVENT_METEOR_SHOWER, mEv_STATUS_ACTIVE) == TRUE) { + msg = msg_base2; + } + mDemo_Set_msg_num(msg[looks] + RANDOM(3) + npcIdx * 3); +} + +static void aTM1_set_talk_info2(ACTOR* actorx) { + static int msg_base[mNpc_LOOKS_NUM] = {0x1EBC, 0x1ECB, 0x1EAD, 0x1EDA, 0x1EE9, 0x1EF8}; + static int msg_base2[mNpc_LOOKS_NUM] = {0x3F52, 0x3F61, 0x3F43, 0x3F70, 0x3F7F, 0x3F8E}; + u8 worldName[LAND_NAME_SIZE]; + mNpc_EventNpc_c* eventNpc; + ACTOR* actorRet; + int looks; + int* msg; + int i; + looks = mNpc_GetNpcLooks(actorx); + msg = msg_base; + + if (mEv_check_status(mEv_EVENT_METEOR_SHOWER, mEv_STATUS_ACTIVE) == TRUE) { + msg = msg_base2; + } + mDemo_Set_msg_num(msg[looks] + RANDOM(3)); +} + +static void aTM1_talk_request(ACTOR* actorx, GAME* game) { + mDemo_REQUEST_PROC funcPtr = (actorx->npc_id == SP_NPC_EV_TUKIMI_4) ? aTM1_set_talk_info2 : aTM1_set_talk_info; + + mDemo_Request(mDemo_TYPE_TALK, actorx, funcPtr); +} + +static int aTM1_talk_init(ACTOR* actorx, GAME* game) { + mDemo_Set_ListenAble(); + return TRUE; +} + +static int aTM1_talk_end_chk(ACTOR* actorx, GAME* game) { + BOOL res = FALSE; + int demoCheck = mDemo_Check(mDemo_TYPE_TALK, actorx); + if (demoCheck == FALSE){ + res = TRUE; + } + return res; +} \ No newline at end of file