From c1960a3c330c666c668f365d2297bb74fd2989d8 Mon Sep 17 00:00:00 2001 From: Prakxo Date: Mon, 26 Feb 2024 20:10:36 +0100 Subject: [PATCH] link ac_br_shop --- config/rel_slices.yml | 4 + include/ac_br_shop.h | 8 +- include/m_name_table.h | 1 + src/ac_br_shop.c | 113 +++++++++++++++ src/ac_br_shop_draw.c_inc | 105 ++++++++++++++ src/ac_br_shop_move.c_inc | 292 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 521 insertions(+), 2 deletions(-) create mode 100644 src/ac_br_shop.c create mode 100644 src/ac_br_shop_draw.c_inc create mode 100644 src/ac_br_shop_move.c_inc diff --git a/config/rel_slices.yml b/config/rel_slices.yml index 3a6ac8cc..2a922403 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -685,6 +685,10 @@ ac_boat.c: .text: [0x805A6CF4, 0x805A856C] .rodata: [0x8064A5B0, 0x8064A630] .data: [0x806C4440, 0x806C4560] +ac_br_shop.c: + .text: [0x805A856C, 0x805A9474] + .rodata: [0x8064A630, 0x8064A660] + .data: [0x806C4560, 0x806C4688] ac_douzou.c: .text: [0x805AD6D8, 0x805AE704] .rodata: [0x8064A7C0, 0x8064A7E8] diff --git a/include/ac_br_shop.h b/include/ac_br_shop.h index 33cb3c5a..f462ec99 100644 --- a/include/ac_br_shop.h +++ b/include/ac_br_shop.h @@ -1,13 +1,17 @@ #ifndef AC_BR_SHOP_H #define AC_BR_SHOP_H -#include "types.h" -#include "m_actor.h" +#include "ac_structure.h" #ifdef __cplusplus extern "C" { #endif +typedef struct actor_broker_shop_s { + STRUCTURE_ACTOR structure_class; +} BRSHOP_ACTOR; + + extern ACTOR_PROFILE BrShop_Profile; #ifdef __cplusplus diff --git a/include/m_name_table.h b/include/m_name_table.h index 9b52e8b9..67a16220 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -2705,6 +2705,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define DUMMY_HANIWA3 (DUMMY_HANIWA2 + 1) #define DUMMY_RESERVE 0xF102 #define DUMMY_SHRINE 0xF103 +#define DUMMY_BROKER_SHOP 0xF104 #define DUMMY_RADIO 0xF109 #define DUMMY_YATAI 0xF10A #define DUMMY_TUKIMI 0xF10A diff --git a/src/ac_br_shop.c b/src/ac_br_shop.c new file mode 100644 index 00000000..f17ebebd --- /dev/null +++ b/src/ac_br_shop.c @@ -0,0 +1,113 @@ +#include "ac_br_shop.h" +#include "m_common_data.h" +#include "m_name_table.h" +#include "m_player_lib.h" +#include "sys_matrix.h" + +static void aBRS_actor_ct(ACTOR*, GAME*); +static void aBRS_actor_dt(ACTOR*, GAME*); +static void aBRS_actor_init(ACTOR*, GAME*); +static void aBRS_actor_draw(ACTOR*, GAME*); + +ACTOR_PROFILE BrShop_Profile = { + mAc_PROFILE_BRSHOP, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + 0x5826, // fix name later + ACTOR_OBJ_BANK_KEEP, + sizeof(BRSHOP_ACTOR), + aBRS_actor_ct, + aBRS_actor_dt, + aBRS_actor_init, + aBRS_actor_draw, + NULL, +}; + +u8 aBRS_shadow_vtx_fix_flg_table[] = {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE}; + +extern Vtx obj_yamishop_shadow_v[]; +extern Gfx obj_yamishop_shadowT_model[]; + +bIT_ShadowData_c aBRS_shadow_data = { + 8, aBRS_shadow_vtx_fix_flg_table, 60.0f, obj_yamishop_shadow_v, obj_yamishop_shadowT_model, +}; + +extern cKF_Skeleton_R_c cKF_bs_r_obj_s_yamishop; +extern cKF_Skeleton_R_c cKF_bs_r_obj_w_yamishop; +extern cKF_Animation_R_c cKF_ba_r_obj_s_yamishop; +extern cKF_Animation_R_c cKF_ba_r_obj_w_yamishop; + +extern Gfx obj_s_yamishop_window_model[]; +extern Gfx obj_w_yamishop_window_model[]; + +static void aBRS_set_bgOffset(STRUCTURE_ACTOR*, int); +static void aBRS_setup_action(STRUCTURE_ACTOR* actor, int type); +static void change_FGUnit(ACTOR*, int); + +static void aBRS_actor_ct(ACTOR* actor, GAME* game) { + static cKF_Skeleton_R_c* skl[] = { + &cKF_bs_r_obj_s_yamishop, + &cKF_bs_r_obj_w_yamishop, + }; + GAME_PLAY* play = (GAME_PLAY*)game; + BRSHOP_ACTOR* shop = (BRSHOP_ACTOR*)actor; + lbRTC_time_c time; + int action; + PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play); + int Px; + int Pz; + int x; + int z; + + shop->structure_class.season = Common_Get(time.season); + + cKF_SkeletonInfo_R_ct(&shop->structure_class.keyframe, skl[shop->structure_class.season == mTM_SEASON_WINTER], NULL, + shop->structure_class.work_area, shop->structure_class.morph_area); + + aBRS_set_bgOffset(&shop->structure_class, 1); + change_FGUnit(actor, 1); + + action = 0; + actor->talk_distance = 80.0f; + shop->structure_class.arg0 = 0; + + Px = player->actor_class.world.position.x; + x = actor->world.position.x; + z = (100.0f + actor->world.position.z); + + if (Px == x && (int)player->actor_class.world.position.z == z) { + action = 1; + shop->structure_class.arg0 = 1; + } else { + time = Save_Get(event_save_data.special.event.broker.end_time); + if (mEv_CheckEvent(mEv_SPNPC_BROKER) != 0 && lbRTC_IsOverRTC(&time) == 0) { + action = 1; + } else { + shop->structure_class.arg0 = 1; + } + } + + aBRS_setup_action(&shop->structure_class, action); + cKF_SkeletonInfo_R_play(&shop->structure_class.keyframe); + + shop->structure_class.arg0_f = aBRS_ctrl_light(actor) != 0 ? 1.0f : 0.0f; +} + +Door_data_c aBRS_br_shop_door_data = { + SCENE_BROKER_SHOP, 4, FALSE, 0, {160, 0, 280}, EMPTY_NO, 1, {0, 0, 0}, +}; + +static void aBRS_actor_dt(ACTOR* actor, GAME* game) { + BRSHOP_ACTOR* shop = (BRSHOP_ACTOR*)actor; + + change_FGUnit(actor, 0); + cKF_SkeletonInfo_R_dt(&shop->structure_class.keyframe); + + if (Save_Get(event_save_data.special.event.broker.used) >= 3) { + mEv_special_event_soldout(75); + } +} + +#include "../src/ac_br_shop_draw.c_inc" + +#include "../src/ac_br_shop_move.c_inc" \ No newline at end of file diff --git a/src/ac_br_shop_draw.c_inc b/src/ac_br_shop_draw.c_inc new file mode 100644 index 00000000..5e8e732e --- /dev/null +++ b/src/ac_br_shop_draw.c_inc @@ -0,0 +1,105 @@ + +static int aBRS_actor_draw_before(GAME* game, cKF_SkeletonInfo_R_c* keyf, int jointNum, Gfx** joint, u8* jointFlag, + void* arg, s_xyz* joint1, xyz_t* trans) { + STRUCTURE_ACTOR* actor = (STRUCTURE_ACTOR*)arg; + GRAPH* graph = game->graph; + f32 shop_color; + Gfx* gfx; + + if (jointNum == 1) { + OPEN_DISP(graph); + shop_color = actor->arg0_f; + gfx = NOW_POLY_OPA_DISP; + + gDPSetPrimColor(gfx++, 0, 0, (int)(0.5f + (255.0f * shop_color)), (int)(0.5f + (255.0f * shop_color)), + (int)(0.5f + (150.0f * shop_color)), 255); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); + } else if (jointNum == 5) { + *joint = NULL; + } + + return 1; +} + +static int aBRS_actor_draw_after(GAME* game, cKF_SkeletonInfo_R_c* keyf, int jointNum, Gfx** joint, u8* jointFlag, + void* arg, s_xyz* joint1, xyz_t* trans) { + static Gfx* mdl[] = { + obj_s_yamishop_window_model, + obj_w_yamishop_window_model, + }; + + STRUCTURE_ACTOR* actor = (STRUCTURE_ACTOR*)arg; + GRAPH* graph = game->graph; + Mtx* mtx; + int isWinter; + int l; + int r; + int g; + int b; + Gfx* gfx; + + if (jointNum == 5) { + mtx = _Matrix_to_Mtx_new(graph); + + if (mtx != NULL) { + if (actor->arg0_f > 0.0f) { + r = 255; + g = 255; + b = 150; + l = (0.5f + (120.0f * actor->arg0_f)); + } else { + l = 0; + r = 0; + g = 0; + b = 0; + } + + isWinter = actor->season == mTM_SEASON_WINTER; + _texture_z_light_fog_prim_shadow(graph); + + OPEN_DISP(graph); + gfx = NOW_SHADOW_DISP; + + gDPSetPrimColor(gfx++, 0, l, r, g, b, 0); + gSPMatrix(gfx++, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(gfx++, mdl[isWinter]); + + SET_SHADOW_DISP(gfx); + CLOSE_DISP(graph); + } + } + + return 1; +} + +static void aBRS_actor_draw(ACTOR* actor, GAME* game) { + STRUCTURE_ACTOR* structure = (STRUCTURE_ACTOR*)actor; + GRAPH* graph = game->graph; + cKF_SkeletonInfo_R_c* keyframe = &structure->keyframe; + Mtx* mtx; + Gfx* gfx; + + mtx = GRAPH_ALLOC_TYPE(graph, Mtx, (u32)keyframe->skeleton->num_shown_joints); + + if (mtx != NULL) { + u16* pal; + + pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_BR_SHOP); + + _texture_z_light_fog_prim(graph); + + OPEN_DISP(graph); + gfx = NOW_POLY_OPA_DISP; + + gSPSegment(gfx++, 8, pal); + + SET_POLY_OPA_DISP(gfx); + CLOSE_DISP(graph); + + cKF_Si3_draw_R_SV(game, keyframe, mtx, &aBRS_actor_draw_before, &aBRS_actor_draw_after, actor); + (*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aBRS_shadow_data, FALSE); + } +} diff --git a/src/ac_br_shop_move.c_inc b/src/ac_br_shop_move.c_inc new file mode 100644 index 00000000..3a21815c --- /dev/null +++ b/src/ac_br_shop_move.c_inc @@ -0,0 +1,292 @@ + +static void change_FGUnit(ACTOR* actor, int type) { + xyz_t pos; + mActor_name_t* name; + + xyz_t_move(&pos, &actor->world.position); + pos.z += 80.0f; + + if (type == 0) { + mFI_SetFG_common(0, pos, 1); + return; + } + + name = mFI_GetUnitFG(pos); + if (name != NULL) { + if (mSN_ClearSnowman(name) == 0) { + int dug = FALSE; + + if ((((*name >= BURIED_PITFALL_START) && (*name <= BURIED_PITFALL_END)) || (*name == SHINE_SPOT))) { + dug = TRUE; + } + + if (dug == TRUE) { + mPB_keep_item(bg_item_fg_sub_dig2take_conv(*name)); + mFI_SetFG_common(RSV_NO, pos, 1); + mFI_Wpos2DepositOFF(pos); + } else { + mFI_Wpos2DepositOFF(pos); + mPB_keep_item(*name); + mFI_SetFG_common(RSV_NO, pos, 1); + } + } else { + mFI_SetFG_common(RSV_NO, pos, 1); + } + } +} + +static void aBRS_set_bgOffset(STRUCTURE_ACTOR* windmill, int idx) { + static mCoBG_OffsetTable_c height_table_ct[9] = { + {0x64, 9, 9, 9, 9, 9, 0}, {0x64, 9, 9, 9, 9, 9, 0}, {0x64, 9, 9, 9, 9, 9, 0}, + {0x64, 9, 9, 9, 9, 9, 0}, {0x64, 9, 9, 9, 9, 9, 0}, {0x64, 9, 9, 9, 9, 9, 0}, + {0x64, 9, 9, 9, 9, 9, 0}, {0x64, 9, 9, 9, 9, 9, 0}, {0x64, 9, 9, 9, 9, 9, 0}, + }; + + static mCoBG_OffsetTable_c* height_table[2] = { + height_table_ct, + height_table_ct, + }; + + static f32 addX[3] = { + -40.0f, + 0.0f, + 40.0f, + }; + static f32 addZ[3] = { + 40.0f, + 0.0f, + -40.0f, + }; + + mCoBG_OffsetTable_c* offset; + int i; + xyz_t pos; + + offset = height_table[idx]; + for (i = 0; i < 3; i++) { + pos.z = windmill->actor_class.home.position.z + addZ[i]; + + pos.x = windmill->actor_class.home.position.x + addX[0]; + mCoBG_SetPluss5PointOffset_file(pos, offset[0], __FILE__, 238); + + pos.x = windmill->actor_class.home.position.x + addX[1]; + mCoBG_SetPluss5PointOffset_file(pos, offset[1], __FILE__, 242); + + pos.x = windmill->actor_class.home.position.x + addX[2]; + mCoBG_SetPluss5PointOffset_file(pos, offset[2], __FILE__, 246); + + offset += 3; + } +} + +static void aBRS_rewrite_out_data(ACTOR* actor, GAME_PLAY* play) { + Door_data_c* door_data = Common_GetPointer(structure_exit_door_data); + + if (play->fb_wipe_mode == 0) { + xyz_t pos; + + door_data->next_scene_id = Save_Get(scene_no); + door_data->exit_orientation = 0; + door_data->exit_type = 0; + door_data->extra_data = 3; + + pos.x = actor->world.position.x; + pos.z = actor->world.position.z + 100.0f; + pos.y = actor->world.position.y; + + 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 = BROKER_TENT; + + door_data->wipe_type = 1; + mBGMPsComp_make_ps_wipe(0x2168); + } +} + +static int aBRS_check_player(ACTOR* actor, GAME_PLAY* play) { + u16 y; + f32 xOffs; + f32 zOffs; + f32 t; + int res; + PLAYER_ACTOR* player; + + player = GET_PLAYER_ACTOR(play); + res = 0; + + if (player == NULL) { + return 0; + } else { + y = player->actor_class.shape_info.rotation.y; + xOffs = SQ(player->actor_class.world.position.x - actor->world.position.x); + zOffs = SQ(player->actor_class.world.position.z - (actor->world.position.z + 60.0f)); + t = (xOffs) + (zOffs); + + if ((y > 0x6000) && (y < 0xA000) && (t < 800.0f)) { + res = 1; + } + } + return res; +} + +static int aBRS_open_check(ACTOR* actor) { + int res = 1; + lbRTC_time_c time; + BRSHOP_ACTOR* shop = (BRSHOP_ACTOR*)actor; + + if (mEv_CheckEvent(mEv_SPNPC_BROKER) != 0) { + time = Save_Get(event_save_data.special.event.broker.end_time); + + if (shop->structure_class.arg0 == 1 && lbRTC_IsOverRTC(&time) != 0) { + res = 1; + } else { + res = 2; + } + } + return res; +} + +static void aBRS_set_talk_info_close_wait(ACTOR* actor) { + rgba_t color; + + mDemo_Set_msg_num(0x7D5); + mDemo_Set_talk_display_name(0); + mDemo_Set_camera(1); + mPlib_Set_able_hand_all_item_in_demo(1); + mDemo_Set_ListenAble(); + + color.r = 145; + color.g = 60; + color.b = 40; + color.a = 255; + mDemo_Set_talk_window_color(&color); +} + +static void aBRS_close_wait(STRUCTURE_ACTOR* actor, GAME_PLAY* play) { + if (mDemo_Check(mDemo_TYPE_TALK, &actor->actor_class) != 1) { + if (aBRS_open_check(&actor->actor_class) == 2) { + aBRS_setup_action(actor, 3); + } else if (mDemo_Check(mDemo_TYPE_TALK, &actor->actor_class) == 0) { + if (ABS(actor->actor_class.player_angle_y) < 0x2000) { + mDemo_Request(mDemo_TYPE_TALK, &actor->actor_class, aBRS_set_talk_info_close_wait); + } + } + } +} + +static void aBRS_open_wait(STRUCTURE_ACTOR* actor, GAME_PLAY* play) { + xyz_t pos; + + if (actor == GET_PLAYER_ACTOR_NOW()->get_door_label_proc(gamePT)) { + aBRS_rewrite_out_data(&actor->actor_class, play); + goto_other_scene(play, &aBRS_br_shop_door_data, 1); + } else if (mPlib_check_player_actor_main_index_OutDoorMove(play) == 0) { + if (aBRS_check_player(&actor->actor_class, play) == 0) { + if (aBRS_open_check(&actor->actor_class) != 2) { + aBRS_setup_action(actor, 2); + } + + } else { + pos.x = actor->actor_class.world.position.x; + pos.y = GET_PLAYER_ACTOR(play)->actor_class.world.position.y; + pos.z = 64.0f + actor->actor_class.world.position.z; + mPlib_request_main_door_type1(&play->game, &pos, -0x8000, 1, &actor->actor_class); + } + } +} + +static void aBRS_close_door(STRUCTURE_ACTOR* actor, GAME_PLAY* play) { + if (actor->keyframe_state == 1) { + aBRS_setup_action(actor, 0); + } +} + +static void aBRS_open_door(STRUCTURE_ACTOR* actor, GAME_PLAY* play) { + if (actor->keyframe_state == 1) { + aBRS_setup_action(actor, 1); + } +} + +static void aBRS_setup_action(STRUCTURE_ACTOR* actor, int type) { + static aSTR_MOVE_PROC process[] = { + aBRS_close_wait, + aBRS_open_wait, + aBRS_close_door, + aBRS_open_door, + }; + static cKF_Animation_R_c* animation[] = { + &cKF_ba_r_obj_s_yamishop, + &cKF_ba_r_obj_w_yamishop, + }; + static f32 start_idx[] = { + 1.0f, + 17.0f, + 17.0f, + 1.0f, + }; + static f32 end_idx[] = { + 1.0f, + 17.0f, + 1.0f, + 17.0f, + }; + static f32 framespeed[] = { + 0.0f, + 0.0f, + 0.5f, + 0.5f, + }; + + BRSHOP_ACTOR* shop = (BRSHOP_ACTOR*)actor; + + int isWinter = shop->structure_class.season == mTM_SEASON_WINTER; + + cKF_SkeletonInfo_R_init(&shop->structure_class.keyframe, shop->structure_class.keyframe.skeleton, + animation[isWinter], start_idx[type], end_idx[type], start_idx[type], framespeed[type], + 0.0f, 0, NULL); + shop->structure_class.action_proc = process[type]; + shop->structure_class.action = type; +} + +static int aBRS_ctrl_light(STRUCTURE_ACTOR* shop) { + int now_sec = Common_Get(time.now_sec); + return !(now_sec < (64800) && now_sec >= (18000)) && (shop->action != 0); +} + +static void aBRS_actor_move(ACTOR* actor, GAME* game) { + GAME_PLAY* play = (GAME_PLAY*)game; + STRUCTURE_ACTOR* shop = (STRUCTURE_ACTOR*)actor; + PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play); + int bx1; + int bz1; + int bx2; + int bz2; + + mFI_Wpos2BlockNum(&bx1, &bz1, actor->world.position); + mFI_Wpos2BlockNum(&bx2, &bz2, player->actor_class.world.position); + + if ((mDemo_Check(mDemo_TYPE_SCROLL, &player->actor_class) == FALSE) && + (mDemo_Check(mDemo_TYPE_SCROLL2, &player->actor_class) == FALSE) && + (mDemo_Check(mDemo_TYPE_SCROLL3, &player->actor_class) == FALSE) && ((bx1 != bx2) || (bz1 != bz2))) { + Actor_delete(actor); + } else { + f32 window; + shop->keyframe_state = cKF_SkeletonInfo_R_play(&shop->keyframe); + if ((shop->arg0 == 0) && (Actor_info_fgName_search(&play->actor_info, 0x2D, ACTOR_PART_NPC) != NULL)) { + shop->arg0 = 1; + } + + shop->action_proc(shop, play); + + window = (aBRS_ctrl_light(shop) != 0) ? 1.0f : 0.0f; + chase_f(&shop->arg0_f, window, 0.019532442f); + } +} + +static void aBRS_actor_init(ACTOR* actor, GAME* game) { + mFI_SetFG_common(DUMMY_BROKER_SHOP, actor->home.position, 0); + aBRS_actor_move(actor, game); + actor->mv_proc = aBRS_actor_move; +}