diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 11afc101..2f2d4b14 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -588,6 +588,10 @@ ac_ev_majin.c: .text: [0x80592A40, 0x80593158] .rodata: [0x80649D98,0x80649DA0] .data: [0x806C2B50, 0x806C2BD0] +ac_boat.c: + .text: [0x805A6CF4, 0x805A856C] + .rodata: [0x8064A5B0, 0x8064A630] + .data: [0x806C4440, 0x806C4560] ac_douzou.c: .text: [0x805AD6D8, 0x805AE704] .rodata: [0x8064A7C0, 0x8064A7E8] diff --git a/include/ac_boat.h b/include/ac_boat.h index 485f638a..7e01d301 100644 --- a/include/ac_boat.h +++ b/include/ac_boat.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "c_keyframe.h" #ifdef __cplusplus extern "C" { @@ -10,9 +11,30 @@ extern "C" { typedef struct boat_s BOAT_ACTOR; +typedef void (*aBT_PROC)(BOAT_ACTOR*, GAME_PLAY*); + struct boat_s { ACTOR actor_class; - // TODO + int _174; + cKF_SkeletonInfo_R_c keyframe; + int _1E8; + s_xyz work[15]; + s_xyz morph[15]; + aBT_PROC action_proc; + int _2A4; + int _2A8; + int _2AC; + int _2B0; + int action; + int roll_cycle; + int roll_timer; + int point; + int direction; + f32 _2C8; + f32 _2CC; + f32 _2D0; + f32 rudder; + int _2D8; }; extern ACTOR_PROFILE Boat_Profile; diff --git a/include/ac_npc.h b/include/ac_npc.h index a4d70dd8..0c0539cb 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -8,6 +8,7 @@ #include "m_npc_schedule.h" #include "m_actor_dlftbls.h" #include "m_npc.h" +#include "c_keyframe.h" #ifdef __cplusplus extern "C" { @@ -137,21 +138,21 @@ typedef struct npc_info_s { mActor_name_t npc_name; } NpcActorInfo_c; +typedef struct npc_animation_s { + cKF_SkeletonInfo_R_c keyframe; + s_xyz work[27]; + s_xyz morph[27]; + int _1B4; + s8 animation_id; +} aNPC_ANIMATION_c; + /* TODO: draw data */ typedef struct npc_draw_info_s { - /* 0x000 */ int _00; - /* 0x004 */ int _04; - /* 0x008 */ u8 _000[0x20 - 8]; - /* 0x020 */ f32 _20; - /* 0x024 */ f32 _24; - /* 0x028 */ u8 _028[0x534 - 0x028]; - /* 0x538 */ u8 _534; - /* 0x538 */ u8 _535; - /* 0x538 */ u8 _536; - /* 0x538 */ u8 _537; - /* 0x538 */ u8 _538; - /* 0x538 */ u8 _539; - /* 0x540 */ u8 _53A[0x580 - 0x53A]; + /* 0x000 */ u8 _000[0x14 - 0]; + /* 0x014 */ aNPC_ANIMATION_c main_animation; + /* 0x1D0 */ aNPC_ANIMATION_c sub_animation0; + /* 0x38C */ aNPC_ANIMATION_c sub_animation1; + /* 0x548 */ u8 _548[0x580 - 0x548]; /* 0x580 */ int animation_id; /* 0x584 */ int texture_bank_idx; /* 0x588 */ u8 _588[0x5BD - 0x588]; @@ -160,7 +161,6 @@ typedef struct npc_draw_info_s { /* 0x5BE */ u8 _5BF[0x630 - 0x5BF]; } aNPC_draw_info_c; - typedef void (*aNPC_THINK_PROC)(NPC_ACTOR*, GAME_PLAY*, int); #define aNPC_THINK_INTERRUPT_FRIENDSHIP (1 << 0) diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index a1a55192..becb8bd5 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -260,6 +260,8 @@ extern int mCoBG_ExistHeightGap_KeepAndNow(xyz_t wpos); extern void mCoBG_GetNorm_By3Point(xyz_t* norm, xyz_t* p0, xyz_t* p1, xyz_t* p2); extern int mCoBG_SearchWaterLimitDistN(xyz_t* water_pos, xyz_t wpos, s16 angle, float max_dist, int divisor); extern f32 mCoBG_GetBalloonGroundY(const xyz_t* pos); +extern void mCoBG_MakeBoatCollision(ACTOR* actor, xyz_t* pos, s16* angle_y); +extern void mCoBG_DeleteBoatCollision(ACTOR* actor); extern void mCoBG_InitMoveBgData(); extern void mCoBG_InitBlockBgCheckMode(); diff --git a/include/m_common_data.h b/include/m_common_data.h index f81028fc..9ef3b760 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -300,7 +300,7 @@ typedef struct common_data_s { /* 0x02DBA2 */ s16 island_weather; /* 0x02DBA4 */ s16 island_weather_intensity; /* 0x02DBA6 */ s16 _2DBA6; - /* 0x02DBA8 */ u8 _2DBA8; + /* 0x02DBA8 */ u8 memcard_slot; /* 0X02DBAC */ int famicom_2DBAC; /* 0x02DBB0 */ s16 can_look_goki_count; /* 0x02DBB4 */ f32 rainbow_opacity; /* current opacity of rainbow (0.0f - 1.0f) */ diff --git a/include/m_name_table.h b/include/m_name_table.h index 69db556a..fa4556b2 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -2164,6 +2164,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define DUMMY_TAMA 0xF110 #define DUMMY_DOUZOU 0xF11D #define DUMMY_NAMEPLATE 0xF11F +#define DUMMY_BOAT 0xF128 #define RSV_DOOR 0xFE1B #define RSV_FE1C 0xFE1C diff --git a/include/m_player_lib.h b/include/m_player_lib.h index afdebe32..edba9e7e 100644 --- a/include/m_player_lib.h +++ b/include/m_player_lib.h @@ -18,7 +18,7 @@ extern void mPlib_request_main_invade_type1(GAME_PLAY* play); extern mActor_name_t mPlib_Get_itemNo_forWindow(); extern int mPlib_check_able_change_camera_normal_index(); extern void mPlib_request_main_refuse_type1(GAME_PLAY* play); -extern void mPlib_request_main_wait_type3(GAME_PLAY* play); +extern void mPlib_request_main_wait_type3(GAME* game); extern void mPlib_Set_able_force_speak_label(ACTOR* actor); extern int mPlib_request_main_demo_walk_type1(GAME* game, f32 goal_x, f32 goal_z, f32 speed, int flag); extern void mPlib_Set_goal_player_demo_walk(f32 goal_x, f32 goal_z, f32 speed); @@ -51,6 +51,10 @@ extern int mPlib_Check_tree_shaken_little(const xyz_t* pos); extern int mPlib_request_main_recieve_wait_type1(GAME* game, mActor_name_t item, int counter_flag); extern int mPlib_able_player_warp_forEvent(); extern int mPlib_Get_unable_wade(); +extern void mPlib_Set_boat_angleZ(s16 angleZ); +extern int mPlib_Get_end_player_demo_walk(); +extern int mPlib_request_main_demo_geton_boat_type1(f32 goal_x, f32 goal_z, s16 angleY); +extern int mPlib_request_main_demo_getoff_boat_standup_type1(const xyz_t* pos, s16 angleY); extern mPlayer_change_data_from_submenu_c* mPlib_Get_change_data_from_submenu_p(); diff --git a/src/ac_airplane.c b/src/ac_airplane.c index dc0c2190..7c174ba4 100644 --- a/src/ac_airplane.c +++ b/src/ac_airplane.c @@ -206,7 +206,7 @@ static void aAp_StartFlyMove(ACTOR* actor, GAME* game) { airplane->rotZ = 0.0f; airplane->y_speed = 0.0f; - mPlib_request_main_wait_type3(play); + mPlib_request_main_wait_type3((GAME*)play); } } @@ -349,7 +349,7 @@ static void aAp_ZbuttonChangeStatus(AIRPLANE_ACTOR* actor, GAME* game) { } } else if (actor->status == aAp_STATUS_START_FLY_MOVE) { - mPlib_request_main_wait_type3(play); + mPlib_request_main_wait_type3((GAME*)play); actor->status = aAp_STATUS_PLAYER_CATCH; } } diff --git a/src/ac_boat.c b/src/ac_boat.c new file mode 100644 index 00000000..040d718e --- /dev/null +++ b/src/ac_boat.c @@ -0,0 +1,222 @@ +#include "ac_boat.h" + +#include "ac_boat_demo.h" +#include "m_play.h" +#include "m_common_data.h" +#include "m_rcp.h" +#include "m_player_lib.h" +#include "libultra/libultra.h" +#include "sys_matrix.h" + +enum { + aBT_DIRECTION_TO_ISLAND, + aBT_DIRECTION_FROM_ISLAND, + + aBT_DIRECTION_NUM +}; + +enum { + aBT_ACTION_DEMO_CTRL_BIRTH_WAIT, + aBT_ACTION_WAIT, + aBT_ACTION_PL_RIDE_MOVE_START_WAIT, + aBT_ACTION_PL_RIDE_MOVE_END_WAIT, + aBT_ACTION_PL_RIDE_ON_START_WAIT, + aBT_ACTION_PL_RIDE_ON_END_WAIT, + aBT_ACTION_SITDOWN_END_WAIT, + aBT_ACTION_MOVE_WAIT, + aBT_ACTION_MOVE, + aBT_ACTION_MOMENT, + aBT_ACTION_DRAW_UP, + aBT_ACTION_ARRIVE_CALL_END_WAIT, + aBT_ACTION_PL_RIDE_OFF_START_WAIT, + aBT_ACTION_PL_RIDE_OFF_END_WAIT, + aBT_ACTION_ANCHOR, + + aBT_ACTION_NUM +}; + +static void aBT_actor_ct(ACTOR*, GAME*); +static void aBT_actor_dt(ACTOR*, GAME*); +static void aBT_actor_init(ACTOR*, GAME*); +static void aBT_actor_draw(ACTOR*, GAME*); + +ACTOR_PROFILE Boat_Profile = { + mAc_PROFILE_BOAT, + ACTOR_PART_ITEM, + ACTOR_STATE_CAN_MOVE_IN_DEMO_SCENES | ACTOR_STATE_TA_SET | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + BOAT, + ACTOR_OBJ_BANK_KEEP, + sizeof(BOAT_ACTOR), + &aBT_actor_ct, + &aBT_actor_dt, + &aBT_actor_init, + &aBT_actor_draw, + NULL +}; + +static xyz_t aBT_chk_point[] = { + // Position Z-X X Z + { 3420.0f, 0.0f, 4260.0f }, // F-5 unit 5.5 - 10.5 + { 3380.0f, 0.0f, 4300.0f }, // F-5 unit 4.5 - 11.5 + { 3340.0f, 0.0f, 4380.0f }, // F-5 unit 3.5 - 13.5 + { 3340.0f, 0.0f, 4620.0f }, // G-5 unit 3.5 - 3.5 + { 3740.0f, 0.0f, 4980.0f }, // G-5 unit 13.5 - 12.5 + { 3740.0f, 0.0f, 5220.0f }, // H-5 unit 13.5 - 2.5 + { 3700.0f, 0.0f, 5300.0f }, // H-5 unit 12.5 - 4.5 + { 3660.0f, 0.0f, 5340.0f } // H-5 unit 11.5 - 5.5 +}; + +static int aBT_last_point_idx[aBT_DIRECTION_NUM] = { 7, 0 }; + +s16 aBT_init_angleY[aBT_DIRECTION_NUM] = { + DEG2SHORT_ANGLE(-45.0f), // 0xE000 + DEG2SHORT_ANGLE(135.0f) // 0x6000 +}; + +static void aBT_setupAction(BOAT_ACTOR* boat_actor, GAME_PLAY* play, int action); +static int aBT_check_other_boat(ACTOR* actorx, GAME* game); + +extern cKF_Skeleton_R_c cKF_bs_r_obj_e_boat; +extern cKF_Animation_R_c cKF_ba_r_obj_e_boat; + +static void aBT_actor_ct(ACTOR* actorx, GAME* game) { + BOAT_ACTOR* boat_actor = (BOAT_ACTOR*)actorx; + + if (aBT_check_other_boat(actorx, game) == TRUE) { + GAME_PLAY* play = (GAME_PLAY*)game; + cKF_SkeletonInfo_R_c* keyframe = &boat_actor->keyframe; + int direction = aBT_DIRECTION_TO_ISLAND; + + if (actorx->block_z != 6) { + direction = aBT_DIRECTION_FROM_ISLAND; + } + + #line 326 + actorx->world.position.y = 1.0f + mCoBG_GetWaterHeight(actorx->world.position); + actorx->shape_info.rotation.y = aBT_init_angleY[direction]; + actorx->world.angle.y = aBT_init_angleY[direction]; + xyz_t_move(&actorx->home.position, &actorx->world.position); + + /* Load & play boat rocking animation */ + cKF_SkeletonInfo_R_ct(keyframe, &cKF_bs_r_obj_e_boat, NULL, boat_actor->work, boat_actor->morph); + cKF_SkeletonInfo_R_init(keyframe, keyframe->skeleton, &cKF_ba_r_obj_e_boat, 1.0f, 81.0f, 1.0f, 0.0f, 0.0f, cKF_FRAMECONTROL_REPEAT, NULL); + cKF_SkeletonInfo_R_play(keyframe); + + actorx->gravity = 0.003f; + actorx->max_velocity_y = 0.1f; + actorx->position_speed.y = 0.1f; + boat_actor->roll_timer = 200; + boat_actor->direction = direction; + aBT_setupAction(boat_actor, play, aBT_ACTION_DEMO_CTRL_BIRTH_WAIT); + mCoBG_MakeBoatCollision(actorx, &actorx->world.position, &actorx->shape_info.rotation.y); + } + else { + Actor_delete(actorx); // another boat already exists + } +} + +static void aBT_actor_dt(ACTOR* actorx, GAME* game) { + BOAT_ACTOR* boat_actor = (BOAT_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + cKF_SkeletonInfo_R_c* keyframe = &boat_actor->keyframe; + BOAT_DEMO_ACTOR* boat_demo; + + cKF_SkeletonInfo_R_dt(keyframe); + mFI_SetFG_common(BOAT, actorx->home.position, FALSE); + + boat_demo = (BOAT_DEMO_ACTOR*)actorx->parent_actor; + if (boat_demo != NULL && boat_demo->boat_actor == boat_actor) { + boat_demo->boat_actor = NULL; + } + + mCoBG_DeleteBoatCollision(actorx); +} + +#include "../src/ac_boat_move.c_inc" + +static u32 aBT_calc_furrow_alpha(BOAT_ACTOR* boat_actor) { + f32 speed = boat_actor->actor_class.speed; + + if (speed > 0.625f) { + speed = 0.625f; + } + + return (u32)((speed / 0.625f) * 150.0f); +} + +static int aBT_actor_draw_before(GAME* game, cKF_SkeletonInfo_R_c* keyframe, int joint_idx, Gfx** joint_shape, u8* joint_flags, void* arg, s_xyz* joint_rot, xyz_t* joint_pos) { + BOAT_ACTOR* boat_actor = (BOAT_ACTOR*)arg; + + switch (joint_idx) { + case 3: + { + Matrix_translate(boat_actor->actor_class.world.position.x, boat_actor->actor_class.world.position.y, boat_actor->actor_class.world.position.z, 0); + Matrix_RotateY(boat_actor->actor_class.shape_info.rotation.y, 1); + Matrix_scale(boat_actor->actor_class.scale.x, boat_actor->actor_class.scale.y, boat_actor->actor_class.scale.z, 1); + break; + } + + case 5: + { + joint_rot->x = 0; + joint_rot->y = 0; + joint_rot->z = boat_actor->_2CC; // boat furrow joint? + break; + } + + case 6: + { + joint_rot->x = 0; + joint_rot->y = 0; + joint_rot->z = boat_actor->_2D0; // boat furrow joint? + break; + } + } + + return TRUE; +} + +static void aBT_actor_draw(ACTOR* actorx, GAME* game) { + BOAT_ACTOR* boat_actor = (BOAT_ACTOR*)actorx; + cKF_SkeletonInfo_R_c* keyframe = &boat_actor->keyframe; + GRAPH* graph = game->graph; + Gfx* scroll_gfx; + f32 _2C8 = boat_actor->_2C8 - actorx->speed * 0.5f; + + while (_2C8 < -32.0f) { + _2C8 += 32.0f; + } + + boat_actor->_2C8 = _2C8; + scroll_gfx = two_tex_scroll_dolphin(graph, 0, 0, 0, 32, 32, 1, 0, _2C8 * 8.0f, 32, 32); + + if (scroll_gfx != NULL) { + Mtx* mtx = GRAPH_ALLOC_TYPE(graph, Mtx, keyframe->skeleton->num_shown_joints); + + if (mtx != NULL) { + Gfx* gfx; + u16* pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_BOAT); + + _texture_z_light_fog_prim(graph); + _texture_z_light_fog_prim_xlu(graph); + + OPEN_DISP(graph); + + gfx = NOW_POLY_OPA_DISP; + gDPPipeSync(gfx++); + gDPLoadTLUT_Dolphin(gfx++, 15, 16, 1, pal); + SET_POLY_OPA_DISP(gfx); + + gfx = NOW_POLY_XLU_DISP; + gDPPipeSync(gfx++); + gSPSegment(gfx++, G_MWO_SEGMENT_9, scroll_gfx); + gDPLoadTLUT_Dolphin(gfx++, 15, 16, 1, pal); + gDPSetEnvColor(gfx++, 155, 155, 255, aBT_calc_furrow_alpha(boat_actor)); + SET_POLY_XLU_DISP(gfx); + + CLOSE_DISP(graph); + + cKF_Si3_draw_R_SV(game, keyframe, mtx, &aBT_actor_draw_before, NULL, actorx); + } + } +} diff --git a/src/ac_boat_move.c_inc b/src/ac_boat_move.c_inc new file mode 100644 index 00000000..e868ef8f --- /dev/null +++ b/src/ac_boat_move.c_inc @@ -0,0 +1,580 @@ +static void aBT_passenger_ctrl(BOAT_ACTOR* boat_actor) { + if (boat_actor->actor_class.child_actor != NULL) { + xyz_t passenger_pos; + s_xyz passenger_angle; + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + xyz_t_add(&boat_actor->actor_class.world.position, &boat_demo->passenger_ofs, &passenger_pos); + passenger_angle.y = boat_actor->actor_class.shape_info.rotation.y - DEG2SHORT_ANGLE(-180.0f); + + (*GET_PLAYER_ACTOR_NOW()->Set_force_position_angle_proc)( + gamePT, + &passenger_pos, &passenger_angle, + mPlayer_FORCE_POSITION_ANGLE_POSX | mPlayer_FORCE_POSITION_ANGLE_POSY | mPlayer_FORCE_POSITION_ANGLE_POSZ | + mPlayer_FORCE_POSITION_ANGLE_ROTY + ); + + mPlib_Set_boat_angleZ(boat_actor->actor_class.shape_info.rotation.z); + } +} + +static int aBT_check_other_boat(ACTOR* actorx, GAME* game) { + GAME_PLAY* play = (GAME_PLAY*)game; + ACTOR* actor = play->actor_info.list[ACTOR_PART_ITEM].actor; + int res = TRUE; + + while (TRUE) { + ACTOR* other_actor = Actor_info_fgName_search_sub(actor, BOAT); + + if (other_actor == NULL) { + break; + } + else if (other_actor != actorx) { + res = FALSE; + break; + } + + actor = other_actor->next_actor; + } + + return res; +} + +static void aBT_anime_proc(BOAT_ACTOR* boat_actor) { + if (boat_actor->action == aBT_ACTION_MOVE) { + NPC_SENDO_ACTOR* sendo_actor = ((BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor)->npc_sendo_actor; + + /* Attempt to sync boat animation with Kapp'n's animation */ + if (sendo_actor != NULL && sendo_actor->npc_class.draw.animation_id == 123) { + cKF_SkeletonInfo_R_c* keyframe = &sendo_actor->npc_class.draw.main_animation.keyframe; + + boat_actor->keyframe.frame_control.current_frame = keyframe->frame_control.current_frame; + + if ( + cKF_FrameControl_passCheck_now(&keyframe->frame_control, 35.0f) == TRUE || + cKF_FrameControl_passCheck_now(&keyframe->frame_control, 52.0f) == TRUE + ) { + boat_actor->roll_timer = 400; + } + } + + cKF_SkeletonInfo_R_play(&boat_actor->keyframe); + } +} + +static void aBT_roll_ctrl(BOAT_ACTOR* boat_actor) { + int timer = boat_actor->roll_timer; + int timer_sub = timer - 200; + int roll_cycle; + + if (ABS(timer_sub) < 2) { + timer = 200; + } + else if (timer_sub < 0) { + timer += 2; + } + else { + timer -= 2; + } + + boat_actor->roll_timer = timer; + roll_cycle = boat_actor->roll_cycle; + roll_cycle += timer; + boat_actor->roll_cycle = roll_cycle; + boat_actor->actor_class.shape_info.rotation.z = sin_s(roll_cycle) * 1024.0f; // [-5.625f, 5.625f] degree rocking arc +} + +static int aBT_check_alive(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + int bx; + int bz; + int alive = FALSE; + + if ( + mFI_Wpos2BlockNum(&bx, &bz, boat_actor->actor_class.world.position) == TRUE && + play->block_table.block_x == bx && play->block_table.block_z == bz + ) { + alive = TRUE; + } + + return alive; +} + +static void aBT_up_down_proc(BOAT_ACTOR* boat_actor) { + if (boat_actor->actor_class.world.position.y < boat_actor->actor_class.home.position.y) { + if (boat_actor->actor_class.max_velocity_y < 0.0f) { + boat_actor->actor_class.gravity = 0.003f + RANDOM_F(0.002f); + } + + boat_actor->actor_class.max_velocity_y = 0.1f; + } + else { + if (boat_actor->actor_class.max_velocity_y > 0.0f) { + boat_actor->actor_class.gravity = 0.003f + RANDOM_F(0.002f); + } + + boat_actor->actor_class.max_velocity_y = -0.1f; + } +} + +static void aBT_position_move(BOAT_ACTOR* boat_actor) { + aBT_up_down_proc(boat_actor); + Actor_position_moveF((ACTOR*)boat_actor); + + if ((boat_actor->actor_class.world.position.y - boat_actor->actor_class.home.position.y) - -1.6f < 0.0f) { + boat_actor->actor_class.world.position.y = boat_actor->actor_class.home.position.y + -1.6f; + } +} + +static void aBT_calc_wave_angl(BOAT_ACTOR* boat_actor, s16 angle) { + f32 var_f1_2; + f32 var_f2_2; + s16 var_r30; + s16 var_r4; + s16 var_r5; + s16 _2CC_diff = boat_actor->_2CC; + s16 _2D0_diff = boat_actor->_2D0; + s16 half_rudder = ABS(boat_actor->rudder) * 0.5f; + + _2CC_diff -= angle; + _2D0_diff -= angle; + + if (ABS((int)_2CC_diff) >= 0x300) { + var_f2_2 = (f32)ABS(_2CC_diff); + if (var_f2_2 > 1536.0f) { + var_f2_2 = 1536.0f; + } + + if (half_rudder > 40) { + var_r4 = half_rudder; + } + else { + var_r4 = 40; + } + + var_r5 = ((int)((f32)(var_r4 - 30) * ((var_f2_2 - 768.0f) / 768.0f)) + 30); + } + else { + var_r5 = 30; + } + + if (ABS(_2D0_diff) >= 0x600) { + var_f1_2 = (f32)ABS(_2D0_diff); + if (var_f1_2 > 2304.0f) { + var_f1_2 = 2304.0f; + } + + if (half_rudder > 30) { + var_r4 = half_rudder; + } + else { + var_r4 = 30; + } + + var_r30 = ((int)((f32)(var_r4 - 20) * ((var_f1_2 - 1536.0f) / 768.0f)) + 20); + } + else { + var_r30 = 20; + } + + chase_angle(&_2CC_diff, 0, var_r5); + chase_angle(&_2D0_diff, 0, var_r30); + boat_actor->_2CC = _2CC_diff; + boat_actor->_2D0 = _2D0_diff; +} + +static void aBT_ctrl_rudder(BOAT_ACTOR* boat_actor, s16 p0, s16 p1, s16 p2) { + s16 rudder = boat_actor->rudder; + s16 step; + + if (rudder * p2 >= 0) { + if (p1 > 256) { + step = ((p1 - 256) * 14) / 768 + 2; + + if (step > 16) { + step = 16; + } + } + else { + step = 2; + } + } + else { + step = 16; + } + + step /= 2.0f; + if (p0 == 0) { + rudder = 0; + } + else if (p0 < 0) { + rudder -= step; + + if (rudder < -38) { + rudder = -38; + } + } + else { + rudder += step; + + if (rudder > 38) { + rudder = 38; + } + } + + boat_actor->rudder = rudder; +} + +static void aBT_ctrl_direction(BOAT_ACTOR* boat_actor) { + int point = boat_actor->point; + s16 anglY = boat_actor->actor_class.shape_info.rotation.y; + xyz_t* chk_point = &aBT_chk_point[point]; + f32 dZ = chk_point->z - boat_actor->actor_class.world.position.z; + f32 dX = chk_point->x - boat_actor->actor_class.world.position.x; + s16 p2 = atans_table(dZ, dX); + s16 p0 = p2 - boat_actor->actor_class.world.angle.y; // diff to target rotation + s16 p1 = ABS(p0); + f32 rudder; + + aBT_ctrl_rudder(boat_actor, p0, p1, p2); + rudder = boat_actor->rudder * 0.5f; + + if ((f32)p0 * rudder <= 0.0f && (f32)p1 < ABS(rudder)) { + boat_actor->actor_class.world.angle.y = p2; + } + else { + boat_actor->actor_class.world.angle.y += rudder; + } + + boat_actor->actor_class.shape_info.rotation.y = boat_actor->actor_class.world.angle.y; + aBT_calc_wave_angl(boat_actor, boat_actor->actor_class.shape_info.rotation.y - anglY); + + if (boat_actor->direction == aBT_DIRECTION_TO_ISLAND) { + if (dZ < 0.0f) { + boat_actor->point = point + 1; + } + } + else { + if (dZ > 0.0f) { + boat_actor->point = point - 1; + } + } +} + +static void aBT_calc_speed(BOAT_ACTOR* boat_actor) { + f32 target; + f32 step; + + if (boat_actor->point == aBT_last_point_idx[boat_actor->direction]) { + target = 0.0f; + step = 0.0017f; + } + else { + target = 0.625f; + step = 0.01f; + } + + chase_f(&boat_actor->actor_class.speed, target, step); +} + +static void aBT_demo_ctrl_birth_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + ACTOR* boat_demo = Actor_info_make_actor(&play->actor_info, (GAME*)play, mAc_PROFILE_BOAT_DEMO, 0.0f, 0.0f, 0.0f, 0, 0, 0, -1, -1, -1, EMPTY_NO, -1, -1, -1); + + if (boat_demo != NULL) { + aBT_setupAction(boat_actor, play, aBT_ACTION_WAIT); + } +} + +static void aBT_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (aBT_check_alive(boat_actor, play) == FALSE) { + boat_actor->action = -1; + } + else { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + if (boat_demo != NULL && boat_demo->action == aBTD_ACTION_PL_RIDE_ON_END_WAIT) { + aBT_setupAction(boat_actor, play, aBT_ACTION_PL_RIDE_MOVE_START_WAIT); + } + } +} + +static void aBT_pl_ride_move_start_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + GAME* game = (GAME*)play; + + if (mPlib_get_player_actor_main_index(game) == mPlayer_INDEX_DEMO_WALK) { + aBT_setupAction(boat_actor, play, aBT_ACTION_PL_RIDE_MOVE_END_WAIT); + } + else { + s16 dir = boat_actor->actor_class.shape_info.rotation.y + DEG2SHORT_ANGLE(90.0f); + f32 x = cos_s(dir); + f32 z = sin_s(dir); + + mPlib_request_main_demo_walk_type1( + game, + boat_actor->actor_class.world.position.x + x * 56.0f, boat_actor->actor_class.world.position.z + z * 56.0f, + 1.0f, + 0 + ); + } +} + +static void aBT_pl_ride_move_end_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (mPlib_Get_end_player_demo_walk()) { + aBT_setupAction(boat_actor, play, aBT_ACTION_PL_RIDE_ON_START_WAIT); + } +} + +static void aBT_pl_ride_on_start_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_GETON_BOAT) { + aBT_setupAction(boat_actor, play, aBT_ACTION_PL_RIDE_ON_END_WAIT); + } + else { + s16 dir = boat_actor->actor_class.shape_info.rotation.y + DEG2SHORT_ANGLE(90.0f); + f32 x = cos_s(dir); + f32 z = sin_s(dir); + + mPlib_request_main_demo_geton_boat_type1( + boat_actor->actor_class.world.position.x + x * 56.0f, boat_actor->actor_class.world.position.z + z * 56.0f, + boat_actor->actor_class.shape_info.rotation.y + DEG2SHORT_ANGLE(-90.0f) + ); + } +} + +static void aBT_pl_ride_on_end_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_GETON_BOAT_SITDOWN) { + aBT_setupAction(boat_actor, play, aBT_ACTION_SITDOWN_END_WAIT); + } +} + +static void aBT_sitdown_end_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_GETON_BOAT_WAIT) { + aBT_setupAction(boat_actor, play, aBT_ACTION_MOVE_WAIT); + } +} + +static void aBT_move_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + if (boat_demo != NULL && boat_demo->action == aBTD_ACTION_SONG_BGM_START_WAIT) { + aBT_setupAction(boat_actor, play, aBT_ACTION_MOVE); + } +} + +static void aBT_move(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + aBT_ctrl_direction(boat_actor); + + if (boat_actor->direction == aBT_DIRECTION_TO_ISLAND) { + if (boat_actor->point >= 8) { + aBT_setupAction(boat_actor, play, aBT_ACTION_DRAW_UP); + } + else { + if (boat_actor->action == aBT_ACTION_MOVE && boat_actor->point == 7) { + aBT_setupAction(boat_actor, play, aBT_ACTION_MOMENT); + } + + aBT_calc_speed(boat_actor); + } + } + else if (boat_actor->point <= -1) { + aBT_setupAction(boat_actor, play, aBT_ACTION_DRAW_UP); + } + else { + if (boat_actor->action == aBT_ACTION_MOVE && boat_actor->point == 0) { + aBT_setupAction(boat_actor, play, aBT_ACTION_MOMENT); + } + + aBT_calc_speed(boat_actor); + } +} + +static void aBT_draw_up(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + int last_point_idx = aBT_last_point_idx[boat_actor->direction]; + xyz_t* last_chk_point = &aBT_chk_point[last_point_idx]; + s16 anglY = boat_actor->actor_class.shape_info.rotation.y; + int drawn_up_point = 0; + + chase_f(&boat_actor->rudder, 16.0f, 0.5f); + + /* Wait for proper rotation */ + if (chase_angle(&boat_actor->actor_class.shape_info.rotation.y, aBT_init_angleY[boat_actor->direction], boat_actor->rudder) == TRUE) { + drawn_up_point++; + } + + boat_actor->actor_class.world.angle.y = boat_actor->actor_class.shape_info.rotation.y; + aBT_calc_wave_angl(boat_actor, boat_actor->actor_class.shape_info.rotation.y - anglY); + + /* Wait for proper X coordinate */ + if (chase_f(&boat_actor->actor_class.world.position.x, last_chk_point->x, 0.05f) == TRUE) { + drawn_up_point++; + } + + /* Wait for proper Z coordinate */ + if (chase_f(&boat_actor->actor_class.world.position.z, last_chk_point->z, 0.05f) == TRUE) { + drawn_up_point++; + } + + /* Ensure all three criteria are met */ + if (drawn_up_point == 3) { + aBT_setupAction(boat_actor, play, aBT_ACTION_ARRIVE_CALL_END_WAIT); + } +} + +static void aBT_arrive_call_end_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + if (boat_demo->action == aBTD_ACTION_PL_RIDE_OFF_END_WAIT) { + aBT_setupAction(boat_actor, play, aBT_ACTION_PL_RIDE_OFF_START_WAIT); + } +} + +static void aBT_pl_ride_off_start_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_GETOFF_BOAT_STANDUP) { + aBT_setupAction(boat_actor, play, aBT_ACTION_PL_RIDE_OFF_END_WAIT); + } + else { + xyz_t pos; + PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play); + s16 dir = boat_actor->actor_class.shape_info.rotation.y + DEG2SHORT_ANGLE(-90.0f); + f32 z = cos_s(dir); + f32 x = sin_s(dir); + + pos.x = player->actor_class.world.position.x + x * 47.0f; + pos.y = 40.0f; + pos.z = player->actor_class.world.position.z + z * 47.0f; + + mPlib_request_main_demo_getoff_boat_standup_type1(&pos, boat_actor->actor_class.shape_info.rotation.y + DEG2SHORT_ANGLE(-90.0f)); + } +} + +static void aBT_pl_ride_off_end_wait(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (mPlib_get_player_actor_main_index((GAME*)play) == mPlayer_INDEX_DEMO_WAIT) { + aBT_setupAction(boat_actor, play, aBT_ACTION_ANCHOR); + } +} + +static void aBT_anchor(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + if (aBT_check_alive(boat_actor, play) == FALSE) { + boat_actor->action = -1; + } +} + +typedef void (*aBT_INIT_PROC)(BOAT_ACTOR*, GAME_PLAY*); + +static void aBT_wait_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + boat_actor->actor_class.speed = 0.0f; +} + +static void aBT_sitdown_end_wait_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play); + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + boat_actor->actor_class.child_actor = (ACTOR*)player; + xyz_t_sub(&player->actor_class.world.position, &boat_actor->actor_class.world.position, &boat_demo->passenger_ofs); + boat_actor->roll_timer += 800; + boat_actor->actor_class.position_speed.y = -0.2f; +} + +static void aBT_move_wait_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + boat_demo->demo_act = aBTD_DEMO_START_CALL_END; +} + +static void aBT_move_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + static int chk_point_idx[aBT_DIRECTION_NUM] = { 1, 6 }; + + boat_actor->point = chk_point_idx[boat_actor->direction]; +} + +static void aBT_moment_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + boat_demo->demo_act = aBTD_DEMO_TOUCH_WHARF_END; +} + +static void aBT_draw_up_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + boat_actor->actor_class.speed = 0.0f; +} + +static void aBT_arrive_call_end_wait_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + boat_demo->demo_act = aBTD_DEMO_PL_RIDE_OFF_START; +} + +static void aBT_pl_ride_off_start_wait_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + boat_actor->actor_class.child_actor = NULL; +} + +static void aBT_pl_ride_off_end_wait_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + boat_actor->roll_timer += 800; +} + +static void aBT_anchor_init(BOAT_ACTOR* boat_actor, GAME_PLAY* play) { + BOAT_DEMO_ACTOR* boat_demo = (BOAT_DEMO_ACTOR*)boat_actor->actor_class.parent_actor; + + boat_demo->demo_act = aBTD_DEMO_ANCHOR; + mPlib_request_main_wait_type3((GAME*)play); +} + +static void aBT_setupAction(BOAT_ACTOR* boat_actor, GAME_PLAY* play, int action) { + static aBT_INIT_PROC init_proc[aBT_ACTION_NUM] = { + (aBT_INIT_PROC)&none_proc1, + &aBT_wait_init, + (aBT_INIT_PROC)&none_proc1, + (aBT_INIT_PROC)&none_proc1, + (aBT_INIT_PROC)&none_proc1, + (aBT_INIT_PROC)&none_proc1, + &aBT_sitdown_end_wait_init, + &aBT_move_wait_init, + &aBT_move_init, + &aBT_moment_init, + &aBT_draw_up_init, + &aBT_arrive_call_end_wait_init, + &aBT_pl_ride_off_start_wait_init, + &aBT_pl_ride_off_end_wait_init, + &aBT_anchor_init + }; + + static aBT_PROC process[aBT_ACTION_NUM] = { + &aBT_demo_ctrl_birth_wait, + &aBT_wait, + &aBT_pl_ride_move_start_wait, + &aBT_pl_ride_move_end_wait, + &aBT_pl_ride_on_start_wait, + &aBT_pl_ride_on_end_wait, + &aBT_sitdown_end_wait, + &aBT_move_wait, + &aBT_move, + &aBT_move, + &aBT_draw_up, + &aBT_arrive_call_end_wait, + &aBT_pl_ride_off_start_wait, + &aBT_pl_ride_off_end_wait, + &aBT_anchor + }; + + boat_actor->action = action; + boat_actor->action_proc = process[action]; + (*init_proc[action])(boat_actor, play); +} + +static void aBT_actor_move(ACTOR* actorx, GAME* game) { + BOAT_ACTOR* boat_actor = (BOAT_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + aBT_anime_proc(boat_actor); + aBT_position_move(boat_actor); + aBT_roll_ctrl(boat_actor); + (*boat_actor->action_proc)(boat_actor, play); + aBT_passenger_ctrl(boat_actor); + + if (boat_actor->action == -1) { + Actor_delete(actorx); + } +} + +static void aBT_actor_init(ACTOR* actorx, GAME* game) { + mFI_SetFG_common(DUMMY_BOAT, actorx->home.position, FALSE); + aBT_actor_move(actorx, game); + actorx->mv_proc = &aBT_actor_move; +} diff --git a/src/ac_npc_rtc.c b/src/ac_npc_rtc.c index 6eef7e3d..57037cfe 100644 --- a/src/ac_npc_rtc.c +++ b/src/ac_npc_rtc.c @@ -113,11 +113,11 @@ void aNRTC_actor_move(ACTOR* actor, GAME* game){ if(info.unk0 != 4){ val = 0.0f; arm_flag = FALSE; - rtc->npc_class.draw._24 = 1.0f + (64.0f * (f32)info.unk8); + rtc->npc_class.draw.main_animation.keyframe.frame_control.current_frame = 1.0f + (64.0f * (f32)info.unk8); } } - rtc->npc_class.draw._20 = val; + rtc->npc_class.draw.main_animation.keyframe.frame_control.speed = val; sAdos_TTKK_ARM(arm_flag); Common_Get(clip.npc_clip)->move_proc(actor,game); mSC_change_player_freeze(play); diff --git a/src/ac_npc_rtc_talk.c.inc b/src/ac_npc_rtc_talk.c.inc index ccb8c4e9..5c9b375e 100644 --- a/src/ac_npc_rtc_talk.c.inc +++ b/src/ac_npc_rtc_talk.c.inc @@ -1,10 +1,8 @@ -void aNRTC_set_slot_name(NPC_ACTOR* actor, int str_no) { - NPCRTC_ACTOR* rtc = (NPCRTC_ACTOR*)actor; - u8 name[16]; - - mString_Load_StringFromRom(name, sizeof(name), &rtc->npc_class.draw._539); +void aNRTC_set_slot_name(int slot_id, int str_no) { + u8 name[mIN_ITEM_NAME_LEN]; + mString_Load_StringFromRom(name, sizeof(name), 0x6CD + slot_id); mMsg_Set_free_str(mMsg_Get_base_window_p(),str_no, name, sizeof(name)); } @@ -145,7 +143,7 @@ void aNRTC_format(NPCRTC_ACTOR* rtc, GAME_PLAY* play) { mMsg_Set_LockContinue(window); break; case 2: - card_ret = mCD_card_format_bg(Common_Get(_2DBA8)); + card_ret = mCD_card_format_bg(Common_Get(memcard_slot)); switch (card_ret) { case 1: mMsg_Set_continue_msg_num(window, 0x9E9); @@ -273,7 +271,7 @@ int aNRTC_talk_init(ACTOR* actor, GAME* game) { NPCRTC_ACTOR* rtc = (NPCRTC_ACTOR*)actor; mDemo_Set_ListenAble(); - aNRTC_set_slot_name((NPC_ACTOR*)Common_Get(_2DBA8), 4); + aNRTC_set_slot_name(Common_Get(memcard_slot), mMsg_FREE_STR4); switch (Common_Get(save_error_type)) { case 0: aNRTC_change_talk_proc(rtc, 2);