diff --git a/configure.py b/configure.py index 72a70c35..e44e9e7a 100644 --- a/configure.py +++ b/configure.py @@ -372,7 +372,7 @@ config.libs = [ "objects": [ Object(Matching, "libultra/contquery.c"), Object(NonMatching, "libultra/contreaddata.c"), - Object(Matching, "libultra/controller.c"), + Object(Matching, "libultra/controller.c"), Object(Matching, "libultra/contsetch.c"), Object(Matching, "libultra/gu/coss.c"), Object(Matching, "libultra/createmesgqueue.c"), @@ -982,7 +982,7 @@ config.libs = [ Object(NonMatching, "actor/ac_hatumode_control.c"), Object(NonMatching, "actor/ac_hatumode_npc0.c"), Object(NonMatching, "actor/ac_house.c"), - Object(NonMatching, "actor/ac_house_clock.c"), + Object(Matching, "actor/ac_house_clock.c"), Object(NonMatching, "actor/ac_house_goki.c"), Object(NonMatching, "actor/ac_htable.c"), Object(Matching, "actor/ac_ins_amenbo.c"), diff --git a/include/ac_house_clock.h b/include/ac_house_clock.h index 8e831ebb..2c362fca 100644 --- a/include/ac_house_clock.h +++ b/include/ac_house_clock.h @@ -3,11 +3,46 @@ #include "types.h" #include "m_actor.h" +#include "c_keyframe.h" #ifdef __cplusplus extern "C" { #endif +#define aHC_JOINT_NUM 5 // body +#define aHC_ALL_JOINT_NUM aHC_JOINT_NUM + 2 // body + hands + +enum { + aHC_TYPE_SHOP1, + aHC_TYPE_SHOP2, + aHC_TYPE_SHOP3, + aHC_TYPE_SHOP4, + aHC_TYPE_SHOP4_2, + aHC_TYPE_POST_OFFICE, + aHC_TYPE_POLICE_BOX, + aHC_TYPE_MUSEUM, + aHC_TYPE_TAILORS, + + aHC_TYPE_NUM +}; + +typedef struct house_clock_s { + s16 clock_num; + xyz_t pos; + u8* bank; + cKF_SkeletonInfo_R_c keyframe; + s_xyz work[aHC_JOINT_NUM]; + s_xyz morph[aHC_JOINT_NUM]; + Mtx mtx[2][aHC_ALL_JOINT_NUM]; +} aHC_clock_c; + +typedef struct house_clock_actor_s HOUSE_CLOCK_ACTOR; + +struct house_clock_actor_s { + ACTOR actor_class; + aHC_clock_c clock; +}; + extern ACTOR_PROFILE House_Clock_Profile; #ifdef __cplusplus @@ -15,4 +50,3 @@ extern ACTOR_PROFILE House_Clock_Profile; #endif #endif - diff --git a/include/audio_defs.h b/include/audio_defs.h index fb936bed..8806f218 100644 --- a/include/audio_defs.h +++ b/include/audio_defs.h @@ -122,6 +122,8 @@ typedef enum audio_sound_effects { NA_SE_SCOOP_UMERU = 0x120, NA_SE_SCOOP_HIT, + NA_SE_12D = 0x12D, + NA_SE_TREE_TOUCH = 0x134, NA_SE_TREE_YURASU, diff --git a/src/actor/ac_house_clock.c b/src/actor/ac_house_clock.c new file mode 100644 index 00000000..d8c3a36f --- /dev/null +++ b/src/actor/ac_house_clock.c @@ -0,0 +1,357 @@ +#include "ac_house_clock.h" + +#include "m_scene.h" +#include "m_name_table.h" +#include "m_rcp.h" +#include "sys_matrix.h" +#include "m_malloc.h" +#include "m_common_data.h" + +enum { + aHC_ENV_MAP_NONE, + aHC_ENV_MAP_OPA, + aHC_ENV_MAP_XLU, + + aHC_ENV_MAP_NUM +}; + +typedef struct house_clock_draw_data_s { + cKF_Skeleton_R_c* skeleton; + cKF_Animation_R_c* animation; + s16 short_joint_no; + s16 long_joint_no; + Gfx* short_model; + Gfx* long_model; + s16 env_map_type; +} aHC_draw_data_c; + +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_shop1; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_shop2; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_shop3; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_shop4; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_yub; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_koban; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_museum1; +extern cKF_Skeleton_R_c cKF_bs_r_obj_clock_tailor; + +extern cKF_Animation_R_c cKF_ba_r_obj_clock_shop1; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_shop2; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_shop3; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_shop4; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_yub; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_koban; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_museum1; +extern cKF_Animation_R_c cKF_ba_r_obj_clock_tailor; + +extern Gfx obj_clock_shop1_short_model[]; +extern Gfx obj_clock_shop1_long_model[]; + +extern Gfx obj_clock_shop2_short_model[]; +extern Gfx obj_clock_shop2_long_model[]; + +extern Gfx obj_clock_shop3_short_model[]; +extern Gfx obj_clock_shop3_long_model[]; + +extern Gfx obj_clock_shop4_short_model[]; +extern Gfx obj_clock_shop4_long_model[]; + +extern Gfx obj_clock_yub_short_model[]; +extern Gfx obj_clock_yub_long_model[]; + +extern Gfx obj_clock_koban_short_model[]; +extern Gfx obj_clock_koban_long_model[]; + +extern Gfx obj_clock_museum1_short_model[]; +extern Gfx obj_clock_museum1_long_model[]; + +extern Gfx obj_clock_tailor_short_model[]; +extern Gfx obj_clock_tailor_long_model[]; + +// clang-format off +static aHC_draw_data_c aHC_draw_data[] = { + { + &cKF_bs_r_obj_clock_shop1, &cKF_ba_r_obj_clock_shop1, + 5, 6, + obj_clock_shop1_short_model, obj_clock_shop1_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_shop2, &cKF_ba_r_obj_clock_shop2, + 3, 4, + obj_clock_shop2_short_model, obj_clock_shop2_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_shop3, &cKF_ba_r_obj_clock_shop3, + 3, 4, + obj_clock_shop3_short_model, obj_clock_shop3_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_shop4, &cKF_ba_r_obj_clock_shop4, + 5, 6, + obj_clock_shop4_short_model, obj_clock_shop4_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_shop4, &cKF_ba_r_obj_clock_shop4, + 5, 6, + obj_clock_shop4_short_model, obj_clock_shop4_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_yub, &cKF_ba_r_obj_clock_yub, + 3, 4, + obj_clock_yub_short_model, obj_clock_yub_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_koban, &cKF_ba_r_obj_clock_koban, + 3, 4, + obj_clock_koban_short_model, obj_clock_koban_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_museum1, &cKF_ba_r_obj_clock_museum1, + 3, 4, + obj_clock_museum1_short_model, obj_clock_museum1_long_model, + aHC_ENV_MAP_NONE + }, + { + &cKF_bs_r_obj_clock_tailor, &cKF_ba_r_obj_clock_tailor, + 5, 6, + obj_clock_tailor_short_model, obj_clock_tailor_long_model, + aHC_ENV_MAP_NONE + }, +}; +// clang-format on + +typedef struct house_clock_pos_data_s { + int scene_no; + xyz_t pos; +} aHC_pos_data_c; + +// clang-format off +static aHC_pos_data_c aHC_position_data[] = { + { SCENE_SHOP0, { 200.0f, 40.0f, 40.0f } }, + { SCENE_CONVENI, { 240.0f, 0.0f, 40.0f } }, + { SCENE_SUPER, { 160.0f, 0.0f, 40.0f } }, + { SCENE_DEPART, { 240.0f, 0.0f, 120.0f } }, + { SCENE_DEPART_2, { 240.0f, 0.0f, 120.0f } }, + { SCENE_POST_OFFICE, { 120.0f, 55.0f, 135.0f } }, + { SCENE_POLICE_BOX, { 200.0f, 0.0f, 30.0f } }, + { SCENE_MUSEUM_ENTRANCE, { 0.0f, 0.0f, 0.0f } }, + { SCENE_NEEDLEWORK, { 0.0f, 0.0f, 0.0f } }, +}; +// clang-format on + +static void House_Clock_Actor_ct(ACTOR* actorx, GAME* game); +static void House_Clock_Actor_dt(ACTOR* actorx, GAME* game); +static void House_Clock_Actor_move(ACTOR* actorx, GAME* game); +static void House_Clock_Actor_draw(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE House_Clock_Profile = { + mAc_PROFILE_HOUSE_CLOCK, + ACTOR_PART_FG, + ACTOR_STATE_NO_DRAW_WHILE_CULLED | ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_KEEP, + sizeof(HOUSE_CLOCK_ACTOR), + &House_Clock_Actor_ct, + &House_Clock_Actor_dt, + &House_Clock_Actor_move, + &House_Clock_Actor_draw, + NULL, +}; +// clang-format on + +static void House_Clock_Actor_no_draw(ACTOR* actorx, GAME* game) { + // nothing +} + +static void aHC_dummy(ACTOR* actorx, GAME* game) { + // nothing +} + +static int aHC_SetClockNum(ACTOR* actorx) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + int i; + int scene_no = Save_Get(scene_no); + + house_clock->clock.clock_num = 0; + for (i = 0; i < aHC_TYPE_NUM; i++) { + if (scene_no == aHC_position_data[i].scene_no) { + house_clock->clock.clock_num = i; + house_clock->clock.pos = aHC_position_data[house_clock->clock.clock_num].pos; + return TRUE; + } + } + + actorx->mv_proc = &aHC_dummy; + actorx->dw_proc = &aHC_dummy; + actorx->dt_proc = &aHC_dummy; + return FALSE; +} + +static void aHC_InitClockAnimation(ACTOR* actorx) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + aHC_clock_c* clock = &house_clock->clock; + cKF_SkeletonInfo_R_c* kf_p = &clock->keyframe; + s16 clock_num = clock->clock_num; + + cKF_SkeletonInfo_R_ct(kf_p, aHC_draw_data[clock_num].skeleton, aHC_draw_data[clock_num].animation, clock->work, + clock->morph); + cKF_SkeletonInfo_R_init_standard_repeat(kf_p, aHC_draw_data[clock_num].animation, NULL); + cKF_SkeletonInfo_R_play(kf_p); + kf_p->frame_control.speed = 0.5f; +} + +static void House_Clock_Actor_ct(ACTOR* actorx, GAME* game) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + + if (aHC_SetClockNum(actorx)) { + aHC_InitClockAnimation(actorx); + house_clock->clock.pos = + aHC_position_data[house_clock->clock.clock_num].pos; // @cleanup - this is already done in aHC_SetClockNum + + // Don't render the clock if the monthly raffle is taking place + if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI && house_clock->clock.clock_num <= 4) { + actorx->dw_proc = &House_Clock_Actor_no_draw; + } + } +} + +static void House_Clock_Actor_dt(ACTOR* actorx, GAME* game) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + + if (house_clock->clock.bank != NULL) { + zelda_free(house_clock->clock.bank); + } +} + +static void aHC_SetEnvMapping(ACTOR* actorx, GAME* game) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + GAME_PLAY* play = (GAME_PLAY*)game; + + switch (aHC_draw_data[house_clock->clock.clock_num].env_map_type) { + case aHC_ENV_MAP_OPA: + _texture_z_light_fog_prim(game->graph); + Setpos_HiliteReflect_init(&house_clock->clock.pos, play); + break; + case aHC_ENV_MAP_XLU: + _texture_z_light_fog_prim_xlu(game->graph); + Setpos_HiliteReflect_xlu_init(&house_clock->clock.pos, play); + break; + } +} + +static int aHC_DrawClockBefore(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) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)arg; + s16 clock_num = house_clock->clock.clock_num; + + if (joint_idx == aHC_draw_data[clock_num].short_joint_no || joint_idx == aHC_draw_data[clock_num].long_joint_no) { + *joint_shape = NULL; + } + + return TRUE; +} + +static int aHC_DrawClockAfter(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) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)arg; + GAME_PLAY* play = (GAME_PLAY*)game; + s16 clock_num = house_clock->clock.clock_num; + xyz_t pos; + xyz_t ofs = { 0.0f, 0.0f, 0.0f }; + + if (clock_num == aHC_TYPE_MUSEUM) { + Global_kankyo_set_room_prim(play); + } + + if (joint_idx == aHC_draw_data[clock_num].short_joint_no) { + OPEN_DISP(game->graph); + + Matrix_Position(&ofs, &pos); + Matrix_push(); + Matrix_translate(pos.x, pos.y, pos.z, 0); + Matrix_RotateZ(DEG2SHORT_ANGLE2(90.0f) - Common_Get(time).rad_hour, 1); + Matrix_scale(0.01f, 0.01f, 0.01f, 1); + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + Matrix_pull(); + gSPDisplayList(NEXT_POLY_OPA_DISP, aHC_draw_data[clock_num].short_model); + + CLOSE_DISP(game->graph); + } else if (joint_idx == aHC_draw_data[clock_num].long_joint_no) { + OPEN_DISP(game->graph); + + Matrix_Position(&ofs, &pos); + Matrix_push(); + Matrix_translate(pos.x, pos.y, pos.z, 0); + Matrix_RotateZ(DEG2SHORT_ANGLE2(90.0f) - Common_Get(time).rad_min, 1); + Matrix_scale(0.01f, 0.01f, 0.01f, 1); + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + Matrix_pull(); + gSPDisplayList(NEXT_POLY_OPA_DISP, aHC_draw_data[clock_num].long_model); + + CLOSE_DISP(game->graph); + } + + return TRUE; +} + +static void aHC_DrawClock(ACTOR* actorx, GAME* game) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + int idx = game->frame_counter & 1; + Mtx* mtx = house_clock->clock.mtx[idx]; + + _texture_z_light_fog_prim(game->graph); + OPEN_DISP(game->graph); + + Matrix_translate(house_clock->clock.pos.x, house_clock->clock.pos.y, house_clock->clock.pos.z, 0); + Matrix_scale(0.01f, 0.01f, 0.01f, 1); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + CLOSE_DISP(game->graph); + + cKF_Si3_draw_R_SV(game, &house_clock->clock.keyframe, mtx, &aHC_DrawClockBefore, &aHC_DrawClockAfter, actorx); +} + +static void House_Clock_Actor_draw(ACTOR* actorx, GAME* game) { + aHC_SetEnvMapping(actorx, game); + aHC_DrawClock(actorx, game); +} + +static void aHC_OperateAnime(ACTOR* actorx, GAME* game) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + aHC_clock_c* clock = &house_clock->clock; + cKF_SkeletonInfo_R_c* kf_p = &clock->keyframe; + GAME_PLAY* play = (GAME_PLAY*)game; + u32 frame = play->game_frame % 120; + + switch (frame) { + case 0: + cKF_SkeletonInfo_R_init_standard_repeat(kf_p, aHC_draw_data[clock->clock_num].animation, NULL); + cKF_SkeletonInfo_R_play(kf_p); + kf_p->frame_control.speed = 0.5f; + break; + case 15: + sAdo_OngenTrgStart(NA_SE_12D, &clock->pos); + break; + case 45: + sAdo_OngenTrgStart(NA_SE_12D, &clock->pos); + break; + } +} + +static void House_Clock_Actor_move(ACTOR* actorx, GAME* game) { + HOUSE_CLOCK_ACTOR* house_clock = (HOUSE_CLOCK_ACTOR*)actorx; + aHC_clock_c* clock = &house_clock->clock; + cKF_SkeletonInfo_R_c* kf_p = &clock->keyframe; + + cKF_SkeletonInfo_R_play(kf_p); + kf_p->frame_control.speed = 0.5f; + aHC_OperateAnime(actorx, game); +}