diff --git a/src/libtrx/game/lara/common.c b/src/libtrx/game/lara/common.c index 2f2274ede..6c9173fc7 100644 --- a/src/libtrx/game/lara/common.c +++ b/src/libtrx/game/lara/common.c @@ -2,6 +2,7 @@ #include "game/const.h" #include "game/item_actions.h" +#include "game/matrix.h" #include "game/rooms/const.h" void Lara_Animate(ITEM *const item) @@ -156,3 +157,52 @@ bool Lara_TestBoundsCollide(const ITEM *const item, const int32_t radius) { return Item_TestBoundsCollide(item, Lara_GetItem(), radius); } + +bool Lara_TestPosition( + const ITEM *const item, const OBJECT_BOUNDS *const bounds) +{ + const ITEM *const lara = Lara_GetItem(); + const XYZ_16 rot = { + .x = lara->rot.x - item->rot.x, + .y = lara->rot.y - item->rot.y, + .z = lara->rot.z - item->rot.z, + }; + const XYZ_32 dist = { + .x = lara->pos.x - item->pos.x, + .y = lara->pos.y - item->pos.y, + .z = lara->pos.z - item->pos.z, + }; + + // clang-format off + if (rot.x < bounds->rot.min.x || + rot.x > bounds->rot.max.x || + rot.y < bounds->rot.min.y || + rot.y > bounds->rot.max.y || + rot.z < bounds->rot.min.z || + rot.z > bounds->rot.max.z + ) { + return false; + } + // clang-format on + + Matrix_PushUnit(); + Matrix_Rot16(item->rot); + const MATRIX *const m = g_MatrixPtr; + const XYZ_32 shift = { + .x = (dist.x * m->_00 + dist.y * m->_10 + dist.z * m->_20) >> W2V_SHIFT, + .y = (dist.x * m->_01 + dist.y * m->_11 + dist.z * m->_21) >> W2V_SHIFT, + .z = (dist.x * m->_02 + dist.y * m->_12 + dist.z * m->_22) >> W2V_SHIFT, + }; + Matrix_Pop(); + + // clang-format off + return ( + shift.x >= bounds->shift.min.x && + shift.x <= bounds->shift.max.x && + shift.y >= bounds->shift.min.y && + shift.y <= bounds->shift.max.y && + shift.z >= bounds->shift.min.z && + shift.z <= bounds->shift.max.z + ); + // clang-format on +} diff --git a/src/libtrx/include/libtrx/game/lara/common.h b/src/libtrx/include/libtrx/game/lara/common.h index 068634600..ae80131aa 100644 --- a/src/libtrx/include/libtrx/game/lara/common.h +++ b/src/libtrx/include/libtrx/game/lara/common.h @@ -15,3 +15,4 @@ void Lara_TakeDamage(int16_t damage, bool hit_status); bool Lara_TestBoundsCollide(const ITEM *item, int32_t radius); void Lara_Push(const ITEM *item, COLL_INFO *coll, bool hit_on, bool big_push); +bool Lara_TestPosition(const ITEM *item, const OBJECT_BOUNDS *bounds); diff --git a/src/libtrx/include/libtrx/game/objects/types.h b/src/libtrx/include/libtrx/game/objects/types.h index 88b289dcd..c22f3c549 100644 --- a/src/libtrx/include/libtrx/game/objects/types.h +++ b/src/libtrx/include/libtrx/game/objects/types.h @@ -38,14 +38,12 @@ typedef struct { bool disable_lighting; } OBJECT_MESH; -#if TR_VERSION == 1 typedef struct { struct { XYZ_16 min; XYZ_16 max; } shift, rot; } OBJECT_BOUNDS; -#endif typedef struct OBJECT { int16_t mesh_count; @@ -66,8 +64,8 @@ typedef struct OBJECT { void (*activate_func)(ITEM *item); void (*handle_flip_func)(ITEM *item, ROOM_FLIP_STATUS flip_status); void (*handle_save_func)(ITEM *item, SAVEGAME_STAGE stage); -#if TR_VERSION == 1 const OBJECT_BOUNDS *(*bounds_func)(void); +#if TR_VERSION == 1 bool (*is_usable_func)(int16_t item_num); #endif diff --git a/src/tr1/game/items.c b/src/tr1/game/items.c index bcc068aa1..69afbf81a 100644 --- a/src/tr1/game/items.c +++ b/src/tr1/game/items.c @@ -196,49 +196,6 @@ bool Item_Test3DRange(int32_t x, int32_t y, int32_t z, int32_t range) && (SQUARE(x) + SQUARE(y) + SQUARE(z) < SQUARE(range)); } -bool Item_TestPosition( - const ITEM *const src_item, const ITEM *const dst_item, - const OBJECT_BOUNDS *const bounds) -{ - const XYZ_16 rot = { - .x = src_item->rot.x - dst_item->rot.x, - .y = src_item->rot.y - dst_item->rot.y, - .z = src_item->rot.z - dst_item->rot.z, - }; - if (rot.x < bounds->rot.min.x || rot.x > bounds->rot.max.x - || rot.y < bounds->rot.min.y || rot.y > bounds->rot.max.y - || rot.z < bounds->rot.min.z || rot.z > bounds->rot.max.z) { - return false; - } - - const XYZ_32 dist = { - .x = src_item->pos.x - dst_item->pos.x, - .y = src_item->pos.y - dst_item->pos.y, - .z = src_item->pos.z - dst_item->pos.z, - }; - - Matrix_PushUnit(); - Matrix_Rot16(dst_item->rot); - MATRIX *mptr = g_MatrixPtr; - const XYZ_32 shift = { - .x = (mptr->_00 * dist.x + mptr->_10 * dist.y + mptr->_20 * dist.z) - >> W2V_SHIFT, - .y = (mptr->_01 * dist.x + mptr->_11 * dist.y + mptr->_21 * dist.z) - >> W2V_SHIFT, - .z = (mptr->_02 * dist.x + mptr->_12 * dist.y + mptr->_22 * dist.z) - >> W2V_SHIFT, - }; - Matrix_Pop(); - - if (shift.x < bounds->shift.min.x || shift.x > bounds->shift.max.x - || shift.y < bounds->shift.min.y || shift.y > bounds->shift.max.y - || shift.z < bounds->shift.min.z || shift.z > bounds->shift.max.z) { - return false; - } - - return true; -} - void Item_AlignPosition(ITEM *src_item, ITEM *dst_item, XYZ_32 *vec) { src_item->rot.x = dst_item->rot.x; diff --git a/src/tr1/game/items.h b/src/tr1/game/items.h index a9bc07b68..1f961833c 100644 --- a/src/tr1/game/items.h +++ b/src/tr1/game/items.h @@ -11,8 +11,6 @@ int16_t Item_Spawn(const ITEM *item, GAME_OBJECT_ID obj_id); bool Item_IsNearItem(const ITEM *item, const XYZ_32 *pos, int32_t distance); bool Item_Test3DRange(int32_t x, int32_t y, int32_t z, int32_t range); -bool Item_TestPosition( - const ITEM *src_item, const ITEM *dst_item, const OBJECT_BOUNDS *bounds); void Item_AlignPosition(ITEM *src_item, ITEM *dst_item, XYZ_32 *vec); bool Item_MovePosition( ITEM *src_item, const ITEM *dst_item, const XYZ_32 *vec, int32_t velocity); diff --git a/src/tr1/game/lara/common.c b/src/tr1/game/lara/common.c index 4e1c95406..ce9755f7a 100644 --- a/src/tr1/game/lara/common.c +++ b/src/tr1/game/lara/common.c @@ -701,11 +701,6 @@ bool Lara_IsNearItem(const XYZ_32 *pos, int32_t distance) return Item_IsNearItem(g_LaraItem, pos, distance); } -bool Lara_TestPosition(const ITEM *item, const OBJECT_BOUNDS *const bounds) -{ - return Item_TestPosition(g_LaraItem, item, bounds); -} - void Lara_AlignPosition(ITEM *item, XYZ_32 *vec) { Item_AlignPosition(g_LaraItem, item, vec); diff --git a/src/tr1/game/lara/common.h b/src/tr1/game/lara/common.h index 291ab20e9..e047b7291 100644 --- a/src/tr1/game/lara/common.h +++ b/src/tr1/game/lara/common.h @@ -26,7 +26,6 @@ void Lara_SwapMeshExtra(void); bool Lara_IsNearItem(const XYZ_32 *pos, int32_t distance); void Lara_UseItem(GAME_OBJECT_ID obj_id); -bool Lara_TestPosition(const ITEM *item, const OBJECT_BOUNDS *bounds); void Lara_AlignPosition(ITEM *item, XYZ_32 *vec); bool Lara_MovePosition(ITEM *item, XYZ_32 *vec); diff --git a/src/tr2/game/items.c b/src/tr2/game/items.c index a66bb7eb3..92df663c4 100644 --- a/src/tr2/game/items.c +++ b/src/tr2/game/items.c @@ -20,40 +20,6 @@ static BOUNDS_16 m_NullBounds = {}; static BOUNDS_16 m_InterpolatedBounds = {}; -static OBJECT_BOUNDS M_ConvertBounds(const int16_t *bounds_in); - -static OBJECT_BOUNDS M_ConvertBounds(const int16_t *const bounds_in) -{ - // TODO: remove this conversion utility once we gain control over its - // incoming arguments - return (OBJECT_BOUNDS) { - .shift = { - .min = { - .x = bounds_in[0], - .y = bounds_in[2], - .z = bounds_in[4], - }, - .max = { - .x = bounds_in[1], - .y = bounds_in[3], - .z = bounds_in[5], - }, - }, - .rot = { - .min = { - .x = bounds_in[6], - .y = bounds_in[8], - .z = bounds_in[10], - }, - .max = { - .x = bounds_in[7], - .y = bounds_in[9], - .z = bounds_in[11], - }, - }, - }; -} - void Item_Control(void) { int16_t item_num = Item_GetNextActive(); @@ -188,57 +154,6 @@ int16_t Item_GetHeight(const ITEM *const item) return height; } -int32_t Item_TestPosition( - const int16_t *const bounds_in, const ITEM *const src_item, - const ITEM *const dst_item) -{ - const OBJECT_BOUNDS bounds = M_ConvertBounds(bounds_in); - - const XYZ_16 rot = { - .x = dst_item->rot.x - src_item->rot.x, - .y = dst_item->rot.y - src_item->rot.y, - .z = dst_item->rot.z - src_item->rot.z, - }; - const XYZ_32 dist = { - .x = dst_item->pos.x - src_item->pos.x, - .y = dst_item->pos.y - src_item->pos.y, - .z = dst_item->pos.z - src_item->pos.z, - }; - - // clang-format off - if (rot.x < bounds.rot.min.x || - rot.x > bounds.rot.max.x || - rot.y < bounds.rot.min.y || - rot.y > bounds.rot.max.y || - rot.z < bounds.rot.min.z || - rot.z > bounds.rot.max.z - ) { - return false; - } - // clang-format on - - Matrix_PushUnit(); - Matrix_Rot16(src_item->rot); - const MATRIX *const m = g_MatrixPtr; - const XYZ_32 shift = { - .x = (dist.x * m->_00 + dist.y * m->_10 + dist.z * m->_20) >> W2V_SHIFT, - .y = (dist.x * m->_01 + dist.y * m->_11 + dist.z * m->_21) >> W2V_SHIFT, - .z = (dist.x * m->_02 + dist.y * m->_12 + dist.z * m->_22) >> W2V_SHIFT, - }; - Matrix_Pop(); - - // clang-format off - return ( - shift.x >= bounds.shift.min.x && - shift.x <= bounds.shift.max.x && - shift.y >= bounds.shift.min.y && - shift.y <= bounds.shift.max.y && - shift.z >= bounds.shift.min.z && - shift.z <= bounds.shift.max.z - ); - // clang-format on -} - void Item_AlignPosition( const XYZ_32 *const vec, const ITEM *const src_item, ITEM *const dst_item) { diff --git a/src/tr2/game/items.h b/src/tr2/game/items.h index 6a26aa675..cb24b329a 100644 --- a/src/tr2/game/items.h +++ b/src/tr2/game/items.h @@ -8,8 +8,6 @@ void Item_Control(void); void Item_ClearKilled(void); void Item_ShiftCol(ITEM *item, COLL_INFO *coll); void Item_UpdateRoom(ITEM *item, int32_t height); -int32_t Item_TestPosition( - const int16_t *bounds, const ITEM *src_item, const ITEM *dst_item); void Item_AlignPosition( const XYZ_32 *vec, const ITEM *src_item, ITEM *dst_item); int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate); diff --git a/src/tr2/game/objects/general/detonator.c b/src/tr2/game/objects/general/detonator.c index 50a4980e6..ec84db708 100644 --- a/src/tr2/game/objects/general/detonator.c +++ b/src/tr2/game/objects/general/detonator.c @@ -10,33 +10,37 @@ #include "game/sound.h" #include "global/vars.h" +#include + #define EXPLOSION_START_FRAME 76 #define EXPLOSION_END_FRAME 99 #define EXPLOSION_ACTION_FRAME 80 static XYZ_32 m_DetonatorPosition = { .x = 0, .y = 0, .z = 0 }; -static int16_t m_GongBounds[12] = { - -WALL_L / 2, - +WALL_L, - -100, - +100, - -WALL_L / 2 - 300, - -WALL_L / 2 + 100, - -30 * DEG_1, - +30 * DEG_1, - +0, - +0, - +0, - +0, +static const OBJECT_BOUNDS m_GongBounds = { + .shift = { + .min = { .x = -WALL_L / 2, .y = -100, .z = -WALL_L / 2 - 300, }, + .max = { .x = +WALL_L, .y = +100, .z = -WALL_L / 2 + 100, }, + }, + .rot = { + .min = { .x = -30 * DEG_1, .y = 0, .z = 0, }, + .max = { .x = +30 * DEG_1, .y = 0, .z = 0, }, + }, }; +static const OBJECT_BOUNDS *M_Bounds(void); static void M_CreateGongBonger(ITEM *lara_item); static void M_Setup1(OBJECT *obj); static void M_Setup2(OBJECT *obj); static void M_Control(int16_t item_num); static void M_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); +static const OBJECT_BOUNDS *M_Bounds(void) +{ + return &m_GongBounds; +} + static void M_CreateGongBonger(ITEM *const lara_item) { const int16_t item_gong_bonger_num = Item_Create(); @@ -64,12 +68,14 @@ static void M_CreateGongBonger(ITEM *const lara_item) static void M_Setup1(OBJECT *const obj) { obj->collision_func = M_Collision; + obj->bounds_func = M_Bounds; } static void M_Setup2(OBJECT *const obj) { obj->collision_func = M_Collision; obj->control_func = M_Control; + obj->bounds_func = Pickup_Bounds; obj->save_flags = 1; obj->save_anim = 1; } @@ -102,6 +108,7 @@ static void M_Collision( } ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); const XYZ_16 old_rot = item->rot; const int16_t x = item->rot.x; const int16_t y = item->rot.y; @@ -117,16 +124,11 @@ static void M_Collision( goto normal_collision; } - if (item->object_id == O_DETONATOR_2) { - if (!Item_TestPosition(g_PickupBounds, item, lara_item)) { - goto normal_collision; - } - } else { - if (!Item_TestPosition(m_GongBounds, item, lara_item)) { - goto normal_collision; - } else { - item->rot = old_rot; - } + if (!Lara_TestPosition(item, obj->bounds_func())) { + goto normal_collision; + } + if (item->object_id == O_DETONATOR_1) { + item->rot = old_rot; } if (g_Inv_Chosen == NO_OBJECT) { diff --git a/src/tr2/game/objects/general/flare_item.c b/src/tr2/game/objects/general/flare_item.c index 0a89767cb..fe893694e 100644 --- a/src/tr2/game/objects/general/flare_item.c +++ b/src/tr2/game/objects/general/flare_item.c @@ -6,6 +6,7 @@ static void M_Setup(OBJECT *obj); static void M_Setup(OBJECT *const obj) { obj->collision_func = Pickup_Collision; + obj->bounds_func = Pickup_Bounds; obj->control_func = Flare_Control; obj->draw_func = Flare_DrawInAir; obj->save_position = 1; diff --git a/src/tr2/game/objects/general/keyhole.c b/src/tr2/game/objects/general/keyhole.c index 359d23110..c564cd3df 100644 --- a/src/tr2/game/objects/general/keyhole.c +++ b/src/tr2/game/objects/general/keyhole.c @@ -17,29 +17,29 @@ static XYZ_32 m_KeyholePosition = { .z = WALL_L / 2 - LARA_RADIUS - 50, }; -static int16_t m_KeyholeBounds[12] = { - // clang-format off - -200, - +200, - +0, - +0, - +WALL_L / 2 - 200, - +WALL_L / 2, - -10 * DEG_1, - +10 * DEG_1, - -30 * DEG_1, - +30 * DEG_1, - -10 * DEG_1, - +10 * DEG_1, - // clang-format on +static const OBJECT_BOUNDS m_KeyHoleBounds = { + .shift = { + .min = { .x = -200, .y = +0, .z = +WALL_L / 2 - 200, }, + .max = { .x = +200, .y = +0, .z = +WALL_L / 2, }, + }, + .rot = { + .min = { .x = -10 * DEG_1, .y = -30 * DEG_1, .z = -10 * DEG_1, }, + .max = { .x = +10 * DEG_1, .y = +30 * DEG_1, .z = +10 * DEG_1, }, + }, }; +static const OBJECT_BOUNDS *M_Bounds(void); static void M_Consume( ITEM *lara_item, ITEM *keyhole_item, GAME_OBJECT_ID key_obj_id); static void M_Refuse(const ITEM *lara_item); static void M_Setup(OBJECT *obj); static void M_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); +static const OBJECT_BOUNDS *M_Bounds(void) +{ + return &m_KeyHoleBounds; +} + static void M_Refuse(const ITEM *const lara_item) { if (lara_item->pos.x == g_InteractPosition.x @@ -71,6 +71,7 @@ static void M_Consume( static void M_Setup(OBJECT *const obj) { obj->collision_func = M_Collision; + obj->bounds_func = M_Bounds; obj->save_flags = 1; } @@ -82,12 +83,13 @@ static void M_Collision( } ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); if ((g_Inv_Chosen == NO_OBJECT && !g_Input.action) || g_Lara.gun_status != LGS_ARMLESS || lara_item->gravity) { return; } - if (!Item_TestPosition(m_KeyholeBounds, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { return; } diff --git a/src/tr2/game/objects/general/movable_block.c b/src/tr2/game/objects/general/movable_block.c index 63f0f1b2b..3dbea88e8 100644 --- a/src/tr2/game/objects/general/movable_block.c +++ b/src/tr2/game/objects/general/movable_block.c @@ -20,21 +20,18 @@ typedef enum { MOVABLE_BLOCK_STATE_PULL = 3, } MOVABLE_BLOCK_STATE; -static int16_t m_MovableBlockBounds[12] = { - -300, - +300, - +0, - +0, - -WALL_L / 2 - LARA_RADIUS - 80, - -WALL_L / 2, - -10 * DEG_1, - +10 * DEG_1, - -30 * DEG_1, - +30 * DEG_1, - -10 * DEG_1, - +10 * DEG_1, +static const OBJECT_BOUNDS m_MovableBlockBounds = { + .shift = { + .min = { .x = -300, .y = 0, .z = -WALL_L / 2 - LARA_RADIUS - 80, }, + .max = { .x = +300, .y = 0, .z = -WALL_L / 2, }, + }, + .rot = { + .min = { .x = -10 * DEG_1, .y = -30 * DEG_1, .z = -10 * DEG_1, }, + .max = { .x = +10 * DEG_1, .y = +30 * DEG_1, .z = +10 * DEG_1, }, + }, }; +static const OBJECT_BOUNDS *M_Bounds(void); static bool M_TestDestination(const ITEM *item, int32_t block_height); static bool M_TestPush( const ITEM *item, int32_t block_height, DIRECTION quadrant); @@ -47,6 +44,11 @@ static void M_Draw(const ITEM *item); static void M_Control(int16_t item_num); static void M_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); +static const OBJECT_BOUNDS *M_Bounds(void) +{ + return &m_MovableBlockBounds; +} + static bool M_TestDestination( const ITEM *const item, const int32_t block_height) { @@ -199,6 +201,7 @@ static void M_Setup(OBJECT *const obj) obj->handle_save_func = M_HandleSave; obj->control_func = M_Control; obj->collision_func = M_Collision; + obj->bounds_func = M_Bounds; obj->draw_func = M_Draw; obj->save_position = 1; obj->save_flags = 1; @@ -303,7 +306,7 @@ static void M_Collision( break; } - if (!Item_TestPosition(m_MovableBlockBounds, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { return; } @@ -346,7 +349,7 @@ static void M_Collision( } else if ( Item_TestAnimEqual(lara_item, LA_PUSHABLE_GRAB) && Item_TestFrameEqual(lara_item, LF_PPREADY)) { - if (!Item_TestPosition(m_MovableBlockBounds, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { return; } diff --git a/src/tr2/game/objects/general/pickup.c b/src/tr2/game/objects/general/pickup.c index 5d0910541..dab94658f 100644 --- a/src/tr2/game/objects/general/pickup.c +++ b/src/tr2/game/objects/general/pickup.c @@ -26,41 +26,29 @@ #define LF_PICKUP_FLARE_UW 20 #define LF_PICKUP_UW 18 -int16_t g_PickupBounds[12] = { - // clang-format off - -WALL_L / 4, - +WALL_L / 4, - -100, - +100, - -WALL_L / 4, - +WALL_L / 4, - -10 * DEG_1, - +10 * DEG_1, - +0, - +0, - +0, - +0, - // clang-format on -}; - static XYZ_32 m_PickupPosition = { .x = 0, .y = 0, .z = -100 }; static XYZ_32 m_PickupPositionUW = { .x = 0, .y = -200, .z = -350 }; -static int16_t m_PickupBoundsUW[12] = { - // clang-format off - -WALL_L / 2, - +WALL_L / 2, - -WALL_L / 2, - +WALL_L / 2, - -WALL_L / 2, - +WALL_L / 2, - -45 * DEG_1, - +45 * DEG_1, - -45 * DEG_1, - +45 * DEG_1, - -45 * DEG_1, - +45 * DEG_1, - // clang-format on +static const OBJECT_BOUNDS m_PickUpBounds = { + .shift = { + .min = { .x = -WALL_L / 4, .y = -100, .z = -WALL_L / 4, }, + .max = { .x = +WALL_L / 4, .y = +100, .z = +WALL_L / 4, }, + }, + .rot = { + .min = { .x = -10 * DEG_1, .y = 0, .z = 0, }, + .max = { .x = +10 * DEG_1, .y = 0, .z = 0, }, + }, +}; + +static const OBJECT_BOUNDS m_PickUpBoundsUW = { + .shift = { + .min = { .x = -WALL_L / 2, .y = -WALL_L / 2, .z = -WALL_L / 2, }, + .max = { .x = +WALL_L / 2, .y = +WALL_L / 2, .z = +WALL_L / 2, }, + }, + .rot = { + .min = { .x = -45 * DEG_1, .y = -45 * DEG_1, .z = -45 * DEG_1, }, + .max = { .x = +45 * DEG_1, .y = +45 * DEG_1, .z = +45 * DEG_1, }, + }, }; static void M_DoPickup(int16_t item_num); @@ -107,13 +95,14 @@ static void M_DoFlarePickup(const int16_t item_num) static void M_DoAboveWater(const int16_t item_num, ITEM *const lara_item) { ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); const XYZ_16 old_rot = item->rot; item->rot.x = 0; item->rot.y = lara_item->rot.y; item->rot.z = 0; - if (!Item_TestPosition(g_PickupBounds, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { goto cleanup; } @@ -163,13 +152,14 @@ cleanup: static void M_DoUnderwater(const int16_t item_num, ITEM *const lara_item) { ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); const XYZ_16 old_rot = item->rot; item->rot.x = -25 * DEG_1; item->rot.y = lara_item->rot.y; item->rot.z = 0; - if (!Item_TestPosition(m_PickupBoundsUW, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { goto cleanup; } @@ -224,6 +214,7 @@ static void M_Setup(OBJECT *const obj) obj->handle_save_func = M_HandleSave; obj->activate_func = M_Activate; obj->collision_func = Pickup_Collision; + obj->bounds_func = Pickup_Bounds; obj->draw_func = M_Draw; obj->save_position = 1; obj->save_flags = 1; @@ -343,6 +334,15 @@ static void M_Draw(const ITEM *const item) Matrix_Pop(); } +const OBJECT_BOUNDS *Pickup_Bounds(void) +{ + if (g_Lara.water_status == LWS_UNDERWATER) { + return &m_PickUpBoundsUW; + } else { + return &m_PickUpBounds; + } +} + void Pickup_Collision( const int16_t item_num, ITEM *const lara_item, COLL_INFO *const coll) { diff --git a/src/tr2/game/objects/general/pickup.h b/src/tr2/game/objects/general/pickup.h index dfac91fc3..1b1a51fff 100644 --- a/src/tr2/game/objects/general/pickup.h +++ b/src/tr2/game/objects/general/pickup.h @@ -2,7 +2,6 @@ #include "global/types.h" -extern int16_t g_PickupBounds[]; - void Pickup_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); bool Pickup_Trigger(int16_t item_num); +const OBJECT_BOUNDS *Pickup_Bounds(void); diff --git a/src/tr2/game/objects/general/puzzle_hole.c b/src/tr2/game/objects/general/puzzle_hole.c index 174755780..45aa8fe52 100644 --- a/src/tr2/game/objects/general/puzzle_hole.c +++ b/src/tr2/game/objects/general/puzzle_hole.c @@ -17,23 +17,18 @@ static XYZ_32 m_PuzzleHolePosition = { .z = WALL_L / 2 - LARA_RADIUS - 85, }; -static int16_t m_PuzzleHoleBounds[12] = { - // clang-format off - -200, - +200, - +0, - +0, - +WALL_L / 2 - 200, - +WALL_L / 2, - -10 * DEG_1, - +10 * DEG_1, - -30 * DEG_1, - +30 * DEG_1, - -10 * DEG_1, - +10 * DEG_1, - // clang-format on +static const OBJECT_BOUNDS m_PuzzleHoleBounds = { + .shift = { + .min = { .x = -200, .y = 0, .z = WALL_L / 2 - 200, }, + .max = { .x = +200, .y = 0, .z = WALL_L / 2, }, + }, + .rot = { + .min = { .x = -10 * DEG_1, .y = -30 * DEG_1, .z = -10 * DEG_1, }, + .max = { .x = +10 * DEG_1, .y = +30 * DEG_1, .z = +10 * DEG_1, }, + }, }; +static const OBJECT_BOUNDS *M_Bounds(void); static void M_Refuse(const ITEM *lara_item); static void M_Consume( ITEM *lara_item, ITEM *puzzle_hole_item, GAME_OBJECT_ID puzzle_obj_id); @@ -43,6 +38,11 @@ static void M_SetupDone(OBJECT *obj); static void M_HandleSave(ITEM *item, SAVEGAME_STAGE stage); static void M_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); +static const OBJECT_BOUNDS *M_Bounds(void) +{ + return &m_PuzzleHoleBounds; +} + static void M_Refuse(const ITEM *const lara_item) { if (lara_item->pos.x != g_InteractPosition.x @@ -82,6 +82,7 @@ static void M_SetupEmpty(OBJECT *const obj) { obj->collision_func = M_Collision; obj->handle_save_func = M_HandleSave; + obj->bounds_func = M_Bounds; obj->save_flags = 1; } @@ -103,10 +104,11 @@ static void M_Collision( const int16_t item_num, ITEM *const lara_item, COLL_INFO *const coll) { ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); if (lara_item->current_anim_state != LS_STOP) { if (lara_item->current_anim_state != LS_USE_PUZZLE - || !Item_TestPosition(m_PuzzleHoleBounds, item, lara_item) + || !Lara_TestPosition(item, obj->bounds_func()) || !Item_TestFrameEqual(lara_item, LF_USE_PUZZLE)) { return; } @@ -120,7 +122,7 @@ static void M_Collision( return; } - if (!Item_TestPosition(m_PuzzleHoleBounds, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { return; } diff --git a/src/tr2/game/objects/general/switch.c b/src/tr2/game/objects/general/switch.c index 3af8f70e2..2053d2a4e 100644 --- a/src/tr2/game/objects/general/switch.c +++ b/src/tr2/game/objects/general/switch.c @@ -17,40 +17,30 @@ static XYZ_32 g_PushSwitchPosition = { .x = 0, .y = 0, .z = 292 }; static XYZ_32 m_AirlockPosition = { .x = 0, .y = 0, .z = 212 }; static XYZ_32 m_SwitchUWPosition = { .x = 0, .y = 0, .z = 108 }; -static int16_t m_SwitchBounds[12] = { - // clang-format off - -220, - +220, - +0, - +0, - +WALL_L / 2 - 220, - +WALL_L / 2, - -10 * DEG_1, - +10 * DEG_1, - -30 * DEG_1, - +30 * DEG_1, - -10 * DEG_1, - +10 * DEG_1, - // clang-format on +static const OBJECT_BOUNDS m_SwitchBounds = { + .shift = { + .min = { .x = -220, .y = +0, .z = +WALL_L / 2 - 220, }, + .max = { .x = +220, .y = +0, .z = +WALL_L / 2, }, + }, + .rot = { + .min = { .x = -10 * DEG_1, .y = -30 * DEG_1, .z = -10 * DEG_1, }, + .max = { .x = +10 * DEG_1, .y = +30 * DEG_1, .z = +10 * DEG_1, }, + }, }; -static int16_t m_SwitchBoundsUW[12] = { - // clang-format off - -WALL_L, - +WALL_L, - -WALL_L, - +WALL_L, - -WALL_L, - +WALL_L / 2, - -80 * DEG_1, - +80 * DEG_1, - -80 * DEG_1, - +80 * DEG_1, - -80 * DEG_1, - +80 * DEG_1, - // clang-format on +static const OBJECT_BOUNDS m_SwitchBoundsUW = { + .shift = { + .min = { .x = -WALL_L, .y = -WALL_L, .z = -WALL_L, }, + .max = { .x = +WALL_L, .y = +WALL_L, .z = +WALL_L / 2, }, + }, + .rot = { + .min = { .x = -80 * DEG_1, .y = -80 * DEG_1, .z = -80 * DEG_1, }, + .max = { .x = +80 * DEG_1, .y = +80 * DEG_1, .z = +80 * DEG_1, }, + }, }; +static const OBJECT_BOUNDS *M_Bounds(void); +static const OBJECT_BOUNDS *M_BoundsUW(void); static void M_AlignLara(ITEM *lara_item, ITEM *switch_item); static void M_SwitchOn(ITEM *switch_item, ITEM *lara_item); static void M_SwitchOff(ITEM *switch_item, ITEM *lara_item); @@ -62,6 +52,16 @@ static void M_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); static void M_CollisionUW(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); static void M_Control(int16_t item_num); +static const OBJECT_BOUNDS *M_Bounds(void) +{ + return &m_SwitchBounds; +} + +static const OBJECT_BOUNDS *M_BoundsUW(void) +{ + return &m_SwitchBoundsUW; +} + static void M_AlignLara(ITEM *const lara_item, ITEM *const switch_item) { switch (switch_item->object_id) { @@ -139,28 +139,32 @@ static void M_Setup(OBJECT *const obj) { M_SetupBase(obj); obj->collision_func = M_Collision; + obj->bounds_func = M_Bounds; } static void M_SetupPushButton(OBJECT *const obj) { M_Setup(obj); obj->enable_interpolation = false; + obj->bounds_func = M_Bounds; } static void M_SetupUW(OBJECT *const obj) { M_SetupBase(obj); obj->collision_func = M_CollisionUW; + obj->bounds_func = M_BoundsUW; } static void M_Collision( const int16_t item_num, ITEM *const lara_item, COLL_INFO *const coll) { ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); if (!g_Input.action || item->status != IS_INACTIVE || g_Lara.gun_status != LGS_ARMLESS || lara_item->gravity || lara_item->current_anim_state != LS_STOP - || !Item_TestPosition(m_SwitchBounds, item, lara_item)) { + || !Lara_TestPosition(item, obj->bounds_func())) { return; } @@ -193,6 +197,7 @@ static void M_CollisionUW( const int16_t item_num, ITEM *const lara_item, COLL_INFO *const coll) { ITEM *const item = Item_Get(item_num); + const OBJECT *const obj = Object_Get(item->object_id); if (!g_Input.action || item->status != IS_INACTIVE || g_Lara.water_status != LWS_UNDERWATER @@ -201,7 +206,7 @@ static void M_CollisionUW( return; } - if (!Item_TestPosition(m_SwitchBoundsUW, item, lara_item)) { + if (!Lara_TestPosition(item, obj->bounds_func())) { return; } diff --git a/src/tr2/game/objects/general/zipline.c b/src/tr2/game/objects/general/zipline.c index 6dd04d867..447cfa4fa 100644 --- a/src/tr2/game/objects/general/zipline.c +++ b/src/tr2/game/objects/general/zipline.c @@ -22,33 +22,35 @@ static XYZ_32 m_ZiplineHandlePosition = { .y = 0, .z = WALL_L / 2 - 141, }; -static int16_t m_ZiplineHandleBounds[12] = { - // clang-format off - -WALL_L / 4, - +WALL_L / 4, - -100, - +100, - +WALL_L / 4, - +WALL_L / 2, - +0, - +0, - -25 * DEG_1, - +25 * DEG_1, - +0, - +0, - // clang-format on + +static const OBJECT_BOUNDS m_ZiplineHandleBounds = { + .shift = { + .min = { .x = -WALL_L / 4, .y = -100, .z = +WALL_L / 4, }, + .max = { .x = +WALL_L / 4, .y = +100, .z = +WALL_L / 2, }, + }, + .rot = { + .min = { .x = +0, .y = -25 * DEG_1, .z = +0, }, + .max = { .x = +0, .y = +25 * DEG_1, .z = +0, }, + }, }; +static const OBJECT_BOUNDS *M_Bounds(void); static void M_Setup(OBJECT *obj); static void M_Initialise(int16_t item_num); static void M_Control(int16_t item_num); static void M_Collision(int16_t item_num, ITEM *lara_item, COLL_INFO *coll); +static const OBJECT_BOUNDS *M_Bounds(void) +{ + return &m_ZiplineHandleBounds; +} + static void M_Setup(OBJECT *const obj) { obj->initialise_func = M_Initialise; obj->control_func = M_Control; obj->collision_func = M_Collision; + obj->bounds_func = M_Bounds; obj->save_position = 1; obj->save_flags = 1; obj->save_anim = 1; @@ -149,7 +151,8 @@ static void M_Collision( return; } - if (!Item_TestPosition(m_ZiplineHandleBounds, item, lara_item)) { + const OBJECT *const obj = Object_Get(item->object_id); + if (!Lara_TestPosition(item, obj->bounds_func())) { return; } diff --git a/src/tr2/global/types_decomp.h b/src/tr2/global/types_decomp.h index 3d1825df8..59ecb25d0 100644 --- a/src/tr2/global/types_decomp.h +++ b/src/tr2/global/types_decomp.h @@ -151,13 +151,6 @@ typedef struct { int32_t pitch; } SKIDOO_INFO; -typedef struct { - struct { - XYZ_16 min; - XYZ_16 max; - } shift, rot; -} OBJECT_BOUNDS; - typedef struct { int32_t xv; int32_t yv;