mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-18 06:15:24 -04:00
357 lines
12 KiB
C
357 lines
12 KiB
C
#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;
|
|
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(game);
|
|
}
|
|
|
|
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);
|
|
}
|