From 9de7febbc1045e9e1138da62626105f099f9b992 Mon Sep 17 00:00:00 2001 From: Colby Austin Brown Date: Wed, 15 Jan 2025 00:13:35 -0800 Subject: [PATCH] Implement & link ac_ev_speech_soncho --- configure.py | 2 +- include/ac_ev_speech_soncho.h | 23 +- include/m_string_data.h | 3 + src/actor/npc/event/ac_ev_speech_soncho.c | 80 +++++++ .../npc/event/ac_ev_speech_soncho_talk.c_inc | 196 ++++++++++++++++++ 5 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 src/actor/npc/event/ac_ev_speech_soncho.c create mode 100644 src/actor/npc/event/ac_ev_speech_soncho_talk.c_inc diff --git a/configure.py b/configure.py index 1f489e19..4c15516d 100644 --- a/configure.py +++ b/configure.py @@ -1170,7 +1170,7 @@ config.libs = [ Object(Matching, "actor/npc/event/ac_ev_santa.c"), Object(Matching, "actor/npc/event/ac_ev_soncho.c"), Object(NonMatching, "actor/npc/event/ac_ev_soncho2.c"), - Object(NonMatching, "actor/npc/event/ac_ev_speech_soncho.c"), + Object(Matching, "actor/npc/event/ac_ev_speech_soncho.c"), Object(NonMatching, "actor/npc/event/ac_ev_turkey.c"), Object(NonMatching, "actor/npc/event/ac_ev_yomise.c"), ], diff --git a/include/ac_ev_speech_soncho.h b/include/ac_ev_speech_soncho.h index 5c10548d..feaf0168 100644 --- a/include/ac_ev_speech_soncho.h +++ b/include/ac_ev_speech_soncho.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { @@ -10,9 +11,29 @@ extern "C" { extern ACTOR_PROFILE Ev_Speech_Soncho_Profile; +typedef struct ac_npc_speech_soncho NPC_SPEECH_SONCHO; + +typedef void (*aESS_PROC)(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play); +typedef void (*aESS_THINK_PROC)(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play); +typedef void (*aESS_SCHEDULE_PROC)(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play); + +struct ac_npc_speech_soncho { + NPC_ACTOR npc_class; + /* 0x994 */ int think_proc; + /* 0x998 */ aESS_PROC _998; +}; + +struct aess_think_info { + aESS_PROC proc; + aNPC_TALK_REQUEST_PROC talk_request_proc; + aNPC_TALK_END_CHECK_PROC talk_end_check_proc; + u8 flag; +}; + +typedef struct aess_think_info aESS_think_info; + #ifdef __cplusplus } #endif #endif - diff --git a/include/m_string_data.h b/include/m_string_data.h index 54c9ff6f..7094a53f 100644 --- a/include/m_string_data.h +++ b/include/m_string_data.h @@ -20,6 +20,9 @@ extern "C" { #define mString_HANIWA_MSG3 0x76D #define mString_MIKANBOX_START 0x77B #define mString_MIKANBOX_END 0x7FE +#define mString_CARPETPEDDLER_START 0x48a +#define mString_TOTAKEKE_START 0x1b93 +#define mString_SPEECH_SONCHO_START 0x3db5 #ifdef __cplusplus } diff --git a/src/actor/npc/event/ac_ev_speech_soncho.c b/src/actor/npc/event/ac_ev_speech_soncho.c new file mode 100644 index 00000000..231338bc --- /dev/null +++ b/src/actor/npc/event/ac_ev_speech_soncho.c @@ -0,0 +1,80 @@ +#include "ac_ev_speech_soncho.h" +#include "m_actor.h" +#include "m_clip.h" +#include "ac_npc.h" +#include "m_common_data.h" +#include "ac_groundhog_control.h" +#include "m_demo.h" +#include "m_string_data.h" + +void aESS_actor_ct(ACTOR* actorx, GAME* game); +void aESS_actor_dt(ACTOR* actorx, GAME* game); +void aESS_actor_init(ACTOR* actorx, GAME* game); +void aESS_actor_save(ACTOR* actorx, GAME* game); +void aESS_schedule_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play, int sche_idx); +void aESS_actor_move(ACTOR* actorx, GAME* game); +void aESS_actor_draw(ACTOR* actorx, GAME* game); +int aESS_talk_init(ACTOR* actorx, GAME* game); +void aESS_norm_talk_request(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play); +int aESS_norm_talk_end_chk(NPC_SPEECH_SONCHO* soncho); +void aESS_force_talk_request(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play); +int aESS_force_talk_end_chk(NPC_SPEECH_SONCHO* soncho); + +// clang-format off +ACTOR_PROFILE Ev_Speech_Soncho_Profile = { + mAc_PROFILE_EV_SPEECH_SONCHO, + ACTOR_PART_NPC, + ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED, + SP_NPC_EV_SPEECH_SONCHO, + ACTOR_OBJ_BANK_KEEP, + sizeof(NPC_SPEECH_SONCHO), + &aESS_actor_ct, + &aESS_actor_dt, + &aESS_actor_init, + mActor_NONE_PROC1, + &aESS_actor_save, +}; +// clang-format on + +void aESS_actor_ct(ACTOR* actorx, GAME* game) { + static aNPC_ct_data_c ct_data = { &aESS_actor_move, + &aESS_actor_draw, + 5, + mActor_NONE_PROC1, + &aESS_talk_init, + (aNPC_TALK_END_CHECK_PROC)mActor_NONE_PROC1, + 1 }; + NPC_SPEECH_SONCHO* soncho = (NPC_SPEECH_SONCHO*)actorx; + if (CLIP(npc_clip)->birth_check_proc(actorx, game) == TRUE) { + soncho->npc_class.schedule.schedule_proc = (aNPC_SCHEDULE_PROC)aESS_schedule_proc; + CLIP(npc_clip)->ct_proc(actorx, game, &ct_data); + CLIP(npc_clip)->animation_init_proc(actorx, 5, 0); + } +} + +void aESS_actor_save(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->save_proc(actorx, game); +} + +void aESS_actor_dt(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->dt_proc(actorx, game); +} + +void aESS_actor_init(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->init_proc(actorx, game); +} + +void aESS_actor_move(ACTOR* actorx, GAME* game) { + GAME_PLAY* play = (GAME_PLAY*)game; + if (actorx->parent_actor == NULL) { + actorx->parent_actor = + Actor_info_name_search(&play->actor_info, mAc_PROFILE_GROUNDHOG_CONTROL, ACTOR_PART_CONTROL); + } + CLIP(npc_clip)->move_proc(actorx, game); +} + +void aESS_actor_draw(ACTOR* actorx, GAME* game) { + CLIP(npc_clip)->draw_proc(actorx, game); +} + +#include "src/actor/npc/event/ac_ev_speech_soncho_talk.c_inc" diff --git a/src/actor/npc/event/ac_ev_speech_soncho_talk.c_inc b/src/actor/npc/event/ac_ev_speech_soncho_talk.c_inc new file mode 100644 index 00000000..5c51ca7d --- /dev/null +++ b/src/actor/npc/event/ac_ev_speech_soncho_talk.c_inc @@ -0,0 +1,196 @@ +void aESS_setup_think_proc(ACTOR* actorx, int think_idx); + +void aESS_set_request_act(NPC_SPEECH_SONCHO* soncho) { + soncho->npc_class.request.act_priority = 0x4; + soncho->npc_class.request.act_idx = aNPC_ACT_SPECIAL; + soncho->npc_class.request.act_type = aNPC_ACT_TYPE_SEARCH; +} + +void aESS_act_init_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + soncho->npc_class.action.step = 0; +} + +void aESS_act_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play, int act_idx) { + static aESS_PROC act_proc[] = { &aESS_act_init_proc, (aESS_PROC)mActor_NONE_PROC1, (aESS_PROC)mActor_NONE_PROC1 }; + act_proc[act_idx](soncho, play); +} + +void aESS_speech_start_wait(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)soncho; + GROUNDHOG_CONTROL_ACTOR* parent = (GROUNDHOG_CONTROL_ACTOR*)actorx->parent_actor; + if (parent != NULL && parent->action == aGHC_ACTION_SONCHO_SPEECH_END_WAIT) { + aESS_setup_think_proc(actorx, 3); + } +} + +void aESS_think_main_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + aGHC_Clip_c* clip; + NPC_ACTOR* actor; + if (soncho->npc_class.action.idx == aNPC_ACT_SPECIAL) { + soncho->_998(soncho, play); + } else if (soncho->npc_class.action.step == 0xff) { + CLIP(npc_clip)->animation_init_proc((ACTOR*)soncho, 0x5, FALSE); + aESS_set_request_act(soncho); + } + clip = CLIP(groundhog_control_clip); + if (clip != NULL && (actor = (NPC_ACTOR*)clip->groundhog_npc_actor) != NULL) { + soncho->npc_class.condition_info.demo_flg = 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; + } else { + soncho->npc_class.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; + } +} + +void aESS_think_init_proc(ACTOR* actorx, GAME_PLAY* play) { + NPC_SPEECH_SONCHO* soncho = (NPC_SPEECH_SONCHO*)actorx; + int next = 0x4; + soncho->npc_class.action.act_proc = (aNPC_ACTION_PROC)aESS_act_proc; + aESS_set_request_act(soncho); + if (Common_Get(time).now_sec < 0x7080) { + next = 0; + if (CLIP(groundhog_control_clip) != NULL && CLIP(groundhog_control_clip)->now_term == 4) { + next = 0x1; + } + } else { + int* common = (int*)mEv_get_common_area(mEv_EVENT_GROUNDHOG_DAY, 0x0); + if (common != NULL && *common == 1) { + next = 2; + } + } + aESS_setup_think_proc((ACTOR*)soncho, next); +} + +void aESS_setup_think_proc(ACTOR* actorx, int think_proc) { + static aESS_think_info dt_tbl[5] = { + { (aESS_PROC)mActor_NONE_PROC1, (aNPC_TALK_REQUEST_PROC)aESS_norm_talk_request, + (aNPC_TALK_END_CHECK_PROC)aESS_norm_talk_end_chk, TRUE }, + { (aESS_PROC)mActor_NONE_PROC1, (aNPC_TALK_REQUEST_PROC)mActor_NONE_PROC1, + (aNPC_TALK_END_CHECK_PROC)mActor_NONE_PROC1, TRUE }, + { aESS_speech_start_wait, (aNPC_TALK_REQUEST_PROC)mActor_NONE_PROC1, + (aNPC_TALK_END_CHECK_PROC)mActor_NONE_PROC1, FALSE }, + { (aESS_PROC)mActor_NONE_PROC1, (aNPC_TALK_REQUEST_PROC)aESS_force_talk_request, + (aNPC_TALK_END_CHECK_PROC)aESS_force_talk_end_chk, TRUE }, + { (aESS_PROC)mActor_NONE_PROC1, (aNPC_TALK_REQUEST_PROC)aESS_norm_talk_request, + (aNPC_TALK_END_CHECK_PROC)aESS_norm_talk_end_chk, TRUE }, + }; + NPC_SPEECH_SONCHO* soncho = (NPC_SPEECH_SONCHO*)actorx; + aESS_think_info* info = &dt_tbl[think_proc]; + soncho->think_proc = think_proc; + soncho->_998 = info->proc; + soncho->npc_class.talk_info.talk_request_proc = info->talk_request_proc; + soncho->npc_class.talk_info.talk_end_check_proc = info->talk_end_check_proc; + soncho->npc_class.head.lock_flag = info->flag; +} + +void aESS_think_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play, int think_id) { + static aESS_THINK_PROC think_proc[] = { (aESS_PROC)aESS_think_init_proc, aESS_think_main_proc }; + think_proc[think_id](soncho, play); +} + +void aESS_schedule_init_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + ACTOR* actorx = (ACTOR*)soncho; + soncho->npc_class.think.think_proc = (aNPC_THINK_PROC)aESS_think_proc; + soncho->npc_class.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; + soncho->npc_class.condition_info.hide_request = FALSE; + soncho->npc_class.palActorIgnoreTimer = -1; + actorx->status_data.weight = 0xfe; + soncho->npc_class.talk_info.turn = aNPC_TALK_TURN_NONE; + actorx->world.position.x -= 20.0f; + + actorx->world.position.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(actorx->world.position, -20.0f); + CLIP(npc_clip)->think_proc((NPC_ACTOR*)soncho, play, 0x9, 0); +} + +void aESS_schedule_main_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + if (CLIP(npc_clip)->think_proc((NPC_ACTOR*)soncho, play, -1, 1) == FALSE) { + CLIP(npc_clip)->think_proc((NPC_ACTOR*)soncho, play, -1, 2); + } +} + +void aESS_schedule_proc(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play, int sche_idx) { + static aESS_SCHEDULE_PROC sche_proc[] = { aESS_schedule_init_proc, aESS_schedule_main_proc }; + sche_proc[sche_idx](soncho, play); +} + +void aESS_set_norm_talk_info(ACTOR* actorx) { + int msg_no; + aGHC_Clip_c* clip = CLIP(groundhog_control_clip); + if (clip != NULL && clip->now_term != 5) { + msg_no = mString_SPEECH_SONCHO_START + 1 + (int)RANDOM_F(5); + } else { + switch (Common_Get(weather)) { + case mEnv_WEATHER_CLEAR: + msg_no = mString_SPEECH_SONCHO_START + 6 + (int)RANDOM_F(5); + break; + case mEnv_WEATHER_SNOW: + msg_no = mString_SPEECH_SONCHO_START + 11 + (int)RANDOM_F(5); + break; + default: + msg_no = mString_SPEECH_SONCHO_START + 6; + break; + } + } + mDemo_Set_msg_num(msg_no); +} + +void aESS_norm_talk_request(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + mDemo_Request(mDemo_TYPE_TALK, (ACTOR*)soncho, aESS_set_norm_talk_info); +} + +void aESS_set_force_talk_info() { + mDemo_Set_msg_num(mString_SPEECH_SONCHO_START); + mDemo_Set_camera(CAMERA2_PROCESS_NUM); +} + +void aESS_force_talk_request(NPC_SPEECH_SONCHO* soncho, GAME_PLAY* play) { + mDemo_Request(0xa, (ACTOR*)soncho, aESS_set_force_talk_info); +} + +int aESS_talk_init(ACTOR* actorx, GAME* game) { + NPC_SPEECH_SONCHO* soncho = (NPC_SPEECH_SONCHO*)actorx; + soncho->npc_class.talk_info.talk_request_proc = mActor_NONE_PROC1; + mDemo_Set_ListenAble(); + return TRUE; +} + +int aESS_norm_talk_end_chk(NPC_SPEECH_SONCHO* soncho) { + ACTOR* actorx = (ACTOR*)soncho; + int res = 0; + if (mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)soncho) == FALSE) { + int think_proc = 4; + if (CLIP(groundhog_control_clip) != NULL) { + switch (CLIP(groundhog_control_clip)->now_term) { + case 4: + think_proc = 0x1; + break; + case 5: + break; + default: + think_proc = 0; + break; + } + } + aESS_setup_think_proc(actorx, think_proc); + res = TRUE; + } + return res; +} + +int aESS_force_talk_end_chk(NPC_SPEECH_SONCHO* soncho) { + ACTOR* actorx = (ACTOR*)soncho; + int res = FALSE; + if (mDemo_Check(mDemo_TYPE_SPEECH, actorx) == FALSE) { + GROUNDHOG_CONTROL_ACTOR* parent = (GROUNDHOG_CONTROL_ACTOR*)actorx->parent_actor; + if (parent != NULL) { + parent->event_state = aGHC_EVENT_STATE_SONCHO_DONE; + aESS_setup_think_proc(actorx, 0x4); + res = TRUE; + } + } + return res; +}