diff --git a/configure.py b/configure.py index 8d54384d..95858b0b 100644 --- a/configure.py +++ b/configure.py @@ -1135,7 +1135,7 @@ config.libs = [ Object(NonMatching, "actor/npc/ac_npc_soncho.c"), Object(NonMatching, "actor/npc/ac_npc_station_master.c"), Object(Matching, "actor/npc/ac_npc_super_master.c"), - Object(NonMatching, "actor/npc/ac_npc_totakeke.c"), + Object(Matching, "actor/npc/ac_npc_totakeke.c"), Object(NonMatching, "actor/npc/ac_present_npc.c"), Object(NonMatching, "actor/npc/ac_taisou_npc0.c"), Object(NonMatching, "actor/npc/ac_tamaire_npc0.c"), diff --git a/include/ac_npc_totakeke.h b/include/ac_npc_totakeke.h index c98d5dfe..efb8ab58 100644 --- a/include/ac_npc_totakeke.h +++ b/include/ac_npc_totakeke.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "ac_npc.h" #ifdef __cplusplus extern "C" { @@ -10,9 +11,134 @@ extern "C" { extern ACTOR_PROFILE Npc_Totakeke_Profile; +#define aNTT_REQUEST_STR_LEN 10 + +typedef struct npc_totakeke_s NPC_TOTAKEKE_ACTOR; +typedef struct npc_totakeke_clip_s aNTT_Clip_c; +typedef struct npc_totakeke_think_data_s aNTT_think_data_c; +typedef struct npc_totakeke_event_save_s aNTT_event_save_c; +typedef struct npc_totakeke_event_common_s aNTT_event_common_c; + +typedef void (*aNTTrequest_str_PROC)(GAME*, s16, u8); +typedef void (*aNTT_08_PROC)(NPC_TOTAKEKE_ACTOR*, GAME_PLAY*, u8); +typedef void (*aNTT_0C_PROC)(NPC_TOTAKEKE_ACTOR*, GAME_PLAY*, int); +typedef int (*aNTT_10_PROC)(int); +typedef u8 (*aNTT_14_PROC)(NPC_TOTAKEKE_ACTOR*); +typedef void (*aNTT_1C_PROC)(NPC_TOTAKEKE_ACTOR*); +typedef void (*aNTT_20_PROC)(int, u8); +typedef void (*aNTT_24_PROC)(); +typedef u8 (*aNTT_PICK_SONG_PROC)(); +typedef void (*aNTT_2C_PROC)(int); + +typedef void (*aNTT_PROC)(NPC_TOTAKEKE_ACTOR* totakeke, GAME_PLAY* play); + +struct npc_totakeke_s { + /* 0x000 */ NPC_ACTOR npc_class; + /* 0x994 */ aNTT_PROC proc; + /* 0x998 */ s16 roll2_count; + /* 0x99a */ s16 roll4_count; + /* 0x99c */ u16 _99c; + /* 0x99e */ u8 song; + /* 0x99f */ u8 _99f; + /* 0x9a0 */ u8 _9a0; + /* 0x9a1 */ u8 _9a1; + /* 0x9a2 */ u8 _9a2; + /* 0x9a3 */ u8 talk; + /* 0x9a4 */ u8 think; + /* 0x9a5 */ u8 pre_roll_think; + /* 0x9a6 */ u8 post_roll_think; + /* 0x9a7 */ u8 melody_inst; + /* 0x9a8 */ u8 think_proc_id; + /* 0x9a9 */ u8 _9a9; + /* 0x9ac */ u8 _9aa; + /* 0x9ac */ u8 _9ab; +}; + +struct npc_totakeke_clip_s { + /* 0x000 */ int _00; + /* 0x004 */ aNTTrequest_str_PROC _04; + /* 0x008 */ aNTT_08_PROC _08; + /* 0x00c */ aNTT_0C_PROC _0C; + /* 0x010 */ aNTT_10_PROC _10; + /* 0x014 */ aNTT_14_PROC _14; + /* 0x018 */ aNTT_PROC _18; + /* 0x01c */ aNTT_1C_PROC _1c; + /* 0x020 */ aNTT_20_PROC _20; + /* 0x024 */ aNTT_24_PROC _24; + /* 0x028 */ aNTT_PICK_SONG_PROC pick_song; + /* 0x02c */ aNTT_2C_PROC _2c; +}; + +struct npc_totakeke_think_data_s { + /* 0x00 */ u8 think_proc_id; + /* 0x01 */ u8 _01; + /* 0x02 */ u8 next_talk; + /* 0x03 */ u8 talk; + /* 0x04 */ u8 pre_roll_think; +}; + +#define aNTT_FLAG_0 1 +#define aNTT_FLAG_AIRCHECK_RECEIVED 1 << 4 + +struct npc_totakeke_event_save_s { + /* 0x00 */ u8 _00; + /* 0x01 */ u8 _01; + /* 0x01 */ u16 bitfield; + /* 0x04 */ u8 request_str[aNTT_REQUEST_STR_LEN]; + /* 0x0e */ u8 _0e; + /* 0x0f */ u8 _0f; + /* 0x10 */ u8 _10; + /* 0x11 */ u8 _11; + /* 0x12 */ u8 _12; + /* 0x13 */ u8 _13; + /* 0x14 */ u8 _14; + /* 0x15 */ u8 _15; +}; + +struct npc_totakeke_event_common_s { + /* 0x00 */ u16 foreigner_bitfield; + /* 0x02 */ u16 _02; + /* 0x04 */ u8 request_str; + /* 0x05 */ u16 _05; + /* 0x07 */ u8 _07; + /* 0x08 */ u8 _08; + /* 0x09 */ u8 _09; + /* 0x0a */ u8 _0a; + /* 0x0b */ u8 _0b; + /* 0x0c */ u8 _0c; + /* 0x0d */ u8 _0d; + /* 0x0e */ u8 _0e; + /* 0x0f */ u8 _0f; +}; + +enum aNTT_talk_proc { + aNTT_TALK_NONE, + aNTT_TALK_SELECT0, + aNTT_TALK_SELECT1, + aNTT_TALK_STOP_PLAYER, + aNTT_TALK_SUBMENU, + aNTT_TALK_SUBMENU2, + aNTT_TALK_GIVE +}; + +enum aNTT_think_proc { + aNTT_THINK_NONE, + aNTT_THINK_WAIT, + aNTT_THINK_ROLL, + aNTT_THINK_ROLL1, + aNTT_THINK_ROLL2, + aNTT_THINK_ROLL4, + aNTT_THINK_ROLL_END, + aNTT_THINK_7, + aNTT_THINK_8, + aNTT_THINK_9, + aNTT_THINK_GIVE_MERODY, + aNTT_THINK_POCKETS_FULL, + aNTT_THINK_GIVE_LATER, +}; + #ifdef __cplusplus } #endif #endif - diff --git a/include/m_clip.h b/include/m_clip.h index 9719e9e8..fd2e1a08 100644 --- a/include/m_clip.h +++ b/include/m_clip.h @@ -34,6 +34,7 @@ #include "ac_turi_clip.h" #include "ac_hatumode_control.h" #include "ac_station_clip.h" +#include "ac_npc_totakeke.h" #ifdef __cplusplus extern "C" { @@ -90,7 +91,7 @@ typedef struct clip_s { /* 0x0CC */ void* _0CC; /* 0x0D0 */ void* _0D0; /* 0x0D4 */ CLIP_NONE_PROC ball_redma_proc; /* removed in DnM+ */ - /* 0x0D8 */ void* _0D8; + /* 0x0D8 */ aNTT_Clip_c* totakeke_clip; /* 0x0DC */ aAL_Clip_c* animal_logo_clip; /* 0x0E0 */ aSTC_clip_c* station_clip; /* 0x0E4 */ aTRC_clip_c* turi_clip; diff --git a/include/m_string_data.h b/include/m_string_data.h index 0d798461..049bf28c 100644 --- a/include/m_string_data.h +++ b/include/m_string_data.h @@ -19,6 +19,9 @@ extern "C" { #define mString_HANIWA_MSG2 0x76C #define mString_HANIWA_MSG3 0x76D #define mString_CARPETPEDDLER_START 0x48a +#define mString_TOTAKEKE_START 0x1b93 + +>>>>>>> 69b951b (Implement & link ac_npc_totakeke.c) #ifdef __cplusplus } diff --git a/src/actor/npc/ac_npc_totakeke.c b/src/actor/npc/ac_npc_totakeke.c new file mode 100644 index 00000000..a80f7faa --- /dev/null +++ b/src/actor/npc/ac_npc_totakeke.c @@ -0,0 +1,140 @@ +#include "ac_npc_totakeke.h" + +#include "m_event.h" +#include "m_common_data.h" +#include "m_npc.h" +#include "m_msg.h" +#include "m_choice.h" +#include "m_bgm.h" +#include "m_player_lib.h" +#include "m_string_data.h" + +void aNTT_schedule_proc(); +int aNTT_change_talk_proc(NPC_TOTAKEKE_ACTOR*, int); +void aNTT_setup_think_proc(NPC_TOTAKEKE_ACTOR*, GAME_PLAY*, u8); +int aNTT_enso_init(NPC_TOTAKEKE_ACTOR*); +void aNTT_actor_ct(ACTOR* actorx, GAME* game); +void aNTT_actor_dt(ACTOR* actorx, GAME* game); +void aNTT_actor_init(ACTOR* actorx, GAME* game); +void aNTT_actor_save(ACTOR* actorx, GAME* game); +void aNTT_actor_move(ACTOR* actorx, GAME* game); +void aNTT_actor_draw(ACTOR* actorx, GAME* game); +int aNTT_talk_init(ACTOR* actorx, GAME* game); +int aNTT_talk_end_chk(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Npc_Totakeke_Profile = { + mAc_PROFILE_NPC_TOTAKEKE, + ACTOR_PART_NPC, + ACTOR_STATE_NONE, + SP_NPC_TOTAKEKE, + ACTOR_OBJ_BANK_KEEP, + sizeof(NPC_TOTAKEKE_ACTOR), + &aNTT_actor_ct, + &aNTT_actor_dt, + &aNTT_actor_init, + (mActor_proc)none_proc1, + &aNTT_actor_save, +}; + +void aNTT_actor_ct(ACTOR *actorx, GAME *game) { + static aNPC_ct_data_c ct_data = { + &aNTT_actor_move, + &aNTT_actor_draw, + 0x5, + (mActor_proc)none_proc1, + &aNTT_talk_init, + &aNTT_talk_end_chk, + 0x0 + }; + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + aNTT_event_common_c *common = (aNTT_event_common_c *)mEv_get_common_area(mEv_EVENT_KK_SLIDER, 0x10); + if (Common_Get(reset_flag) == TRUE) { + Actor_delete(actorx); + actorx->sv_proc = 0; + actorx->dt_proc = 0; + mNpc_RenewalSetNpc(actorx); + mEv_actor_dying_message(mEv_EVENT_KK_SLIDER, actorx); + } else if (CLIP(npc_clip)->birth_check_proc(actorx, game) == TRUE) { + xyz_t wpos; + + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + totakeke->npc_class.schedule.schedule_proc = aNTT_schedule_proc; + CLIP(npc_clip)->ct_proc(actorx, game, &ct_data); + totakeke->npc_class.palActorIgnoreTimer = -1; + totakeke->npc_class.condition_info.hide_flg = FALSE; + totakeke->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; + totakeke->npc_class.talk_info.default_animation = aNPC_ANIM_WAIT_E1; + totakeke->npc_class.talk_info.default_act = aNPC_ACT_TALK2; + totakeke->npc_class.talk_info.turn = 2; + + aNTT_enso_init(totakeke); + totakeke->_9a1 = FALSE; + + if (save == NULL) { + save = (aNTT_event_save_c *)mEv_reserve_save_area(mEv_EVENT_KK_SLIDER, 0xa); + save->bitfield = 0; + } + + save->bitfield = save->bitfield & 0x3fff; + + { + int i; + for (i = 0; i < aNTT_REQUEST_STR_LEN; i++) { + save->request_str[i] = 0; + } + } + + save->_14 = 0; + save->_15 = 0; + + if (common == NULL) { + common = (aNTT_event_common_c *)mEv_reserve_common_area(mEv_EVENT_KK_SLIDER, 0x10); + common->foreigner_bitfield = 0; + } + totakeke->npc_class.collision.pipe.attribute.pipe.radius = 0x1e; + totakeke->melody_inst = 0; + totakeke->_9a9 = 0; + totakeke->_99f = 0xff; + mCoBG_SetPlussOffset(actorx->world.position, 0x3, 0x64); + } +} + +void aNTT_actor_save(ACTOR *actorx, GAME *game) { + mNpc_RenewalSetNpc(actorx); +} + +void aNTT_actor_dt(ACTOR *actorx, GAME *game) { + mEv_actor_dying_message(mEv_EVENT_KK_SLIDER, actorx); + CLIP(npc_clip)->dt_proc(actorx, game); + mCoBG_SetPlussOffset(actorx->world.position, 0x0, 0x64); +} + +void aNTT_actor_init(ACTOR *actorx, GAME *game) { + CLIP(npc_clip)->init_proc(actorx, game); +} + +void aNTT_actor_move(ACTOR *actorx, GAME *game) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + CLIP(npc_clip)->move_proc(actorx, game); + if (totakeke->npc_class.draw.animation_id == aNPC_ANIM_ENSOU_E1) { + totakeke->npc_class.draw.main_animation.keyframe.frame_control.mode = 1; + } +} + +void aNTT_actor_draw(ACTOR *actorx, GAME *game) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + CLIP(npc_clip)->draw_proc(actorx, game); + if (save == NULL || (save->bitfield & 0x4000) == 0 || CLIP(totakeke_clip) == NULL) { + return; + } + CLIP(totakeke_clip)->_04(game, totakeke->roll2_count, totakeke->_9a2); +} + +#include "../src/actor/npc/ac_npc_totakeke_talk.c_inc" +#include "../src/actor/npc/ac_npc_totakeke_think.c_inc" diff --git a/src/actor/npc/ac_npc_totakeke_talk.c_inc b/src/actor/npc/ac_npc_totakeke_talk.c_inc new file mode 100644 index 00000000..17829abc --- /dev/null +++ b/src/actor/npc/ac_npc_totakeke_talk.c_inc @@ -0,0 +1,259 @@ +u16 aNTT_bitset_func(u16 field, int flag) { + u32 player_no = Common_Get(player_no); + aNTT_event_common_c *common = (aNTT_event_common_c *)mEv_get_common_area(mEv_EVENT_KK_SLIDER, 0x10); + if (player_no == mPr_FOREIGNER) { + common->foreigner_bitfield |= flag; + } else { + field |= ((u16)flag << player_no); + } + return field; +} + +int aNTT_bitcheck_func(int field, u16 flag) { + u16 player_no = Common_Get(player_no); + aNTT_event_common_c *common = (aNTT_event_common_c *)mEv_get_common_area(mEv_EVENT_KK_SLIDER, 0x10); + if (player_no == mPr_FOREIGNER) { + return common->foreigner_bitfield & flag; + } else { + return (u16)field & (flag << player_no); + } +} + +int aNTT_enso_init(NPC_TOTAKEKE_ACTOR *totakeke) { + totakeke->npc_class.request.act_priority = 0x4; + totakeke->npc_class.request.act_idx = 0xd; + totakeke->npc_class.request.act_type = 0x0; +} + +void aTTN_give_merody(NPC_TOTAKEKE_ACTOR *totakeke) { + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + + if (mPr_GetPossessionItemSumWithCond(Now_Private, EMPTY_NO, mPr_ITEM_COND_NORMAL) == 0) { + totakeke->post_roll_think = aNTT_THINK_POCKETS_FULL; + } else { + totakeke->post_roll_think = aNTT_THINK_GIVE_MERODY; + mPr_SetFreePossessionItem(Now_Private, ITM_MINIDISK_START + totakeke->song, mPr_ITEM_COND_NORMAL); + save->bitfield = aNTT_bitset_func(save->bitfield, aNTT_FLAG_AIRCHECK_RECEIVED); + CLIP(totakeke_clip)->_2c(totakeke->song); + } +} + +void aNTT_talk_select0(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + int value = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 0x9); + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + if (value == 0x1 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) { + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 0x9, 0x0); + save->bitfield = aNTT_bitset_func(save->bitfield, aNTT_FLAG_0); + switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) { + case mChoice_CHOICE0: + if (aNTT_bitcheck_func(save->bitfield, aNTT_FLAG_AIRCHECK_RECEIVED)) { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), mString_TOTAKEKE_START + 4); + aNTT_change_talk_proc(totakeke, aNTT_TALK_NONE); + } else { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), mString_TOTAKEKE_START + 5); + aNTT_change_talk_proc(totakeke, aNTT_TALK_SELECT1); + } + break; + case mChoice_CHOICE1: + aNTT_change_talk_proc(totakeke, aNTT_TALK_NONE); + break; + } + } +} + +void aNTT_talk_select1(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + int value = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 0x9); + if (value == 0x2 && mMsg_Check_MainNormalContinue(mMsg_Get_base_window_p()) == TRUE) { + int count; + mDemo_Set_OrderValue(mDemo_ORDER_NPC0, 0x9, 0x0); + switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) { + case mChoice_CHOICE1: + mMsg_request_main_disappear_wait_type1(mMsg_Get_base_window_p()); + aNTT_change_talk_proc(totakeke, aNTT_TALK_SUBMENU); + break; + case mChoice_CHOICE0: + totakeke->song = CLIP(totakeke_clip)->pick_song(); + for (count = 0; count < 3 && totakeke->song == totakeke->_99f; count++) { + totakeke->song = CLIP(totakeke_clip)->pick_song(); + } + totakeke->_99f = totakeke->song; + CLIP(totakeke_clip)->_20(0x1, totakeke->song); + CLIP(totakeke_clip)->_20(0x2, totakeke->song); + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), mString_TOTAKEKE_START + 10); + aNTT_change_talk_proc(totakeke, aNTT_TALK_STOP_PLAYER); + totakeke->pre_roll_think = aNTT_THINK_ROLL2; + aTTN_give_merody(totakeke); + break; + } + } +} + +void aNTT_talk_stop_player(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + ACTOR *actorx = (ACTOR *)totakeke; + GAME *game = (GAME *)play; + if (mMsg_Check_MainDisappear(mMsg_Get_base_window_p()) && totakeke->_9ab == FALSE) { + aWeather_Clip_c *clip = CLIP(weather_clip); + if (clip != NULL) { + clip->stop_sound(); + } + mBGMPsComp_scene_mode(0x5); + totakeke->_9ab = TRUE; + } + if (mDemo_Check(mDemo_TYPE_TALK, actorx) == 0 && mDemo_Check(mDemo_TYPE_SPEAK, actorx) == 0x0) { + if (mPlib_get_player_actor_main_index(game) != 0x4a) { + mPlib_request_main_demo_wait_type1(game, 0x0, 0x0); + } else { + aNTT_change_talk_proc(totakeke, aNTT_TALK_NONE); + } + } +} + +void aNTT_talk_submenu(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + Submenu *submenu = &play->submenu; + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + if (mMsg_Check_main_wait(mMsg_Get_base_window_p()) == TRUE) { + aNTT_change_talk_proc(totakeke, aNTT_TALK_SUBMENU2); + mSM_open_submenu_new(submenu, mSM_OVL_LEDIT, 0x4, 0x0, save->request_str); + mMsg_request_main_appear_wait_type1(mMsg_Get_base_window_p()); + } +} + +void aNTT_talk_submenu2(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + if (play->submenu.open_flag == FALSE && mMsg_Check_not_series_main_wait(mMsg_Get_base_window_p()) == TRUE) { + Submenu_Item_c *submenu_item = play->submenu.item_p; + CLIP(totakeke_clip)->_24(); + mMsg_Set_ForceNext(mMsg_Get_base_window_p()); + if (submenu_item->item == ITM_MINIDISK_END) { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), mString_TOTAKEKE_START + 6); + totakeke->post_roll_think = 0xc; + totakeke->song = 0x37 + (int)RANDOM_F(3); + } else { + totakeke->song = submenu_item->item - ITM_MINIDISK_START; + if (totakeke->song >= 0x34) { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), mString_TOTAKEKE_START + 8); + } else { + mMsg_Set_continue_msg_num(mMsg_Get_base_window_p(), mString_TOTAKEKE_START + 9); + } + CLIP(totakeke_clip)->_20(0x2, totakeke->song); + aTTN_give_merody(totakeke); + } + aNTT_change_talk_proc(totakeke, aNTT_TALK_STOP_PLAYER); + totakeke->pre_roll_think = aNTT_THINK_ROLL2; + } +} + +void aNTT_talk_give(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + int value = mDemo_Get_OrderValue(mDemo_ORDER_NPC0, 0x1); + if (value == 0x2) { + mDemo_Set_OrderValue(0x5, 0x0, ITM_MINIDISK_START + totakeke->song); + mDemo_Set_OrderValue(0x5, 0x1, 0x7); + mDemo_Set_OrderValue(0x5, 0x2, 0x0); + aNTT_change_talk_proc(totakeke, aNTT_TALK_NONE); + } +} + +int aNTT_change_talk_proc(NPC_TOTAKEKE_ACTOR *totakeke, int talk) { + static aNTT_PROC proc[7] = { + (aNTT_PROC)none_proc1, + aNTT_talk_select0, + aNTT_talk_select1, + aNTT_talk_stop_player, + aNTT_talk_submenu, + aNTT_talk_submenu2, + aNTT_talk_give + }; + totakeke->proc = proc[talk]; + if (talk == aNTT_TALK_STOP_PLAYER) { + mEv_SetTitleDemo(-0x9); + mDemo_Set_talk_return_demo_wait(0x1); + totakeke->_9ab = FALSE; + } + return TRUE; +} + +void aNTT_set_force_talk_info(ACTOR *actorx) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + static u8 msg[3] = {0xc, 0xb, 0x7}; + mDemo_Set_msg_num(mString_TOTAKEKE_START + msg[totakeke->talk]); + mDemo_Set_talk_turn(TRUE); + mDemo_Set_camera(TRUE); + if (totakeke->talk == 0) { + totakeke->proc = aNTT_talk_give; + } else { + totakeke->proc = (void *)none_proc1; + } + if (totakeke->npc_class.talk_info.melody_inst) { + totakeke->melody_inst = totakeke->npc_class.talk_info.melody_inst; + } + totakeke->npc_class.talk_info.melody_inst = 0; +} + +void aNTT_force_talk_request(ACTOR *actorx, GAME *game) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + if (totakeke->_9a1 == FALSE) { + mDemo_Request(0x8, (ACTOR *)totakeke, aNTT_set_force_talk_info); + } else { + totakeke->_9a1 = FALSE; + } +} + +void aNTT_set_norm_talk_info(ACTOR *actorx) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + static u8 msg[4] = {0x0, 0x1, 0x2, 0xd}; + mDemo_Set_msg_num(mString_TOTAKEKE_START + msg[totakeke->talk]); + mDemo_Set_talk_turn(TRUE); + mDemo_Set_camera(TRUE); + switch (totakeke->talk) { + case 0: + totakeke->proc = (void *)none_proc1; + break; + case 3: + Now_Private->state_flags |= mPr_FLAG_TOTAKEKE_INTRODUCTION; + totakeke->proc = aNTT_talk_select0; + break; + default: + totakeke->proc = aNTT_talk_select0; + break; + } +} + +void aNTT_norm_talk_request(ACTOR *actorx, GAME *game) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + if (totakeke->_9a1 == FALSE) { + mDemo_Request(0x7, (ACTOR *)totakeke, aNTT_set_norm_talk_info); + } else { + totakeke->_9a1 = FALSE; + } +} + +int aNTT_talk_init(ACTOR *actorx, GAME *game) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + totakeke->npc_class.talk_info.talk_request_proc = (void *)none_proc1; + mDemo_Set_ListenAble(); + mDemo_Start(actorx); + switch (totakeke->think) { + case aNTT_THINK_GIVE_MERODY: + case aNTT_THINK_POCKETS_FULL: + case aNTT_THINK_GIVE_LATER: + mEv_SetTitleDemo(0); + break; + } + return TRUE; +} + +int aNTT_talk_end_chk(ACTOR *actorx, GAME *game) { + NPC_TOTAKEKE_ACTOR *totakeke = (NPC_TOTAKEKE_ACTOR *)actorx; + GAME_PLAY *play = (GAME_PLAY *)game; + int res = FALSE; + totakeke->proc(totakeke, play); + if (mDemo_Check(mDemo_TYPE_SPEAK, actorx) == FALSE && mDemo_Check(mDemo_TYPE_TALK, actorx) == FALSE) { + aNTT_setup_think_proc(totakeke, play, totakeke->pre_roll_think); + res = TRUE; + aNTT_enso_init(totakeke); + if (totakeke->melody_inst != 0) { + totakeke->npc_class.talk_info.melody_inst = totakeke->melody_inst; + totakeke->melody_inst = 0; + } + } + return res; +} diff --git a/src/actor/npc/ac_npc_totakeke_think.c_inc b/src/actor/npc/ac_npc_totakeke_think.c_inc new file mode 100644 index 00000000..2d865092 --- /dev/null +++ b/src/actor/npc/ac_npc_totakeke_think.c_inc @@ -0,0 +1,209 @@ +void aNTT_wait(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + ACTOR *actorx = (ACTOR *)totakeke; + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + if (ABS(actorx->player_angle_y) > 4000) { + if (totakeke->think != aNTT_THINK_NONE) { + aNTT_setup_think_proc(totakeke, play, 0x0); + } + } else if ((Now_Private->state_flags & mPr_FLAG_TOTAKEKE_INTRODUCTION) == 0) { + if (totakeke->think != aNTT_THINK_ROLL1) { + aNTT_setup_think_proc(totakeke, play, 0x3); + } + } else if (aNTT_bitcheck_func(save->bitfield, aNTT_FLAG_0) == 0) { + if (totakeke->think != aNTT_THINK_WAIT) { + aNTT_setup_think_proc(totakeke, play, 0x1); + } + } else if (totakeke->think != aNTT_THINK_ROLL) { + aNTT_setup_think_proc(totakeke, play, 0x2); + } +} + +void aNTT_roll(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + staffroll_light_proc_start(play); + if (totakeke->roll2_count > 0) { + totakeke->roll2_count -= 1; + } else { + aNTT_setup_think_proc(totakeke, play, ++totakeke->think); + } + CLIP(totakeke_clip)->_18(totakeke, play); +} + +void aNTT_roll1(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + u8 bgm = CLIP(totakeke_clip)->_14(totakeke); + if (bgm == mBGMPsComp_execute_bgm_num_get()) { + if (CLIP(totakeke_clip) != NULL) { + CLIP(totakeke_clip)->_0C(totakeke, play, 0); + if (CLIP(totakeke_clip)->_10(0x2)) { + aNTT_setup_think_proc(totakeke, play, ++totakeke->think); + } + } + CLIP(totakeke_clip)->_18(totakeke, play); + } +} + +void aNTT_roll2(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + aWeather_Clip_c *weather; + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + if (CLIP(totakeke_clip) != NULL) { + CLIP(totakeke_clip)->_0C(totakeke, play, 0x0); + } + staffroll_light_proc_start(play); + totakeke->roll2_count += 1; + totakeke->roll4_count += 1; + CLIP(totakeke_clip)->_18(totakeke, play); + weather = CLIP(weather_clip); + if (weather != NULL) { + if (totakeke->roll4_count == 0x15e0) { + weather->change_weather(weather->actor, mEnv_WEATHER_SAKURA, mEnv_WEATHER_INTENSITY_HEAVY); + } else if (totakeke->roll4_count == 0x51e) { + weather->change_weather(weather->actor, mEnv_WEATHER_RAIN, mEnv_WEATHER_INTENSITY_HEAVY); + } else if (totakeke->roll4_count == 0x992) { + weather->change_weather(weather->actor, mEnv_WEATHER_LEAVES, mEnv_WEATHER_INTENSITY_HEAVY); + } else if (totakeke->roll4_count == 0xf46) { + weather->change_weather(weather->actor, mEnv_WEATHER_SNOW, mEnv_WEATHER_INTENSITY_HEAVY); + } else if (totakeke->roll4_count == 0x74e) { + weather->change_weather(weather->actor, mEnv_WEATHER_RAIN, mEnv_WEATHER_INTENSITY_NONE); + } else if (totakeke->roll4_count == 0xb9a) { + weather->change_weather(weather->actor, mEnv_WEATHER_LEAVES, mEnv_WEATHER_INTENSITY_NONE); + } else if (totakeke->roll4_count == 0x12c0) { + weather->change_weather(weather->actor, mEnv_WEATHER_SNOW, mEnv_WEATHER_INTENSITY_NONE); + } else if (totakeke->roll4_count == 0x18ce) { + weather->change_weather(weather->actor, mEnv_WEATHER_SAKURA, mEnv_WEATHER_INTENSITY_NONE); + } + } + if (totakeke->roll2_count > 0x1be) { + totakeke->_9a2 += 1; + if (totakeke->_9a2 >= 0x10) { + aNTT_setup_think_proc(totakeke, play, 0x8); + save->bitfield |= 0x8000; + save->bitfield &= ~(0x4000); + } else { + aNTT_setup_think_proc(totakeke, play, 0x7); + } + } +} + +void aNTT_roll4(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + aNTT_event_save_c *save = (aNTT_event_save_c *)mEv_get_save_area(mEv_EVENT_KK_SLIDER, 0xa); + totakeke->roll4_count += 1; + CLIP(totakeke_clip)->_18(totakeke, play); + if (totakeke->roll4_count >= 0x1d88 || totakeke->roll4_count <= 0x1c70) { + save->_15 = 0; + } else if (totakeke->roll4_count > 0x1d38) { + save->_15 = 3.1875f * (0x1d88 - totakeke->roll4_count); + } else if (totakeke->roll4_count < 0x1cc0) { + save->_15 = 3.1875f * (totakeke->roll4_count - 0x1c70); + } else { + save->_15 = 0xff; + } + + if (CLIP(totakeke_clip) != NULL) { + CLIP(totakeke_clip)->_0C(totakeke, play, 0); + if (CLIP(totakeke_clip)->_10(0x4) && totakeke->roll4_count > 0x1d88) { + save->_15 = 0; + aNTT_setup_think_proc(totakeke, play, 0x9); + } + } +} + +void aNTT_roll_end(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + totakeke->npc_class.draw.main_animation.keyframe.frame_control.current_frame = totakeke->_9a0; + if (totakeke->_9aa != 0) { + CLIP(totakeke_clip)->_1c(totakeke); + } + if (staffroll_light_proc_end(play)) { + aNTT_setup_think_proc(totakeke, play, totakeke->post_roll_think); + totakeke->npc_class.condition_info.demo_flg = FALSE; + } +} + +static aNTT_PROC proc_table[7] = { + (aNTT_PROC)none_proc1, + aNTT_wait, + aNTT_roll, + aNTT_roll1, + aNTT_roll2, + aNTT_roll4, + aNTT_roll_end +}; + +void aNTT_think_main_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + proc_table[totakeke->think_proc_id](totakeke, play); +} + +void aNTT_think_init_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + totakeke->npc_class.actor_class.status_data.weight = 0xff; + totakeke->npc_class.condition_info.hide_request = FALSE; + aNTT_setup_think_proc(totakeke, play, 0); +} + +static aNTT_think_data_c dt_tbl[13] = { + {aNTT_THINK_WAIT, 0, 1, aNTT_TALK_NONE, aNTT_THINK_NONE}, + {aNTT_THINK_WAIT, 0, 1, aNTT_TALK_SELECT0, aNTT_THINK_WAIT}, + {aNTT_THINK_WAIT, 0, 1, aNTT_TALK_SELECT1, aNTT_THINK_ROLL}, + {aNTT_THINK_WAIT, 0, 1, aNTT_TALK_STOP_PLAYER, aNTT_THINK_ROLL1}, + {aNTT_THINK_ROLL, 1, 0, aNTT_TALK_NONE, aNTT_THINK_ROLL2}, + {aNTT_THINK_ROLL1, 2, 0, aNTT_TALK_NONE, aNTT_THINK_ROLL4}, + {aNTT_THINK_ROLL2, 3, 0, aNTT_TALK_NONE, aNTT_THINK_ROLL_END}, + {aNTT_THINK_ROLL2, 4, 0, aNTT_TALK_NONE, aNTT_THINK_7}, + {aNTT_THINK_ROLL4, 0, 0, aNTT_TALK_NONE, aNTT_THINK_8}, + {aNTT_THINK_ROLL_END, 5, 0, aNTT_TALK_NONE, aNTT_THINK_9}, + {aNTT_THINK_NONE, 6, 2, aNTT_TALK_NONE, aNTT_THINK_NONE}, + {aNTT_THINK_NONE, 6, 2, aNTT_TALK_SELECT0, aNTT_THINK_NONE}, + {aNTT_THINK_NONE, 6, 2, aNTT_TALK_SELECT1, aNTT_THINK_NONE} +}; + +void aNTT_setup_think_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play, u8 think_id) { + static aNPC_TALK_REQUEST_PROC talk_request_table[3] = { + (aNPC_TALK_REQUEST_PROC)none_proc1, + aNTT_norm_talk_request, + aNTT_force_talk_request + }; + aNTT_think_data_c *think = &dt_tbl[think_id]; + if (totakeke->think != think_id) { + totakeke->_9a1 = TRUE; + } + totakeke->think = think_id; + totakeke->think_proc_id = think->think_proc_id; + totakeke->npc_class.talk_info.talk_request_proc = talk_request_table[think->next_talk]; + totakeke->talk = think->talk; + totakeke->pre_roll_think = think->pre_roll_think; + + if (CLIP(totakeke_clip) != NULL) { + CLIP(totakeke_clip)->_08(totakeke, play, think->_01); + } +} + +void aNTT_think_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play, int think_id) { + switch (think_id) { + case 0x0: + aNTT_think_init_proc(totakeke, play); + break; + case 0x1: + aNTT_think_main_proc(totakeke, play); + break; + } +} + +void aNTT_schedule_init_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + totakeke->npc_class.think.think_proc = (aNPC_THINK_PROC)aNTT_think_proc; + CLIP(npc_clip)->think_proc((NPC_ACTOR *)totakeke, play, aNPC_THINK_SPECIAL, 0); +} + +void aNTT_schedule_main_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play) { + if (CLIP(npc_clip)->think_proc((NPC_ACTOR *)totakeke, play, -1, 1) == FALSE) { + CLIP(npc_clip)->think_proc((NPC_ACTOR *)totakeke, play, -1, 2); + } +} + +void aNTT_schedule_proc(NPC_TOTAKEKE_ACTOR *totakeke, GAME_PLAY *play, int schedule_id) { + switch (schedule_id) { + case 0: + aNTT_schedule_init_proc(totakeke, play); + break; + case 1: + aNTT_schedule_main_proc(totakeke, play); + break; + } +} +