mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
tr2/objects: use common OBJECT_BOUNDS
This updates all relevant TR2 objects to use OBJECT_BOUNDS rather than an arbitrary array of values for testing bounds. The approach is equivalent to TR1. Lara_TestPosition has also been moved to TRX, and kept in Lara's module rather than in items.c, as it's only used by Lara.
This commit is contained in:
parent
cdfb5942c1
commit
ff86b5e712
19 changed files with 224 additions and 303 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -10,33 +10,37 @@
|
|||
#include "game/sound.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/game/lara.h>
|
||||
|
||||
#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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue