From b36ceb776a5ebe82759eea6ce7622a721a668b04 Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Sun, 1 Dec 2024 06:46:48 -0500 Subject: [PATCH] Implement & link ac_htable --- configure.py | 2 +- include/ac_htable.h | 3 + include/m_name_table.h | 1 + src/actor/ac_htable.c | 357 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 src/actor/ac_htable.c diff --git a/configure.py b/configure.py index 47ad3425..3ce3c7e8 100644 --- a/configure.py +++ b/configure.py @@ -982,7 +982,7 @@ config.libs = [ Object(Matching, "actor/ac_house.c"), Object(Matching, "actor/ac_house_clock.c"), Object(NonMatching, "actor/ac_house_goki.c"), - Object(NonMatching, "actor/ac_htable.c"), + Object(Matching, "actor/ac_htable.c"), Object(Matching, "actor/ac_ins_amenbo.c"), Object(Matching, "actor/ac_ins_batta.c"), Object(Matching, "actor/ac_ins_chou.c"), diff --git a/include/ac_htable.h b/include/ac_htable.h index 1e48db36..b2a4da7a 100644 --- a/include/ac_htable.h +++ b/include/ac_htable.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_actor.h" +#include "ac_structure.h" #ifdef __cplusplus extern "C" { @@ -16,6 +17,8 @@ typedef struct htable_clip_s { s16 pickup_counter; } aHTBL_Clip_c; +typedef STRUCTURE_ACTOR HTABLE_ACTOR; + extern ACTOR_PROFILE Htable_Profile; #ifdef __cplusplus diff --git a/include/m_name_table.h b/include/m_name_table.h index d7c2c23a..9936d9d0 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -3291,6 +3291,7 @@ extern int mNT_check_unknown(mActor_name_t item_no); #define DUMMY_FLAG 0xF122 #define DUMMY_COTTAGE_MY 0xF123 #define DUMMY_COTTAGE_NPC 0xF124 +#define DUMMY_HTABLE 0xF126 #define DUMMY_TENT 0xF127 #define DUMMY_BOAT 0xF128 #define RSV_POLICE_ITEM_0 0xF128 // why is this duplicated? diff --git a/src/actor/ac_htable.c b/src/actor/ac_htable.c new file mode 100644 index 00000000..a04919d1 --- /dev/null +++ b/src/actor/ac_htable.c @@ -0,0 +1,357 @@ +#include "ac_htable.h" + +#include "m_common_data.h" +#include "m_player_lib.h" +#include "m_rcp.h" +#include "sys_matrix.h" +#include "m_malloc.h" +#include "libultra/libultra.h" + +// clang-format off +static u8 aHTBL_shadow_vtx_fix_flg_tableA[] = { + TRUE, TRUE, FALSE, FALSE, + FALSE, TRUE, TRUE, TRUE, + FALSE, FALSE, FALSE, TRUE, + TRUE, TRUE, FALSE, FALSE, + FALSE, TRUE, TRUE, TRUE, + FALSE, FALSE, FALSE, TRUE, + TRUE, TRUE, TRUE, TRUE, +}; +// clang-format on + +// clang-format off +static u8 aHTBL_shadow_vtx_fix_flg_tableB[] = { + FALSE, TRUE, TRUE, FALSE, + FALSE, TRUE, FALSE, TRUE, + TRUE, FALSE, FALSE, TRUE, + FALSE, TRUE, TRUE, FALSE, + FALSE, TRUE, FALSE, TRUE, + TRUE, FALSE, FALSE, TRUE, + TRUE, TRUE, TRUE, TRUE, +}; +// clang-format on + +// clang-format off +static u8 aHTBL_shadow_vtx_fix_flg_tableC[] = { + FALSE, TRUE, TRUE, FALSE, + FALSE, TRUE, FALSE, TRUE, + TRUE, FALSE, FALSE, TRUE, + FALSE, TRUE, TRUE, FALSE, + FALSE, TRUE, FALSE, TRUE, + TRUE, FALSE, FALSE, TRUE, + TRUE, TRUE, TRUE, TRUE, +}; +// clang-format on + +extern Vtx obj_e_hfes_shadow_a_v[]; +extern Gfx obj_e_hfes_shadow_a_modelT[]; + +static bIT_ShadowData_c aHTBL_shadow_dataA = { + ARRAY_COUNT(aHTBL_shadow_vtx_fix_flg_tableA), + aHTBL_shadow_vtx_fix_flg_tableA, + 20.0f, + obj_e_hfes_shadow_a_v, + obj_e_hfes_shadow_a_modelT, +}; + +extern Vtx obj_e_hfes_shadow_b_v[]; +extern Gfx obj_e_hfes_shadow_b_modelT[]; + +static bIT_ShadowData_c aHTBL_shadow_dataB = { + ARRAY_COUNT(aHTBL_shadow_vtx_fix_flg_tableB), + aHTBL_shadow_vtx_fix_flg_tableB, + 20.0f, + obj_e_hfes_shadow_b_v, + obj_e_hfes_shadow_b_modelT, +}; + +extern Vtx obj_e_hfes_shadow_c_v[]; +extern Gfx obj_e_hfes_shadow_c_modelT[]; + +static bIT_ShadowData_c aHTBL_shadow_dataC = { + ARRAY_COUNT(aHTBL_shadow_vtx_fix_flg_tableC), + aHTBL_shadow_vtx_fix_flg_tableC, + 20.0f, + obj_e_hfes_shadow_c_v, + obj_e_hfes_shadow_c_modelT, +}; + +static bIT_ShadowData_c* aHTBL_shadow_data_table[] = { + &aHTBL_shadow_dataA, + &aHTBL_shadow_dataB, + &aHTBL_shadow_dataC, +}; + +static void aHTBL_actor_ct(ACTOR* actorx, GAME* game); +static void aHTBL_actor_dt(ACTOR* actorx, GAME* game); +static void aHTBL_actor_init(ACTOR* actorx, GAME* game); +static void aHTBL_actor_draw(ACTOR* actorx, GAME* game); + +// clang-format off +ACTOR_PROFILE Htable_Profile = { + mAc_PROFILE_HTABLE, + ACTOR_PART_ITEM, + ACTOR_STATE_TA_SET, + HTABLE0, + ACTOR_OBJ_BANK_KEEP, + sizeof(HTABLE_ACTOR), + &aHTBL_actor_ct, + &aHTBL_actor_dt, + &aHTBL_actor_init, + &aHTBL_actor_draw, + NULL, +}; +// clang-format on + +static void aHTBL_GetPlayerLookAtUnit(int* ux, int* uz, s16 angle_y, int chk_ofs) { + // clang-format off + static s16 unit_offset[][2] = { + { 0, 1 }, // 0 + { 1, 1 }, // 22.5 + { 1, 1 }, // 45 + { 1, 0 }, // 67.5 + { 1, 0 }, // 90 + { 1, -1 }, // 112.5 + { 1, -1 }, // 135 + { 0, -1 }, // 157.5 + { 0, -1 }, // 180 + { -1, -1 }, // 202.5 + { -1, -1 }, // 225 + { -1, 0 }, // 247.5 + { -1, 0 }, // 270 + { -1, 1 }, // 292.5 + { -1, 1 }, // 315 + { 0, 1 }, // 337.5 + }; + // clang-format on + + static int high_offset[] = { 0, 2, -2 }; + int angle_idx = ((angle_y >> 12) & 0xF); // converts the full angle into steps of 0x1000 or 22.5 degrees + + if (chk_ofs >= 0 && chk_ofs < ARRAY_COUNT(high_offset)) { + angle_idx = (angle_idx + high_offset[chk_ofs]) & 0xF; + + (*ux) += unit_offset[angle_idx][0]; + (*uz) += unit_offset[angle_idx][1]; + } +} + +static mActor_name_t aHTBL_SearchPickUpItemLayer2(GAME* game) { + ACTOR* player = GET_PLAYER_ACTOR_GAME_ACTOR(game); + int ux; + int uz; + xyz_t pos = player->world.position; + xyz_t center_pos; + s16 angle_y = player->shape_info.rotation.y; + int i; + + if (mFI_Wpos2UtNum(&ux, &uz, pos)) { + for (i = 0; i < 3; i++) { + aHTBL_GetPlayerLookAtUnit(&ux, &uz, angle_y, i); + if (mFI_UtNum2CenterWpos(¢er_pos, ux, uz)) { + f32 dx = center_pos.x - pos.x; + f32 dz = center_pos.z - pos.z; + + if (SQ(dx) + SQ(dz) <= SQ(56.0f)) { + mActor_name_t* fg_p = mFI_GetUnitFG(center_pos); + + if (fg_p != NULL && *fg_p == ITM_KNIFE_AND_FORK) { + return ITM_KNIFE_AND_FORK; + } + } + } + } + } + + return EMPTY_NO; +} + +static void aHTBL_SetFork(HTABLE_ACTOR* htable) { + int ux; + int uz; + + if (mPr_GetPossessionItemIdxWithCond(Now_Private, ITM_KNIFE_AND_FORK, mPr_ITEM_COND_NORMAL) == -1) { + if (mFI_Wpos2UtNum(&ux, &uz, htable->actor_class.world.position)) { + mFI_UtNumtoFGSet_common(ITM_KNIFE_AND_FORK, ux + 1, uz + 1, TRUE); + } + } +} + +static void aHTBL_SetClip(HTABLE_ACTOR* htable) { + if (CLIP(htbl_clip) == NULL) { + CLIP(htbl_clip) = (aHTBL_Clip_c*)zelda_malloc(sizeof(aHTBL_Clip_c)); + if (CLIP(htbl_clip) != NULL) { + xyz_t pos = htable->actor_class.world.position; + + bzero(CLIP(htbl_clip), sizeof(aHTBL_Clip_c)); + pos.x += mFI_UT_WORLDSIZE_X_F; + pos.z += mFI_UT_WORLDSIZE_Z_F; + pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos(pos, 0.0f); + CLIP(htbl_clip)->search_pick_up_item_layer2_proc = &aHTBL_SearchPickUpItemLayer2; + CLIP(htbl_clip)->pickup_pos = pos; + } + } +} + +static void aHTBL_set_bgOffset(HTABLE_ACTOR* htable); + +static void aHTBL_actor_ct(ACTOR* actorx, GAME* game) { + HTABLE_ACTOR* htable = (HTABLE_ACTOR*)actorx; + + htable->arg0 = actorx->npc_id - HTABLE0; + aHTBL_set_bgOffset(htable); + + if (htable->arg0 == 2) { + aHTBL_SetFork(htable); + aHTBL_SetClip(htable); + actorx->world.position.z += mFI_UT_WORLDSIZE_HALF_Z_F; + } +} + +static void aHTBL_actor_dt(ACTOR* actorx, GAME* game) { + HTABLE_ACTOR* htable = (HTABLE_ACTOR*)actorx; + + if (htable->arg0 == 2 && CLIP(htbl_clip) != NULL) { + zelda_free(CLIP(htbl_clip)); + CLIP(htbl_clip) = NULL; + } +} + +static void aHTBL_set_bgOffset(HTABLE_ACTOR* htable) { + // clang-format off + static const mCoBG_OffsetTable_c rewrite_dataA[] = { + { mCoBG_ATTRIBUTE_NONE, 2, 0, 2, 2, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 2, 0, 1 }, + { mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 0, 2, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 2, 2, 0 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 2, 0, 1 }, + { mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 0, 2, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 0, 2, 1 }, + }; + // clang-format on + + // clang-format off + static const mCoBG_OffsetTable_c rewrite_dataB[] = { + { mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 }, + { mCoBG_ATTRIBUTE_NONE, 2, 0, 2, 2, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 2, 0, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 0, 2, 2, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 2, 2, 0 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 0, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 0, 2, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 0, 2, 1 }, + { mCoBG_ATTRIBUTE_NONE, 0, 0, 0, 0, 0, 0 }, + }; + // clang-format on + + // clang-format off + static const mCoBG_OffsetTable_c rewrite_dataC[] = { + { mCoBG_ATTRIBUTE_NONE, 2, 2, 2, 2, 2, 0 }, + }; + // clang-format on + + int type = htable->arg0; + int j; + int i; + int idx = 0; + xyz_t pos; + + switch (type) { + case 0: + for (i = -1; i <= 1; i++) { + for (j = -1; j <= 1; j++) { + pos = htable->actor_class.world.position; + pos.x += (f32)j * mFI_UT_WORLDSIZE_X_F; + pos.z += (f32)i * mFI_UT_WORLDSIZE_Z_F; + mCoBG_SetPluss5PointOffset_file(pos, rewrite_dataA[idx], __FILE__, 422); + idx++; + } + } + break; + case 1: + for (i = -1; i <= 1; i++) { + for (j = -1; j <= 1; j++) { + pos = htable->actor_class.world.position; + pos.x += (f32)j * mFI_UT_WORLDSIZE_X_F; + pos.z += (f32)i * mFI_UT_WORLDSIZE_Z_F; + mCoBG_SetPluss5PointOffset_file(pos, rewrite_dataB[idx], __FILE__, 436); + idx++; + } + } + break; + case 2: + for (i = 0; i <= 1; i++) { + for (j = -1; j <= 1; j++) { + pos = htable->actor_class.world.position; + pos.x += (f32)j * mFI_UT_WORLDSIZE_X_F; + pos.z += (f32)i * mFI_UT_WORLDSIZE_Z_F; + mCoBG_SetPluss5PointOffset_file(pos, rewrite_dataC[0], __FILE__, 450); + } + } + break; + } +} + +static void aHTBL_actor_move(ACTOR* actorx, GAME* game) { + if (CLIP(htbl_clip) != NULL && CLIP(htbl_clip)->pickup_counter != 0) { + if (CLIP(htbl_clip)->pickup_counter == 1) { + int ux; + int uz; + + if (mFI_Wpos2UtNum(&ux, &uz, CLIP(htbl_clip)->pickup_pos)) { + mFI_UtNumtoFGSet_common(RSV_NO, ux, uz, TRUE); + } + } + + CLIP(htbl_clip)->pickup_counter--; + } +} + +static void aHTBL_actor_init(ACTOR* actorx, GAME* game) { + mFI_SetFG_common(DUMMY_HTABLE, actorx->home.position, FALSE); + aHTBL_actor_move(actorx, game); + actorx->mv_proc = &aHTBL_actor_move; +} + +extern Gfx obj_e_hfes_a_model[]; +extern Gfx obj_e_hfes_b_model[]; +extern Gfx obj_e_hfes_c_model[]; + +extern Gfx obj_e_hfes_a_modelT[]; +extern Gfx obj_e_hfes_b_modelT[]; +extern Gfx obj_e_hfes_c_modelT[]; + +static Gfx* aHTBL_displaylist_table_opa[] = { + obj_e_hfes_a_model, + obj_e_hfes_b_model, + obj_e_hfes_c_model, +}; + +static Gfx* aHTBL_displaylist_table_xlu[] = { + obj_e_hfes_a_modelT, + obj_e_hfes_b_modelT, + obj_e_hfes_c_modelT, +}; + +static void aHTBL_actor_draw(ACTOR* actorx, GAME* game) { + GRAPH* graph = game->graph; + HTABLE_ACTOR* htable = (HTABLE_ACTOR*)actorx; + int type = htable->arg0; + + _texture_z_light_fog_prim_npc(graph); + _texture_z_light_fog_prim_xlu(graph); + _texture_z_light_fog_prim_shadow(graph); + + OPEN_DISP(graph); + + gSPMatrix(NEXT_POLY_OPA_DISP, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPMatrix(NEXT_POLY_XLU_DISP, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(NEXT_POLY_OPA_DISP, aHTBL_displaylist_table_opa[type]); + gSPDisplayList(NEXT_POLY_XLU_DISP, aHTBL_displaylist_table_xlu[type]); + + CLOSE_DISP(graph); + + CLIP(bg_item_clip)->draw_shadow_proc(game, aHTBL_shadow_data_table[type], TRUE); +}