From 8da5ae63bf41673cb26367cbc044b2d81eceec08 Mon Sep 17 00:00:00 2001 From: Prakxo Date: Sun, 29 Oct 2023 18:32:53 +0100 Subject: [PATCH] link ac_toudai --- config/rel_slices.yml | 4 + include/ac_toudai.h | 23 +++ include/m_collision_bg.h | 11 + rel/ac_toudai.c | 432 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 470 insertions(+) create mode 100644 rel/ac_toudai.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 52338d9a..a5ee8922 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -496,6 +496,10 @@ ac_structure.c: .rodata: [0x8064AC30, 0x8064AC38] .data: [0x806C6C00, 0x806C6ED0] .bss: [0x813280F0, 0x8133DEB0] +ac_toudai.c: + .text: [0x805BEA00, 0x805BFC28] + .rodata: [0x8064ACB0,0x8064AD28] + .data: [0x806C7200, 0x806C72D0] ac_train0.c: .text: [0x805BFC28, 0x805C0614] .rodata: [0x8064AD28, 0x8064AD80] diff --git a/include/ac_toudai.h b/include/ac_toudai.h index 6d6d3009..61bc3f6d 100644 --- a/include/ac_toudai.h +++ b/include/ac_toudai.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "c_keyframe.h" #ifdef __cplusplus extern "C" { @@ -10,6 +11,28 @@ extern "C" { extern ACTOR_PROFILE Toudai_Profile; +typedef void (*TOUDAI_PROC)(ACTOR*, GAME_PLAY*); + +typedef struct actor_toudai_s{ + ACTOR actor_class; + int keyframe_state; + cKF_SkeletonInfo_R_c keyframe; + int current_frame; + s_xyz work[15]; + s_xyz target[15]; + TOUDAI_PROC proc; + u8 unk2A4[0x10]; + int current_proc; + u8 unk2B8[0x4]; + int ready_flag; + u8 unk2C0[0x8]; + f32 unk2C8; + f32 unk2CC; + f32 unk2D0; + u8 unk2D4[0x4]; + int season; +}TOUDAI_ACTOR; + #ifdef __cplusplus } #endif diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index d7f9d2b3..6baef4e0 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -153,6 +153,16 @@ typedef struct bg_register_s { f32* scale_percent; } mCoBG_bg_regist_c; +typedef struct collision_offset_table_s { + u8 unit_attribute; + s8 centerRight_offset; + s8 leftUp_offset; + s8 leftDown_offset; + s8 rightDown_offset; + s8 rightUp_offset; + s8 slate_switch; +} mCoBG_OffsetTable_c; + extern u32 mCoBG_Wpos2BgAttribute_Original(xyz_t wpos); extern u32 mCoBG_Wpos2Attribute(xyz_t wpos, char* is_diggable); extern int mCoBG_CheckWaterAttribute(u32 attribute); @@ -171,6 +181,7 @@ extern int mCoBG_BnumUnum2HoleNumber(int block_x, int block_z, int ut_x, int ut_ extern u32 mCoBG_UtNum2BgAttr(int ut_x, int ut_z); extern f32 mCoBG_UtNum2UtCenterY(int ut_x, int ut_z); extern int mCoBG_CheckCliffAttr(u32 attribute); +extern void mCoBG_SetPluss5PointOffset_file(xyz_t pos, mCoBG_OffsetTable_c offsetptr, const char* file, int line); extern int mCoBG_Change2PoorAttr(mCoBG_Collision_u* col); extern int mCoBG_CheckHole(xyz_t wpos); extern int mCoBG_CheckSkySwing(xyz_t wpos); diff --git a/rel/ac_toudai.c b/rel/ac_toudai.c new file mode 100644 index 00000000..885182d9 --- /dev/null +++ b/rel/ac_toudai.c @@ -0,0 +1,432 @@ +#include "ac_toudai.h" + +#include "m_name_table.h" +#include "m_rcp.h" +#include "sys_matrix.h" +#include "bg_item.h" +#include "m_player_lib.h" +#include "m_common_data.h" +#include "m_bgm.h" + + +static void aTOU_actor_ct(ACTOR*, GAME*); +static void aTOU_actor_dt(ACTOR*, GAME*); +static void aTOU_actor_init(ACTOR*, GAME*); +static void aTOU_actor_draw(ACTOR*, GAME*); + +ACTOR_PROFILE Toudai_Profile = { + mAc_PROFILE_TOUDAI, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + TOUDAI, + ACTOR_OBJ_BANK_KEEP, + sizeof(TOUDAI_ACTOR), + aTOU_actor_ct, + aTOU_actor_dt, + aTOU_actor_init, + aTOU_actor_draw, + NULL, +}; + +extern Vtx obj_s_toudai_shadow_v[]; +extern Gfx obj_s_toudai_shadow_1_model[]; + +u8 aTOU_shadow_vtx_fix_flg_table[] = {1,0,1,0, + 0,1,1,0, + 1,0,0,0,}; +bIT_ShadowData_c aTOU_shadow_data = { + 10, + aTOU_shadow_vtx_fix_flg_table, + 60.0f, + obj_s_toudai_shadow_v, + obj_s_toudai_shadow_1_model, +}; + + +static void aTOU_set_bgOffset(TOUDAI_ACTOR*, int); +static void aTOU_setup_action(ACTOR*, int); + +static void aTOU_fgunit_on(ACTOR* actor){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + xyz_t pos; + int i; + mActor_name_t* nameptr; + + xyz_t_move(&pos, &light->actor_class.home.position); + + pos.x -= 40.0f; + pos.z -= 80.0f; + for(i = 0; i < 2; i++){ + nameptr = mFI_GetUnitFG(pos); + if(nameptr != NULL){ + if(mSN_ClearSnowman(nameptr) == 0){ + if (((*nameptr >= 0x2A) && (*nameptr <= 0x42)) || (*nameptr == 0x5C)) { + mPB_keep_item(bg_item_fg_sub_dig2take_conv(*nameptr)); + mFI_SetFG_common(RSV_NO, pos, 1); + mFI_Wpos2DepositOFF(pos); + } + else{ + mFI_Wpos2DepositOFF(pos); + mPB_keep_item(*nameptr); + mFI_SetFG_common(RSV_NO, pos, 1); + } + } + else{ + mFI_SetFG_common(RSV_NO, pos, 1); + } + } + pos.x += 40.0f; + } +} + +static void aTOU_fgunit_off(ACTOR* actor){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + int i; + xyz_t pos; + + xyz_t_move(&pos, &light->actor_class.home.position); + + pos.x -= 40.0f; + pos.z -= 80.0f; + for (i = 0; i < 2; i++){ + mFI_SetFG_common(EMPTY_NO, pos, 1); + pos.x += 40.0f; + } +} + +extern cKF_Skeleton_R_c cKF_bs_r_obj_s_toudai; +extern cKF_Skeleton_R_c cKF_bs_r_obj_w_toudai; + +static void aTOU_actor_ct(ACTOR* actor, GAME* game){ + static cKF_Skeleton_R_c* skl[] = {&cKF_bs_r_obj_s_toudai, &cKF_bs_r_obj_w_toudai}; + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + light->season = Common_Get(time.season); + cKF_SkeletonInfo_R_ct(&light->keyframe, skl[light->season == mTM_SEASON_WINTER], NULL, light->work, light->target); + aTOU_set_bgOffset(light, 1); + aTOU_fgunit_on(actor); + aTOU_setup_action(actor, 0); + cKF_SkeletonInfo_R_play(&light->keyframe); + actor->world.position.x -= 20.0f; + actor->world.position.z -= 20.0f; +} + +static void aTOU_actor_dt(ACTOR* actor, GAME* game){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + aTOU_fgunit_off(&light->actor_class); + cKF_SkeletonInfo_R_dt(&light->keyframe); + light->actor_class.world.position.x += 20.0f; + light->actor_class.world.position.z += 20.0f; + +} + +static void aTOU_rewrite_door(ACTOR* actor, GAME_PLAY* play){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + xyz_t pos; + Door_data_c* door_data = Common_GetPointer(structure_exit_door_data); + + if(play->fb_wipe_mode == 0){ + door_data->next_scene_id = Save_Get(scene_no); + door_data->exit_orientation = 4; + door_data->exit_type = 0; + door_data->extra_data = 3; + + pos.x = light->actor_class.world.position.x; + pos.z = light->actor_class.world.position.z - 70.0f; + pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(pos, 0.0f); + door_data->exit_position.x = pos.x; + door_data->exit_position.y = pos.y; + door_data->exit_position.z = pos.z; + door_data->door_actor_name = light->actor_class.npc_id; + door_data->wipe_type = 1; + mBGMPsComp_make_ps_wipe(0x2168); + } +} + +static int aTOU_check_door_pos(ACTOR* actor, GAME_PLAY* play){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + PLAYER_ACTOR* player = get_player_actor_withoutCheck(play); + f32 diff; + + if(player != NULL){ + diff = (player->actor_class.world.position.z - light->actor_class.world.position.z); + if(fabsf(player->actor_class.world.position.x - light->actor_class.world.position.x) < 20.0f && + diff > -65.0f && diff < 0.0f){ + if((player->actor_class.shape_info.rotation.y > -0x2000) && + (player->actor_class.shape_info.rotation.y < 0x2000)){ + return 1; + } + } + } + + return 0; +} + +Door_data_c aTOU_door_data = { + SCENE_LIGHTHOUSE, + 0, + FALSE, + 0, + {120,0,100}, + EMPTY_NO, + 1, + {0,0,0}, +}; + +static void aTOU_set_bgOffset(TOUDAI_ACTOR* light, int idx){ + static mCoBG_OffsetTable_c height_table_ct[] = { { 0x64, 16, 16, 16, 16, 16, 0 }, + { 0x64, 16, 16, 16, 16, 16, 0 }, + { 0x64, 16, 16, 16, 16, 16, 0 }, + { 0x64, 16, 16, 16, 16, 16, 0 } }; + static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct }; + static f32 addX[] = { -40.0f, 0.0f }; + static f32 addZ[] = { -40.0f, 0.0f }; + + mCoBG_OffsetTable_c* offset; + int i; + xyz_t pos; + + offset = height_table[idx]; + + for(i = 0; i < 2; i++){ + pos.z = light->actor_class.home.position.z + addZ[i]; + pos.x = light->actor_class.home.position.x + addX[0]; + mCoBG_SetPluss5PointOffset_file(pos, *offset, "ac_toudai_move.c_inc", 184); + offset++; + pos.x = light->actor_class.home.position.x + addX[1]; + mCoBG_SetPluss5PointOffset_file(pos, *offset, "ac_toudai_move.c_inc", 188); + offset++; + } +} + +static void aTOU_color_ctrl(TOUDAI_ACTOR* light) { + f32 factor; + int timer; + + if (light->ready_flag == 0) { + add_calc(&light->unk2C8, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f); + add_calc(&light->unk2CC, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f); + add_calc(&light->unk2D0, 0.0f, 1.0f - sqrtf(0.9), 50.0f, 0.5f); + return; + } + + timer = light->current_frame - 51; + factor = (timer < 0) ? 1.0f : -1.0f; + timer = ABS(timer); + + if (timer == 0) { + light->unk2C8 = 220.0f; + light->unk2CC = 240.0f; + + } else if (timer >= 40) { + add_calc(&light->unk2C8, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f); + add_calc(&light->unk2CC, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f); + + } else if (timer < 10) { + light->unk2C8 += (4.5f * factor); + light->unk2CC += (7.0f * factor); + + } else if (timer < 30) { + light->unk2C8 += (1.25f * factor); + light->unk2CC += (2.25f * factor); + + } else { + light->unk2C8 += (4.0f * factor); + light->unk2CC += (0.5f * factor); + } + + add_calc(&light->unk2D0, 255.0f, 1.0f - sqrtf(0.9), 50.0f, 0.5f); +} + +static void aTOU_init(ACTOR* actor, GAME_PLAY* play){ + aTOU_setup_action(actor, 1); +} + +static void aTOU_wait(ACTOR* actor, GAME_PLAY* play){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + int sec = Common_Get(time.now_sec); + + if(mSC_LightHouse_Switch_Check() != 0 && (sec >= 64800 || sec < 18000)){ + light->keyframe.frame_control.speed = 0.5f; + light->ready_flag = TRUE; + aTOU_setup_action(actor, 2); + } +} + +static void aTOU_lighting(ACTOR* actor, GAME_PLAY* play){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + int sec = Common_Get(time.now_sec); + + if((mSC_LightHouse_Switch_Check() == 0) || ((sec < 64800) + && (sec >= 18000))){ + aTOU_setup_action(actor, 3); + } +} + +static void aTOU_lightout(ACTOR* actor, GAME_PLAY* play){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + if(light->current_frame == 0x33){ + light->keyframe.frame_control.speed = 0.0f; + light->ready_flag = 0; + aTOU_setup_action(actor, 1); + } +} + +extern cKF_Animation_R_c cKF_ba_r_obj_s_toudai; +extern cKF_Animation_R_c cKF_ba_r_obj_w_toudai; + +static void aTOU_setup_action(ACTOR* actor, int action) { + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + static cKF_Animation_R_c* ani[] = { &cKF_ba_r_obj_s_toudai, &cKF_ba_r_obj_w_toudai }; + static TOUDAI_PROC process[] = { aTOU_init, aTOU_wait, aTOU_lighting, aTOU_lightout }; + + int type; + + if(action == 0){ + type = light->season == mTM_SEASON_WINTER; + cKF_SkeletonInfo_R_init(&light->keyframe, light->keyframe.skeleton, ani[type], + 1.0f, 100.0f, 51.0f, 0.0f, 0.0f, cKF_FRAMECONTROL_REPEAT, NULL); + } + + light->proc = process[action]; + light->current_proc = action; +} + +static void aTOU_actor_move(ACTOR* actor, GAME* game){ + GAME_PLAY* play = (GAME_PLAY*)game; + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + light->keyframe_state = cKF_SkeletonInfo_R_play(&light->keyframe); + light->current_frame = light->keyframe.frame_control.current_frame; + + if(get_player_actor_withoutCheck((GAME_PLAY*)gamePT)->get_door_label_proc(gamePT) == light){ + aTOU_rewrite_door(&light->actor_class, play); + goto_other_scene(play, &aTOU_door_data, 0); + } + else{ + light->proc(actor,play); + + if((mSC_LightHouse_In_Check() != 0) && (aTOU_check_door_pos(actor,play) != 0)){ + xyz_t pos; + pos.x = light->actor_class.world.position.x; + pos.y = light->actor_class.world.position.y; + pos.z = light->actor_class.world.position.z - 60.0f; + mPlib_request_main_door_type1(play, &pos, 0, 1, light); + } + } + aTOU_color_ctrl(light); +} + +static void aTOU_actor_init(ACTOR* actor, GAME* game){ + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + mFI_SetFG_common(0xF11E, light->actor_class.home.position, 0); + aTOU_actor_move(actor, game); + light->actor_class.mv_proc = aTOU_actor_move; +} + +static int aTOU_actor_draw_before(GAME*,cKF_SkeletonInfo_R_c*, int idx, Gfx** gfxp,u8* dispbuf, void* actor, s_xyz* rotation, xyz_t* translation){ + + if(idx == 4){ + *gfxp = NULL; + } + + return 1; +} + +extern Gfx obj_s_toudai_light_model[]; +extern Gfx obj_w_toudai_light_model[]; + +static int aTOU_actor_draw_after(GAME* game,cKF_SkeletonInfo_R_c* info, int idx, Gfx** gfxp, +u8* dispbuf, void* actor, s_xyz* rotation, xyz_t* translation){ + static Gfx* mdl[] = {obj_s_toudai_light_model, obj_w_toudai_light_model}; + static rgba_t prmcol = {255,255,150,120}; + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + GRAPH* graph = game->graph; + Mtx* work; + u16* pal; + Gfx* gfx; + int type; + + if((idx == 4) && ((int)light->unk2CC != 0)){ + work = _Matrix_to_Mtx_new(graph); + + if(work != NULL){ + type = light->season == mTM_SEASON_WINTER; + pal = Common_Get(clip.structure_clip)->get_pal_segment_proc(aSTR_PAL_TOUDAI); + _texture_z_light_fog_prim_light(graph); + + OPEN_DISP(graph); + + gfx = NOW_LIGHT_DISP; + gSPSegment(gfx++, 0x8, pal); + + prmcol.b = light->unk2C8; + prmcol.a = light->unk2CC; + + if(prmcol.a > (u8)light->unk2D0){ + prmcol.a = light->unk2D0; + } + + gDPPipeSync(gfx++); + gDPSetPrimColor(gfx++, 0, (s8)light->unk2D0, prmcol.r, prmcol.g, prmcol.b, prmcol.a); + gSPMatrix(gfx++, work, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(gfx++, mdl[type]); + + SET_LIGHT_DISP(gfx); + CLOSE_DISP(graph); + } + } + + return 1; +} + + +static void aTOU_actor_draw(ACTOR* actor, GAME* game){ + GAME_PLAY* play = (GAME_PLAY*)game; + GRAPH* graph; + + Gfx* gfx; + u16* pal; + cKF_SkeletonInfo_R_c* keyf; + Mtx* mtx; + xyz_t* pos; + TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; + + graph = game->graph; + pos = &light->actor_class.world.position; + keyf = &light->keyframe; + mtx = GRAPH_ALLOC_TYPE(graph, Mtx, keyf->skeleton->num_shown_joints); + + if(mtx != NULL){ + pal = Common_Get(clip.structure_clip)->get_pal_segment_proc(aSTR_PAL_TOUDAI); + + OPEN_DISP(graph); + + _texture_z_light_fog_prim_npc(graph); + + gfx = NOW_POLY_OPA_DISP; + gSPSegment(gfx++, 0x8, pal); + SET_POLY_OPA_DISP(gfx); + + _texture_z_light_fog_prim_xlu(graph); + + gfx = NOW_POLY_XLU_DISP; + gSPSegment(gfx++, 0x8, pal); + SET_POLY_XLU_DISP(gfx); + + Setpos_HiliteReflect_init(pos, play); + Setpos_HiliteReflect_xlu_init(pos, play); + + cKF_Si3_draw_R_SV(game, keyf, mtx, aTOU_actor_draw_before, aTOU_actor_draw_after, light); + (*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aTOU_shadow_data, TRUE); + CLOSE_DISP(graph); + } +} \ No newline at end of file