From 1cbe0b55d00f2442dc7e8b82f85fb305a65fbe99 Mon Sep 17 00:00:00 2001 From: Hexalotl <15166449+Hexalotl@users.noreply.github.com> Date: Mon, 25 Mar 2024 03:23:46 -0700 Subject: [PATCH] Implement & link ac_police_box (#313) --- config/rel_slices.yml | 4 + include/ac_police_box.h | 2 +- include/m_name_table.h | 1 + src/ac_police_box.c | 91 +++++++++++++++++++++++ src/ac_police_box_draw.c_inc | 87 ++++++++++++++++++++++ src/ac_police_box_move.c_inc | 139 +++++++++++++++++++++++++++++++++++ 6 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 src/ac_police_box.c create mode 100644 src/ac_police_box_draw.c_inc create mode 100644 src/ac_police_box_move.c_inc diff --git a/config/rel_slices.yml b/config/rel_slices.yml index aef920db..dc05fc08 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -798,6 +798,10 @@ ac_needlework_shop.c: .text: [0x805B65C4, 0x805B7338] .rodata: [0x8064AAA0, 0x8064AAE8] .data: [0x806C6138, 0x806C62D0] +ac_police_box.c: + .text: [0x805B7338, 0x805B7B0C] + .rodata: [0x8064AAE8, 0x8064AB18] + .data: [0x806C62D0, 0x806C63C0] ac_post_office.c: .text: [0x805B7B0C, 0x805B887C] .rodata: [0x8064AB18, 0x8064AB58] diff --git a/include/ac_police_box.h b/include/ac_police_box.h index c9198254..2410ba14 100644 --- a/include/ac_police_box.h +++ b/include/ac_police_box.h @@ -2,7 +2,7 @@ #define AC_POLICE_BOX_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 9935fa74..37023042 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -2714,6 +2714,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define DUMMY_HANIWA3 (DUMMY_HANIWA2 + 1) #define DUMMY_POST_OFFICE 0xF0FF #define DUMMY_NEEDLEWORK_SHOP 0xF0FF +#define DUMMY_POLICE_STATION 0xF101 #define DUMMY_RESERVE 0xF102 #define DUMMY_SHRINE 0xF103 #define DUMMY_BROKER_SHOP 0xF104 diff --git a/src/ac_police_box.c b/src/ac_police_box.c new file mode 100644 index 00000000..ba33ef4e --- /dev/null +++ b/src/ac_police_box.c @@ -0,0 +1,91 @@ +#include "ac_police_box.h" + +#include "m_name_table.h" +#include "bg_item_h.h" +#include "m_common_data.h" +#include "m_house.h" +#include "m_player_lib.h" +#include "m_demo.h" +#include "ac_intro_demo.h" +#include "m_bgm.h" +#include "sys_matrix.h" +#include "m_rcp.h" +#include "libforest/gbi_extensions.h" + +static void aPBOX_actor_ct(ACTOR* actor, GAME* game); +static void aPBOX_actor_init(ACTOR* actor, GAME* game); +static void aPBOX_actor_draw(ACTOR* actor, GAME* game); + +// clang-format off +ACTOR_PROFILE Police_Box_Profile = { + mAc_PROFILE_POLICE_BOX, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + POLICE_STATION, + ACTOR_OBJ_BANK_KEEP, + sizeof(STRUCTURE_ACTOR), + &aPBOX_actor_ct, + mActor_NONE_PROC1, + &aPBOX_actor_init, + &aPBOX_actor_draw, + NULL +}; +// clang-format on + +// clang-format off +static u8 aPBOX_shadow_vtx_fix_flg_table0[] = { + TRUE, FALSE, TRUE, FALSE, + TRUE, FALSE, TRUE, FALSE, + TRUE, FALSE, FALSE, TRUE, + TRUE, FALSE, FALSE, TRUE, + TRUE, FALSE, FALSE, TRUE +}; +// clang-format on + +extern Vtx obj_s_kouban_shadow_v[]; +extern Gfx obj_s_kouban_shadow_model[]; + +// clang-format off +static bIT_ShadowData_c aPBOX_shadow_data = { + 20, + aPBOX_shadow_vtx_fix_flg_table0, + 60.0f, + obj_s_kouban_shadow_v, + obj_s_kouban_shadow_model +}; +// clang-format on + +// clang-format off +static Door_data_c aPBOX_police_box_enter_data = { + SCENE_POLICE_BOX, + mSc_DIRECT_NORTH, + FALSE, + 0, + { 200, 0, 380 }, + EMPTY_NO, + 1, + { 0, 0, 0 }, +}; +// clang-format on + +static void aPBOX_set_bgOffset(STRUCTURE_ACTOR* shop, int idx); +static int aPBOX_ctrl_light(STRUCTURE_ACTOR* shop); + +static void aPBOX_actor_ct(ACTOR* actor, GAME* game) { + STRUCTURE_ACTOR* box; + + box = (STRUCTURE_ACTOR*)actor; + + box->season = Common_Get(time.season); + aPBOX_set_bgOffset(box, 0); + + if (aPBOX_ctrl_light(box) != FALSE) { + box->action = DEG2SHORT_ANGLE(90.0f) - 1; // 0x3FFF + } else { + box->action = DEG2SHORT_ANGLE(0.0f); + } +} + +#include "../src/ac_police_box_move.c_inc" + +#include "../src/ac_police_box_draw.c_inc" diff --git a/src/ac_police_box_draw.c_inc b/src/ac_police_box_draw.c_inc new file mode 100644 index 00000000..3516e8be --- /dev/null +++ b/src/ac_police_box_draw.c_inc @@ -0,0 +1,87 @@ +extern Gfx obj_s_kouban_model[]; +extern Gfx obj_w_kouban_model[]; +extern Gfx obj_s_kouban_window_model[]; +extern Gfx obj_w_kouban_window_model[]; + +static void aPBOX_actor_draw(ACTOR* actor, GAME* game) { + static Gfx* displayList[] = { obj_s_kouban_model, obj_w_kouban_model }; + static Gfx* mdl[] = { obj_s_kouban_window_model, obj_w_kouban_window_model }; + + STRUCTURE_ACTOR* box; + GRAPH* graph; + f32 angle; + int winter; + int r1; + int g1; + int b1; + int l2; + int r2; + int g2; + int b2; + u16* pal; + Gfx* poly_opa; + Gfx* poly_xlu; + + box = (STRUCTURE_ACTOR*)actor; + graph = game->graph; + pal = Common_Get(clip).structure_clip->get_pal_segment_proc(aSTR_PAL_POLICE_BOX); + winter = box->season == mTM_SEASON_WINTER; + + if (box->action == DEG2SHORT_ANGLE(90.0f) - 1) { // 0x3FFF + r1 = 255; + g1 = 255; + b1 = 150; + + l2 = 120; + r2 = 255; + g2 = 255; + b2 = 150; + } else if (box->action == DEG2SHORT_ANGLE(0.0f)) { + r1 = 0; + g1 = 0; + b1 = 0; + + l2 = 0; + r2 = 0; + g2 = 0; + b2 = 0; + } else { + r2 = 255; + g2 = 255; + b2 = 150; + + angle = (1.0f / (DEG2SHORT_ANGLE(90.0f) - 1)) * box->action; + r1 = angle * 255.0f; + g1 = angle * 255.0f; + b1 = angle * 150.0f; + l2 = angle * 120.0f; + } + + OPEN_DISP(graph); + { + _texture_z_light_fog_prim_npc(graph); + + poly_opa = NOW_POLY_OPA_DISP; + + gSPMatrix(poly_opa++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(poly_opa++, G_MWO_SEGMENT_8, pal); + gDPPipeSync(poly_opa++); + gDPSetEnvColor(poly_opa++, r1, g1, b1, 0); + gSPDisplayList(poly_opa++, displayList[winter]); + SET_POLY_OPA_DISP(poly_opa); + } + { + _texture_z_light_fog_prim_xlu(graph); + + poly_xlu = NOW_POLY_XLU_DISP; + + gDPSetPrimColor(poly_xlu++, 0, l2, r2, g2, b2, 0); + gSPMatrix(poly_xlu++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(poly_xlu++, mdl[winter]); + SET_POLY_XLU_DISP(poly_xlu); + } + CLOSE_DISP(graph); + + _texture_z_light_fog_prim_shadow(graph); + (*Common_Get(clip).bg_item_clip->draw_shadow_proc)(game, &aPBOX_shadow_data, FALSE); +} diff --git a/src/ac_police_box_move.c_inc b/src/ac_police_box_move.c_inc new file mode 100644 index 00000000..02d056ac --- /dev/null +++ b/src/ac_police_box_move.c_inc @@ -0,0 +1,139 @@ +static void aPBOX_set_bgOffset(STRUCTURE_ACTOR* box, int idx) { + // clang-format off + static mCoBG_OffsetTable_c height_table_ct[] = { + { mCoBG_ATTRIBUTE_NONE, 10, 10, 0, 10, 10, 1 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 10, 10, 0 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 0, 10, 1 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 10, 10, 0 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 10, 10, 0 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 10, 10, 0 }, + { mCoBG_ATTRIBUTE_NONE, 10, 0, 10, 10, 10, 1 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 10, 10, 0 }, + { mCoBG_ATTRIBUTE_NONE, 10, 10, 10, 10, 0, 1 } + }; + // clang-format on + + static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct }; + + static f32 addX[] = { -40.0f, 0.0f, 40.0f }; + static f32 addZ[] = { 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 = box->actor_class.home.position.z + addZ[i]; + pos.x = box->actor_class.home.position.x + addX[0]; + mCoBG_SetPluss5PointOffset_file(pos, offset[0], __FILE__, 142); + + pos.x = box->actor_class.home.position.x + addX[1]; + mCoBG_SetPluss5PointOffset_file(pos, offset[1], __FILE__, 146); + + pos.x = box->actor_class.home.position.x + addX[2]; + mCoBG_SetPluss5PointOffset_file(pos, offset[2], __FILE__, 150); + + offset += 3; + } +} + +static void aPBOX_rewrite_out_data(STRUCTURE_ACTOR* shop, GAME_PLAY* play) { + Door_data_c* door_data; + xyz_t pos; + + 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 = mSc_DIRECT_SOUTH_EAST; + door_data->exit_type = 0; + door_data->extra_data = 3; + + pos.x = shop->actor_class.home.position.x + 60.0f; + pos.z = shop->actor_class.home.position.z + 60.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 = POLICE_STATION; + + door_data->wipe_type = 1; + + mBGMPsComp_make_ps_wipe(0x2168); + } +} + +static int aPBOX_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 = 1; + + if (player == NULL) { + return 0; + } + + y = player->actor_class.shape_info.rotation.y; + xOffs = actor->world.position.x + 24.0f; + zOffs = actor->world.position.z + 40.0f; + xOffs = SQ(player->actor_class.world.position.x - xOffs); + zOffs = SQ(player->actor_class.world.position.z - zOffs); + + t = (xOffs) + (zOffs); + + if ((y > 0x8000) && (y < 0xC000) && (t < 1100.0f)) { + res = 2; + } + + return res; +} + +static int aPBOX_ctrl_light(STRUCTURE_ACTOR* shop) { + int now_sec = Common_Get(time.now_sec); + return !(now_sec < (64800) && now_sec >= (18000)); +} + +static void aPBOX_actor_move(ACTOR* actor, GAME* game) { + STRUCTURE_ACTOR* box; + GAME_PLAY* play; + s16 target; + xyz_t pos; + + box = (STRUCTURE_ACTOR*)actor; + play = (GAME_PLAY*)game; + + target = (s16)box->action; + if (aPBOX_ctrl_light(box)) { + chase_s(&target, DEG2SHORT_ANGLE(90.0f) - 1, 320); // 0x3FFF + } else { + chase_s(&target, DEG2SHORT_ANGLE(0.0f), 320); + } + + box->action = target; + + if (box == (*GET_PLAYER_ACTOR_NOW()->get_door_label_proc)(gamePT)) { + aPBOX_rewrite_out_data(box, play); + goto_other_scene(play, &aPBOX_police_box_enter_data, FALSE); + } else { + if (aPBOX_check_player(actor, play) == 2) { + pos.x = actor->world.position.x + 50.0f; + pos.y = GET_PLAYER_ACTOR(play)->actor_class.world.position.y; + pos.z = actor->world.position.z + 50.0f; + mPlib_request_main_door_type1(game, &pos, -DEG2SHORT_ANGLE(135.0f), TRUE, actor); //-0x6000 + } + } +} + +static void aPBOX_actor_init(ACTOR* actor, GAME* game) { + mFI_SetFG_common(DUMMY_POLICE_STATION, actor->home.position, FALSE); + aPBOX_actor_move(actor, game); + actor->mv_proc = &aPBOX_actor_move; +}