diff --git a/configure.py b/configure.py index 469d9363..38b7cb5a 100644 --- a/configure.py +++ b/configure.py @@ -1100,7 +1100,7 @@ config.libs = [ Object(NonMatching, "actor/npc/ac_kamakura_npc0.c"), Object(NonMatching, "actor/npc/ac_normal_npc.c"), Object(Matching, "actor/npc/ac_npc.c"), - Object(NonMatching, "actor/npc/ac_npc2.c"), + Object(Matching, "actor/npc/ac_npc2.c"), Object(Matching, "actor/npc/ac_npc_conv_master.c"), Object(Matching, "actor/npc/ac_npc_curator.c"), Object(Matching, "actor/npc/ac_npc_depart_master.c"), diff --git a/include/ac_npc.h b/include/ac_npc.h index 922ba313..f0066e67 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -155,6 +155,7 @@ enum { aNPC_ATTENTION_TYPE_NUM }; +#ifndef aNPC_NPC2 enum { aNPC_THINK_WAIT, aNPC_THINK_WANDER, @@ -169,6 +170,19 @@ enum { aNPC_THINK_NUM }; +#else +enum { + aNPC_THINK_WAIT, + aNPC_THINK_HIDE, + aNPC_THINK_WANDER, + aNPC_THINK_OUT_OF_ROOM, + aNPC_THINK_EXIT_WAIT, + aNPC_THINK_INTO_ROOM, + aNPC_THINK_SPECIAL, + + aNPC_THINK_NUM +}; +#endif enum { aNPC_THINK_TYPE_INIT, @@ -459,6 +473,15 @@ enum { #define aNPC_ACT_NONE 0xFF +enum { + aNPC_ACTION_PROC_TYPE_INIT, + aNPC_ACTION_PROC_TYPE_CHG_DATA, + aNPC_ACTION_PROC_TYPE_MAIN, + + aNPC_ACTION_PROC_TYPE_NUM +}; + +#ifndef aNPC_NPC2 enum { aNPC_ACT_WAIT, aNPC_ACT_WALK, @@ -487,14 +510,6 @@ enum { aNPC_ACT_NUM }; -enum { - aNPC_ACTION_PROC_TYPE_INIT, - aNPC_ACTION_PROC_TYPE_CHG_DATA, - aNPC_ACTION_PROC_TYPE_MAIN, - - aNPC_ACTION_PROC_TYPE_NUM -}; - enum { aNPC_ACTION_TYPE_WAIT, aNPC_ACTION_TYPE_WAIT_KI, @@ -556,6 +571,77 @@ enum { aNPC_ACTION_TYPE_NUM }; +#else +enum { + aNPC_ACT_WAIT, + aNPC_ACT_WALK, + aNPC_ACT_RUN, + aNPC_ACT_TURN, + aNPC_ACT_TURN2, + aNPC_ACT_TALK, + aNPC_ACT_KEITAI_ON, + aNPC_ACT_KEITAI_OFF, + aNPC_ACT_ENSOU, + aNPC_ACT_WAIT_E, + aNPC_ACT_TRANS, + aNPC_ACT_GET, + aNPC_ACT_CONTRACT, + aNPC_ACT_NOT_CONTRACT, + aNPC_ACT_NOT_CONTRACT2, + aNPC_ACT_CHANGE_CLOTH, + aNPC_ACT_SPECIAL, + + aNPC_ACT_NUM +}; + +enum { + aNPC_ACTION_TYPE_WAIT, + aNPC_ACTION_TYPE_WAIT_KI, + aNPC_ACTION_TYPE_WAIT_DO, + aNPC_ACTION_TYPE_WAIT_AI, + aNPC_ACTION_TYPE_WAIT_NEMU, + aNPC_ACTION_TYPE_WALK, + aNPC_ACTION_TYPE_WALK_KI, + aNPC_ACTION_TYPE_WALK_DO, + aNPC_ACTION_TYPE_WALK_AI, + aNPC_ACTION_TYPE_RUN, + aNPC_ACTION_TYPE_RUN_KI, + aNPC_ACTION_TYPE_RUN_DO, + aNPC_ACTION_TYPE_RUN_AI, + aNPC_ACTION_TYPE_TURN, + aNPC_ACTION_TYPE_TURN2, + aNPC_ACTION_TYPE_TALK_TURN, + aNPC_ACTION_TYPE_TALK, + aNPC_ACTION_TYPE_KEITAI_ON, + aNPC_ACTION_TYPE_KEITAI_OFF, + aNPC_ACTION_TYPE_TRANS_MOVE, + aNPC_ACTION_TYPE_TRANSFER, + aNPC_ACTION_TYPE_TRANS_WAIT, + aNPC_ACTION_TYPE_SEND_MAIL, + aNPC_ACTION_TYPE_GET_MOVE, + aNPC_ACTION_TYPE_GET, + aNPC_ACTION_TYPE_GET_PULL, + aNPC_ACTION_TYPE_GET_PULL_WAIT, + aNPC_ACTION_TYPE_GET_PUTAWAY, + aNPC_ACTION_TYPE_GET_EAT, + aNPC_ACTION_TYPE_GET_CHANGE, + aNPC_ACTION_TYPE_GET_RETURN, + aNPC_ACTION_TYPE_GET_F, + aNPC_ACTION_TYPE_GET_PULL_F, + aNPC_ACTION_TYPE_GET_PULL_WAIT_F, + aNPC_ACTION_TYPE_GET_PUTAWAY_F, + aNPC_ACTION_TYPE_GET_RETURN_F, + aNPC_ACTION_TYPE_ESTIMATE_F, + aNPC_ACTION_TYPE_CONTRACT, + aNPC_ACTION_TYPE_CONTRACT_PULL, + aNPC_ACTION_TYPE_CONTRACT_PUTAWAY, + aNPC_ACTION_TYPE_NOT_CONTRACT, + aNPC_ACTION_TYPE_ENSOU, + aNPC_ACTION_TYPE_WAIT_E, + + aNPC_ACTION_TYPE_NUM +}; +#endif typedef void (*aNPC_ACTION_PROC)(NPC_ACTOR*, GAME_PLAY*, int); diff --git a/include/audio.h b/include/audio.h index d0cce542..6d3e5974 100644 --- a/include/audio.h +++ b/include/audio.h @@ -63,7 +63,7 @@ extern void sAdo_SysTrgStart(u16 id); extern void sAdo_PlyWalkSe(u16 walk, const xyz_t* pos); extern void sAdo_PlyWalkSeRoom(u8 walk, const xyz_t* pos); extern void sAdo_NpcWalkSe(u16 se_no, const xyz_t* pos); -extern void sAdo_NpcWalkSeRoom(u16 se_no, const xyz_t* pos); +extern void sAdo_NpcWalkSeRoom(u8 se_no, const xyz_t* pos); extern void sAdo_PlayerStatusLevel(f32 speed, int p); diff --git a/include/audio_defs.h b/include/audio_defs.h index c7fd5dcb..6996a144 100644 --- a/include/audio_defs.h +++ b/include/audio_defs.h @@ -177,8 +177,12 @@ typedef enum audio_sound_effects { NA_SE_UCHIWA = 0x167, NA_SE_LAWNMOWER = 0x177, + NA_SE_207 = 0x207, + NA_SE_SCOOP_SHIGEMI = 0x401, + NA_SE_40B = 0x40B, + NA_SE_CAMERA_MOVE1 = 0x40D, NA_SE_CAMERA_MOVE2, diff --git a/include/jaudio_NES/game64.h b/include/jaudio_NES/game64.h index b94f8b29..7805c134 100644 --- a/include/jaudio_NES/game64.h +++ b/include/jaudio_NES/game64.h @@ -17,7 +17,7 @@ extern void Na_SysTrgStart(u16); extern void Na_PlyWalkSe(u16, u16, f32); extern void Na_PlyWalkSeRoom(u8, u16, f32); extern void Na_NpcWalkSe(u16, u16, f32); -extern void Na_NpcWalkSeRoom(u16, u16, f32); +extern void Na_NpcWalkSeRoom(u8, u16, f32); extern void Na_PlayerStatusLevel(f32, int); extern void Na_VoiceSe(u8, u8, u8, s16, u8, u8); extern void Na_MessageStatus(u8); diff --git a/src/actor/npc/ac_npc2.c b/src/actor/npc/ac_npc2.c new file mode 100644 index 00000000..6fddc893 --- /dev/null +++ b/src/actor/npc/ac_npc2.c @@ -0,0 +1,151 @@ +#define aNPC_NPC2 +#include "ac_npc2.h" +#include "ac_npc.h" + +#include "libultra/libultra.h" +#include "m_common_data.h" +#include "m_player_lib.h" +#include "m_msg.h" +#include "ac_handOverItem.h" +#include "sys_matrix.h" +#include "m_rcp.h" +#include "jsyswrap.h" +#include "dolphin/os.h" +#include "ac_ev_ghost.h" +#include "m_melody.h" +#include "m_actor_shadow.h" +#include "m_event_map_npc.h" +#include "m_malloc.h" + +#define aNPC_UNIT_RIGHT (1 << 0) +#define aNPC_UNIT_LEFT (1 << 1) +#define aNPC_UNIT_DOWN (1 << 2) +#define aNPC_UNIT_UP (1 << 3) +#define aNPC_UNIT_ALL (aNPC_UNIT_UP | aNPC_UNIT_DOWN | aNPC_UNIT_LEFT | aNPC_UNIT_RIGHT) + +enum { + aNPC_SEARCH_ROUTE_FORWARD, + aNPC_SEARCH_ROUTE_BACKWARD, + aNPC_SEARCH_ROUTE_CANCEL, + + aNPC_SEARCH_ROUTE_NUM = aNPC_SEARCH_ROUTE_CANCEL +}; + +enum { + aNPC_ROUTE_ERROR, + aNPC_ROUTE_FINISH, + aNPC_ROUTE_MOVING, + + aNPC_ROUTE_NUM +}; + +extern aNPC_draw_data_c npc_draw_data_tbl[]; + +#define aNPC_CLOTH_TEX_SIZE ((32*32)/2) +#define aNPC_CLOTH_PAL_SIZE (16*sizeof(u16)) + +#define aNPC_GET_TYPE(npc) (ITEM_NAME_GET_TYPE((npc)->actor_class.npc_id)) +#define aNPC_IS_NRM_NPC(npc) (aNPC_GET_TYPE(npc) == NAME_TYPE_NPC) +#define aNPC_IS_SP_NPC(npc) (aNPC_GET_TYPE(npc) == NAME_TYPE_SPNPC) +#define aNPC_GET_ANM(npc) ((npc)->npc_info.animal) +#define aNPC_GET_LOOKS(npc) (aNPC_GET_ANM(npc)->id.looks) + +typedef struct npc_control_cloth_s { + /* 0x00 */ u8 dma_flag; + /* 0x01 */ u8 init_flag; + /* 0x02 */ s16 _02; + /* 0x04 */ mActor_name_t cloth_item; + /* 0x06 */ s8 in_use_count; + /* 0x07 */ u8 id; + /* 0x08 */ Object_Bank_c texture_bank; + /* 0x0A */ Object_Bank_c palette_bank; +} aNPC_cloth_c; + +typedef struct npc_unit_info_s { + int x; + int z; + int direct; +} aNPC_unit_info_c; + +#define aNPC_CTRL_CLOTH_NUM 10 +#define aNPC2_UNIT_X_NUM 6 +#define aNPC2_UNIT_Z_NUM 7 +#define aNPC2_UNIT_NUM (aNPC2_UNIT_X_NUM * aNPC2_UNIT_Z_NUM) +#define aNPC_ROUTE_NODE_MAX 20 + +typedef struct npc_control_actor_s { + /* 0x000 */ ACTOR actor_class; + /* 0x174 */ aNPC_cloth_c cloth[aNPC_CTRL_CLOTH_NUM]; + /* 0x8F4 */ u8 _8F4[0x928 - 0x8F4]; // TODO + /* 0x928 */ int unit_info[aNPC2_UNIT_Z_NUM][aNPC2_UNIT_X_NUM]; + /* 0x9D0 */ aNPC_unit_info_c route[aNPC_ROUTE_NODE_MAX]; + /* 0xAC0 */ int route_node_count; + /* 0xAC4 */ int safe_ux[4]; + /* 0xAD4 */ int safe_uz[4]; +} NPC_CONTROL_ACTOR; + +static aNPC_Clip_c aNPC_clip; +static u16 aNPC_req_default_data[aNPC_REQUEST_ARG_NUM] = { 0, 0, 0, 0, 0, 0 }; +static ACTOR* aNPC_ctrlActor = NULL; + +static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game); +static void aNPC_actor_dt_c(ACTOR* actorx, GAME* game); +static void aNPC_actor_move_c(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Npc2_Profile = { + mAc_PROFILE_NPC, // @BUG - shouldn't this be mAc_PROFILE_NPC2??? + ACTOR_PART_CONTROL, + ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(NPC_CONTROL_ACTOR), + &aNPC_actor_ct_c, + &aNPC_actor_dt_c, + &aNPC_actor_move_c, + mActor_NONE_PROC1, + NULL, +}; +// clang-format on + +static void aNPC_set_frame_sub_speed(NPC_ACTOR* nactorx, int seqNo); +static void aNPC_TumbleSe(xyz_t* pos_p); +static void aNPC_WalkSe(xyz_t* pos_p); +static void aNPC_OngenTrgStart(NPC_ACTOR* nactorx, u16 se_no); +static int aNPC_set_request_act(NPC_ACTOR* nactorx, u8 prio, u8 act_idx, u8 act_type, u16* args); +static int aNPC_set_head_request(NPC_ACTOR* nactorx, u8 prio, u8 type, ACTOR* target_actor, xyz_t* target_pos); +static void aNPC_set_feel_info(NPC_ACTOR* nactorx, int feel, int timer); +static void aNPC_set_dst_pos(NPC_ACTOR* nactorx, f32 pos_x, f32 pos_z); +static void aNPC_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play); +static void aNPC_action_proc(NPC_ACTOR* nactorx, GAME_PLAY* play); +static void aNPC_talk_area_check(NPC_ACTOR* nactorx, GAME_PLAY* play); +static void aNPC_set_feel_effect(GAME* game, NPC_ACTOR* nactorx); +static void aNPC_set_other_effect(GAME* game, NPC_ACTOR* nactorx); +static void aNPC_act_get_chg_cloth(NPC_ACTOR* nactorx, GAME_PLAY* play); +static void aNPC_set_hide_request(NPC_ACTOR* nactorx, u8 req); +static int aNPC_setP_friendship(NPC_ACTOR* nactorx); +static void aNPC_set_schedule(NPC_ACTOR* nactorx, GAME_PLAY* play); +static void aNPC_dma_draw_data_proc(aNPC_draw_data_c* draw_data_p, mActor_name_t npc_name); +static void aNPC_WalkSeRoom(xyz_t* pos_p); +static int aNPC_route_check(NPC_ACTOR* nactorx, GAME_PLAY* play, int ux, int uz, int turn); + +#include "../src/actor/npc/ac_npc_data.c_inc" +#include "../src/actor/npc/ac_npc_cloth.c_inc" +#include "../src/actor/npc/ac_npc_anime.c_inc" +#include "../src/actor/npc/ac_npc_sound.c_inc" +#include "../src/actor/npc/ac_npc_hand.c_inc" +#include "../src/actor/npc/ac_npc_head.c_inc" +#include "../src/actor/npc/ac_npc_talk.c_inc" +#include "../src/actor/npc/ac_npc2_move.c_inc" +#include "../src/actor/npc/ac_npc_draw.c_inc" +#include "../src/actor/npc/ac_npc_effect.c_inc" +#include "../src/actor/npc/ac_npc2_action.c_inc" +#include "../src/actor/npc/ac_npc2_think.c_inc" +#include "../src/actor/npc/ac_npc2_schedule.c_inc" +#include "../src/actor/npc/ac_npc_init.c_inc" +#include "../src/actor/npc/ac_npc_ct.c_inc" +#include "../src/actor/npc/ac_npc_dt.c_inc" +#include "../src/actor/npc/ac_npc_save.c_inc" +#include "../src/actor/npc/ac_npc_ctrl.c_inc" + +#undef aNPC_NPC2 diff --git a/src/actor/npc/ac_npc2_act_contract.c_inc b/src/actor/npc/ac_npc2_act_contract.c_inc new file mode 100644 index 00000000..8cdcf93a --- /dev/null +++ b/src/actor/npc/ac_npc2_act_contract.c_inc @@ -0,0 +1,108 @@ +enum { + aNPC_ACT_CONTRACT_STEP_CONTRACT1, + aNPC_ACT_CONTRACT_STEP_CONTRACT2, + aNPC_ACT_CONTRACT_STEP_CONTRACT3, + + aNPC_ACT_CONTRACT_STEP_NUM +}; + +static void aNPC_act_contract_chg_step(NPC_ACTOR* nactorx, u8 step) { + static u8 act_idx[] = { + aNPC_ACTION_TYPE_CONTRACT, + aNPC_ACTION_TYPE_CONTRACT_PULL, + aNPC_ACTION_TYPE_CONTRACT_PUTAWAY, + }; + + nactorx->action.step = step; + aNPC_setupAction(nactorx, act_idx[step]); +} + +static int aNPC_act_contract_return_contract(NPC_ACTOR* nactorx) { + int ret = FALSE; + + if (nactorx->condition_info.talk_condition != aNPC_TALK_TYPE_NONE) { + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_TALK, aNPC_ACT_OBJ_DEFAULT, aNPC_req_default_data) == TRUE) { + nactorx->condition_info.demo_flg = 0; + nactorx->action.step = aNPC_ACTION_END_STEP; + ret = TRUE; + } + } else { + nactorx->condition_info.demo_flg = 0; + nactorx->action.step = aNPC_ACTION_END_STEP; + ret = TRUE; + } + + return ret; +} + +static void aNPC_act_contract1(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->draw.main_animation_state == cKF_STATE_STOPPED) { + ACTOR* item = CLIP(handOverItem_clip)->chg_master_proc((ACTOR*)nactorx); + + if (item != NULL) { + CLIP(handOverItem_clip)->chg_request_mode_proc((ACTOR*)nactorx, aHOI_REQUEST_GET_PULL); + nactorx->left_hand.item_actor_p = item; + nactorx->left_hand.item = CLIP(handOverItem_clip)->item; + if (nactorx->action.idx == aNPC_ACT_NOT_CONTRACT) { + CLIP(handOverItem_clip)->player_after_mode = aHOI_REQUEST_RETURN; + } + + aNPC_act_contract_chg_step(nactorx, aNPC_ACT_CONTRACT_STEP_CONTRACT2); + } + } +} + +static void aNPC_act_contract2(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->draw.main_animation_state == cKF_STATE_STOPPED) { + switch (CLIP(handOverItem_clip)->player_after_mode) { + case aHOI_REQUEST_PUTAWAY: + CLIP(handOverItem_clip)->chg_request_mode_proc((ACTOR*)nactorx, aHOI_REQUEST_PUTAWAY); + aNPC_act_contract_chg_step(nactorx, aNPC_ACT_CONTRACT_STEP_CONTRACT3); + break; + case aHOI_REQUEST_RETURN: + aNPC_act_contract_return_contract(nactorx); + break; + } + } +} + +static void aNPC_act_contract3(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->draw.main_animation_state == cKF_STATE_STOPPED) { + aNPC_clear_left_hand_info(nactorx); + aNPC_act_contract_return_contract(nactorx); + } +} + +static void aNPC_act_contract_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + static aNPC_SUB_PROC act_proc[] = { + &aNPC_act_contract1, + &aNPC_act_contract2, + &aNPC_act_contract3, + }; + + if ((*nactorx->talk_info.talk_end_check_proc)((ACTOR*)nactorx, (GAME*)play) == TRUE) { + aNPC_setup_talk_end(nactorx); + nactorx->action.step = aNPC_ACTION_END_STEP; + } else { + (*act_proc[nactorx->action.step])(nactorx, play); + } +} + +static void aNPC_act_contract_chg_data_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->action.act_obj = aNPC_ACT_OBJ_PLAYER; +} + +static void aNPC_act_contract_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_TALK_CHECK | aNPC_COND_DEMO_SKIP_ITEM | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | aNPC_COND_DEMO_SKIP_OBJ_COL_CHECK | aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK; + aNPC_act_contract_chg_step(nactorx, aNPC_ACT_CONTRACT_STEP_CONTRACT1); +} + +static void aNPC_act_contract_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC act_proc[] = { + &aNPC_act_contract_init_proc, + &aNPC_act_contract_chg_data_proc, + &aNPC_act_contract_main_proc, + }; + + (*act_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_act_not_contract.c_inc b/src/actor/npc/ac_npc2_act_not_contract.c_inc new file mode 100644 index 00000000..a7977388 --- /dev/null +++ b/src/actor/npc/ac_npc2_act_not_contract.c_inc @@ -0,0 +1,58 @@ +enum { + aNPC_ACT_NOT_CONTRACT_STEP_NOT_CONTRACT1, + + aNPC_ACT_NOT_CONTRACT_STEP_NUM +}; + +static void aNPC_act_not_contract_chg_step(NPC_ACTOR* nactorx, u8 step) { + static u8 act_idx[] = { + aNPC_ACTION_TYPE_NOT_CONTRACT, + }; + + nactorx->action.step = step; + aNPC_setupAction(nactorx, act_idx[step]); +} + +static void aNPC_act_not_contract1(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->draw.main_animation_frame >= 18) { + if (nactorx->left_hand.item_actor_p != NULL) { + aNPC_clear_left_hand_info(nactorx); + } else if (nactorx->draw.main_animation_state == cKF_STATE_STOPPED && aNPC_act_contract_return_contract(nactorx) == TRUE) { + CLIP(handOverItem_clip)->chg_request_mode_proc((ACTOR*)nactorx, aHOI_REQUEST_RETURN_WAIT); + CLIP(handOverItem_clip)->player_after_mode = aHOI_REQUEST_PUTAWAY; + } + } +} + +static void aNPC_act_not_contract_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + static aNPC_SUB_PROC act_proc[] = { + &aNPC_act_not_contract1, + }; + + if ((*nactorx->talk_info.talk_end_check_proc)((ACTOR*)nactorx, (GAME*)play) == TRUE) { + aNPC_setup_talk_end(nactorx); + nactorx->action.step = aNPC_ACTION_END_STEP; + } else { + (*act_proc[nactorx->action.step])(nactorx, play); + } +} + +static void aNPC_act_not_contract_chg_data_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->action.act_obj = aNPC_ACT_OBJ_PLAYER; +} + +static void aNPC_act_not_contract_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_TALK_CHECK | aNPC_COND_DEMO_SKIP_ITEM | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | aNPC_COND_DEMO_SKIP_OBJ_COL_CHECK | aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK; + CLIP(handOverItem_clip)->chg_request_mode_proc((ACTOR*)nactorx, aHOI_REQUEST_RETURN); + aNPC_act_not_contract_chg_step(nactorx, aNPC_ACT_NOT_CONTRACT_STEP_NOT_CONTRACT1); +} + +static void aNPC_act_not_contract_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC act_proc[] = { + &aNPC_act_not_contract_init_proc, + &aNPC_act_not_contract_chg_data_proc, + &aNPC_act_not_contract_main_proc, + }; + + (*act_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_act_putaway.c_inc b/src/actor/npc/ac_npc2_act_putaway.c_inc new file mode 100644 index 00000000..25f43282 --- /dev/null +++ b/src/actor/npc/ac_npc2_act_putaway.c_inc @@ -0,0 +1,31 @@ +enum { + aNPC_ACT_PUTAWAY_STEP_PUTAWAY, + + aNPC_ACT_PUTAWAY_STEP_NUM +}; + +static void aNPC_act_putaway_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (!aNPC_act_anm_seq(nactorx) && CLIP(tools_clip) != NULL) { + if (CLIP(tools_clip)->aTOL_chg_request_mode_proc((ACTOR*)nactorx, nactorx->right_hand.item_actor_p, aTOL_ACTION_DESTRUCT) == TRUE) { + nactorx->right_hand.item_type = aNPC_ITEM_TYPE_NONE; + nactorx->right_hand.item_actor_p = NULL; + nactorx->action.step = aNPC_ACTION_END_STEP; + } + } +} + +static void aNPC_act_putaway_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->action.step = aNPC_ACT_PUTAWAY_STEP_PUTAWAY; + nactorx->draw.sub_anim_type = aNPC_SUB_ANIM_NONE; + aNPC_setupAction(nactorx, aNPC_ACTION_TYPE_KEITAI_OFF); +} + +static void aNPC_act_putaway_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC act_proc[] = { + &aNPC_act_putaway_init_proc, + (aNPC_SUB_PROC)&none_proc1, + &aNPC_act_putaway_main_proc, + }; + + (*act_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_act_takeout.c_inc b/src/actor/npc/ac_npc2_act_takeout.c_inc new file mode 100644 index 00000000..eee2b2dc --- /dev/null +++ b/src/actor/npc/ac_npc2_act_takeout.c_inc @@ -0,0 +1,20 @@ +enum { + aNPC_ACT_TAKEOUT_STEP_TAKEOUT, + + aNPC_ACT_TAKEOUT_STEP_NUM +}; + +static void aNPC_act_takeout_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->action.step = aNPC_ACT_TAKEOUT_STEP_TAKEOUT; + aNPC_setupAction(nactorx, aNPC_ACTION_TYPE_KEITAI_ON); +} + +static void aNPC_act_takeout_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC act_proc[] = { + &aNPC_act_takeout_init_proc, + (aNPC_SUB_PROC)&none_proc1, + &aNPC_act_anm_seq_allways_proc, + }; + + (*act_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_act_walk.c_inc b/src/actor/npc/ac_npc2_act_walk.c_inc new file mode 100644 index 00000000..56593119 --- /dev/null +++ b/src/actor/npc/ac_npc2_act_walk.c_inc @@ -0,0 +1,94 @@ +enum { + aNPC_ACT_WALK_STEP_MAIN, + + aNPC_ACT_WALK_STEP_NUM +}; + +static void aNPC_act_walk_setupAction(NPC_ACTOR* nactorx, u8 feel) { + static u8 walk_action[] = { + aNPC_ACTION_TYPE_WALK, + aNPC_ACTION_TYPE_WALK_KI, + aNPC_ACTION_TYPE_WALK_DO, + aNPC_ACTION_TYPE_WALK_AI, + aNPC_ACTION_TYPE_WALK, + aNPC_ACTION_TYPE_WALK, + aNPC_ACTION_TYPE_WALK_DO, + aNPC_ACTION_TYPE_WALK_AI, + aNPC_ACTION_TYPE_WALK_DO + }; + static u8 run_action[] = { + aNPC_ACTION_TYPE_RUN, + aNPC_ACTION_TYPE_RUN_KI, + aNPC_ACTION_TYPE_RUN_DO, + aNPC_ACTION_TYPE_RUN_AI, + aNPC_ACTION_TYPE_RUN, + aNPC_ACTION_TYPE_RUN, + aNPC_ACTION_TYPE_RUN_DO, + aNPC_ACTION_TYPE_RUN_AI, + aNPC_ACTION_TYPE_RUN_DO + }; + u8 act; + + nactorx->action.feel = feel; + if (nactorx->action.idx == aNPC_ACT_WALK) { + act = walk_action[feel]; + } else { + act = run_action[feel]; + } + + aNPC_setupAction(nactorx, act); +} + +typedef int (*aNPC_ACT_WALK_PROC)(NPC_ACTOR* nactorx, GAME_PLAY* play); + +static void aNPC_act_walk_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + static aNPC_ACT_WALK_PROC act_proc[] = { + &aNPC_act_move, + &aNPC_act_avoid_move, + &aNPC_act_search_move, + &aNPC_act_to_point_move, + }; + + if (nactorx->draw.main_animation_state == cKF_STATE_CONTINUE) { + u8 feel = aNPC_get_feel_info(nactorx); + + if (nactorx->action.feel != feel) { + aNPC_act_walk_setupAction(nactorx, feel); + } + } + + if (!(*act_proc[nactorx->action.type])(nactorx, play)) { + nactorx->action.step = aNPC_ACTION_END_STEP; + } +} + +static void aNPC_act_walk_chg_data_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u16* arg_p = nactorx->request.act_args; + s16 prev_move_x = nactorx->action.move_x; + s16 prev_move_z = nactorx->action.move_z; + + nactorx->action.act_obj = arg_p[0]; + nactorx->action.act_obj_id = arg_p[1]; + nactorx->action.move_x = arg_p[2]; + nactorx->action.move_z = arg_p[3]; + + if (nactorx->action.step == aNPC_ACTION_END_STEP && (nactorx->action.move_x != prev_move_x || nactorx->action.move_z != prev_move_z)) { + nactorx->action.step = aNPC_ACT_WALK_STEP_MAIN; + } +} + +static void aNPC_act_walk_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u16* arg_p = nactorx->request.act_args; + u8 feel; + + nactorx->action.step = aNPC_ACT_WALK_STEP_MAIN; + nactorx->movement.arrival_area_radius = 72.0f; + feel = aNPC_get_feel_info(nactorx); + aNPC_act_walk_setupAction(nactorx, feel); +} + +static void aNPC_act_walk_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + static aNPC_SUB_PROC act_proc[] = { &aNPC_act_walk_init_proc, &aNPC_act_walk_chg_data_proc, &aNPC_act_walk_main_proc }; + + (*act_proc[type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_action.c_inc b/src/actor/npc/ac_npc2_action.c_inc new file mode 100644 index 00000000..ac5eb681 --- /dev/null +++ b/src/actor/npc/ac_npc2_action.c_inc @@ -0,0 +1,380 @@ +// clang-format off +static u8 aNPC_wait_action[] = { + aNPC_ACTION_TYPE_WAIT, + aNPC_ACTION_TYPE_WAIT_KI, + aNPC_ACTION_TYPE_WAIT_DO, + aNPC_ACTION_TYPE_WAIT_AI, + aNPC_ACTION_TYPE_WAIT_NEMU, + aNPC_ACTION_TYPE_WAIT, + aNPC_ACTION_TYPE_WAIT_DO, + aNPC_ACTION_TYPE_WAIT_AI, + aNPC_ACTION_TYPE_WAIT_DO, +}; +// clang-format on + +static void aNPC_set_be_out_home(NPC_ACTOR* nactorx) { + mNpc_NpcList_c* list_p; + + aNPC_GET_ANM(nactorx)->is_home = FALSE; + list_p = nactorx->npc_info.list; + list_p->position.x = list_p->house_position.x + mFI_UT_WORLDSIZE_HALF_X_F; + list_p->position.y = list_p->house_position.y; + list_p->position.z = list_p->house_position.z + mFI_UT_WORLDSIZE_HALF_Z_F; +} + +static int aNPC_check_arrive_destination(NPC_ACTOR* nactorx) { + f32 range = nactorx->movement.arrival_area_radius; + f32 dist; + f32 distX = nactorx->movement.avoid_pos_x - nactorx->actor_class.world.position.x; + f32 distZ = nactorx->movement.avoid_pos_z - nactorx->actor_class.world.position.z; + int ret = FALSE; + + dist = SQ(distX) + SQ(distZ); + if (dist < range) { + ret = TRUE; + } + + return ret; +} + +static int aNPC_trace_route(NPC_ACTOR* nactorx) { + int ret = TRUE; + + if (aNPC_check_arrive_destination(nactorx) == TRUE) { + switch (nactorx->schedule.type) { + case aNPC_SCHEDULE_TYPE_FIELD: + case aNPC_SCHEDULE_TYPE_IN_HOUSE: + case aNPC_SCHEDULE_TYPE_WANDER: { + NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + aNPC_unit_info_c* route = ctrl->route + nactorx->movement.avoid_direction; + + aNPC_set_avoid_pos(nactorx, (route->x + 1.5f) * mFI_UT_WORLDSIZE_X_F, (route->z + 1.5f) * mFI_UT_WORLDSIZE_Z_F); + if (ctrl->route_node_count == nactorx->movement.avoid_direction) { + aNPC_set_dst_pos(nactorx, nactorx->movement.avoid_pos_x, nactorx->movement.avoid_pos_z); + ret = FALSE; + } else { + nactorx->movement.avoid_direction++; + } + } + break; + + default: + ret = FALSE; + break; + } + } + return ret; +} + +static void aNPC_set_feel_info(NPC_ACTOR* nactorx, int feel, int timer) { + Animal_c* animal = nactorx->npc_info.animal; + + if (animal != NULL) { + int feel_timer = nactorx->condition_info.feel_tim; + + if (feel != animal->mood) { + animal->mood = feel; + if (feel == mNpc_FEEL_NORMAL) { + feel_timer = 0; + } else { + feel_timer = timer * FRAMES_PER_MINUTE; + } + } else { + feel_timer += timer * FRAMES_PER_MINUTE; + if (feel_timer > (10 * FRAMES_PER_MINUTE)) { + feel_timer = 10 * FRAMES_PER_MINUTE; + } + } + + nactorx->condition_info.feel_tim = feel_timer; + } +} + +static void aNPC_set_act_obj(NPC_ACTOR* nactorx, GAME_PLAY* play) { + switch (nactorx->action.act_obj) { + case aNPC_ACT_OBJ_PLAYER: + nactorx->movement.target = GET_PLAYER_ACTOR_ACTOR(play); + break; + case aNPC_ACT_OBJ_TARGET_NPC: + nactorx->movement.target = + Actor_info_fgName_search(&play->actor_info, nactorx->action.act_obj_id, ACTOR_PART_NPC); + break; + default: + nactorx->movement.target = NULL; + break; + } +} + +static int aNPC_check_live_target(ACTOR* actorx) { + int ret = TRUE; + + if (actorx == NULL || (actorx->mv_proc == NULL && actorx->dw_proc == NULL)) { + ret = FALSE; + } + + return ret; +} + +static int aNPC_act_wait(NPC_ACTOR* nactorx) { + int ret = TRUE; + + if (nactorx->draw.main_animation_state == cKF_STATE_CONTINUE) { + if (nactorx->draw.loop_flag == FALSE) { + if (nactorx->condition_info.fatigue < 200) { + ret = FALSE; + } + } else { + nactorx->draw.loop_flag--; + } + } + + return ret; +} + +static int aNPC_act_move(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = TRUE; + + aNPC_set_mv_angl(nactorx); + if (aNPC_trace_route(nactorx) == FALSE) { + ret = FALSE; + } + + return ret; +} + +static int aNPC_act_search_move(NPC_ACTOR* nactorx, GAME_PLAY* play) { + ACTOR* target = nactorx->movement.target; + int ret = TRUE; + + if (!aNPC_check_live_target(target)) { + ret = FALSE; + } else { + xyz_t dst_pos; + int ux; + int uz; + + xyz_t_move(&dst_pos, &target->world.position); + mFI_Wpos2UtNum(&ux, &uz, dst_pos); + + aNPC_route_check(nactorx, play, ux, uz, FALSE); + aNPC_set_mv_angl(nactorx); + if (aNPC_trace_route(nactorx) == FALSE) { + ret = FALSE; + } + } + + return ret; +} + +static int aNPC_act_avoid_move(NPC_ACTOR* nactorx, GAME_PLAY* play) { + ACTOR* target = nactorx->movement.target; + int ret = TRUE; + + if (!aNPC_check_live_target(target)) { + ret = FALSE; + } else { + aNPC_set_mv_angl(nactorx); + if (aNPC_trace_route(nactorx) == FALSE) { + ret = FALSE; + } + } + + return ret; +} + +static int aNPC_act_demo_move(NPC_ACTOR* nactorx) { + ACTOR* target = nactorx->movement.target; + int ret = TRUE; + + if (!aNPC_check_live_target(target)) { + ret = FALSE; + } else { + xyz_t pos; + + xyz_t_move(&pos, &target->world.position); + aNPC_set_dst_pos(nactorx, pos.x, pos.z); + aNPC_set_mv_angl(nactorx); + if (aNPC_check_arrive_destination(nactorx) == TRUE) { + ret = FALSE; + } + } + + return ret; +} + +static int aNPC_act_to_point_move(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = TRUE; + + if (nactorx->movement.dst_pos_x == nactorx->movement.avoid_pos_x && nactorx->movement.dst_pos_z == nactorx->movement.avoid_pos_z) { + aNPC_set_dst_pos(nactorx, nactorx->action.move_x, nactorx->action.move_z); + } else { + nactorx->movement.dst_pos_x = nactorx->action.move_x; + nactorx->movement.dst_pos_z = nactorx->action.move_z; + } + + aNPC_set_mv_angl(nactorx); + if (aNPC_check_arrive_destination(nactorx) == TRUE) { + ret = FALSE; + } + return ret; +} + +static int aNPC_act_turn(NPC_ACTOR* nactorx) { + int ret = TRUE; + + if (nactorx->actor_class.shape_info.rotation.y == nactorx->movement.mv_angl) { + ret = FALSE; + } + + return ret; +} + +static int aNPC_act_search_turn(NPC_ACTOR* nactorx) { + ACTOR* target = nactorx->movement.target; + int ret = TRUE; + + if (!aNPC_check_live_target(target)) { + ret = FALSE; + } else { + aNPC_set_dst_pos(nactorx, target->world.position.x, target->world.position.z); + if (nactorx->actor_class.shape_info.rotation.y == nactorx->movement.mv_angl) { + ret = FALSE; + } + } + + return ret; +} + +static int aNPC_act_to_point_turn(NPC_ACTOR* nactorx) { + int ret = TRUE; + + aNPC_set_dst_pos(nactorx, nactorx->action.move_x, nactorx->action.move_z); + if (nactorx->actor_class.shape_info.rotation.y == nactorx->movement.mv_angl) { + ret = FALSE; + } + + return ret; +} + +static int aNPC_act_anm_seq(NPC_ACTOR* nactorx) { + int ret = TRUE; + + if (nactorx->draw.main_animation_state == cKF_STATE_STOPPED) { + ret = FALSE; + } + + return ret; +} + +static void aNPC_act_anm_seq_allways_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (!aNPC_act_anm_seq(nactorx)) { + nactorx->action.step = aNPC_ACTION_END_STEP; + } +} + +static void aNPC_act_return_trans_item(NPC_ACTOR* nactorx) { + if (nactorx->condition_info.talk_condition != aNPC_TALK_TYPE_NONE) { + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_TALK, aNPC_ACT_OBJ_DEFAULT, aNPC_req_default_data) == TRUE) { + nactorx->condition_info.demo_flg = nactorx->condition_info.trans_demo_flg_save; + nactorx->action.step = aNPC_ACTION_END_STEP; + } + } else { + nactorx->condition_info.demo_flg = 0; + nactorx->action.step = aNPC_ACTION_END_STEP; + } +} + +static void aNPC_act_special_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { + (*nactorx->action.act_proc)(nactorx, play, type); +} + +// included act files + +#include "../src/actor/npc/ac_npc_act_wait.c_inc" +#include "../src/actor/npc/ac_npc2_act_walk.c_inc" +#include "../src/actor/npc/ac_npc_act_turn.c_inc" +#include "../src/actor/npc/ac_npc_act_talk.c_inc" +#include "../src/actor/npc/ac_npc2_act_takeout.c_inc" +#include "../src/actor/npc/ac_npc2_act_putaway.c_inc" +#include "../src/actor/npc/ac_npc_act_trans.c_inc" +#include "../src/actor/npc/ac_npc_act_get.c_inc" +#include "../src/actor/npc/ac_npc2_act_contract.c_inc" +#include "../src/actor/npc/ac_npc2_act_not_contract.c_inc" +#include "../src/actor/npc/ac_npc_act_ensou.c_inc" + +typedef void (*aNPC_ACT_PROC)(NPC_ACTOR* nactorx, GAME_PLAY* play, int type); + +static aNPC_ACT_PROC aNPC_act_proc[] = { + &aNPC_act_wait_proc, + &aNPC_act_walk_proc, + &aNPC_act_walk_proc, + &aNPC_act_turn_proc, + &aNPC_act_turn_proc, + &aNPC_act_talk_proc, + &aNPC_act_takeout_proc, + &aNPC_act_putaway_proc, + &aNPC_act_ensou_proc, + &aNPC_act_talk_proc, + &aNPC_act_trans_proc, + &aNPC_act_get_proc, + &aNPC_act_contract_proc, + &aNPC_act_contract_proc, + &aNPC_act_not_contract_proc, + &aNPC_act_get_proc, + &aNPC_act_special_proc, +}; + +static void aNPC_chk_request_act(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->request.act_priority >= nactorx->action.priority && nactorx->request.act_priority != 0) { + u8 prev_idx = nactorx->action.idx; + u8 prev_obj = nactorx->action.act_obj; + mActor_name_t prev_obj_name = nactorx->action.act_obj_id; + + nactorx->action.prev_idx = nactorx->action.idx; + nactorx->action.prev_step = nactorx->action.step; + nactorx->action.priority = nactorx->request.act_priority; + nactorx->action.idx = nactorx->request.act_idx; + nactorx->action.type = nactorx->request.act_type; + + (*aNPC_act_proc[nactorx->action.idx])(nactorx, play, aNPC_ACTION_PROC_TYPE_CHG_DATA); + if (nactorx->action.act_obj != prev_obj || nactorx->action.act_obj_id != prev_obj_name) { + aNPC_set_act_obj(nactorx, play); + } + + if (nactorx->request.act_idx != prev_idx) { + (*aNPC_act_proc[nactorx->action.idx])(nactorx, play, aNPC_ACTION_PROC_TYPE_INIT); + } + } + + nactorx->request.act_priority = 0; +} + +static int aNPC_set_request_act(NPC_ACTOR* nactorx, u8 prio, u8 act_idx, u8 act_type, u16* args) { + int ret = FALSE; + + if (prio >= nactorx->request.act_priority) { + nactorx->request.act_priority = prio; + nactorx->request.act_idx = act_idx; + nactorx->request.act_type = act_type; + + if (args != NULL) { + mem_copy((u8*)nactorx->request.act_args, (u8*)args, sizeof(nactorx->request.act_args)); + } + + ret = TRUE; + } + + return ret; +} + +static void aNPC_action_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_chk_request_act(nactorx, play); + + if (nactorx->action.step != aNPC_ACTION_END_STEP && nactorx->action.idx != aNPC_ACT_NONE) { + (*aNPC_act_proc[nactorx->action.idx])(nactorx, play, aNPC_ACTION_PROC_TYPE_MAIN); + } + + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + nactorx->action.priority = 0; + } +} diff --git a/src/actor/npc/ac_npc2_move.c_inc b/src/actor/npc/ac_npc2_move.c_inc new file mode 100644 index 00000000..1313e1d1 --- /dev/null +++ b/src/actor/npc/ac_npc2_move.c_inc @@ -0,0 +1,294 @@ +static f32 aNPC_get_rev_val(f32 rev, f32 amount) { + if (ABS(rev) >= amount) { + if (rev < 0.0f) { + return -amount; + } else { + return amount; + } + } else { + return rev; + } +} + +static void aNPC_BGcheck(NPC_ACTOR* nactorx, ACTOR* actorx) { + if ((nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_BGCHECK) == 0) { + if (ClObj_DID_COLLIDE(nactorx->collision.pipe.collision_obj)) { + mCoBG_BgCheckControll(NULL, actorx, nactorx->collision.BGcheck_radius, 0.0f, TRUE, FALSE, 0); + nactorx->collision.bg_rev_add = 0.0f; + } else { + xyz_t rev; + f32 amount; + + mCoBG_BgCheckControll(&rev, actorx, nactorx->collision.BGcheck_radius, 0.0f, TRUE, TRUE, 0); + amount = nactorx->collision.bg_rev_add; + + amount += 1.0f; + if (amount > 4.0f) { + amount = 4.0f; + } + + nactorx->collision.bg_rev_add = amount; + actorx->world.position.x += aNPC_get_rev_val(rev.x, amount); + actorx->world.position.y += aNPC_get_rev_val(rev.y, amount); + actorx->world.position.z += aNPC_get_rev_val(rev.z, amount); + } + } else { + mCoBG_InitBgCheckResult(&actorx->bg_collision_check.result); + nactorx->collision.bg_rev_add = 0.0f; + } +} + +static void aNPC_set_over_friendship(NPC_ACTOR* nactorx) { + if (ITEM_NAME_GET_TYPE(nactorx->actor_class.npc_id) != NAME_TYPE_SPNPC) { + int over_friendship = 0; + + switch (Now_Private->destiny.type) { + case mPr_DESTINY_UNPOPULAR: + over_friendship = -0x100; + break; + case mPr_DESTINY_POPULAR: + if (mNpc_GetLooks2Sex(nactorx->npc_info.animal->id.looks) != Now_Private->gender) { + over_friendship = 0x100; + } + break; + } + + nactorx->condition_info.over_friendship = over_friendship; + } +} + +static void aNPC_set_mv_angl(NPC_ACTOR* nactorx) { + s16 angle = atans_table(nactorx->movement.avoid_pos_z - nactorx->actor_class.world.position.z, + nactorx->movement.avoid_pos_x - nactorx->actor_class.world.position.x); + + nactorx->movement.mv_angl = angle; +} + +static void aNPC_set_avoid_pos(NPC_ACTOR* nactorx, f32 avoid_pos_x, f32 avoid_pos_z) { + nactorx->movement.avoid_pos_x = avoid_pos_x; + nactorx->movement.avoid_pos_z = avoid_pos_z; + aNPC_set_mv_angl(nactorx); +} + +static void aNPC_set_dst_pos(NPC_ACTOR* nactorx, f32 dst_pos_x, f32 dst_pos_z) { + nactorx->movement.dst_pos_x = dst_pos_x; + nactorx->movement.dst_pos_z = dst_pos_z; + nactorx->movement.move_timer = 0; + aNPC_set_avoid_pos(nactorx, dst_pos_x, dst_pos_z); +} + +static void aNPC_check_feel_tim(NPC_ACTOR* nactorx) { + Animal_c* animal_p = nactorx->npc_info.animal; + + if (animal_p != NULL) { + if ((nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_FEEL_CHECK) == 0 && + nactorx->condition_info.feel_tim > 0) { + nactorx->condition_info.feel_tim--; + } + + if (nactorx->condition_info.feel_tim == 0) { + animal_p->mood = mNpc_FEEL_NORMAL; + } + } +} + +static void aNPC_calc_force_call_timer(NPC_ACTOR* nactorx) { + if (mDemo_Get_talk_actor() == NULL && nactorx->think.force_call_timer != 0) { + nactorx->think.force_call_timer--; + } +} + + +static void aNPC_calc_timer(NPC_ACTOR* nactorx) { + aNPC_calc_force_call_timer(nactorx); +} + +static void aNPC_position_move(ACTOR* actorx) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; + f32 accel; + + if (actorx->speed < nactorx->movement.speed.max_speed) { + accel = nactorx->movement.speed.acceleration; + } else { + accel = nactorx->movement.speed.deceleration; + } + + chase_f(&actorx->speed, nactorx->movement.speed.max_speed, accel * 0.5f); +#ifndef aNPC_NPC2 + Actor_position_speed_set(actorx); +#else + Actor_position_moveF(actorx); +#endif +} + +static void aNPC_angle_calc(NPC_ACTOR* nactorx) { + chase_angle(&nactorx->actor_class.shape_info.rotation.y, nactorx->movement.mv_angl, nactorx->movement.mv_add_angl); + nactorx->actor_class.world.angle.y = nactorx->actor_class.shape_info.rotation.y; +} + +static void aNPC_set_body_angle(NPC_ACTOR* nactorx) { + s16 angle; + + if (nactorx->movement.override_body_angle_flag == TRUE) { + angle = nactorx->movement.body_angle; + } else { + angle = (nactorx->actor_class.speed * 3640.0f) / 3.0f; + } + + chase_angle(&nactorx->actor_class.shape_info.rotation.x, angle, 224); +} + +static void aNPC_calc_fatigue(NPC_ACTOR* nactorx) { + static int fatigue_add_table[] = { + -2, -2, -2, -2, -2, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + int fatigue = nactorx->condition_info.fatigue; + + fatigue += fatigue_add_table[nactorx->condition_info.action]; + if (fatigue < 0) { + fatigue = 0; + } else if (fatigue > 1600) { + fatigue = 1600; + } + + nactorx->condition_info.fatigue = fatigue; +} + +typedef struct { + int talk_flag; + s16 mv_angl_add; + u8 speed_type; +} aNPC_setup_data_c; + +static void aNPC_setupAction(NPC_ACTOR* nactorx, u8 action) { + // clang-format off + static aNPC_setup_data_c setup_data[aNPC_ACTION_TYPE_NUM] = { + {FALSE, 0x0100, 0x00}, + {FALSE, 0x0100, 0x00}, + {FALSE, 0x0100, 0x00}, + {FALSE, 0x0100, 0x00}, + {FALSE, 0x0100, 0x00}, + {FALSE, 0x0400, 0x01}, + {FALSE, 0x0400, 0x01}, + {FALSE, 0x0400, 0x01}, + {FALSE, 0x0400, 0x01}, + {FALSE, 0x0400, 0x02}, + {FALSE, 0x0400, 0x02}, + {FALSE, 0x0400, 0x02}, + {FALSE, 0x0400, 0x02}, + {FALSE, 0x0800, 0x00}, + {FALSE, 0x0800, 0x00}, + {FALSE, 0x0800, 0x00}, + { TRUE, 0x0400, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + {FALSE, 0x0000, 0x00}, + { TRUE, 0x0000, 0x00}, + }; + // clang-format on + + aNPC_setup_data_c* data_p = &setup_data[action]; + aNPC_spd_c* speed_p = &aNPC_spd_data[data_p->speed_type]; + + nactorx->condition_info.action = action; + nactorx->movement.mv_add_angl = data_p->mv_angl_add; + nactorx->movement.speed.max_speed = speed_p->max_speed; + nactorx->movement.speed.acceleration = speed_p->acceleration; + nactorx->movement.speed.deceleration = speed_p->deceleration; + + if (data_p->speed_type == 0) { + nactorx->actor_class.speed = 0.0f; + } + + nactorx->talk_info.demo_code = aNPC_MANPU_CODE_NONE; + aNPC_Animation_init((ACTOR*)nactorx, aNPC_animeSeqNoTable[(int)action], data_p->talk_flag); +} + +static void aNPC_actor_move_hide(ACTOR* actorx, GAME* game) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + aNPC_schedule_proc(nactorx, play); + aNPC_action_proc(nactorx, play); + aNPC_check_feel_tim(nactorx); +} + +static void aNPC_actor_move_show_before(ACTOR* actorx, GAME* game) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; + + aNPC_anime_proc(nactorx, game); + aNPC_tex_anm_ctrl(nactorx); + aNPC_position_move(actorx); + aNPC_BGcheck(nactorx, actorx); +} + +static void aNPC_actor_move_show_after(ACTOR* actorx, GAME* game) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + aNPC_set_anime_speed(nactorx); + aNPC_set_body_angle(nactorx); + aNPC_check_feel_tim(nactorx); + aNPC_calc_timer(nactorx); + Actor_world_to_eye(actorx, nactorx->eye_y); + + if ((nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_OBJ_COL_CHECK) == 0) { + CollisionCheck_Uty_ActorWorldPosSetPipeC(actorx, &nactorx->collision.pipe); + CollisionCheck_setOC(game, &play->collision_check, &nactorx->collision.pipe.collision_obj); + } +} + +static void aNPC_actor_move_show(ACTOR* actorx, GAME* game) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + aNPC_set_over_friendship(nactorx); + aNPC_actor_move_show_before(actorx, game); + aNPC_schedule_proc(nactorx, play); + aNPC_action_proc(nactorx, play); + aNPC_talk_request_check(actorx, game); + aNPC_angle_calc(nactorx); + aNPC_calc_fatigue(nactorx); + aNPC_actor_move_show_after(actorx, game); +} + +static void aNPC_actor_move(ACTOR* actorx, GAME* game) { + NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; + + if (nactorx->condition_info.hide_flg != nactorx->condition_info.hide_request) { + u8 hide_req = nactorx->condition_info.hide_request; + + nactorx->condition_info.hide_flg = hide_req; + actorx->shape_info.draw_shadow = hide_req ^ 1; + } + + if (nactorx->condition_info.hide_flg == TRUE) { + aNPC_actor_move_hide(actorx, game); + } else { + aNPC_actor_move_show(actorx, game); + } +} diff --git a/src/actor/npc/ac_npc2_schedule.c_inc b/src/actor/npc/ac_npc2_schedule.c_inc new file mode 100644 index 00000000..f08a7f8a --- /dev/null +++ b/src/actor/npc/ac_npc2_schedule.c_inc @@ -0,0 +1,131 @@ +static void aNPC_set_hide_request(NPC_ACTOR* nactorx, u8 hide) { + nactorx->condition_info.hide_request = hide; + if (nactorx->condition_info.hide_flg != hide && hide != TRUE) { + aNPC_clear_all_morph_counter(nactorx); + nactorx->condition_info.fatigue = 0; + } +} + +static void aNPC_set_hide_flg(NPC_ACTOR* nactorx, u8 hide_flg) { + u8 inv = hide_flg ^ 1; + + aNPC_set_hide_request(nactorx, hide_flg); + nactorx->condition_info.hide_flg = hide_flg; + nactorx->actor_class.shape_info.draw_shadow = inv; +} + +#include "../src/actor/npc/ac_npc2_schedule_field.c_inc" +#include "../src/actor/npc/ac_npc2_schedule_in_house.c_inc" + +static void aNPC_sleep_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->schedule.type != nactorx->npc_info.schedule->current_type) { + aNPC_set_schedule(nactorx, play); + } +} + +static void aNPC_sleep_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_set_hide_flg(nactorx, TRUE); + aNPC_think_init_proc(nactorx, play, aNPC_THINK_WAIT); +} + +static void aNPC_sleep_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC sche_proc[] = { + &aNPC_sleep_schedule_init_proc, + &aNPC_sleep_schedule_main_proc, + }; + + (*sche_proc[proc_type])(nactorx, play); +} + +static void aNPC_stand_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (!aNPC_think_chk_interrupt_proc(nactorx, play) && nactorx->action.step == aNPC_ACTION_END_STEP) { + if (nactorx->action.idx == aNPC_ACT_WAIT) { + aNPC_think_main_proc(nactorx, play); + } else { + aNPC_think_init_proc(nactorx, play, aNPC_THINK_WAIT); + } + } +} + +static void aNPC_stand_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_set_hide_flg(nactorx, FALSE); + aNPC_think_init_proc(nactorx, play, aNPC_THINK_WAIT); +} + +static void aNPC_stand_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC sche_proc[] = { + &aNPC_stand_schedule_init_proc, + &aNPC_stand_schedule_main_proc, + }; + + (*sche_proc[proc_type])(nactorx, play); +} + +static void aNPC_wander_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_think_main_proc(nactorx, play); +} + +static void aNPC_wander_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_set_hide_flg(nactorx, FALSE); + aNPC_think_init_proc(nactorx, play, aNPC_THINK_WANDER); +} + +static void aNPC_wander_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC sche_proc[] = { + &aNPC_wander_schedule_init_proc, + &aNPC_wander_schedule_main_proc, + }; + + (*sche_proc[proc_type])(nactorx, play); +} + +static void aNPC_special_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + (*nactorx->schedule.schedule_proc)(nactorx, play, proc_type); +} + +static aNPC_SCHEDULE_PROC aNPC_sche_proc[] = { + &aNPC_field_schedule_proc, + &aNPC_in_house_schedule_proc, + &aNPC_sleep_schedule_proc, + &aNPC_stand_schedule_proc, + &aNPC_wander_schedule_proc, + &aNPC_wander_schedule_proc, + &aNPC_special_schedule_proc, +}; + +static void aNPC_schedule_init(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int type = nactorx->schedule.type; + + (*aNPC_sche_proc[type])(nactorx, play, aNPC_SCHEDULE_PROC_INIT); +} + +static void aNPC_chg_schedule(NPC_ACTOR* nactorx, GAME_PLAY* play, u8 type) { + nactorx->schedule.type = type; + aNPC_schedule_init(nactorx, play); +} + +static void aNPC_set_schedule(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_chg_schedule(nactorx, play, nactorx->npc_info.schedule->current_type); +} + +static void aNPC_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int type = nactorx->schedule.type; + + if (type != aNPC_SCHEDULE_NONE) { + (*aNPC_sche_proc[type])(nactorx, play, aNPC_SCHEDULE_PROC_MAIN); + } +} + +static void aNPC_first_set_schedule(NPC_ACTOR* nactorx) { + mNPS_schedule_c* sched_p = mNPS_get_schedule_area(&aNPC_GET_ANM(nactorx)->id); + + if (sched_p == NULL) { + sched_p = &nactorx->schedule.schedule; + sched_p->current_type = mNPS_SCHED_WANDER; + nactorx->schedule.type = aNPC_SCHEDULE_TYPE_WANDER; + } else { + nactorx->schedule.type = sched_p->current_type; + } + + nactorx->npc_info.schedule = sched_p; +} diff --git a/src/actor/npc/ac_npc2_schedule_field.c_inc b/src/actor/npc/ac_npc2_schedule_field.c_inc new file mode 100644 index 00000000..37acb783 --- /dev/null +++ b/src/actor/npc/ac_npc2_schedule_field.c_inc @@ -0,0 +1,56 @@ +enum { + aNPC_SCHEDULE_FIELD_STEP_OUT_OF_ROOM, + aNPC_SCHEDULE_FIELD_STEP_EXIT_WAIT, + aNPC_SCHEDULE_FIELD_STEP_HIDE, + + aNPC_SCHEDULE_FIELD_STEP_NUM +}; + +static void aNPC_field_schedule_think_init(NPC_ACTOR* nactorx, GAME_PLAY* play) { + static int think_idx[] = { aNPC_THINK_OUT_OF_ROOM, aNPC_THINK_EXIT_WAIT, aNPC_THINK_WAIT }; + + aNPC_think_init_proc(nactorx, play, think_idx[nactorx->schedule.step]); +} + +static void aNPC_field_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_think_main_proc(nactorx, play); + + if (nactorx->think.end_flag == TRUE) { + nactorx->schedule.step++; + if (nactorx->schedule.step > aNPC_SCHEDULE_FIELD_STEP_HIDE) { + nactorx->schedule.step = aNPC_SCHEDULE_FIELD_STEP_HIDE; + } + + aNPC_field_schedule_think_init(nactorx, play); + } else if (nactorx->schedule.step == aNPC_SCHEDULE_FIELD_STEP_HIDE) { + if (nactorx->schedule.type != nactorx->npc_info.schedule->current_type && + nactorx->condition_info.talk_condition == aNPC_TALK_TYPE_NONE) { + aNPC_set_schedule(nactorx, play); + } + } +} + +static void aNPC_field_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u8 step = aNPC_SCHEDULE_FIELD_STEP_OUT_OF_ROOM; + u8 hide = FALSE; + + if (!aNPC_GET_ANM(nactorx)->is_home) { + step = aNPC_SCHEDULE_FIELD_STEP_HIDE; + hide = TRUE; + nactorx->actor_class.world.position.x = 0.0f; + nactorx->actor_class.world.position.z = 0.0f; + } + + aNPC_set_hide_flg(nactorx, hide); + nactorx->schedule.step = step; + aNPC_field_schedule_think_init(nactorx, play); +} + +static void aNPC_field_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC sche_proc[] = { + &aNPC_field_schedule_init_proc, + &aNPC_field_schedule_main_proc, + }; + + (*sche_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_schedule_in_house.c_inc b/src/actor/npc/ac_npc2_schedule_in_house.c_inc new file mode 100644 index 00000000..07eda0f6 --- /dev/null +++ b/src/actor/npc/ac_npc2_schedule_in_house.c_inc @@ -0,0 +1,56 @@ +enum { + aNPC_SCHEDULE_IN_HOUSE_STEP_HIDE, + aNPC_SCHEDULE_IN_HOUSE_STEP_INTO_ROOM, + aNPC_SCHEDULE_IN_HOUSE_STEP_WANDER, + + aNPC_SCHEDULE_IN_HOUSE_STEP_NUM +}; + +static void aNPC_in_house_schedule_think_init(NPC_ACTOR* nactorx, GAME_PLAY* play) { + static int think_idx[] = { aNPC_THINK_HIDE, aNPC_THINK_INTO_ROOM, aNPC_THINK_WANDER }; + + aNPC_think_init_proc(nactorx, play, think_idx[nactorx->schedule.step]); +} + +static void aNPC_in_house_schedule_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_think_main_proc(nactorx, play); + + if (nactorx->think.end_flag == TRUE) { + nactorx->schedule.step++; + aNPC_in_house_schedule_think_init(nactorx, play); + } else { + u8 type = (u32)nactorx->npc_info.schedule->current_type; + + if (nactorx->schedule.type != type) { + if (type != mNPS_SCHED_SLEEP && + nactorx->condition_info.talk_condition == aNPC_TALK_TYPE_NONE) { + aNPC_set_schedule(nactorx, play); + } + } + } +} + +static void aNPC_in_house_schedule_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u8 step = aNPC_SCHEDULE_IN_HOUSE_STEP_WANDER; + u8 hide = FALSE; + + if (!aNPC_GET_ANM(nactorx)->is_home && aNPC_IS_NRM_NPC(nactorx)) { + step = aNPC_SCHEDULE_IN_HOUSE_STEP_HIDE; + hide = TRUE; + nactorx->actor_class.world.position.x = 0.0f; + nactorx->actor_class.world.position.z = 0.0f; + } + + aNPC_set_hide_flg(nactorx, hide); + nactorx->schedule.step = step; + aNPC_in_house_schedule_think_init(nactorx, play); +} + +static void aNPC_in_house_schedule_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC sche_proc[] = { + &aNPC_in_house_schedule_init_proc, + &aNPC_in_house_schedule_main_proc, + }; + + (*sche_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_think.c_inc b/src/actor/npc/ac_npc2_think.c_inc new file mode 100644 index 00000000..9589c108 --- /dev/null +++ b/src/actor/npc/ac_npc2_think.c_inc @@ -0,0 +1,853 @@ +static void aNPC_chg_entrance_fg(mActor_name_t fg) { + mActor_name_t* fg_p = mFI_UtNum2UtFG(3, 8); + fg_p[0] = fg; + fg_p[1] = fg; +} + +static int aNPC_check_uzai_cross(NPC_ACTOR* nactorx) { + int ret = FALSE; + + if (ClObj_DID_COLLIDE(nactorx->collision.pipe.collision_obj)) { + ACTOR* collide_actor = nactorx->collision.pipe.collision_obj.collided_actor; + + if (collide_actor->part == ACTOR_PART_PLAYER && !F32_IS_ZERO(gamePT->mcon.adjusted_pR)) { + // @BUG - this should access x and not z +#ifndef BUGFIXES + f32 dx = nactorx->actor_class.world.position.z - collide_actor->world.position.x; +#else + f32 dx = nactorx->actor_class.world.position.x - collide_actor->world.position.x; +#endif + f32 dz = nactorx->actor_class.world.position.z - collide_actor->world.position.z; + s16 angleY = atans_table(dz, dx); + s16 d_angleY = angleY - collide_actor->world.angle.y; + + if (ABS(d_angleY) < DEG2SHORT_ANGLE2(135.0f)) { + ret = TRUE; + } + } + } + + return ret; +} + +static void aNPC_check_uzai(NPC_ACTOR* nactorx) { + static int max_uzai_cross[] = { 600, 240 }; + static int max_uzai_tool[] = { 3, 1 }; + // clang-format off + static int base_msg_no_table[][mNpc_LOOKS_NUM] = { + { + 0x2E11, + 0x2E1C, + 0x2E0C, + 0x2E27, + 0x2E2C, + 0x2E37, + }, + { + 0x3579, + 0x357C, + 0x357F, + 0x3582, + 0x3585, + 0x3588, + }, + }; + // clang-format on + + if (aNPC_IS_NRM_NPC(nactorx)) { + int mem_idx = + mNpc_GetAnimalMemoryIdx(&Now_Private->player_ID, nactorx->npc_info.animal->memories, ANIMAL_MEMORY_NUM); + + if (mem_idx != -1 && (nactorx->condition_info.demo_flg & aNPC_COND_DEMO_SKIP_LOVE_CHECK) == 0) { + int step = nactorx->uzai.step; + + if (aNPC_check_uzai_cross(nactorx) == TRUE) { + step += 2; + } else { + step -= 1; + } + + if (step > max_uzai_cross[nactorx->uzai.cross == 1] || + nactorx->uzai.tool == max_uzai_tool[nactorx->uzai.cross == 1]) { + Animal_c* animal = nactorx->npc_info.animal; + int msg_no; + f32 msg_max = 5; + int pushed = FALSE; + int islander = FALSE; + + if (mNpc_CheckIslandAnimal(animal) == TRUE) { + msg_max = 3; + islander = TRUE; + } + + mISL_SetNowPlayerAction(mISL_PLAYER_ACTION_UZAI_PUSHED); + msg_no = base_msg_no_table[islander][animal->id.looks]; + if (aNPC_force_call_req_proc(nactorx, msg_no + (int)RANDOM_F(msg_max)) == TRUE) { + nactorx->uzai.tool = 0; + nactorx->uzai.cross = 1; + step = 0; + aNPC_set_feel_info(nactorx, aNPC_uzai_feel[mNpc_GetNpcLooks((ACTOR*)nactorx)], 1); + nactorx->think.force_call_camera_type = CAMERA2_PROCESS_TALK; + nactorx->uzai.flag = 0; + } + } else { + if (step < 0) { + step = 0; + } + + nactorx->uzai.flag = 0; + } + + nactorx->uzai.step = step; + } + } +} + +static int aNPC_chk_talk_start(NPC_ACTOR* nactorx) { + ACTOR* palActor = nactorx->palActor; + int ret = FALSE; + + if (palActor != NULL) { + switch (nactorx->condition_info.talk_condition) { + case aNPC_TALK_TYPE_START: + aNPC_set_request_act(nactorx, 4, nactorx->talk_info.default_act, aNPC_ACT_TYPE_DEFAULT, + aNPC_req_default_data); + ret = TRUE; + break; + case aNPC_TALK_TYPE_CONTINUE: + if (aNPC_chk_right_hand(nactorx) == TRUE) { + aNPC_chk_left_hand(nactorx); + } + + ret = TRUE; + break; + } + } + + return ret; +} + +static int aNPC_check_fatigue(NPC_ACTOR* nactorx) { + int ret = FALSE; + + if (aNPC_IS_NRM_NPC(nactorx)) { + switch (nactorx->action.type) { + case aNPC_ACT_TYPE_DEFAULT: + case aNPC_ACT_TYPE_TO_POINT: + if ((nactorx->think.interrupt_flags & aNPC_THINK_INTERRUPT_FATIGUE) != 0 && + nactorx->condition_info.fatigue >= 1600) { + ret = TRUE; + } + break; + } + } + + return ret; +} + +static int aNPC_drt_table[4] = { + aNPC_UNIT_DOWN, + aNPC_UNIT_RIGHT, + aNPC_UNIT_UP, + aNPC_UNIT_LEFT, +}; + +static int aNPC_back_drt_table[5] = { + aNPC_UNIT_LEFT, aNPC_UNIT_RIGHT, aNPC_UNIT_UP, 0, aNPC_UNIT_DOWN, +}; + +static int aNPC_left_drt_table[5] = { + aNPC_UNIT_UP, aNPC_UNIT_DOWN, aNPC_UNIT_RIGHT, 0, aNPC_UNIT_LEFT, +}; + +static int aNPC_right_drt_table[5] = { + aNPC_UNIT_DOWN, aNPC_UNIT_UP, aNPC_UNIT_LEFT, 0, aNPC_UNIT_RIGHT, +}; + +static int aNPC_pl_chk_drt_table[4] = { + aNPC_UNIT_UP, + aNPC_UNIT_DOWN, + aNPC_UNIT_LEFT, + aNPC_UNIT_RIGHT, +}; + +static int aNPC_add_numX[5] = { + 1, -1, 0, 0, 0, +}; + +static int aNPC_add_numZ[5] = { + 0, 0, 1, 0, -1, +}; + +typedef struct { + aNPC_unit_info_c unit_info; + int unit; + int move_dir; +} aNPC_route_work_c; + +typedef struct { + aNPC_route_work_c work[aNPC2_UNIT_NUM]; + int n_work; + u8 _34C[aNPC2_UNIT_NUM]; + int* unit_info_p; + u8 dst_ux; + u8 dst_uz; + s8 dx; + s8 dz; + u8 now_ux; + u8 now_uz; + u8 now_dir; + u8 now_idx; + int* now_unit_p; + aNPC_route_work_c* now_work_p; + u8 first; + u8 initial_lookup; + u8 player_ux; + u8 player_uz; + int calc_dx; + int calc_dz; +} aNPC_route_search_table_c; + +static aNPC_route_search_table_c tbl; + +static int aNPC_think_turn_this_unit(void) { + int ret = FALSE; + + tbl.dx = tbl.dst_ux - tbl.now_ux; + tbl.dz = tbl.dst_uz - tbl.now_uz; + + if (tbl.now_dir == aNPC_UNIT_UP || tbl.now_dir == aNPC_UNIT_DOWN) { + if (tbl.dx != 0) { + if (ABS(tbl.dx) > ABS(tbl.dz)) { + if (tbl.dx < 0) { + if ((*tbl.now_unit_p) & aNPC_UNIT_LEFT) { + tbl.now_dir = aNPC_UNIT_LEFT; + ret = TRUE; + } + } else { + if ((*tbl.now_unit_p) & aNPC_UNIT_RIGHT) { + tbl.now_dir = aNPC_UNIT_RIGHT; + ret = TRUE; + } + } + } + } + } else { + if (tbl.dz != 0) { + if (ABS(tbl.dz) > ABS(tbl.dx)) { + if (tbl.dz < 0) { + if ((*tbl.now_unit_p) & aNPC_UNIT_UP) { + tbl.now_dir = aNPC_UNIT_UP; + ret = TRUE; + } + } else { + if ((*tbl.now_unit_p) & aNPC_UNIT_DOWN) { + tbl.now_dir = aNPC_UNIT_DOWN; + ret = TRUE; + } + } + } + } + } + + return ret; +} + +static int aNPC_decide_turn_this_unit(void) { + int ret = FALSE; + + if (((*tbl.now_unit_p) & aNPC_left_drt_table[tbl.now_dir >> 1]) != 0) { + tbl.now_dir = aNPC_left_drt_table[tbl.now_dir >> 1]; + } else if (((*tbl.now_unit_p) & aNPC_right_drt_table[tbl.now_dir >> 1]) != 0) { + tbl.now_dir = aNPC_right_drt_table[tbl.now_dir >> 1]; + } else { + ret = TRUE; + } + + return ret; +} + +static int aNPC_forward_search_turn_point(void) { + if (tbl.n_work >= aNPC2_UNIT_NUM) { + tbl.n_work = -1; + return aNPC_SEARCH_ROUTE_CANCEL; + } + + if (!tbl.first) { + tbl.now_work_p = tbl.work + (tbl.n_work + 1); + tbl.n_work++; + tbl.now_work_p->unit_info.x = tbl.now_ux + aNPC_add_numX[tbl.now_dir >> 1]; + tbl.now_work_p->unit_info.z = tbl.now_uz + aNPC_add_numZ[tbl.now_dir >> 1]; + tbl.now_work_p->unit_info.direct = tbl.now_dir; + tbl.now_work_p->move_dir = tbl.now_dir; + } else { + tbl.now_work_p = tbl.work + tbl.n_work; + tbl.first = FALSE; + } + + tbl.now_ux = tbl.now_work_p->unit_info.x; + tbl.now_uz = tbl.now_work_p->unit_info.z; + tbl.now_dir = tbl.now_work_p->unit_info.direct; + tbl.now_idx = tbl.now_ux + tbl.now_uz * aNPC2_UNIT_X_NUM; + tbl.now_unit_p = &tbl.now_work_p->unit; + + if (!tbl.initial_lookup) { + *tbl.now_unit_p = tbl.unit_info_p[tbl.now_idx]; + } + + tbl.initial_lookup = FALSE; + tbl.calc_dx = tbl.player_ux - tbl.now_ux; + tbl.calc_dz = tbl.player_uz - tbl.now_uz; + + if (ABS((int)tbl.calc_dx) + ABS((int)tbl.calc_dz) == 1) { + (*tbl.now_unit_p) &= aNPC_pl_chk_drt_table[ABS((int)tbl.calc_dx) * 2 + (((int)tbl.calc_dx + 1) >> 1) + + (((int)tbl.calc_dz + 1) >> 1)] ^ + aNPC_UNIT_ALL; + } + + if (*tbl.now_unit_p == 0) { + tbl.n_work = -1; + return aNPC_SEARCH_ROUTE_CANCEL; + } + + if (tbl.now_ux == tbl.dst_ux && tbl.now_uz == tbl.dst_uz) { + return aNPC_SEARCH_ROUTE_CANCEL; + } + + if (tbl._34C[tbl.now_idx] == TRUE) { + return aNPC_SEARCH_ROUTE_BACKWARD; + } + + if (!aNPC_think_turn_this_unit() && ((*tbl.now_unit_p) & tbl.now_dir) == 0 && + aNPC_decide_turn_this_unit() == TRUE) { + return aNPC_SEARCH_ROUTE_BACKWARD; + } + + tbl._34C[tbl.now_idx] = TRUE; + tbl.now_work_p->unit_info.direct = tbl.now_dir; + (*tbl.now_unit_p) &= tbl.now_dir ^ aNPC_UNIT_ALL; + return aNPC_SEARCH_ROUTE_FORWARD; +} + +static int aNPC_back_search_turn_point(void) { + int unit; + int back_dir; + int i; + + tbl.initial_lookup = TRUE; + if (tbl.n_work == 0) { + if (((*tbl.now_unit_p) & aNPC_back_drt_table[tbl.now_dir >> 1]) == 0) { + if (((*tbl.now_unit_p) & aNPC_left_drt_table[tbl.now_dir >> 1]) == 0) { + if (((*tbl.now_unit_p) & aNPC_right_drt_table[tbl.now_dir >> 1]) == 0) { + tbl.n_work = -1; + return aNPC_SEARCH_ROUTE_CANCEL; + } else { + tbl.now_work_p->unit_info.direct = aNPC_right_drt_table[tbl.now_dir >> 1]; + } + } else { + tbl.now_work_p->unit_info.direct = aNPC_left_drt_table[tbl.now_dir >> 1]; + } + } else { + tbl.now_work_p->unit_info.direct = aNPC_back_drt_table[tbl.now_dir >> 1]; + } + + tbl.first = TRUE; + return aNPC_SEARCH_ROUTE_FORWARD; + } + + tbl.now_work_p = &tbl.work[--tbl.n_work]; + tbl.now_ux = tbl.now_work_p->unit_info.x; + tbl.now_uz = tbl.now_work_p->unit_info.z; + tbl.now_dir = tbl.now_work_p->unit_info.direct; + tbl.now_idx = tbl.now_ux + tbl.now_uz * aNPC2_UNIT_X_NUM; + tbl.now_unit_p = &tbl.now_work_p->unit; + + (*tbl.now_unit_p) &= ((u8)tbl.now_work_p->unit_info.direct ^ aNPC_UNIT_ALL); + + if ((*tbl.now_unit_p) == 0) { + tbl.n_work = -1; + return aNPC_SEARCH_ROUTE_CANCEL; + } + + unit = *tbl.now_unit_p; + back_dir = aNPC_back_drt_table[tbl.now_work_p->move_dir >> 1]; + for (i = 0; i < 4; i++) { + if (unit & (1 << 3)) { + if (back_dir != aNPC_pl_chk_drt_table[i]) { + break; + } + } + + unit <<= 1; + } + + if (i == 4) { + tbl._34C[tbl.now_idx] = FALSE; + return aNPC_SEARCH_ROUTE_BACKWARD; + } + + tbl.now_dir = aNPC_pl_chk_drt_table[i]; + tbl.now_work_p->unit_info.direct = (u8)aNPC_pl_chk_drt_table[i]; + tbl.initial_lookup = FALSE; + return aNPC_SEARCH_ROUTE_FORWARD; +} + +static void aNPC_copy_route(NPC_CONTROL_ACTOR* ctrl, aNPC_route_search_table_c* search, int n) { + aNPC_unit_info_c* route = ctrl->route; + int dir; + int dir_flag; + int i; + int node_count; + + route->x = search->work[1].unit_info.x; + route->z = search->work[1].unit_info.z; + dir = search->work[0].unit_info.direct; + route->direct = dir; + route++; + + dir_flag = FALSE; + for (i = 1, node_count = 1; i <= n; i++) { + if (dir != search->work[i].unit_info.direct) { + if (dir_flag == TRUE) { + node_count++; + route->x = search->work[i].unit_info.x; + route->z = search->work[i].unit_info.z; + route->direct = dir; + route++; + } + + dir_flag = FALSE; + node_count++; + route->x = search->work[i + 1].unit_info.x; + route->z = search->work[i + 1].unit_info.z; + route->direct = search->work[i].unit_info.direct; + route++; + + dir = search->work[i].unit_info.direct; + } else { + dir_flag = TRUE; + } + } + + route->x = search->work[n].unit_info.x; + route->z = search->work[n].unit_info.z; + route->direct = search->work[n].unit_info.direct; + ctrl->route_node_count = node_count; +} + +typedef int (*aNPC_SEARCH_ROUTE_PROC)(void); + +static int aNPC_route_check(NPC_ACTOR* nactorx, GAME_PLAY* play, int dst_ux, int dst_uz, int turn_flag) { + static aNPC_SEARCH_ROUTE_PROC search_route_proc[] = { + &aNPC_forward_search_turn_point, + &aNPC_back_search_turn_point, + }; + + int ret = aNPC_ROUTE_ERROR; + + if (nactorx->movement.movement_ut_x != dst_ux || nactorx->movement.movement_ut_z != dst_uz || turn_flag == TRUE) { + NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + int* unit_info_p = (int*)ctrl->unit_info; + int dir; + int ux; + int uz; + int turn_unit_info = 0; + + dir = aNPC_drt_table[((nactorx->actor_class.world.angle.y + DEG2SHORT_ANGLE2(45.0f)) >> 14) & + 3]; // >> 14 = / DEG2SHORT_ANGLE2(90.0f) [0x4000] + bzero(&tbl, sizeof(tbl)); + mFI_Wpos2UtNum(&ux, &uz, nactorx->actor_class.world.position); + ux--; + uz--; + + tbl.work[0].unit_info.x = ux; + tbl.work[0].unit_info.z = uz; + tbl.work[0].unit_info.direct = dir; + tbl.unit_info_p = unit_info_p; + tbl.dst_ux = dst_ux; + tbl.dst_uz = dst_uz; + tbl.first = TRUE; + tbl.initial_lookup = FALSE; + + { + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + + if (playerx == NULL) { + tbl.player_ux = 0xFF; + tbl.player_uz = 0xFF; + } else { + mFI_Wpos2UtNum(&ux, &uz, playerx->world.position); + ux--; + uz--; + tbl.player_ux = ux; + tbl.player_uz = uz; + } + } + + if (turn_flag == TRUE) { + turn_unit_info = dir & *(unit_info_p + ux + uz * aNPC2_UNIT_X_NUM); + *(unit_info_p + ux + uz * aNPC2_UNIT_X_NUM) &= dir ^ aNPC_UNIT_ALL; + } + + { + int res = aNPC_SEARCH_ROUTE_FORWARD; + int count = 0; + + while (TRUE) { + res = (*search_route_proc[res])(); + if (res == aNPC_SEARCH_ROUTE_CANCEL) { + break; + } + + if (count > (aNPC2_UNIT_X_NUM * (aNPC2_UNIT_Z_NUM - 1))) { + tbl.n_work = -1; + break; + } + + count++; + } + } + + if (tbl.n_work < 0) { + ret = aNPC_ROUTE_ERROR; + } else if (tbl.n_work == 0) { + ret = aNPC_ROUTE_FINISH; + } else { + aNPC_unit_info_c* route; + f32 pos_x; + f32 pos_z; + + nactorx->movement.movement_ut_x = dst_ux; + nactorx->movement.movement_ut_z = dst_uz; + aNPC_copy_route(ctrl, &tbl, tbl.n_work); + if (dst_uz == (aNPC2_UNIT_Z_NUM - 1)) { + pos_x = 160.0f; + pos_z = 300.0f; + } else { + pos_x = (dst_ux + 1) * mFI_UT_WORLDSIZE_X_F; + pos_z = (dst_uz + 1) * mFI_UT_WORLDSIZE_Z_F; + } + + aNPC_set_dst_pos(nactorx, pos_x, pos_z); + nactorx->movement.avoid_direction = 1; + + ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + route = ctrl->route; + pos_x = (route[0].x + 1.5f) * mFI_UT_WORLDSIZE_X_F; + pos_z = (route[0].z + 1.5f) * mFI_UT_WORLDSIZE_Z_F; + aNPC_set_avoid_pos(nactorx, pos_x, pos_z); + ret = aNPC_ROUTE_MOVING; + } + + if (turn_flag == TRUE) { + *(unit_info_p + ux + uz * aNPC2_UNIT_X_NUM) |= turn_unit_info; + } + } + + return ret; +} + +static void aNPC_turn_to_another_route(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + u8 act_idx = aNPC_ACT_WAIT; + + bzero(arg_data, sizeof(arg_data)); + if (aNPC_route_check(nactorx, play, nactorx->movement.movement_ut_x, nactorx->movement.movement_ut_z, TRUE) == + aNPC_ROUTE_MOVING) { + act_idx = aNPC_ACT_TURN; + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } + + aNPC_set_request_act(nactorx, 1, act_idx, aNPC_ACT_TYPE_DEFAULT, arg_data); +} + +static int aNPC_avoid_obstacle(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + + if ((nactorx->think.interrupt_flags & aNPC_THINK_INTERRUPT_OBSTACLE) != 0) { + if (ClObj_DID_COLLIDE(nactorx->collision.pipe.collision_obj)) { + if ((nactorx->collision.pipe.collision_obj.collision_flags1 & 1)) { + s16 d_angle = nactorx->actor_class.player_angle_y - nactorx->actor_class.shape_info.rotation.y; + + if (ABS(d_angle) < DEG2SHORT_ANGLE2(45.0f)) { + aNPC_turn_to_another_route(nactorx, play); + } else { + aNPC_set_request_act(nactorx, 1, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); + } + + ret = TRUE; + } + } + } + + return ret; +} + +static int aNPC_hate_player(NPC_ACTOR* nactorx, GAME_PLAY* play) { + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + u8 act_idx; + + bzero(arg_data, sizeof(arg_data)); + arg_data[0] = aNPC_ACT_OBJ_PLAYER; + + if (playerx == NULL) { + act_idx = aNPC_ACT_WAIT; + } else { + NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + int safe_ux; + int safe_uz; + int player_ux; + int player_uz; + int idx; + + mFI_Wpos2UtNum(&player_ux, &player_uz, playerx->world.position); + player_ux--; + player_uz--; + + idx = (player_uz < 3) + (player_ux < 3) * 2; + safe_ux = ctrl->safe_ux[idx]; + safe_uz = ctrl->safe_uz[idx]; + + if (nactorx->movement.movement_ut_x == safe_ux && nactorx->movement.movement_ut_z == safe_uz) { + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + if (nactorx->action.idx == aNPC_ACT_TURN) { + act_idx = aNPC_ACT_WALK; + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } else { + act_idx = aNPC_ACT_WAIT; + } + } else { + act_idx = nactorx->action.idx; + } + } else { + if (aNPC_route_check(nactorx, play, safe_ux, safe_uz, FALSE) == aNPC_ROUTE_MOVING) { + aNPC_unit_info_c* route = ctrl->route; + int dir = route[0].direct; + + if (dir != + aNPC_drt_table[(((nactorx->actor_class.world.angle.y + DEG2SHORT_ANGLE2(45.0f)) >> 14) & 3)]) { + act_idx = aNPC_ACT_TURN; + } else { + act_idx = aNPC_ACT_WALK; + } + + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } else { + act_idx = aNPC_ACT_WAIT; + } + } + } + + return aNPC_set_request_act(nactorx, 1, act_idx, aNPC_ACT_TYPE_AVOID, arg_data); +} + +static int aNPC_love_player(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + + if (Now_Private->gender != mNpc_GetLooks2Sex(aNPC_GET_LOOKS(nactorx))) { + NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + u8 next_act = aNPC_ACT_WAIT; + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + + bzero(arg_data, sizeof(arg_data)); + arg_data[0] = aNPC_ACT_OBJ_PLAYER; + if (nactorx->think.force_call_flag == aNPC_FORCE_CALL_NONE && nactorx->think.force_call_timer == 0) { + nactorx->think.force_call_flag = aNPC_FORCE_CALL_REQUEST; + } + + if (playerx != NULL) { + int player_ux; + int player_uz; + + mFI_Wpos2UtNum(&player_ux, &player_uz, playerx->world.position); + player_ux--; + player_uz--; + + if (nactorx->movement.movement_ut_x == player_ux && nactorx->movement.movement_ut_z == player_uz) { + if (nactorx->action.step == aNPC_ACTION_END_STEP && nactorx->action.idx == aNPC_ACT_TURN) { + next_act = aNPC_ACT_WALK; + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } + } else if (aNPC_route_check(nactorx, play, player_ux, player_uz, FALSE) == aNPC_ROUTE_MOVING) { + aNPC_unit_info_c* route = ctrl->route; + int dir = route[0].direct; + + if (dir != + aNPC_drt_table[(((nactorx->actor_class.world.angle.y + DEG2SHORT_ANGLE2(45.0f)) >> 14) & 3)]) { + next_act = aNPC_ACT_TURN; + } else { + next_act = aNPC_ACT_WALK; + } + + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } + } + + ret = aNPC_set_request_act(nactorx, 1, next_act, aNPC_ACT_TYPE_AVOID, arg_data); + } + + return ret; +} + +static int aNPC_chk_friendship_lv(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + int friendship = (*nactorx->condition_info.friendship) + nactorx->condition_info.over_friendship; + + if (friendship < 0) { + ret = aNPC_hate_player(nactorx, play); + } else if (friendship > 128) { + ret = aNPC_love_player(nactorx, play); + } + + return ret; +} + +static int aNPC_chk_friendship_sub(NPC_ACTOR* nactorx, GAME_PLAY* play) { + s8* friendship_p = nactorx->condition_info.friendship; + int ret = FALSE; + + if (friendship_p == NULL) { + if (aNPC_IS_NRM_NPC(nactorx) && aNPC_setP_friendship(nactorx) == TRUE) { + ret = aNPC_chk_friendship_lv(nactorx, play); + } + } else { + ret = aNPC_chk_friendship_lv(nactorx, play); + } + + return ret; +} + +static int aNPC_chk_friendship(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + + if ((nactorx->think.interrupt_flags & aNPC_THINK_INTERRUPT_FRIENDSHIP) != 0 && !aNPC_IS_SP_NPC(nactorx)) { + switch (nactorx->action.idx) { + case aNPC_ACT_WAIT: + case aNPC_ACT_WALK: + case aNPC_ACT_RUN: + ret = aNPC_chk_friendship_sub(nactorx, play); + break; + default: + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + ret = aNPC_chk_friendship_sub(nactorx, play); + } + break; + } + } + + return ret; +} + +static int aNPC_think_chk_interrupt_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + + if (aNPC_chk_talk_start(nactorx) == TRUE) { + ret = TRUE; + } else if (aNPC_chk_right_hand(nactorx) == FALSE) { + ret = TRUE; + } else if (aNPC_chk_left_hand(nactorx) == FALSE) { + ret = TRUE; + } else { + aNPC_check_uzai(nactorx); + if (!F32_IS_ZERO(nactorx->actor_class.speed)) { + if (aNPC_check_fatigue(nactorx) == TRUE) { + aNPC_set_request_act(nactorx, 1, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); + ret = TRUE; + } else { + ret = aNPC_avoid_obstacle(nactorx, play); + } + } + + if (ret == FALSE) { + ret = aNPC_chk_friendship(nactorx, play); + } + } + + return ret; +} + +static void aNPC_think_wait_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + aNPC_set_request_act(nactorx, 1, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); +} + +static void aNPC_think_wait_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + if (proc_type == aNPC_THINK_PROC_INIT) { + aNPC_think_wait_init_proc(nactorx, play); + } +} + +static void aNPC_think_hide_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); + + if (playerx != NULL && playerx->world.position.z < 270.0f && + mEvNM_CheckJointEvent(nactorx->actor_class.npc_id) == FALSE) { + nactorx->think.end_flag = TRUE; + } +} + +static void aNPC_think_hide_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + static aNPC_SUB_PROC think_proc[] = { + &aNPC_think_wait_init_proc, + &aNPC_think_hide_main_proc, + }; + + (*think_proc[proc_type])(nactorx, play); +} + +static void aNPC_think_special_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + (*nactorx->think.think_proc)(nactorx, play, proc_type); +} + +#include "../src/actor/npc/ac_npc2_think_wander.c_inc" +#include "../src/actor/npc/ac_npc2_think_out_of_room.c_inc" +#include "../src/actor/npc/ac_npc2_think_exit_wait.c_inc" +#include "../src/actor/npc/ac_npc2_think_into_room.c_inc" + +static aNPC_THINK_PROC aNPC_think_proc_tbl[] = { + &aNPC_think_wait_proc, + &aNPC_think_hide_proc, + &aNPC_think_wander_proc, + &aNPC_think_out_of_room_proc, + &aNPC_think_exit_wait_proc, + &aNPC_think_into_room_proc, + &aNPC_think_special_proc, +}; + +static void aNPC_think_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int think_idx) { + nactorx->think.interrupt_flags = aNPC_THINK_INTERRUPT_OBSTACLE | + aNPC_THINK_INTERRUPT_FATIGUE | aNPC_THINK_INTERRUPT_FRIENDSHIP; + nactorx->think.idx = think_idx; + (*aNPC_think_proc_tbl[think_idx])(nactorx, play, aNPC_THINK_PROC_INIT); + nactorx->think.end_flag = FALSE; +} + +static void aNPC_think_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int think_idx = nactorx->think.idx; + + (*aNPC_think_proc_tbl[think_idx])(nactorx, play, aNPC_THINK_PROC_MAIN); +} + +static int aNPC_think_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int think_idx, int proc_type) { + int ret = FALSE; + + switch (proc_type) { + case aNPC_THINK_TYPE_INIT: + aNPC_think_init_proc(nactorx, play, think_idx); + break; + case aNPC_THINK_TYPE_CHK_INTERRUPT: + ret = aNPC_think_chk_interrupt_proc(nactorx, play); + break; + case aNPC_THINK_TYPE_MAIN: + aNPC_think_main_proc(nactorx, play); + break; + } + + return ret; +} diff --git a/src/actor/npc/ac_npc2_think_exit_wait.c_inc b/src/actor/npc/ac_npc2_think_exit_wait.c_inc new file mode 100644 index 00000000..5dea5f89 --- /dev/null +++ b/src/actor/npc/ac_npc2_think_exit_wait.c_inc @@ -0,0 +1,80 @@ +static void aNPC_think_exit_wait_decide_next_act_idx(NPC_ACTOR* nactorx) { + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + u8 act_idx = aNPC_ACT_WALK; + s16 angle = DEG2SHORT_ANGLE2(45.0f); + + bzero(arg_data, sizeof(arg_data)); + nactorx->condition_info.demo_flg = + aNPC_COND_DEMO_SKIP_FEEL_CHECK | aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | + aNPC_COND_DEMO_SKIP_TALK_CHECK | 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; + if (nactorx->action.idx == aNPC_ACT_WALK) { + nactorx->action.step = 0; + angle = DEG2SHORT_ANGLE2(22.5f); + } + + if (ABS(nactorx->actor_class.shape_info.rotation.y) > angle) { + act_idx = aNPC_ACT_TURN; + } + + arg_data[2] = (int)nactorx->actor_class.world.position.x; + arg_data[3] = 360; + aNPC_set_request_act(nactorx, 4, act_idx, aNPC_ACT_TYPE_TO_POINT, arg_data); +} + +static void aNPC_think_exit_wait_setup_exit_info(NPC_ACTOR* nactorx) { + aNPC_OngenTrgStart(nactorx, NA_SE_40B); + nactorx->actor_class.world.position.x = 0.0f; + nactorx->actor_class.world.position.z = 0.0f; + aNPC_set_hide_request(nactorx, TRUE); + aNPC_chg_entrance_fg(EXIT_DOOR); + nactorx->think.end_flag = TRUE; + nactorx->actor_class.status_data.weight = 50; +} + +static int aNPC_think_exit_wait_chk_interrupt(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + + if (aNPC_chk_talk_start(nactorx) == TRUE) { + ret = TRUE; + } else if (aNPC_chk_right_hand(nactorx) == FALSE) { + ret = TRUE; + } else if (aNPC_chk_left_hand(nactorx) == FALSE) { + ret = TRUE; + } + + return ret; +} + +static void aNPC_think_exit_wait_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (aNPC_think_exit_wait_chk_interrupt(nactorx, play) == FALSE) { + if (nactorx->action.step == aNPC_ACTION_END_STEP && !mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)nactorx)) { + if (nactorx->action.idx == aNPC_ACT_WALK && nactorx->actor_class.world.position.z >= 360.0f) { + aNPC_think_exit_wait_setup_exit_info(nactorx); + } else { + aNPC_think_exit_wait_decide_next_act_idx(nactorx); + } + } + } +} + +static void aNPC_think_exit_wait_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->think.force_call_flag = aNPC_FORCE_CALL_NONE; + nactorx->actor_class.status_data.weight = MASSTYPE_HEAVY; + aNPC_set_be_out_home(nactorx); + aNPC_chg_entrance_fg(RSV_NO); + if (!mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)nactorx)) { + aNPC_think_exit_wait_decide_next_act_idx(nactorx); + } +} + +static void aNPC_think_exit_wait_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + // clang-format off + static aNPC_SUB_PROC think_proc[] = { + &aNPC_think_exit_wait_init_proc, + &aNPC_think_exit_wait_main_proc, + }; + // clang-format on + + (*think_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_think_into_room.c_inc b/src/actor/npc/ac_npc2_think_into_room.c_inc new file mode 100644 index 00000000..31e5da34 --- /dev/null +++ b/src/actor/npc/ac_npc2_think_into_room.c_inc @@ -0,0 +1,42 @@ +static void aNPC_think_into_room_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + aNPC_chg_entrance_fg(EXIT_DOOR); + nactorx->actor_class.status_data.weight = 50; + nactorx->think.end_flag = TRUE; + } +} + +static void aNPC_think_into_room_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + + bzero(arg_data, sizeof(arg_data)); + nactorx->think.force_call_flag = aNPC_FORCE_CALL_NONE; + nactorx->actor_class.status_data.weight = MASSTYPE_HEAVY; + nactorx->actor_class.world.position.x = 160.0f; + nactorx->actor_class.world.position.y = 40.0f; + nactorx->actor_class.world.position.z = 360.0f; + nactorx->actor_class.shape_info.rotation.y = DEG2SHORT_ANGLE2(180.0f); + nactorx->actor_class.world.angle.y = DEG2SHORT_ANGLE2(180.0f); + aNPC_set_hide_request(nactorx, FALSE); + aNPC_chg_entrance_fg(RSV_NO); + + aNPC_GET_ANM(nactorx)->is_home = TRUE; + nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_FEEL_CHECK | aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | + aNPC_COND_DEMO_SKIP_TALK_CHECK | 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; + aNPC_OngenTrgStart(nactorx, NA_SE_40B); + arg_data[2] = 160; + arg_data[3] = 300; + aNPC_set_request_act(nactorx, 4, aNPC_ACT_WALK, aNPC_ACT_TYPE_TO_POINT, arg_data); +} + +static void aNPC_think_into_room_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + // clang-format off + static aNPC_SUB_PROC think_proc[] = { + &aNPC_think_into_room_init_proc, + &aNPC_think_into_room_main_proc, + }; + // clang-format on + + (*think_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_think_out_of_room.c_inc b/src/actor/npc/ac_npc2_think_out_of_room.c_inc new file mode 100644 index 00000000..fd10dfb8 --- /dev/null +++ b/src/actor/npc/ac_npc2_think_out_of_room.c_inc @@ -0,0 +1,84 @@ +static u8 aNPC_think_out_of_room_route_check(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u8 act_idx = aNPC_ACT_WAIT; + int route_ret; + int i; + + nactorx->movement.movement_ut_x = -1; + nactorx->movement.movement_ut_z = -1; + for (i = 2; i < 4; i++) { + route_ret = aNPC_route_check(nactorx, play, i, aNPC2_UNIT_Z_NUM - 1, FALSE); + if (route_ret == aNPC_ROUTE_MOVING) { + NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + aNPC_unit_info_c* route = ctrl->route; + int dir = route[0].direct; + + if (dir != + aNPC_drt_table[(((nactorx->actor_class.world.angle.y + DEG2SHORT_ANGLE2(45.0f)) >> 14) & 3)]) { + act_idx = aNPC_ACT_TURN; + } else { + act_idx = aNPC_ACT_WALK; + } + break; + } + + if (route_ret == aNPC_ROUTE_FINISH) { + nactorx->think.end_flag = TRUE; + act_idx = aNPC_ACT_WAIT; + break; + } + } + + return act_idx; +} + +static int aNPC_think_out_of_room_chk_interrupt(NPC_ACTOR* nactorx, GAME_PLAY* play) { + int ret = FALSE; + + if (aNPC_chk_talk_start(nactorx) == TRUE) { + ret = TRUE; + } else if (aNPC_chk_right_hand(nactorx) == FALSE) { + ret = TRUE; + } else if (aNPC_chk_left_hand(nactorx) == FALSE) { + ret = TRUE; + } else { + if (!F32_IS_ZERO(nactorx->actor_class.speed)) { + ret = aNPC_avoid_obstacle(nactorx, play); + } + } + + return ret; +} + +static void aNPC_think_out_of_room_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (aNPC_think_out_of_room_chk_interrupt(nactorx, play) == FALSE) { + if (nactorx->actor_class.world.position.z >= 294.0f) { + nactorx->think.end_flag = TRUE; + } else { + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + u8 act_idx = aNPC_think_out_of_room_route_check(nactorx, play); + + if (act_idx == nactorx->action.idx) { + nactorx->action.step = 0; + } + + aNPC_set_request_act(nactorx, 1, act_idx, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); + } + } + } +} + +static void aNPC_think_out_of_room_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->think.force_call_flag = aNPC_FORCE_CALL_NONE; + aNPC_set_request_act(nactorx, 1, aNPC_think_out_of_room_route_check(nactorx, play), aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); +} + +static void aNPC_think_out_of_room_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + // clang-format off + static aNPC_SUB_PROC think_proc[] = { + &aNPC_think_out_of_room_init_proc, + &aNPC_think_out_of_room_main_proc, + }; + // clang-format on + + (*think_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc2_think_wander.c_inc b/src/actor/npc/ac_npc2_think_wander.c_inc new file mode 100644 index 00000000..fcfec3e5 --- /dev/null +++ b/src/actor/npc/ac_npc2_think_wander.c_inc @@ -0,0 +1,86 @@ +static void aNPC_think_wander_decide_next(NPC_ACTOR* nactorx, GAME_PLAY* play) { + NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; + u8 act_type; + u16 arg_data[aNPC_REQUEST_ARG_NUM]; + u8 act_idx; + + act_type = aNPC_ACT_TYPE_DEFAULT; + bzero(arg_data, sizeof(arg_data)); + + if (aNPC_check_fatigue(nactorx) == TRUE) { + act_idx = aNPC_ACT_WAIT; + } else if (nactorx->action.idx == aNPC_ACT_TURN) { + act_idx = aNPC_ACT_WALK; + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } else { + int x; + int z; + + if (RANDOM_F(1.0f) < 0.75f) { + act_idx = aNPC_ACT_WAIT; + } else { + int* unit_info_p = (int*)ctrl->unit_info; + while (TRUE) { + x = RANDOM(aNPC2_UNIT_X_NUM); + z = RANDOM(aNPC2_UNIT_Z_NUM - 1); + + if (*(unit_info_p + x + z * aNPC2_UNIT_X_NUM) != 0) { + break; + } + } + + if (aNPC_route_check(nactorx, play, x, z, FALSE) == aNPC_ROUTE_MOVING) { + aNPC_unit_info_c* route = ctrl->route; + int dir = route[0].direct; + + if (dir != + aNPC_drt_table[(((nactorx->actor_class.world.angle.y + DEG2SHORT_ANGLE2(45.0f)) >> 14) & 3)]) { + act_idx = aNPC_ACT_TURN; + } else { + act_idx = aNPC_ACT_WALK; + } + + arg_data[2] = (int)nactorx->movement.avoid_pos_x; + arg_data[3] = (int)nactorx->movement.avoid_pos_z; + } else { + act_idx = aNPC_ACT_WAIT; + } + } + } + + if (act_idx == nactorx->action.idx) { + nactorx->action.step = 0; + } + + aNPC_set_request_act(nactorx, 1, act_idx, act_type, arg_data); +} + +static void aNPC_think_wander_next_act(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (nactorx->action.step == aNPC_ACTION_END_STEP) { + aNPC_think_wander_decide_next(nactorx, play); + } +} + +static void aNPC_think_wander_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + if (aNPC_think_chk_interrupt_proc(nactorx, play) == FALSE) { + aNPC_think_wander_next_act(nactorx, play); + } +} + +static void aNPC_think_wander_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + nactorx->condition_info.demo_flg = 0; + nactorx->think.force_call_flag = aNPC_FORCE_CALL_NONE; + aNPC_set_request_act(nactorx, 1, aNPC_ACT_WAIT, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); +} + +static void aNPC_think_wander_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int proc_type) { + // clang-format off + static aNPC_SUB_PROC think_proc[] = { + &aNPC_think_wander_init_proc, + &aNPC_think_wander_main_proc, + }; + // clang-format on + + (*think_proc[proc_type])(nactorx, play); +} diff --git a/src/actor/npc/ac_npc_act_ensou.c_inc b/src/actor/npc/ac_npc_act_ensou.c_inc index 7755d694..fa91c36b 100644 --- a/src/actor/npc/ac_npc_act_ensou.c_inc +++ b/src/actor/npc/ac_npc_act_ensou.c_inc @@ -5,6 +5,7 @@ enum { }; static void aNPC_act_ensou_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { +#ifndef aNPC_NPC2 u8 step = aNPC_ACT_ENSOU_STEP_ENSOU; if (nactorx->draw.main_animation_state == cKF_STATE_CONTINUE) { @@ -13,12 +14,24 @@ static void aNPC_act_ensou_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { } nactorx->action.step = step; +#else + nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_HEAD_LOOKAT; + nactorx->action.step = aNPC_ACTION_END_STEP; +#endif } static void aNPC_act_ensou_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { +#ifndef aNPC_NPC2 nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK; +#else + nactorx->condition_info.demo_flg = -1; +#endif nactorx->action.step = aNPC_ACT_ENSOU_STEP_ENSOU; +#ifndef aNPC_NPC2 aNPC_setupAction(nactorx, aNPC_ACTION_TYPE_ENSOU_E); +#else + aNPC_setupAction(nactorx, aNPC_ACTION_TYPE_ENSOU); +#endif } static void aNPC_act_ensou_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { diff --git a/src/actor/npc/ac_npc_act_get.c_inc b/src/actor/npc/ac_npc_act_get.c_inc index 3d2c13fe..463a4305 100644 --- a/src/actor/npc/ac_npc_act_get.c_inc +++ b/src/actor/npc/ac_npc_act_get.c_inc @@ -107,11 +107,19 @@ static void aNPC_act_get_move(NPC_ACTOR* nactorx, GAME_PLAY* play) { nactorx->movement.demo_move_timer--; } +#ifndef aNPC_NPC2 if (!aNPC_act_search_move(nactorx) || (nactorx->collision.collision_flag & (mCoBG_HIT_WALL | mCoBG_HIT_WALL_FRONT)) != 0 || nactorx->movement.demo_move_timer == 0) { aNPC_act_get_chg_step(nactorx, aNPC_ACT_GET_STEP_GET); } +#else + if (!aNPC_act_demo_move(nactorx) || + (nactorx->collision.collision_flag & (mCoBG_HIT_WALL | mCoBG_HIT_WALL_FRONT)) != 0 || + nactorx->movement.demo_move_timer == 0) { + aNPC_act_get_chg_step(nactorx, aNPC_ACT_GET_STEP_GET); + } +#endif } static void aNPC_act_get(NPC_ACTOR* nactorx, GAME_PLAY* play) { @@ -220,6 +228,7 @@ static void aNPC_act_get_chg_cloth(NPC_ACTOR* nactorx, GAME_PLAY* play) { } } +#ifndef aNPC_NPC2 static void aNPC_act_get_chg_umb(NPC_ACTOR* nactorx, GAME_PLAY* play) { if (nactorx->draw.umb_state == aNPC_CLOTH_CHG_STEP_END) { aNPC_act_get_putaway(nactorx, play); @@ -283,6 +292,7 @@ static void aNPC_act_get_chg_cloth_and_umb(NPC_ACTOR* nactorx, GAME_PLAY* play) break; } } +#endif static void aNPC_act_get_return(NPC_ACTOR* nactorx, GAME_PLAY* play) { if (nactorx->draw.main_animation_state == cKF_STATE_STOPPED) { @@ -309,8 +319,13 @@ static void aNPC_act_get_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { &aNPC_act_get_putaway, &aNPC_act_get_putaway, &aNPC_act_get_chg_cloth, +#ifndef aNPC_NPC2 &aNPC_act_get_chg_umb, &aNPC_act_get_chg_cloth_and_umb, +#else + (aNPC_SUB_PROC)&none_proc1, + (aNPC_SUB_PROC)&none_proc1, +#endif &aNPC_act_get_return, &aNPC_act_trans_wait, &aNPC_act_estimate diff --git a/src/actor/npc/ac_npc_act_talk.c_inc b/src/actor/npc/ac_npc_act_talk.c_inc index 340710e4..3c3e580a 100644 --- a/src/actor/npc/ac_npc_act_talk.c_inc +++ b/src/actor/npc/ac_npc_act_talk.c_inc @@ -39,6 +39,7 @@ static int aNPC_talk_end_check(ACTOR* actorx, GAME* game) { return ret; } +#ifndef aNPC_NPC2 static void aNPC_act_talk_chg_step(NPC_ACTOR* nactorx, u8 step) { // clang-format off static u8 act_idx[] = { @@ -51,6 +52,34 @@ static void aNPC_act_talk_chg_step(NPC_ACTOR* nactorx, u8 step) { nactorx->action.step = step; aNPC_setupAction(nactorx, act_idx[step]); } +#else +static void aNPC_act_talk_chg_step(NPC_ACTOR* nactorx, u8 step) { + // clang-format off + static u8 act_idx[][3] = { + { + aNPC_ACTION_TYPE_TALK_TURN, + aNPC_ACTION_TYPE_TALK, + aNPC_ACTION_TYPE_TALK, + }, + { + aNPC_ACTION_TYPE_WAIT_E, + aNPC_ACTION_TYPE_WAIT_E, + aNPC_ACTION_TYPE_WAIT_E, + }, + }; + // clang-format on + int idx; + + if (nactorx->action.idx == aNPC_ACT_TALK) { + idx = 0; + } else { + idx = 1; + } + + nactorx->action.step = step; + aNPC_setupAction(nactorx, act_idx[idx][step]); +} +#endif static void aNPC_act_talk_turn(NPC_ACTOR* nactorx, GAME_PLAY* play) { if (!aNPC_act_turn(nactorx)) { @@ -96,6 +125,7 @@ static void aNPC_act_talk_main_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { (*act_proc[nactorx->action.step])(nactorx, play); } +#ifndef aNPC_NPC2 static void aNPC_act_talk_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { u8 step = aNPC_ACT_TALK_STEP_TALK_TURN; @@ -119,6 +149,29 @@ static void aNPC_act_talk_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { aNPC_act_talk_chg_step(nactorx, step); } +#else +static void aNPC_act_talk_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { + u8 step = aNPC_ACT_TALK_STEP_TALK_TURN; + + if (nactorx->action.idx == aNPC_ACT_WAIT_E) { + nactorx->condition_info.demo_flg = aNPC_COND_DEMO_SKIP_ENTRANCE_CHECK | aNPC_COND_DEMO_SKIP_HEAD_LOOKAT | aNPC_COND_DEMO_SKIP_FORWARD_CHECK | aNPC_COND_DEMO_SKIP_BGCHECK | aNPC_COND_DEMO_SKIP_OBJ_COL_CHECK | aNPC_COND_DEMO_SKIP_MOVE_Y | aNPC_COND_DEMO_SKIP_MOVE_CIRCLE_REV | aNPC_COND_DEMO_SKIP_MOVE_RANGE_CHECK; + } else { + nactorx->condition_info.demo_flg = 0; + } + + if (nactorx->condition_info.talk_condition == aNPC_TALK_TYPE_CONTINUE) { + step = aNPC_ACT_TALK_STEP_TALK; + } else { + aNPC_Init_OrderValue(); + if (nactorx->talk_info.turn != aNPC_TALK_TURN_NORMAL) { + step = aNPC_ACT_TALK_STEP_TALK_WAIT; + } + nactorx->condition_info.talk_condition = aNPC_TALK_TYPE_CONTINUE; + } + + aNPC_act_talk_chg_step(nactorx, step); +} +#endif static void aNPC_act_talk_proc(NPC_ACTOR* nactorx, GAME_PLAY* play, int type) { static aNPC_SUB_PROC act_proc[] = { &aNPC_act_talk_init_proc, (aNPC_SUB_PROC)&none_proc1, &aNPC_act_talk_main_proc }; diff --git a/src/actor/npc/ac_npc_act_trans.c_inc b/src/actor/npc/ac_npc_act_trans.c_inc index 1aa935ad..4a7e3653 100644 --- a/src/actor/npc/ac_npc_act_trans.c_inc +++ b/src/actor/npc/ac_npc_act_trans.c_inc @@ -11,6 +11,7 @@ enum { }; static void aNPC_act_trans_chg_step(NPC_ACTOR* nactorx, u8 step) { +#ifndef aNPC_NPC2 // clang-format off static u8 act_idx[] = { aNPC_ACTION_TYPE_WALK, @@ -22,6 +23,19 @@ static void aNPC_act_trans_chg_step(NPC_ACTOR* nactorx, u8 step) { aNPC_ACTION_TYPE_TALK, }; // clang-format on +#else + // clang-format off + static u8 act_idx[] = { + aNPC_ACTION_TYPE_WALK, + aNPC_ACTION_TYPE_TRANSFER, + aNPC_ACTION_TYPE_TRANSFER, + aNPC_ACTION_TYPE_TRANS_WAIT, + aNPC_ACTION_TYPE_TRANS_WAIT, + aNPC_ACTION_TYPE_SEND_MAIL, + aNPC_ACTION_TYPE_TALK, + }; + // clang-format on +#endif u8 timer = 0; @@ -67,12 +81,21 @@ static void aNPC_act_trans_move(NPC_ACTOR* nactorx, GAME_PLAY* play) { nactorx->movement.demo_move_timer--; } +#ifndef aNPC_NPC2 if (!aNPC_act_search_move(nactorx) || (nactorx->collision.collision_flag & (mCoBG_HIT_WALL | mCoBG_HIT_WALL_FRONT)) != 0 || nactorx->movement.demo_move_timer == 0) { aNPC_act_trans_set_arg_data(nactorx); aNPC_act_trans_chg_step(nactorx, aNPC_ACT_TRANS_STEP_TRANS); } +#else + if (!aNPC_act_demo_move(nactorx) || + (nactorx->collision.collision_flag & (mCoBG_HIT_WALL | mCoBG_HIT_WALL_FRONT)) != 0 || + nactorx->movement.demo_move_timer == 0) { + aNPC_act_trans_set_arg_data(nactorx); + aNPC_act_trans_chg_step(nactorx, aNPC_ACT_TRANS_STEP_TRANS); + } +#endif } static void aNPC_act_trans(NPC_ACTOR* nactorx, GAME_PLAY* play) { diff --git a/src/actor/npc/ac_npc_act_turn.c_inc b/src/actor/npc/ac_npc_act_turn.c_inc index 7a98c7e9..97fcc9f1 100644 --- a/src/actor/npc/ac_npc_act_turn.c_inc +++ b/src/actor/npc/ac_npc_act_turn.c_inc @@ -41,7 +41,11 @@ static void aNPC_act_turn_init_proc(NPC_ACTOR* nactorx, GAME_PLAY* play) { nactorx->action.step = aNPC_ACT_TURN_STEP_MAIN; if (nactorx->action.type == aNPC_ACT_TYPE_AVOID) { +#ifndef aNPC_NPC2 aNPC_set_avoid_pos(nactorx, nactorx->action.move_x, nactorx->action.move_z, nactorx->request.act_args[4]); +#else + aNPC_set_avoid_pos(nactorx, nactorx->action.move_x, nactorx->action.move_z); +#endif } else { aNPC_set_dst_pos(nactorx, nactorx->action.move_x, nactorx->action.move_z); } diff --git a/src/actor/npc/ac_npc_anime.c_inc b/src/actor/npc/ac_npc_anime.c_inc index 2427093d..40e93869 100644 --- a/src/actor/npc/ac_npc_anime.c_inc +++ b/src/actor/npc/ac_npc_anime.c_inc @@ -28,7 +28,7 @@ static int aNPC_check_talk_anime(NPC_ACTOR* nactorx, int seqNo) { seqNo = nactorx->talk_info.default_turn_animation; } else { // clang-format off - static int talk_def_anime[mNpc_FEEL_ALL_NUM] = { + static int talk_turn_def_anime[mNpc_FEEL_ALL_NUM] = { aNPC_ANIM_WALK1, aNPC_ANIM_WALK1, aNPC_ANIM_WALK_DO1, @@ -46,7 +46,7 @@ static int aNPC_check_talk_anime(NPC_ACTOR* nactorx, int seqNo) { feel = aNPC_get_feel_info(nactorx); } - seqNo = talk_def_anime[feel]; + seqNo = talk_turn_def_anime[feel]; } break; case aNPC_ANIM_TALK1: @@ -292,12 +292,17 @@ static void aNPC_anime_proc_foot(NPC_ACTOR* nactorx, GAME* game, xyz_t* pos_p, a break; } +#ifndef aNPC_NPC2 if (nactorx->draw.animation_id == aNPC_ANIM_KOKERU1) { aNPC_TumbleSe(pos_p); } else { aNPC_WalkSe(pos_p); } +#else + aNPC_WalkSeRoom(pos_p); +#endif } + } static void aNPC_anime_proc_other(NPC_ACTOR* nactorx, aNPC_other_se_data_c* other_se_p) { diff --git a/src/actor/npc/ac_npc_ct.c_inc b/src/actor/npc/ac_npc_ct.c_inc index 2b783b0a..472fd3bf 100644 --- a/src/actor/npc/ac_npc_ct.c_inc +++ b/src/actor/npc/ac_npc_ct.c_inc @@ -29,6 +29,7 @@ static int aNPC_setP_friendship(NPC_ACTOR* nactorx) { return ret; } +#ifndef aNPC_NPC2 static void aNPC_check_force_use_umbrella(NPC_ACTOR* nactorx) { u8 req = FALSE; @@ -42,10 +43,150 @@ static void aNPC_check_force_use_umbrella(NPC_ACTOR* nactorx) { static void aNPC_set_start_pos(ACTOR* actorx) { NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; Animal_c* animal = aNPC_GET_ANM(nactorx); - + mNpcW_GetAppearStatusWay(&nactorx->condition_info.appear_flag, &nactorx->condition_info.appear_rotation, animal); } +#else + +static int aNPC_set_start_pos_sub(ACTOR* actorx, int uz) { + int ux; + int* unit_info_p; + int unit_flag; + int i; + int ret; + + unit_info_p = (int*)((NPC_CONTROL_ACTOR*)aNPC_ctrlActor)->unit_info; + unit_flag = 0; + i = 0; + ret = TRUE; + unit_info_p += uz * aNPC2_UNIT_X_NUM; + for (i; i < aNPC2_UNIT_X_NUM; i++) { + while (TRUE) { + ux = RANDOM(aNPC2_UNIT_X_NUM); + if (((unit_flag >> ux) & 1) == 0) { + break; + } + } + + if (*(unit_info_p + ux) != 0) { + goto exit; + } + + unit_flag |= (1 << ux); + } + + ret = FALSE; +exit: + actorx->world.position.x = (ux + 1.5f) * mFI_UT_WORLDSIZE_X_F; + actorx->world.position.z = (uz + 1.5f) * mFI_UT_WORLDSIZE_Z_F; + return ret; +} + +static void aNPC_set_start_pos(ACTOR* actorx) { + static int uz_def_tbl[3][2] = { + { 1, 2 }, + { 0, 3 }, + { 4, 5 }, + }; + + static f32 chk_val000[3] = { + 0.4f, + 0.1f, + 0.0f, + }; + + static f32 chk_val001[3] = { + 1.0f, + 0.25f, + 0.0f, + }; + + static f32 chk_val010[3] = { + 0.14f, + 1.0f, + 0.0f, + }; + + static f32 chk_val011[3] = { + 1.0f, + 1.0f, + 0.0f, + }; + + static f32 chk_val100[3] = { + 0.3f, + 0.0f, + 1.0f, + }; + + static f32 chk_val101[3] = { + 1.0f, + 0.0f, + 1.0f, + }; + + static f32 chk_val110[3] = { + 0.0f, + 1.0f, + 1.0f, + }; + + static f32* chk_val_tbl[8] = { + chk_val000, chk_val001, chk_val010, chk_val011, chk_val100, chk_val101, chk_val110, NULL, + }; + + static s16 angl_tbl[] = { + DEG2SHORT_ANGLE2(0.0f), + DEG2SHORT_ANGLE2(90.0f), + DEG2SHORT_ANGLE2(180.0f), + DEG2SHORT_ANGLE2(270.0f), + }; + + f32 rnd; + int uz; + int j; + int idx; + int uz_tbl[3][2]; + f32* check_p; + int i; + s16 angle; + + i = 0; + mem_copy((u8*)uz_tbl, (u8*)uz_def_tbl, sizeof(uz_tbl)); + uz = 0; + idx = 0; + + while (TRUE) { + check_p = chk_val_tbl[i]; + rnd = RANDOM_F(1.0f); + for (j = 0; j < 3; j++) { + if (rnd >= check_p[j]) { + idx = RANDOM(2); + uz = uz_tbl[j][idx]; + break; + } + } + + if (aNPC_set_start_pos_sub(actorx, uz) != TRUE) { + if (uz_tbl[j][0] == uz_tbl[j][1]) { + i |= 1 << j; + } else { + uz_tbl[j][idx] = uz_tbl[j][idx ^ 1]; + } + } else { + angle = angl_tbl[RANDOM(ARRAY_COUNT(angl_tbl))]; + + actorx->shape_info.rotation.y = angle; + actorx->world.angle.y = angle; + ((NPC_ACTOR*)actorx)->movement.mv_angl = angle; + break; + } + } +} + +#endif + static void aNPC_actor_schedule(NPC_ACTOR* nactorx, int type) { mNPS_schedule_c* sched_p = &nactorx->schedule.schedule; @@ -59,14 +200,26 @@ static void aNPC_actor_schedule(NPC_ACTOR* nactorx, int type) { nactorx->schedule.type = aNPC_SCHEDULE_TYPE_STAND; break; case aNPC_CT_SCHED_TYPE_WANDER: +#ifndef aNPC_NPC2 sched_p->current_type = mNPS_SCHED_WANDER; nactorx->npc_info.schedule = sched_p; nactorx->schedule.type = aNPC_SCHEDULE_TYPE_WANDER; +#else + sched_p->current_type = aNPC_SCHEDULE_TYPE_IN_HOUSE; + nactorx->npc_info.schedule = sched_p; + nactorx->schedule.type = aNPC_SCHEDULE_TYPE_IN_HOUSE; +#endif break; case aNPC_CT_SCHED_TYPE_WALK_WANDER: +#ifndef aNPC_NPC2 sched_p->current_type = mNPS_SCHED_WALK_WANDER; nactorx->npc_info.schedule = sched_p; nactorx->schedule.type = aNPC_SCHEDULE_TYPE_WALK_WANDER; +#else + sched_p->current_type = aNPC_SCHEDULE_TYPE_IN_HOUSE; + nactorx->npc_info.schedule = sched_p; + nactorx->schedule.type = aNPC_SCHEDULE_TYPE_IN_HOUSE; +#endif break; case aNPC_CT_SCHED_TYPE_SPECIAL: sched_p->current_type = mNPS_SCHED_SPECIAL; @@ -120,12 +273,15 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { eye_y = (f32)draw_data.eye_height; scale = draw_data.scale; - cKF_SkeletonInfo_R_ct(&nactorx->draw.main_animation.keyframe, skeleton, NULL, nactorx->draw.main_animation.work, nactorx->draw.main_animation.morph); - cKF_SkeletonInfo_R_ct(&nactorx->draw.sub_animation0.keyframe, skeleton, NULL, nactorx->draw.sub_animation0.work, nactorx->draw.sub_animation0.morph); - cKF_SkeletonInfo_R_ct(&nactorx->draw.sub_animation1.keyframe, skeleton, NULL, nactorx->draw.sub_animation1.work, nactorx->draw.sub_animation1.morph); + cKF_SkeletonInfo_R_ct(&nactorx->draw.main_animation.keyframe, skeleton, NULL, nactorx->draw.main_animation.work, + nactorx->draw.main_animation.morph); + cKF_SkeletonInfo_R_ct(&nactorx->draw.sub_animation0.keyframe, skeleton, NULL, nactorx->draw.sub_animation0.work, + nactorx->draw.sub_animation0.morph); + cKF_SkeletonInfo_R_ct(&nactorx->draw.sub_animation1.keyframe, skeleton, NULL, nactorx->draw.sub_animation1.work, + nactorx->draw.sub_animation1.morph); Shape_Info_init(actorx, 0.0f, &mAc_ActorShadowEllipse, 9.0f, 17.0f); actorx->shape_info.ofs_y = 2.0f; - + { ClObjPipe_c* pipe_p = &nactorx->collision.pipe; @@ -146,7 +302,7 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { nactorx->collision.BGcheck_radius = 18.0f; nactorx->collision.check_kind = aNPC_BG_CHECK_TYPE_RANGE; - + nactorx->eye_y = eye_y; nactorx->action.idx = aNPC_ACT_NONE; @@ -194,7 +350,7 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { xyz_t_move(&nactorx->feet[aNPC_FOOT_LEFT], &actorx->world.position); xyz_t_move(&nactorx->feet[aNPC_FOOT_RIGHT], &actorx->world.position); aNPC_set_hide_flg(nactorx, TRUE); - + if (name_type == NAME_TYPE_NPC) { Animal_c* animal = aNPC_GET_ANM(nactorx); mActor_name_t cloth = animal->cloth; @@ -213,7 +369,9 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { nactorx->talk_info.talk_end_check_proc = &aNPC_talk_end_check; aNPC_set_start_pos(actorx); aNPC_setP_friendship(nactorx); +#ifndef aNPC_NPC2 aNPC_check_force_use_umbrella(nactorx); +#endif nactorx->talk_info.melody_inst = draw_data.voice_type; nactorx->talk_info.npc_voice_id = draw_data.voice_type; } else { @@ -237,7 +395,7 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { npc_name = mask_id; // r29 nactorx->npc_info.mask = mask_npc; mask_npc->exists = TRUE; - + if (ITEM_NAME_GET_TYPE(npc_name) == NAME_TYPE_NPC) { aNPC_dma_draw_data_proc(&draw_data, mask_id); } @@ -250,6 +408,7 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { } nactorx->npc_info.npc_name = npc_name; +#ifndef aNPC_NPC2 actorx->max_velocity_y = -20.0f; actorx->gravity = -1.0f; @@ -260,12 +419,16 @@ static void aNPC_actor_ct(ACTOR* actorx, GAME* game, aNPC_ct_data_c* ct_data) { mFI_SetFG_common(EMPTY_NO, actorx->world.position, TRUE); } } +#else + actorx->max_velocity_y = 0.0f; + actorx->gravity = 0.0f; +#endif actorx->scale.x = scale; actorx->scale.y = scale; actorx->scale.z = scale; actorx->unknown_b4 = TRUE; - + if (ct_data->sched_type != aNPC_CT_SCHED_TYPE_NONE) { aNPC_actor_schedule(nactorx, ct_data->sched_type); } diff --git a/src/actor/npc/ac_npc_ctrl.c_inc b/src/actor/npc/ac_npc_ctrl.c_inc index 62368796..b5a62cf7 100644 --- a/src/actor/npc/ac_npc_ctrl.c_inc +++ b/src/actor/npc/ac_npc_ctrl.c_inc @@ -46,6 +46,101 @@ static void aNPC_rebuild_dma(void) { aNPC_rebuild_cloth_data(); } +#ifdef aNPC_NPC2 +static void aNPC_set_safe_ut(NPC_CONTROL_ACTOR* ctrl) { + static int chkX[4][9] = { + { 0, 1, 0, 1, 2, 0, 2, 1, 2 }, + { 0, 1, 0, 1, 2, 0, 2, 1, 2 }, + { 5, 4, 5, 4, 3, 5, 3, 4, 3 }, + { 5, 4, 5, 4, 3, 5, 3, 4, 3 }, + }; + + static int chkZ[4][9] = { + { 0, 0, 1, 1, 0, 2, 1, 2, 2 }, + { 5, 5, 4, 4, 5, 3, 4, 3, 3 }, + { 0, 0, 1, 1, 0, 2, 1, 2, 2 }, + { 5, 5, 4, 4, 5, 3, 4, 3, 3 }, + }; + + int* unit_info_p = (int*)ctrl->unit_info; + int* safe_ux_p = ctrl->safe_ux; + int* safe_uz_p = ctrl->safe_uz; + int i; + int j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 9; j++) { + if (*(unit_info_p + chkZ[i][j] * aNPC2_UNIT_X_NUM + chkX[i][j]) != 0) { + *safe_ux_p = chkX[i][j]; + *safe_uz_p = chkZ[i][j]; + break; + } + } + + safe_ux_p++; + safe_uz_p++; + } +} + +static int aNPC_make_unitInfo_sub(int ux, int uz, int* unit_info_p) { + int ret = 0; + + if (*((unit_info_p + ux) + uz * aNPC2_UNIT_X_NUM) == 0) { + if (uz != 0 && *((unit_info_p + ux) + (uz - 1) * aNPC2_UNIT_X_NUM) == 0) { + ret |= aNPC_UNIT_UP; + } + + if (uz != (aNPC2_UNIT_Z_NUM - 1) && *((unit_info_p + ux) + (uz + 1) * aNPC2_UNIT_X_NUM) == 0) { + ret |= aNPC_UNIT_DOWN; + } + + if (ux != 0 && *((unit_info_p + (ux - 1)) + uz * aNPC2_UNIT_X_NUM) == 0) { + ret |= aNPC_UNIT_LEFT; + } + + if (ux != (aNPC2_UNIT_X_NUM - 1) && *((unit_info_p + (ux + 1)) + uz * aNPC2_UNIT_X_NUM) == 0) { + ret |= aNPC_UNIT_RIGHT; + } + } + + return ret; +} + +static void aNPC_make_unitInfo(NPC_CONTROL_ACTOR* ctrl) { + int table[aNPC2_UNIT_Z_NUM][aNPC2_UNIT_X_NUM]; + int x; + int z; + mActor_name_t* fg_p = mFI_UtNum2UtFG(1, 1); + + for (z = 0; z < aNPC2_UNIT_Z_NUM; z++) { + for (x = 0; x < aNPC2_UNIT_X_NUM; x++) { + table[z][x] = *fg_p != RSV_NO; + fg_p++; + } + + fg_p += (UT_X_NUM - aNPC2_UNIT_X_NUM); + } + + { + int* unit_info_p = (int*)ctrl->unit_info; + + for (z = 0; z < aNPC2_UNIT_Z_NUM; z++) { + for (x = 0; x < aNPC2_UNIT_X_NUM; x++) { + *unit_info_p = aNPC_make_unitInfo_sub(x, z, (int*)table); + unit_info_p++; + } + + // why are we doing this after every x row + ctrl->unit_info[6][2] = aNPC_UNIT_UP; + ctrl->unit_info[6][3] = aNPC_UNIT_UP; + } + } + + aNPC_set_safe_ut(ctrl); +} + +#endif + static void aNPC_set_attention_request_proc(u8 type, ACTOR* target_p, xyz_t* pos_p) { aNPC_attention_c* attention_request = &CLIP(npc_clip)->attention_request; @@ -195,7 +290,8 @@ static int aNPC_setupActor_sub(GAME_PLAY* play, s8 idx, mActor_name_t name, s16 return ret; } -static int aNPC_setupActor_proc(GAME_PLAY* play, mActor_name_t name, s8 idx, int mvlist_no, s16 arg, int bx, int bz, int ux, int uz) { +static int aNPC_setupActor_proc(GAME_PLAY* play, mActor_name_t name, s8 idx, int mvlist_no, s16 arg, int bx, int bz, + int ux, int uz) { // clang-format off static s16 event_npc_profile_table[] = { mAc_PROFILE_EV_ARTIST, @@ -423,6 +519,7 @@ static int aNPC_setupActor_proc(GAME_PLAY* play, mActor_name_t name, s8 idx, int aNPC_setupActor_sub(play, idx, name, profile, &pos, mvlist_no, arg); } +#ifndef aNPC_NPC2 static int aNPC_get_overlay_free_area_idx(aNPC_overlay_c* overlay, int max) { int i; @@ -437,7 +534,8 @@ static int aNPC_get_overlay_free_area_idx(aNPC_overlay_c* overlay, int max) { return -1; } -static void aNPC_get_overlay_area_proc_sub(ACTOR_DLFTBL* dlftbl, size_t size, size_t max_size, aNPC_overlay_c* overlay, int max, mActor_name_t npc_name) { +static void aNPC_get_overlay_area_proc_sub(ACTOR_DLFTBL* dlftbl, size_t size, size_t max_size, aNPC_overlay_c* overlay, + int max, mActor_name_t npc_name) { int idx = aNPC_get_overlay_free_area_idx(overlay, max); if (idx != -1) { @@ -478,16 +576,17 @@ static void aNPC_get_overlay_area_proc(ACTOR_DLFTBL* dlftbl, u8* name_p, size_t case SP_NPC_SENDO: case SP_NPC_MASK_CAT: case SP_NPC_GO_HONE_NPC: - aNPC_get_overlay_area_proc_sub(dlftbl, size, 0x3000, CLIP(npc_clip)->keep_k_overlay, 3, npc_name); + aNPC_get_overlay_area_proc_sub(dlftbl, size, 0x3000, CLIP(npc_clip)->keep_k_overlay, 3, + npc_name); break; default: - aNPC_get_overlay_area_proc_sub(dlftbl, size, 0x2000, CLIP(npc_clip)->keep_s_overlay, 2, npc_name); + aNPC_get_overlay_area_proc_sub(dlftbl, size, 0x2000, CLIP(npc_clip)->keep_s_overlay, 2, + npc_name); break; } } } - } - break; + } break; } } @@ -561,7 +660,9 @@ static ACTOR* aNPC_get_actor_area_proc(size_t size, const char* actor_name, int return NULL; } +#endif +#ifndef aNPC_NPC2 static void aNPC_free_actor_area_proc(ACTOR* actorx) { NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; NPC_ACTOR** actor = CLIP(npc_clip)->keep_actors; @@ -578,6 +679,11 @@ static void aNPC_free_actor_area_proc(ACTOR* actorx) { used++; } } +#else +static void aNPC_free_actor_area_proc(ACTOR* actorx) { + zelda_free(actorx); +} +#endif static void aNPC_dma_draw_data_proc(aNPC_draw_data_c* draw_data_p, mActor_name_t npc_name) { int idx = aNPC_get_draw_data_idx(npc_name); @@ -585,6 +691,7 @@ static void aNPC_dma_draw_data_proc(aNPC_draw_data_c* draw_data_p, mActor_name_t mem_copy((u8*)draw_data_p, (u8*)&npc_draw_data_tbl[idx], sizeof(aNPC_draw_data_c)); } +#ifndef aNPC_NPC2 typedef struct { u64 align; u8 buf[0x9D0]; @@ -693,6 +800,7 @@ static void aNPC_free_overlay_area(aNPC_overlay_c* overlay_p, int n) { overlay_p++; } } +#endif static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { GAME_PLAY* play = (GAME_PLAY*)game; @@ -706,10 +814,16 @@ static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { CLIP(npc_clip) = &aNPC_clip; bzero(&aNPC_clip, sizeof(aNPC_clip)); +#ifndef aNPC_NPC2 CLIP(npc_clip)->setupActor_proc = &aNPC_setupActor_proc; CLIP(npc_clip)->get_overlay_area_proc = &aNPC_get_overlay_area_proc; CLIP(npc_clip)->free_overlay_area_proc = &aNPC_free_overlay_area_proc; CLIP(npc_clip)->get_actor_area_proc = &aNPC_get_actor_area_proc; +#else + CLIP(npc_clip)->get_overlay_area_proc = (aNPC_GET_OVERLAY_AREA_PROC)&Actor_get_overlay_area; + CLIP(npc_clip)->free_overlay_area_proc = &Actor_free_overlay_area; + CLIP(npc_clip)->get_actor_area_proc = (aNPC_GET_ACTOR_AREA_PROC)&zelda_malloc; +#endif CLIP(npc_clip)->free_actor_area_proc = &aNPC_free_actor_area_proc; CLIP(npc_clip)->dma_draw_data_proc = &aNPC_dma_draw_data_proc; CLIP(npc_clip)->set_attention_request_proc = &aNPC_set_attention_request_proc; @@ -733,11 +847,17 @@ static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { CLIP(npc_clip)->force_call_req_proc = &aNPC_force_call_req_proc; CLIP(npc_clip)->set_start_pos_proc = &aNPC_set_start_pos; +#ifndef aNPC_NPC2 aNPC_keep_actor_class(); aNPC_keep_n_overlay_area(CLIP(npc_clip)->keep_n_overlay); aNPC_keep_s_overlay_area(CLIP(npc_clip)->keep_s_overlay); aNPC_keep_k_overlay_area(CLIP(npc_clip)->keep_k_overlay); aNPC_keep_e_overlay_area(CLIP(npc_clip)->keep_e_overlay); +#else + if (Save_Get(scene_no) != SCENE_NPC_HOUSE) { + Common_Set(make_npc2_actor, TRUE); + } +#endif } if (play->block_table.block_z == mISL_BLOCK_Z) { @@ -749,7 +869,7 @@ static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { Animal_c* islander_p; mNpc_NpcList_c* list_p; mNPS_schedule_c* sched_p; - + island_p = &Save_Get(island); islander_p = &island_p->animal; list_p = &Common_Get(island_npclist[0]); @@ -762,7 +882,7 @@ static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { uz = (int)islander_p->home_info.ut_z; } else { int ret = mFI_Wpos2BkandUtNuminBlock(&bx, &bz, &ux, &uz, list_p->position); - + if (ret == FALSE) { bx = (int)islander_p->home_info.block_x; bz = (int)islander_p->home_info.block_z; @@ -780,7 +900,7 @@ static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { if (mFI_RegistMoveActorList(list_p->name, bx, bz, ux, uz, -ANIMAL_NUM_MAX, 0)) { sched_p = Common_GetPointer(npc_schedule[ANIMAL_NUM_MAX]); - + if (sched_p->id != NULL) { mNPS_reset_schedule_area(sched_p->id); } @@ -792,11 +912,13 @@ static void aNPC_actor_ct_c(ACTOR* actorx, GAME* game) { static void aNPC_actor_dt_c(ACTOR* actorx, GAME* game) { if (CLIP(npc_clip) != NULL) { +#ifndef aNPC_NPC2 aNPC_free_actor_class(); aNPC_free_overlay_area(CLIP(npc_clip)->keep_n_overlay, 1); aNPC_free_overlay_area(CLIP(npc_clip)->keep_s_overlay, 2); aNPC_free_overlay_area(CLIP(npc_clip)->keep_k_overlay, 3); aNPC_free_overlay_area(CLIP(npc_clip)->keep_e_overlay, 2); +#endif CLIP(npc_clip) = NULL; } } @@ -804,7 +926,8 @@ static void aNPC_actor_dt_c(ACTOR* actorx, GAME* game) { static int aNPC_check_cond_to_greeting(NPC_ACTOR* nactorx) { int ret = TRUE; - if (nactorx->actor_class.ct_proc != NULL || nactorx->palActor != NULL || nactorx->palActorIgnoreTimer != 0 || nactorx->condition_info.hide_flg == TRUE) { + if (nactorx->actor_class.ct_proc != NULL || nactorx->palActor != NULL || nactorx->palActorIgnoreTimer != 0 || + nactorx->condition_info.hide_flg == TRUE) { ret = FALSE; } else { switch (aNPC_get_feel_info(nactorx)) { @@ -866,7 +989,7 @@ static void aNPC_greeting_area_check(GAME_PLAY* play) { actor = list->actor; for (n = list->num_actors; n != 0; n--) { NPC_ACTOR* nactor = (NPC_ACTOR*)actor; - + if (nactor->palActorIgnoreTimer > 0) { nactor->palActorIgnoreTimer--; } @@ -888,6 +1011,7 @@ static void aNPC_set_attention(void) { req_p->type = aNPC_ATTENTION_TYPE_NONE; } +#ifndef aNPC_NPC2 static void aNPC_force_reset_out_of_door_flg(NPC_CONTROL_ACTOR* ctrl) { int timer; @@ -915,6 +1039,7 @@ static void aNPC_reset_umb_open_flg(NPC_CONTROL_ACTOR* ctrl, ACTOR* actorx) { aNPC_force_reset_umb_open_flg(ctrl); } } +#endif static void aNPC_actor_move_c(ACTOR* actorx, GAME* game) { NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)actorx; @@ -926,6 +1051,7 @@ static void aNPC_actor_move_c(ACTOR* actorx, GAME* game) { } aNPC_set_attention(); +#ifndef aNPC_NPC2 if (mFI_ActorisBorn() == TRUE) { aNPC_force_reset_out_of_door_flg(ctrl); aNPC_force_reset_umb_open_flg(ctrl); @@ -942,8 +1068,16 @@ static void aNPC_actor_move_c(ACTOR* actorx, GAME* game) { } else { aNPC_force_reset_umb_open_flg(ctrl); } +#else + if (CLIP(npc_clip)->setupActor_proc == NULL && Common_Get(make_npc2_actor)) { + aNPC_make_unitInfo(ctrl); + ctrl->route_node_count = 0; + CLIP(npc_clip)->setupActor_proc = &aNPC_setupActor_proc; + } +#endif } +#ifndef aNPC_NPC2 static void aNPC_set_talk_area_info(GAME_PLAY* play) { NPC_CONTROL_ACTOR* ctrl = (NPC_CONTROL_ACTOR*)aNPC_ctrlActor; ACTOR* playerx = GET_PLAYER_ACTOR_ACTOR(play); @@ -957,7 +1091,7 @@ static void aNPC_set_talk_area_info(GAME_PLAY* play) { if (talk_actor != NULL && talk_actor->part == ACTOR_PART_NPC) { f32 dx; f32 dz; - + talk_area->frame_counter = play->game_frame; talk_area->talk_actor = talk_actor; @@ -1000,3 +1134,4 @@ static void aNPC_talk_area_check(NPC_ACTOR* nactorx, GAME_PLAY* play) { nactorx->collision.turn_flag = turn; } +#endif diff --git a/src/actor/npc/ac_npc_data.c_inc b/src/actor/npc/ac_npc_data.c_inc index 269dd181..f0bc9efb 100644 --- a/src/actor/npc/ac_npc_data.c_inc +++ b/src/actor/npc/ac_npc_data.c_inc @@ -496,6 +496,7 @@ static aNPC_anim_info_c aNPC_animeTable[aNPC_ANIM_NUM] = { }; // clang-format on +#ifndef aNPC_NPC2 // clang-format off static s16 aNPC_animeSeqNoTable[] = { aNPC_ANIM_WAIT1, @@ -557,6 +558,55 @@ static s16 aNPC_animeSeqNoTable[] = { aNPC_ANIM_CLAP1, }; // clang-format on +#else +// clang-format off +static s16 aNPC_animeSeqNoTable[] = { + aNPC_ANIM_WAIT1, + aNPC_ANIM_WAIT_KI1, + aNPC_ANIM_WAIT_DO1, + aNPC_ANIM_WAIT_AI1, + aNPC_ANIM_WAIT_NEMU1, + aNPC_ANIM_WALK1, + aNPC_ANIM_WALK_KI1, + aNPC_ANIM_WALK_DO1, + aNPC_ANIM_WALK_AI1, + aNPC_ANIM_RUN1, + aNPC_ANIM_WALK_KI1, + aNPC_ANIM_WALK_DO1, + aNPC_ANIM_WALK_AI1, + aNPC_ANIM_WALK1, + aNPC_ANIM_WAIT1, + aNPC_ANIM_TALK_TURN1, + aNPC_ANIM_TALK1, + aNPC_ANIM_KEITAI_ON1, + aNPC_ANIM_KEITAI_OFF1, + aNPC_ANIM_WALK1, + aNPC_ANIM_TRANSFER1, + aNPC_ANIM_TRANS_WAIT1, + aNPC_ANIM_SEND_MAIL1, + aNPC_ANIM_WALK1, + aNPC_ANIM_GET1, + aNPC_ANIM_GET_PULL1, + aNPC_ANIM_GET_PULL_WAIT1, + aNPC_ANIM_GET_PUTAWAY1, + aNPC_ANIM_GET_EAT1, + aNPC_ANIM_GET_CHANGE1, + aNPC_ANIM_GET_RETURN1, + aNPC_ANIM_GET_F1, + aNPC_ANIM_GET_PULL_F1, + aNPC_ANIM_GET_PULL_WAIT_F1, + aNPC_ANIM_GET_PUTAWAY_F1, + aNPC_ANIM_GET_RETURN_F1, + aNPC_ANIM_ESTIMATE_F1, + aNPC_ANIM_CONTRACT1, + aNPC_ANIM_CONTRACT2, + aNPC_ANIM_CONTRACT3, + aNPC_ANIM_NOT_CONTRACT1, + aNPC_ANIM_4HAKU_E1, + aNPC_ANIM_WAIT_E1, +}; +// clang-format on +#endif static s16 aNPC_sub_animeSeqNoTable[] = { -1, aNPC_ANIM_UMBRELLA1, aNPC_ANIM_UTIWA_WAIT1, aNPC_ANIM_TUE1 }; diff --git a/src/actor/npc/ac_npc_dt.c_inc b/src/actor/npc/ac_npc_dt.c_inc index b4ca6728..59beea95 100644 --- a/src/actor/npc/ac_npc_dt.c_inc +++ b/src/actor/npc/ac_npc_dt.c_inc @@ -3,8 +3,10 @@ static void aNPC_actor_dt(ACTOR* actorx, GAME* game) { NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; ACTOR* palActor = nactorx->palActor; +#ifndef aNPC_NPC2 aNPC_reset_out_of_door_flg(ctrl, actorx); aNPC_reset_umb_open_flg(ctrl, actorx); +#endif if (eEC_CLIP != NULL) { eEC_CLIP->effect_kill_all_proc(actorx->npc_id); diff --git a/src/actor/npc/ac_npc_hand.c_inc b/src/actor/npc/ac_npc_hand.c_inc index 248dc05b..7a176217 100644 --- a/src/actor/npc/ac_npc_hand.c_inc +++ b/src/actor/npc/ac_npc_hand.c_inc @@ -1,3 +1,4 @@ +#ifndef aNPC_NPC2 static int aNPC_change_umbrella(NPC_ACTOR* nactorx) { int ret = FALSE; @@ -18,9 +19,14 @@ static int aNPC_change_umbrella(NPC_ACTOR* nactorx) { return ret; } +#endif static int aNPC_putaway_right_item(NPC_ACTOR* nactorx) { +#ifndef aNPC_NPC2 static u8 next_act_idx[] = { aNPC_ACT_UMB_CLOSE, aNPC_ACT_NONE }; +#else + static u8 next_act_idx[] = { aNPC_ACT_NONE, aNPC_ACT_KEITAI_OFF }; +#endif int ret = TRUE; if (CLIP(tools_clip) != NULL && @@ -37,7 +43,11 @@ static int aNPC_putaway_right_item(NPC_ACTOR* nactorx) { } static int aNPC_takeout_right_item(NPC_ACTOR* nactorx) { +#ifndef aNPC_NPC2 static u8 next_act_idx[] = { aNPC_ACT_UMB_OPEN, aNPC_ACT_NONE }; +#else + static u8 next_act_idx[] = { aNPC_ACT_NONE, aNPC_ACT_KEITAI_ON }; +#endif static int itemIdx_table[] = { TOOL_UMBRELLA0, TOOL_KEITAI }; int ret = TRUE; @@ -72,9 +82,12 @@ static int aNPC_takeout_right_item(NPC_ACTOR* nactorx) { nactorx->right_hand.item_type = requested; nactorx->right_hand.requested_item_type = aNPC_ITEM_TYPE_NONE; nactorx->right_hand.item_actor_p = tool; + +#ifndef aNPC_NPC2 if (mode == aTOL_ACTION_S_TAKEOUT) { nactorx->draw.sub_anim_type = aNPC_SUB_ANIM_UMBRELLA; } +#endif aNPC_set_request_act(nactorx, 4, next_act_idx[requested - aNPC_ITEM_TYPE_UMBRELLA], aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); @@ -136,7 +149,11 @@ static int aNPC_chk_left_hand(NPC_ACTOR* nactorx) { nactorx->left_hand.requested_item_type = aNPC_ITEM_TYPE_NONE; nactorx->left_hand.item_type = aNPC_ITEM_TYPE_LEFT_HAND; nactorx->left_hand.item_actor_p = item_p; +#ifndef aNPC_NPC2 aNPC_set_request_act(nactorx, 4, aNPC_ACT_TRANS, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); +#else + aNPC_set_request_act(nactorx, 4, aNPC_ACT_TRANS, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data); +#endif } break; default: diff --git a/src/actor/npc/ac_npc_head.c_inc b/src/actor/npc/ac_npc_head.c_inc index ad04c343..e8b4b1c3 100644 --- a/src/actor/npc/ac_npc_head.c_inc +++ b/src/actor/npc/ac_npc_head.c_inc @@ -81,7 +81,9 @@ static void aNPC_look_target(NPC_ACTOR* nactorx, GAME_PLAY* play) { if (nactorx->palActor != NULL) { switch (nactorx->action.idx) { +#ifndef aNPC_NPC2 case aNPC_ACT_GREETING: +#endif case aNPC_ACT_TALK: if (nactorx->talk_info.turn != aNPC_TALK_TURN_NONE) { target = nactorx->palActor; diff --git a/src/actor/npc/ac_npc_save.c_inc b/src/actor/npc/ac_npc_save.c_inc index 2d7ae3d9..ffcc6a4c 100644 --- a/src/actor/npc/ac_npc_save.c_inc +++ b/src/actor/npc/ac_npc_save.c_inc @@ -2,6 +2,7 @@ static void aNPC_actor_save_for_normal(ACTOR* actorx) { NPC_ACTOR* nactorx = (NPC_ACTOR*)actorx; Animal_c* animal = aNPC_GET_ANM(nactorx); +#ifndef aNPC_NPC2 if (nactorx->action.idx == aNPC_ACT_INTO_HOUSE) { int home_ux = animal->home_info.block_x * UT_X_NUM + animal->home_info.ut_x; int home_uz = animal->home_info.block_z * UT_Z_NUM + animal->home_info.ut_z; @@ -10,6 +11,7 @@ static void aNPC_actor_save_for_normal(ACTOR* actorx) { aNPC_setup_stay_my_house(nactorx); } } +#endif aNPC_cancel_cloth_data(nactorx); animal->cloth = nactorx->draw.next_cloth_no; @@ -22,8 +24,10 @@ static void aNPC_actor_save_for_normal(ACTOR* actorx) { int feel_tim; switch (animal->mood) { +#ifndef aNPC_NPC2 case mNpc_FEEL_PITFALL: mFI_SetFG_common(EMPTY_NO, actorx->world.position, TRUE); +#endif // fallthrough 5 -> 4, 7, & 8 case mNpc_FEEL_SLEEPY: case mNpc_FEEL_UZAI_0: @@ -38,6 +42,12 @@ static void aNPC_actor_save_for_normal(ACTOR* actorx) { animal->mood_time = feel_tim; } + +#ifdef aNPC_NPC2 + if (nactorx->schedule.type == aNPC_SCHEDULE_TYPE_FIELD && nactorx->think.idx == aNPC_THINK_EXIT_WAIT) { + aNPC_set_be_out_home(nactorx); + } +#endif } static void aNPC_actor_save_for_special(ACTOR* actorx) { @@ -69,9 +79,11 @@ static void aNPC_actor_save(ACTOR* actorx, GAME* game) { aNPC_actor_save_for_special(actorx); } +#ifndef aNPC_NPC2 if (nactorx->movement.move_timer >= 18000 && nactorx->npc_info.list != NULL) { xyz_t_move(&actorx->world.position, &nactorx->npc_info.list->position); } +#endif mNpc_RenewalSetNpc(actorx); } diff --git a/src/actor/npc/ac_npc_sound.c_inc b/src/actor/npc/ac_npc_sound.c_inc index a92ec6ef..b9a93351 100644 --- a/src/actor/npc/ac_npc_sound.c_inc +++ b/src/actor/npc/ac_npc_sound.c_inc @@ -2,6 +2,7 @@ static void aNPC_OngenTrgStart(NPC_ACTOR* nactorx, u16 se_no) { sAdo_OngenTrgStart(se_no, &nactorx->actor_class.world.position); } +#ifndef aNPC_NPC2 static void aNPC_WalkSe(xyz_t* pos_p) { u32 attr; u16 se_no; @@ -18,3 +19,23 @@ static void aNPC_WalkSe(xyz_t* pos_p) { static void aNPC_TumbleSe(xyz_t* pos_p) { sAdo_OngenTrgStart(sAdo_Get_KokeruLabel(mCoBG_Wpos2Attribute(*pos_p, NULL)), pos_p); } +#else +static void aNPC_WalkSeRoom(xyz_t* pos_p) { + switch (Save_Get(scene_no)) { + case SCENE_START_DEMO: + case SCENE_START_DEMO2: + case SCENE_START_DEMO3: + sAdo_NpcWalkSe(NA_SE_207, pos_p); + break; + default: { + s8 floor_idx = Common_Get(floor_idx); + + if (floor_idx >= 0 && floor_idx < FLOOR_ETC_END) { + sAdo_NpcWalkSeRoom(floor_idx, pos_p); + } + + break; + } + } +} +#endif diff --git a/src/actor/npc/ac_npc_talk.c_inc b/src/actor/npc/ac_npc_talk.c_inc index 3a26d554..cea83d9b 100644 --- a/src/actor/npc/ac_npc_talk.c_inc +++ b/src/actor/npc/ac_npc_talk.c_inc @@ -369,7 +369,7 @@ static int aNPC_check_timing_demoCode(ACTOR* actorx) { case 3: break; } - +#ifndef aNPC_NPC2 switch (order) { case 3: case 5: { @@ -406,6 +406,70 @@ static int aNPC_check_timing_demoCode(ACTOR* actorx) { break; } } +#else + switch (order) { + case 3: + case 5: { + u16 args[aNPC_REQUEST_ARG_NUM]; + + bzero(args, sizeof(args)); + args[0] = mDemo_Get_OrderValue(mDemo_ORDER_NPC1, 0); + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_GET, aNPC_ACT_TYPE_DEFAULT, args) == TRUE) { + aNPC_clear_timing_demoCode(type); + ret = FALSE; + } + break; + } + case 2: + case 4: { + u16 args[aNPC_REQUEST_ARG_NUM]; + + bzero(args, sizeof(args)); + args[0] = mDemo_Get_OrderValue(mDemo_ORDER_NPC1, 0); + args[1] = mDemo_Get_OrderValue(mDemo_ORDER_NPC1, 1); + args[2] = mDemo_Get_OrderValue(mDemo_ORDER_NPC1, 2); + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_TRANS, aNPC_ACT_TYPE_DEFAULT, args) == TRUE) { + aNPC_clear_timing_demoCode(type); + ret = FALSE; + } + break; + } + case 6: + nactorx->right_hand.requested_item_type = aNPC_ITEM_TYPE_KEITAI; + aNPC_clear_timing_demoCode(type); + break; + case 7: + nactorx->right_hand.requested_item_type = aNPC_ITEM_TYPE_PUTAWAY; + aNPC_clear_timing_demoCode(type); + break; + case 8: + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_CONTRACT, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data) == TRUE) { + aNPC_clear_timing_demoCode(type); + ret = FALSE; + } + break; + case 9: + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_NOT_CONTRACT, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data) == TRUE) { + aNPC_clear_timing_demoCode(type); + ret = FALSE; + } + break; + case 13: + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_NOT_CONTRACT2, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data) == TRUE) { + aNPC_clear_timing_demoCode(type); + ret = FALSE; + } + break; + case 15: { + if (aNPC_set_request_act(nactorx, 4, aNPC_ACT_CHANGE_CLOTH, aNPC_ACT_TYPE_DEFAULT, aNPC_req_default_data) == TRUE) { + Common_Set(npc_chg_cloth, Now_Private->cloth.item); + aNPC_clear_timing_demoCode(type); + ret = FALSE; + } + break; + } + } +#endif return ret; } @@ -467,6 +531,9 @@ static void aNPC_setup_talk_end(NPC_ACTOR* nactorx) { } nactorx->talk_info.feel = 0xFF; nactorx->condition_info.demo_flg = nactorx->condition_info.talk_demo_flg_save; +#ifdef aNPC_NPC2 + nactorx->talk_info.melody_inst = 0; +#endif } static void aNPC_set_talk_info_talk_request_check(ACTOR* actorx) { @@ -581,12 +648,20 @@ static void aNPC_talk_request_check(ACTOR* actorx, GAME* game) { nactorx->condition_info.talk_condition == aNPC_TALK_TYPE_NONE && !nactorx->condition_info.hide_flg) { if (mEv_CheckTitleDemo() == 0 || mEv_CheckTitleDemo() == -9) { if (nactorx->action.idx != aNPC_ACT_TALK) { +#ifndef aNPC_NPC2 if (ITEM_NAME_GET_TYPE(actorx->npc_id) == NAME_TYPE_SPNPC && (nactorx->npc_info.animal == NULL || nactorx->npc_info.animal->mood != mNpc_FEEL_PITFALL)) { aNPC_talk_request_event_npc(actorx, game); } else { aNPC_talk_request_normal_npc(actorx, game); } +#else + if (ITEM_NAME_GET_TYPE(actorx->npc_id) == NAME_TYPE_SPNPC) { + aNPC_talk_request_event_npc(actorx, game); + } else { + aNPC_talk_request_normal_npc(actorx, game); + } +#endif } } } diff --git a/src/audio.c b/src/audio.c index 7b26f6b3..8cddb73f 100644 --- a/src/audio.c +++ b/src/audio.c @@ -87,7 +87,7 @@ extern void sAdo_NpcWalkSe(u16 se_no, const xyz_t* pos) { Na_NpcWalkSe(se_no, scalc, fcalc); } -extern void sAdo_NpcWalkSeRoom(u16 se_no, const xyz_t* pos) { +extern void sAdo_NpcWalkSeRoom(u8 se_no, const xyz_t* pos) { f32 fcalc; u16 scalc;