From 00b8dd6f6e716734f5319e2197a29680464824ab Mon Sep 17 00:00:00 2001 From: Hexalotl <15166449+Hexalotl@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:03:10 -0700 Subject: [PATCH] Implement & link ac_flag --- config/rel_slices.yml | 4 + include/ac_flag.h | 2 +- include/m_name_table.h | 1 + include/m_needlework.h | 2 +- src/ac_flag.c | 407 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 src/ac_flag.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index a236d992..b3c71abb 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -419,6 +419,10 @@ ac_field_draw.c: .rodata: [0x80643F00, 0x80643F88] .data: [0x806829E0, 0x80682B68] .bss: [0x812F98C0, 0x812F9C28] +ac_flag.c: + .text: [0x80423E30, 0x80424B88] + .rodata: [0x80643F88, 0x80643FC0] + .data: [0x80682B90, 0x80682C00] ac_handOverItem.c: .text: [0x80426A50, 0x80427624] .rodata: [0x806440A0, 0x806440B8] diff --git a/include/ac_flag.h b/include/ac_flag.h index c796b936..5fad2c1c 100644 --- a/include/ac_flag.h +++ b/include/ac_flag.h @@ -2,7 +2,7 @@ #define AC_FLAG_H #include "types.h" -#include "m_actor.h" +#include "ac_structure.h" #ifdef __cplusplus extern "C" { diff --git a/include/m_name_table.h b/include/m_name_table.h index 785c8eea..c9ce2064 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -2725,6 +2725,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define DUMMY_LOTUS 0xF11B #define DUMMY_DOUZOU 0xF11D #define DUMMY_NAMEPLATE 0xF11F +#define DUMMY_FLAG 0xF122 #define DUMMY_TENT 0xF127 #define DUMMY_BOAT 0xF128 diff --git a/include/m_needlework.h b/include/m_needlework.h index 7af819c9..29b0b8a3 100644 --- a/include/m_needlework.h +++ b/include/m_needlework.h @@ -50,7 +50,7 @@ typedef struct original_texture_s { typedef struct original_data_s { /* 0x000 */ u8 name[mNW_ORIGINAL_DESIGN_NAME_LEN]; /* 0x010 */ u8 palette; - + /* 0x011 */ u8 flag_design_set; /* 0x020 */ mNW_original_tex_c design; /* this is aligned to 32 bytes for ARAM transfer */ } mNW_original_design_c; diff --git a/src/ac_flag.c b/src/ac_flag.c new file mode 100644 index 00000000..ee334fe7 --- /dev/null +++ b/src/ac_flag.c @@ -0,0 +1,407 @@ +#include "ac_flag.h" + +#include "m_name_table.h" +#include "sys_matrix.h" +#include "m_lib.h" +#include "m_rcp.h" +#include "m_common_data.h" +#include "m_player_lib.h" +#include "m_msg.h" +#include "m_debug.h" + +enum { + aFLAG_ACTION_WAIT, + aFLAG_ACTION_TALK, + aFLAG_ACTION_TALK_END, + aFLAG_ACTION_OPEN_WAIT, + aFLAG_ACTION_END_WAIT, + aFLAG_ACTION_UP, + aFLAG_ACTION_DOWN, + + aFLAG_ACTION_NUM +}; + +static void aFLAG_actor_ct(ACTOR* actor, GAME* game); +static void aFLAG_actor_dt(ACTOR* actor, GAME* game); +static void aFLAG_actor_init(ACTOR* actor, GAME* game); +static void aFLAG_actor_draw(ACTOR* actor, GAME* game); + +ACTOR_PROFILE Flag_Profile = { + mAc_PROFILE_FLAG, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + FLAG, + ACTOR_OBJ_BANK_KEEP, + sizeof(STRUCTURE_ACTOR), + &aFLAG_actor_ct, + &aFLAG_actor_dt, + &aFLAG_actor_init, + &aFLAG_actor_draw, + NULL +}; + +static u8 aFLAG_shadow_vtx_fix_flg_table[8] = { FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE }; + +extern Vtx obj_frag_shadow_v[]; +extern Gfx obj_frag_shadowT_model[]; +static bIT_ShadowData_c aFLAG_shadow_data = { + 8, + aFLAG_shadow_vtx_fix_flg_table, + 60.0f, + obj_frag_shadow_v, + obj_frag_shadowT_model +}; + +extern cKF_Skeleton_R_c cKF_bs_r_obj_s_frag; +extern cKF_Skeleton_R_c cKF_bs_r_obj_w_frag; +extern cKF_Animation_R_c cKF_ba_r_obj_s_frag; +extern cKF_Animation_R_c cKF_ba_r_obj_w_frag; + +extern u8 hakushi_tex[]; +extern u16 hakushi_pal[]; + +static void aFLAG_setup_action(STRUCTURE_ACTOR* flag, int action); + +static void aFLAG_actor_ct(ACTOR* actor, GAME* game) { + static cKF_Skeleton_R_c* skl[] = { &cKF_bs_r_obj_s_frag, &cKF_bs_r_obj_w_frag }; + static cKF_Animation_R_c* ani[] = { &cKF_ba_r_obj_s_frag, &cKF_ba_r_obj_w_frag }; + + STRUCTURE_ACTOR* flag; + int isWinter; + + flag = (STRUCTURE_ACTOR*)actor; + isWinter = Common_Get(time.season) == mTM_SEASON_WINTER; + flag->action = 32; + flag->arg1_f = 132.5f; + + cKF_SkeletonInfo_R_ct(&flag->keyframe, skl[isWinter], ani[isWinter], flag->work_area, flag->morph_area); + cKF_SkeletonInfo_R_init_standard_repeat(&flag->keyframe, ani[isWinter], NULL); + cKF_SkeletonInfo_R_play(&flag->keyframe); + + aFLAG_setup_action(flag, aFLAG_ACTION_WAIT); +} + +static void aFLAG_actor_dt(ACTOR* actor, GAME* game) { + STRUCTURE_ACTOR* flag = (STRUCTURE_ACTOR*)actor; + cKF_SkeletonInfo_R_dt(&flag->keyframe); +} + +static void aFLAG_set_talk_info(ACTOR* actor) { + rgba_t window_color; + + mDemo_Set_msg_num(0x3066); + mDemo_Set_talk_display_name(FALSE); + mDemo_Set_ListenAble(); + + window_color.r = 185; + window_color.g = 60; + window_color.b = 40; + window_color.a = 255; + + mDemo_Set_talk_window_color(&window_color); + mDemo_Set_camera(TRUE); + mDemo_Set_use_zoom_sound(TRUE); +} + +static void aFLAG_talk_end(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + mMsg_Window_c* msg_p = mMsg_Get_base_window_p(); + + if (mMsg_Check_main_wait(msg_p) != FALSE) { + mMsg_request_main_forceoff(); + aFLAG_setup_action(flag, aFLAG_ACTION_WAIT); + } +} + +static void aFLAG_talk(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + mMsg_Window_c* msg_p; + PLAYER_ACTOR* player_actor; + s16 target_y; + s_xyz target_rot; + + msg_p = mMsg_Get_base_window_p(); + if (mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)flag) != FALSE) { + player_actor = get_player_actor_withoutCheck(game_play); + + target_rot = player_actor->actor_class.shape_info.rotation; + target_y = search_position_angleY(&player_actor->actor_class.world.position, &flag->actor_class.world.position); + add_calc_short_angle2(&target_rot.y, target_y, 0.3f, 0x1000, 0x100); + + (*get_player_actor_withoutCheck((GAME_PLAY*)gamePT)->Set_force_position_angle_proc)( + gamePT, NULL, &target_rot, mPlayer_FORCE_POSITION_ANGLE_ROTY); + + if (mMsg_Check_MainNormalContinue(msg_p) == TRUE) { + switch (mChoice_Get_ChoseNum(mChoice_Get_base_window_p())) { + case mChoice_CHOICE0: + mMsg_request_main_disappear_wait_type1(mMsg_Get_base_window_p()); + aFLAG_setup_action(flag, aFLAG_ACTION_DOWN); + break; + + case mChoice_CHOICE1: + mMsg_request_main_disappear_wait_type1(mMsg_Get_base_window_p()); + aFLAG_setup_action(flag, aFLAG_ACTION_TALK_END); + break; + } + } + } else { + aFLAG_setup_action(flag, aFLAG_ACTION_WAIT); + } +} + +static void aFLAG_wait(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + PLAYER_ACTOR* player_actor; + if (mDemo_Check(mDemo_TYPE_TALK, (ACTOR*)flag) == FALSE) { + player_actor = get_player_actor_withoutCheck(game_play); + if (player_actor != NULL) { + mDemo_Request(mDemo_TYPE_TALK, (ACTOR*)flag, aFLAG_set_talk_info); + } + } else { + aFLAG_setup_action(flag, aFLAG_ACTION_TALK); + } +} + +static void aFLAG_menu_open_wait(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + mSM_open_submenu(&game_play->submenu, mSM_OVL_NEEDLEWORK, 0, common_data.player_no); + aFLAG_setup_action(flag, aFLAG_ACTION_END_WAIT); +} + +static void aFLAG_menu_end_wait(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + Submenu* submenu; + Submenu_Item_c* sm_item; + u8 design_index; + + submenu = &game_play->submenu; + if (submenu->open_flag == FALSE) { + sm_item = submenu->item_p; + if (sm_item->item == RSV_NO) { + design_index = mNW_get_image_no(submenu, sm_item->slot_no) & 7; + + bcopy(Player_Design_Get(design_index), Save_GetPointer(island.flag_design.design), + sizeof(mNW_original_tex_c)); + osWritebackDCache(Save_GetPointer(island.flag_design.design), sizeof(mNW_original_tex_c)); + + Save_Get(island.flag_design).flag_design_set = TRUE; + Save_Get(island.flag_design).palette = Player_Palette_Get(design_index); + + sAdo_OngenTrgStart(0x461, &flag->actor_class.world.position); + + mISL_SetNowPlayerAction(4); + } + + sAdo_OngenTrgStart(0x163, &flag->actor_class.world.position); + aFLAG_setup_action(flag, aFLAG_ACTION_UP); + } +} + +static void aFLAG_up(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + f32 starting_x; + f32 middle_x; + f32 ending_x; + f32 ending_frame; + f32 third_point_frame; + f32 second_point_frame; + f32 first_point_frame; + f32 normalized_x_length; + + // Flag moves from bottom to top in two distinct "phases" as if the rope was pulled twice + starting_x = 72.5f; + middle_x = 110.0f; + ending_x = 132.5f; + ending_frame = 100.0f; + third_point_frame = 70.0f; + second_point_frame = 55.0f; + first_point_frame = 15.0f; + + if (REGADDR(NMREG, 0) != 0) { + starting_x = REGADDR(NMREG, 0); + } + + if (REGADDR(NMREG, 1) != 0) { + ending_x = REGADDR(NMREG, 1); + } + + if (REGADDR(NMREG, 2) != 0) { + middle_x = REGADDR(NMREG, 2); + } + + if (REGADDR(NMREG, 3) != 0) { + ending_frame = REGADDR(NMREG, 3); + } + + if (REGADDR(NMREG, 4) != 0) { + second_point_frame = REGADDR(NMREG, 4); + } + + if (REGADDR(NMREG, 5) != 0) { + first_point_frame = REGADDR(NMREG, 5); + } + + if (REGADDR(NMREG, 6) != 0) { + third_point_frame = REGADDR(NMREG, 6); + } + + if (flag->arg1 == second_point_frame) { + sAdo_OngenTrgStart(0x163U, &flag->actor_class.world.position); + } + + if (flag->arg1 <= first_point_frame) { + normalized_x_length = (middle_x - starting_x) / (first_point_frame * second_point_frame); + flag->arg1_f = starting_x + (normalized_x_length * flag->arg1 * flag->arg1); + } else if (flag->arg1 <= second_point_frame) { + normalized_x_length = (middle_x - starting_x) / (second_point_frame * (first_point_frame - second_point_frame)); + flag->arg1_f = middle_x + (normalized_x_length * (flag->arg1 - second_point_frame) * (flag->arg1 - second_point_frame)); + } else if (flag->arg1 <= third_point_frame) { + normalized_x_length = (ending_x - middle_x) / ((third_point_frame - second_point_frame) * (ending_frame - second_point_frame)); + flag->arg1_f = middle_x + (normalized_x_length * (flag->arg1 - second_point_frame) * (flag->arg1 - second_point_frame)); + } else { + normalized_x_length = (ending_x - middle_x) / ((ending_frame - second_point_frame) * ((third_point_frame - second_point_frame) - (ending_frame - second_point_frame))); + flag->arg1_f = ending_x + (normalized_x_length * (flag->arg1 - ending_frame) * (flag->arg1 - ending_frame)); + } + + flag->arg1 += 1; + if (flag->arg1 >= ending_frame) { + flag->arg1 = 0; + mMsg_request_main_forceoff(); + aFLAG_setup_action(flag, aFLAG_ACTION_WAIT); + } +} + +static void aFLAG_down(STRUCTURE_ACTOR* flag, GAME_PLAY* game_play) { + f32 normalized_x_length; + f32 x_length; + f32 starting_x; + f32 ending_x; + f32 ending_frame; + f32 midpoint_frame; + + if (mMsg_Check_main_wait(mMsg_Get_base_window_p()) != FALSE) { + // Flag moves down in a smooth motion from top to bottom + starting_x = 72.5; + ending_x = 132.5; + ending_frame = 40.0f; + midpoint_frame = 16.0f; + + if (REGADDR(NMREG, 0) != 0) { + starting_x = REGADDR(NMREG, 0); + } + + if (REGADDR(NMREG, 1) != 0) { + ending_x = REGADDR(NMREG, 1); + } + + if (REGADDR(NMREG, 7) != 0) { + ending_frame = REGADDR(NMREG, 7); + } + + if (REGADDR(NMREG, 8) != 0) { + midpoint_frame = REGADDR(NMREG, 8); + } + + x_length = ending_x - starting_x; + if (flag->arg1 == 2) { + sAdo_OngenTrgStart(0x164U, &flag->actor_class.world.position); + } + + // arg1_f is used to set the joint x position + if (flag->arg1 <= midpoint_frame) { + normalized_x_length = -(x_length / (midpoint_frame * ending_frame)); + flag->arg1_f = ending_x + (flag->arg1 * (normalized_x_length * flag->arg1)); + } else { + normalized_x_length = -(x_length / (ending_frame * (midpoint_frame - ending_frame))); + flag->arg1_f = starting_x + (normalized_x_length * (flag->arg1 - ending_frame) * (flag->arg1 - ending_frame)); + } + + flag->arg1 += 1; + if (flag->arg1 >= ending_frame) { + flag->arg1 = 0; + aFLAG_setup_action(flag, aFLAG_ACTION_OPEN_WAIT); + } + } +} + +static void aFLAG_setup_action(STRUCTURE_ACTOR* flag, int action) { + static aSTR_MOVE_PROC process[aFLAG_ACTION_NUM] = { + &aFLAG_wait, + &aFLAG_talk, + &aFLAG_talk_end, + &aFLAG_menu_open_wait, + &aFLAG_menu_end_wait, + &aFLAG_up, + &aFLAG_down + }; + + flag->action_proc = process[action]; +} + +static void aFLAG_actor_move(ACTOR* actor, GAME* game) { + STRUCTURE_ACTOR* flag; + f32 wind_power; + s16 wind_angle; + + flag = (STRUCTURE_ACTOR*)actor; + + wind_power = mEnv_GetWindPowerF(); + flag->arg0_f = wind_power; + flag->keyframe.frame_control.speed = flag->arg0_f * 0.5f + 0.5f; + + wind_angle = mEnv_GetWindAngleS(); + flag->arg2_f = wind_angle; + + cKF_SkeletonInfo_R_play(&flag->keyframe); + + (*flag->action_proc)(flag, (GAME_PLAY*)game); +} + +static void aFLAG_actor_init(ACTOR* actor, GAME* game) { + mFI_SetFG_common(DUMMY_FLAG, actor->home.position, FALSE); + aFLAG_actor_move(actor, game); + actor->mv_proc = &aFLAG_actor_move; +} + +static int aFLAG_before_draw(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) { + STRUCTURE_ACTOR* flag = (STRUCTURE_ACTOR*)arg; + if (joint_idx == 4) { + joint_pos->x = flag->arg1_f * 100.0f; + } + + return TRUE; +} + +static void aFLAG_actor_draw(ACTOR* actor, GAME* game) { + GRAPH* graph; + cKF_SkeletonInfo_R_c* keyframe; + Gfx* gfx; + Mtx* mtx; + STRUCTURE_ACTOR* flag; + u16* pal; + u8* texture; + + flag = (STRUCTURE_ACTOR*)actor; + graph = game->graph; + keyframe = &flag->keyframe; + mtx = GRAPH_ALLOC_TYPE(graph, Mtx, keyframe->skeleton->num_shown_joints); + if (mtx != NULL) { + _texture_z_light_fog_prim_npc(graph); + _texture_z_light_fog_prim_xlu(graph); + + if (Save_Get(island.flag_design).flag_design_set != FALSE) { + pal = mNW_PaletteIdx2Palette(Save_Get(island.flag_design).palette); + texture = (u8*)Save_GetPointer(island.flag_design.design); + } else { + pal = hakushi_pal; + texture = hakushi_tex; + } + + OPEN_DISP(graph); + gfx = NOW_POLY_OPA_DISP; + + gSPSegment(gfx++, G_MWO_SEGMENT_8, pal); + gSPSegment(gfx++, G_MWO_SEGMENT_9, texture); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); + + cKF_Si3_draw_R_SV(game, keyframe, mtx, &aFLAG_before_draw, NULL, actor); + (*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aFLAG_shadow_data, FALSE); + } +}