From 68d9e2d8fb4228049fd9d529a731bba9d3eb4356 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Thu, 28 Nov 2024 03:24:34 -0500 Subject: [PATCH] Implement & link ac_depart --- configure.py | 2 +- include/ac_depart.h | 8 +- src/actor/ac_depart.c | 126 +++++++++++ src/actor/ac_depart_draw.c_inc | 111 ++++++++++ src/actor/ac_depart_move.c_inc | 368 +++++++++++++++++++++++++++++++++ 5 files changed, 613 insertions(+), 2 deletions(-) create mode 100644 src/actor/ac_depart.c create mode 100644 src/actor/ac_depart_draw.c_inc create mode 100644 src/actor/ac_depart_move.c_inc diff --git a/configure.py b/configure.py index 2a464561..1205cd58 100644 --- a/configure.py +++ b/configure.py @@ -955,7 +955,7 @@ config.libs = [ Object(Matching, "actor/ac_cottage.c"), Object(NonMatching, "actor/ac_count02.c"), Object(NonMatching, "actor/ac_countdown.c"), - Object(NonMatching, "actor/ac_depart.c"), + Object(Matching, "actor/ac_depart.c"), Object(Matching, "actor/ac_douzou.c"), Object(Matching, "actor/ac_dummy.c"), Object(Matching, "actor/ac_dump.c"), diff --git a/include/ac_depart.h b/include/ac_depart.h index a09afbb4..ec146999 100644 --- a/include/ac_depart.h +++ b/include/ac_depart.h @@ -3,11 +3,18 @@ #include "types.h" #include "m_actor.h" +#include "ac_structure.h" #ifdef __cplusplus extern "C" { #endif +typedef struct depart_actor_s DEPART_ACTOR; + +struct depart_actor_s { + STRUCTURE_ACTOR struct_class; +}; + extern ACTOR_PROFILE Depart_Profile; #ifdef __cplusplus @@ -15,4 +22,3 @@ extern ACTOR_PROFILE Depart_Profile; #endif #endif - diff --git a/src/actor/ac_depart.c b/src/actor/ac_depart.c new file mode 100644 index 00000000..cfd0dd33 --- /dev/null +++ b/src/actor/ac_depart.c @@ -0,0 +1,126 @@ +#include "ac_depart.h" + +#include "m_name_table.h" +#include "bg_item_h.h" +#include "m_common_data.h" +#include "m_house.h" +#include "m_player_lib.h" +#include "m_demo.h" +#include "ac_intro_demo.h" +#include "m_bgm.h" +#include "sys_matrix.h" +#include "m_rcp.h" +#include "libforest/gbi_extensions.h" + +// clang-format off +enum { + aDPT_ACTION_CLOSE_WAIT, + aDPT_ACTION_OPEN_WAIT, + aDPT_ACTION_CLOSE_DOOR, + aDPT_ACTION_OPEN_DOOR, + aDPT_ACTION_PL_INTO_WAIT, + + aDPT_ACTION_NUM +}; +// clang-format on + +static void aDPT_actor_ct(ACTOR* actorx, GAME* game); +static void aDPT_actor_dt(ACTOR* actorx, GAME* game); +static void aDPT_actor_init(ACTOR* actorx, GAME* game); +static void aDPT_actor_draw(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Depart_Profile = { + mAc_PROFILE_DEPART, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + SHOP3, + ACTOR_OBJ_BANK_KEEP, + sizeof(DEPART_ACTOR), + &aDPT_actor_ct, + &aDPT_actor_dt, + &aDPT_actor_init, + &aDPT_actor_draw, + NULL +}; +// clang-format on + +// clang-format off +static u8 aDPT_shadow_vtx_fix_flg_table[] = { + FALSE, TRUE, TRUE, FALSE, + TRUE, FALSE, TRUE, FALSE, + FALSE, TRUE, TRUE, FALSE, +}; +// clang-format on + +extern Vtx obj_shop4_shadow_v[]; +extern Gfx obj_shop4_shadowT_model[]; + +// clang-format off +static bIT_ShadowData_c aDPT_shadow_data = { + ARRAY_COUNT(aDPT_shadow_vtx_fix_flg_table), + aDPT_shadow_vtx_fix_flg_table, + 60.0f, + obj_shop4_shadow_v, + obj_shop4_shadowT_model +}; +// clang-format on + +extern cKF_Skeleton_R_c cKF_bs_r_obj_s_shop4; +extern cKF_Skeleton_R_c cKF_bs_r_obj_w_shop4; + +static void aDPT_set_bgOffset(DEPART_ACTOR* depart, int offs); +static void aDPT_setup_action(DEPART_ACTOR* depart, int action); +static f32 aDPT_ctrl_light(DEPART_ACTOR* depart); + +static void aDPT_actor_ct(ACTOR* actorx, GAME* game) { + static cKF_Skeleton_R_c* skl[] = { &cKF_bs_r_obj_s_shop4, &cKF_bs_r_obj_w_shop4 }; + + GAME_PLAY* play; + DEPART_ACTOR* depart; + ACTOR* player; + int winter; + int action; + int x; + int z; + + depart = (DEPART_ACTOR*)actorx; + play = (GAME_PLAY*)game; + player = GET_PLAYER_ACTOR_ACTOR(play); + + depart->struct_class.season = Common_Get(time.season); + action = aDPT_ACTION_CLOSE_WAIT; + winter = depart->struct_class.season == mTM_SEASON_WINTER; + + cKF_SkeletonInfo_R_ct(&depart->struct_class.keyframe, skl[winter], NULL, depart->struct_class.work_area, depart->struct_class.morph_area); + + aDPT_set_bgOffset(depart, 1); + + actorx->world.position.x = actorx->world.position.x + -mFI_UT_WORLDSIZE_HALF_X_F; + actorx->world.position.z = actorx->world.position.z + -mFI_UT_WORLDSIZE_HALF_Z_F; + actorx->talk_distance = 120.0f; + actorx->cull_width = 600.0f; + actorx->cull_radius = 600.0f; + + x = (int)(depart->struct_class.actor_class.world.position.x - 62.00f); + z = (int)(depart->struct_class.actor_class.world.position.z + 118.57f); + if ((int)player->world.position.x == x && (int)player->world.position.z == z) { + action = aDPT_ACTION_OPEN_WAIT; + } + + aDPT_setup_action(depart, action); + depart->struct_class.keyframe_state = cKF_SkeletonInfo_R_play(&depart->struct_class.keyframe); + depart->struct_class.keyframe_saved_keyframe = cKF_STATE_STOPPED; + depart->struct_class.arg0_f = aDPT_ctrl_light(depart); +} + +static void aDPT_actor_dt(ACTOR* actorx, GAME* game) { + DEPART_ACTOR* depart; + depart = (DEPART_ACTOR*)actorx; + + cKF_SkeletonInfo_R_dt(&depart->struct_class.keyframe); + actorx->world.position.x -= -mFI_UT_WORLDSIZE_HALF_X_F; +} + +#include "../src/actor/ac_depart_move.c_inc" +#include "../src/actor/ac_depart_draw.c_inc" diff --git a/src/actor/ac_depart_draw.c_inc b/src/actor/ac_depart_draw.c_inc new file mode 100644 index 00000000..7f8004d7 --- /dev/null +++ b/src/actor/ac_depart_draw.c_inc @@ -0,0 +1,111 @@ +extern Gfx obj_s_shop4_window_model[]; +extern Gfx obj_w_shop4_window_model[]; + +static int aDPT_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) { + DEPART_ACTOR* depart; + GRAPH* graph; + int l; + xyz_t pos; + + depart = (DEPART_ACTOR*)arg; + graph = game->graph; + + if (joint_idx == 5) { + OPEN_POLY_OPA_DISP(graph); + + l = 0.5f + (255 * depart->struct_class.arg0_f); + gDPSetPrimColor(POLY_OPA_DISP++, 0, l, 255, 255, 220, 0); + + CLOSE_POLY_OPA_DISP(graph); + } else if (joint_idx == 8) { + *joint_shape = NULL; + } else if (joint_idx == 1) { + Matrix_Position_Zero(&pos); + Setpos_HiliteReflect_xlu_init(&pos, (GAME_PLAY*)game); + } + + return TRUE; +} + +static int aDPT_actor_draw_after(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) { + static Gfx* mdl[] = { obj_s_shop4_window_model, obj_w_shop4_window_model }; + + DEPART_ACTOR* depart; + GRAPH* graph; + Mtx* mtx; + int winter; + int l; + int r; + int g; + int b; + + depart = (DEPART_ACTOR*)arg; + graph = game->graph; + + if (joint_idx == 8) { + mtx = _Matrix_to_Mtx_new(graph); + if (mtx != NULL) { + if (depart->struct_class.arg0_f > 0.0f) { + l = depart->struct_class.arg0_f * 120.0f + 0.5f; + r = 255; + g = 255; + b = 220; + } else { + l = 0; + r = 0; + g = 0; + b = 0; + } + + winter = depart->struct_class.season == mTM_SEASON_WINTER; + + _texture_z_light_fog_prim_xlu(graph); + + OPEN_POLY_XLU_DISP(graph); + + gDPSetPrimColor(POLY_XLU_DISP++, 0, l, r, g, b, 0); + gSPMatrix(POLY_XLU_DISP++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, mdl[winter]); + + CLOSE_POLY_XLU_DISP(graph); + } + } + + return TRUE; +} + +static void aDPT_actor_draw(ACTOR* actor, GAME* game) { + GRAPH* graph; + cKF_SkeletonInfo_R_c* keyframe; + Mtx* mtx; + u16* pal; + GAME_PLAY* play; + DEPART_ACTOR* depart; + + graph = game->graph; + play = (GAME_PLAY*)game; + depart = (DEPART_ACTOR*)actor; + keyframe = &depart->struct_class.keyframe; + + mtx = GRAPH_ALLOC_TYPE(graph, Mtx, (u32)keyframe->skeleton->num_shown_joints); + if (mtx == NULL) { + return; + } + + pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_SHOP4); + + _texture_z_light_fog_prim_npc(graph); + _texture_z_light_fog_prim_xlu(game->graph); + + OPEN_POLY_OPA_DISP(graph); + + gSPSegment(POLY_OPA_DISP++, 8, pal); + + CLOSE_POLY_OPA_DISP(graph); + + cKF_Si3_draw_R_SV(game, keyframe, mtx, &aDPT_actor_draw_before, &aDPT_actor_draw_after, actor); + _texture_z_light_fog_prim_shadow(graph); + (*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aDPT_shadow_data, FALSE); +} diff --git a/src/actor/ac_depart_move.c_inc b/src/actor/ac_depart_move.c_inc new file mode 100644 index 00000000..bcd4e143 --- /dev/null +++ b/src/actor/ac_depart_move.c_inc @@ -0,0 +1,368 @@ +extern cKF_Animation_R_c cKF_ba_r_obj_s_shop4; +extern cKF_Animation_R_c cKF_ba_r_obj_w_shop4; + +// clang-format off +static Door_data_c aDPT_depart_door_data = { + SCENE_DEPART, + mSc_DIRECT_NORTH, + FALSE, + 0, + {320, 0, 540}, + EMPTY_NO, + 1, + {0, 0, 0}, +}; +// clang-format on + +static void aDPT_set_door_SE(DEPART_ACTOR* depart, u16 se_no) { + sAdo_OngenTrgStart(se_no, &depart->struct_class.actor_class.world.position); +} + +static void aDPT_rewrite_out_data(DEPART_ACTOR* depart, GAME_PLAY* play) { + Door_data_c* out_data_p = Common_GetPointer(structure_exit_door_data); + xyz_t pos; + + if (play->fb_wipe_mode == 0) { + out_data_p->next_scene_id = Save_Get(scene_no); + out_data_p->exit_orientation = mSc_DIRECT_SOUTH_WEST; + out_data_p->exit_type = 0; + out_data_p->extra_data = 3; + + pos.x = depart->struct_class.actor_class.world.position.x - 62.0f; + pos.z = depart->struct_class.actor_class.world.position.z + 118.57f; + pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(pos, 0.0f); + + out_data_p->exit_position.x = (s16)pos.x; + out_data_p->exit_position.y = (s16)pos.y; + out_data_p->exit_position.z = (s16)pos.z; + out_data_p->door_actor_name = SHOP3; + out_data_p->wipe_type = 1; + mBGMPsComp_make_ps_wipe(0x2168); + } +} + +static int aDPT_check_player2(GAME_PLAY* play) { + ACTOR* player = GET_PLAYER_ACTOR_ACTOR(play); + int ret = FALSE; + + if ((u16)player->world.angle.y > DEG2SHORT_ANGLE2(90.0f) && (u16)player->world.angle.y < DEG2SHORT_ANGLE2(180.0f) && + player->speed > 0.0f) { + ret = TRUE; + } + + return ret; +} + +static int aDPT_check_player(ACTOR* actorx, GAME_PLAY* play) { + ACTOR* player = GET_PLAYER_ACTOR_ACTOR(play); + int ret = 0; + f32 dx; + f32 dz; + f32 dist; + + if (player == NULL) { + return 0; + } + + dx = player->world.position.x - (actorx->world.position.x - 38.0f); + dz = player->world.position.z - (actorx->world.position.z + 96.0f); + dist = SQ(dx) + SQ(dz); + + if ((u16)player->shape_info.rotation.y > DEG2SHORT_ANGLE2(90.0f) && (u16)player->shape_info.rotation.y < DEG2SHORT_ANGLE2(180.f) && + dist < 240.0f) { + ret = 2; + } else if (dist < 820.0f) { + ret = 1; + } + + return ret; +} + +static void aDPT_set_talk_info_close_wait(ACTOR* actorx) { + rgba_t window_color; + int msg_no; + int now_sec; + int status; + + now_sec = Common_Get(time.now_sec); + if (mSP_CheckFukubikiDay() != FALSE) { + if (now_sec >= (6 * mTM_SECONDS_IN_HOUR)) { + msg_no = mSP_ShopOpen() == mSP_SHOP_STATUS_PRE ? 0x7D6 : 0x7D7; + } else { + msg_no = 0x7D0; + } + } else { + switch (mSP_ShopOpen()) { + case mSP_SHOP_STATUS_PRE: // 0 + case mSP_SHOP_STATUS_END: // 1 + msg_no = 0x7D0; + break; + case mSP_SHOP_STATUS_PREEVENT: // 4 + msg_no = 0x7D4; + break; + case mSP_SHOP_STATUS_ENDEVENT: // 5 + msg_no = 0x7D9; + break; + case mSP_SHOP_STATUS_RENEW: // 3 + msg_no = 0x7D8; + break; + default: + msg_no = 0x7D0; + break; + } + } + + mDemo_Set_msg_num(msg_no); + + mDemo_Set_talk_display_name(FALSE); + mDemo_Set_camera(TRUE); + mPlib_Set_able_hand_all_item_in_demo(TRUE); + mDemo_Set_ListenAble(); + + window_color.r = 145; + window_color.g = 60; + window_color.b = 40; + window_color.a = 255; + mDemo_Set_talk_window_color(&window_color); +} + +static f32 aDPT_ctrl_light(DEPART_ACTOR* depart) { + f32 ret = 0.0f; + + if ((mSP_ShopOpen() == mSP_SHOP_STATUS_OPEN || mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT) == TRUE) { + ret = 1.0f; + } else if (depart->struct_class.action == aDPT_ACTION_PL_INTO_WAIT) { + ret = 1.0f; + } + + return ret; +} + +static void aDPT_set_bgOffset(DEPART_ACTOR* depart, int offs) { + // clang-format off + static mCoBG_OffsetTable_c height_table_ct[] = { + { mCoBG_ATTRIBUTE_NONE, 20, 20, 0, 20, 20, 1 }, + { mCoBG_ATTRIBUTE_NONE, 20, 20, 20, 0, 20, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 0, 15, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 20, 20, 20, 20, 20, 0 }, + { mCoBG_ATTRIBUTE_NONE, 20, 20, 20, 20, 20, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 0, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 0, 15, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 20, 15, 20, 20, 20, 0 }, + { mCoBG_ATTRIBUTE_NONE, 20, 20, 20, 20, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 0, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 0, 15, 15, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 0, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 0, 15, 15, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 15, 0 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 0, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 0, 15, 15, 15, 1 }, + { mCoBG_ATTRIBUTE_NONE, 15, 15, 15, 15, 0, 1 }, + }; + // clang-format on + + static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct }; + + // clang-format off + static f32 addX[] = { + -mFI_UT_WORLDSIZE_X_F, + 0.0, + -(2 * mFI_UT_WORLDSIZE_X_F), + -mFI_UT_WORLDSIZE_X_F, + 0.0, + mFI_UT_WORLDSIZE_X_F, + -(3 * mFI_UT_WORLDSIZE_X_F), + -(2 * mFI_UT_WORLDSIZE_X_F), + -mFI_UT_WORLDSIZE_X_F, + 0.0, + mFI_UT_WORLDSIZE_X_F, + (2 * mFI_UT_WORLDSIZE_X_F), + -(3 * mFI_UT_WORLDSIZE_X_F), + -(2 * mFI_UT_WORLDSIZE_X_F), + -mFI_UT_WORLDSIZE_X_F, + 0.0, + mFI_UT_WORLDSIZE_X_F, + (2 * mFI_UT_WORLDSIZE_X_F), + -(2 * mFI_UT_WORLDSIZE_X_F), + -mFI_UT_WORLDSIZE_X_F, + 0.0, + mFI_UT_WORLDSIZE_X_F, + -mFI_UT_WORLDSIZE_X_F, + 0.0, + + }; + // clang-format on + // clang-format off + static f32 addZ[] = { + (2 * mFI_UT_WORLDSIZE_Z_F), + (2 * mFI_UT_WORLDSIZE_Z_F), + mFI_UT_WORLDSIZE_Z_F, + mFI_UT_WORLDSIZE_Z_F, + mFI_UT_WORLDSIZE_Z_F, + mFI_UT_WORLDSIZE_Z_F, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + -mFI_UT_WORLDSIZE_Z_F, + -mFI_UT_WORLDSIZE_Z_F, + -mFI_UT_WORLDSIZE_Z_F, + -mFI_UT_WORLDSIZE_Z_F, + -mFI_UT_WORLDSIZE_Z_F, + -mFI_UT_WORLDSIZE_Z_F, + -(2 * mFI_UT_WORLDSIZE_Z_F), + -(2 * mFI_UT_WORLDSIZE_Z_F), + -(2 * mFI_UT_WORLDSIZE_Z_F), + -(2 * mFI_UT_WORLDSIZE_Z_F), + -(3 * mFI_UT_WORLDSIZE_Z_F), + -(3 * mFI_UT_WORLDSIZE_Z_F), + }; + // clang-format on + + mCoBG_OffsetTable_c* offset; + xyz_t pos; + int i; + + offset = height_table[offs]; + for (i = 0; i < ARRAY_COUNT(height_table_ct); i++) { + pos.z = depart->struct_class.actor_class.home.position.z + addZ[i]; + pos.x = depart->struct_class.actor_class.home.position.x + addX[i]; + mCoBG_SetPluss5PointOffset_file(pos, *offset, __FILE__, 430); + + offset++; + } +} + +static void aDPT_close_wait(DEPART_ACTOR* depart, GAME_PLAY* play) { + ACTOR* actorx; + + actorx = (ACTOR*)depart; + + if (mDemo_Check(mDemo_TYPE_TALK, actorx) == TRUE) { + return; + } + + if ((mSP_ShopOpen() == mSP_SHOP_STATUS_OPEN) || (mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT)) { + if (aDPT_check_player(actorx, play) != 0) { + aDPT_setup_action(depart, aDPT_ACTION_OPEN_DOOR); + } + return; + } + + if (aDPT_check_player(actorx, play) == 2) { + mDemo_Request(mDemo_TYPE_TALK, actorx, &aDPT_set_talk_info_close_wait); + } +} + +static void aDPT_open_wait(DEPART_ACTOR* depart, GAME_PLAY* play) { + ACTOR* actorx; + xyz_t pos; + + actorx = (ACTOR*)depart; + if (!mPlib_check_player_actor_main_index_OutDoorMove((GAME*)play)) { + if (mSP_ShopOpen() != mSP_SHOP_STATUS_OPEN && mSP_ShopOpen() != mSP_SHOP_STATUS_OPENEVENT) { + aDPT_setup_action(depart, aDPT_ACTION_CLOSE_DOOR); + } else if (aDPT_check_player(actorx, play) != 2) { + if (aDPT_check_player(actorx, play) == 0) { + aDPT_setup_action(depart, aDPT_ACTION_CLOSE_DOOR); + } + } else if (aDPT_check_player2(play)) { + pos.y = GET_PLAYER_ACTOR_ACTOR(play)->world.position.y; + pos.x = actorx->world.position.x - 45.0f; + pos.z = actorx->world.position.z + 102.5f; + mSP_SetTanukiShopStatus(); + + if (mPlib_request_main_door_type1((GAME*)play, &pos, DEG2SHORT_ANGLE(135.0f), TRUE, depart)) { + aDPT_setup_action(depart, aDPT_ACTION_PL_INTO_WAIT); + } + } + } +} + +static void aDPT_close_door(DEPART_ACTOR* depart, GAME_PLAY* play) { + if (depart->struct_class.keyframe_state == cKF_STATE_STOPPED) { + aDPT_setup_action(depart, aDPT_ACTION_CLOSE_WAIT); + } +} + +static void aDPT_open_door(DEPART_ACTOR* depart, GAME_PLAY* play) { + if (depart->struct_class.keyframe_state == cKF_STATE_STOPPED) { + aDPT_setup_action(depart, aDPT_ACTION_OPEN_WAIT); + } +} + +static void aDPT_pl_into_wait(DEPART_ACTOR* depart, GAME_PLAY* play) { + if (depart != GET_PLAYER_ACTOR_NOW()->get_door_label_proc(gamePT)) { + return; + } + + aDPT_rewrite_out_data(depart, play); + goto_other_scene(play, &aDPT_depart_door_data, FALSE); +} + +static void aDPT_setup_action(DEPART_ACTOR* depart, int action) { + static cKF_Animation_R_c* ani[] = { &cKF_ba_r_obj_s_shop4, &cKF_ba_r_obj_w_shop4 }; + static f32 anime_spd[] = { 0.0f, 0.0f, 0.5f, 0.5f, 0.0f }; + static f32 set[] = { 1.0f, 16.0f, 16.0f, 1.0f, 16.0f }; + static f32 end[] = { 1.0f, 16.0f, 1.0f, 16.0f, 16.0f }; + + // clang-format off + static void* process[] = { + &aDPT_close_wait, + &aDPT_open_wait, + &aDPT_close_door, + &aDPT_open_door, + &aDPT_pl_into_wait, + }; + // clang-format on + + int winter; + + winter = depart->struct_class.season == mTM_SEASON_WINTER; + + cKF_SkeletonInfo_R_init(&depart->struct_class.keyframe, depart->struct_class.keyframe.skeleton, ani[winter], 1.0f, + end[action], set[action], anime_spd[action], 0.0f, cKF_FRAMECONTROL_STOP, NULL); + + switch (action) { + case aDPT_ACTION_CLOSE_DOOR: + aDPT_set_door_SE(depart, NA_SE_44C); + break; + case aDPT_ACTION_OPEN_DOOR: + aDPT_set_door_SE(depart, NA_SE_44B); + break; + } + + depart->struct_class.action_proc = process[action]; + depart->struct_class.action = action; +} + +static void aDPT_actor_move(ACTOR* actor, GAME* game) { + DEPART_ACTOR* depart; + GAME_PLAY* play; + s16 target; + xyz_t pos; + + depart = (DEPART_ACTOR*)actor; + play = (GAME_PLAY*)game; + + depart->struct_class.keyframe_state = cKF_SkeletonInfo_R_play(&depart->struct_class.keyframe); + depart->struct_class.keyframe_saved_keyframe = depart->struct_class.keyframe.frame_control.current_frame; + + (*depart->struct_class.action_proc)((STRUCTURE_ACTOR*)depart, play); + chase_f(&depart->struct_class.arg0_f, aDPT_ctrl_light(depart), 0.019532442f); // approx sqrt(0.000385f) +} + +static void aDPT_actor_init(ACTOR* actor, GAME* game) { + mFI_SetFG_common(DUMMY_SHOP3, actor->home.position, FALSE); + aDPT_actor_move(actor, game); + actor->mv_proc = aDPT_actor_move; +}