mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 12:47:58 +03:00
tr2/movable_block: fix pushblock stacking issues
This resolves issues with being unable to stack pushblocks across multiple rooms.
This commit is contained in:
parent
e89d6932bf
commit
34ff171fa3
4 changed files with 112 additions and 79 deletions
|
@ -9,6 +9,7 @@
|
|||
- fixed several issues with pushblocks (#2036)
|
||||
- fixed an invisible wall above stacked pushblocks if near a ceiling portal
|
||||
- fixed floor height issues with pushblocks poised to fall in various scenarios
|
||||
- fixed being unable to stack multiple pushblocks over multiple rooms
|
||||
- fixed play any level causing the game to hang when no gym level is present (#2560, regression from 0.9)
|
||||
- fixed extremely large item quantities crashing the game (#2497, regression from 0.3)
|
||||
- fixed missing new game text in the passport when play any level is enabled (#2563, regression from 0.9)
|
||||
|
|
|
@ -81,8 +81,10 @@ game with new enhancements and features.
|
|||
- fixed smashed windows blocking enemy pathing after loading a save
|
||||
- fixed Lara getting stuck in a T-pose after jumping/falling and then dying before reaching fast fall speed
|
||||
- fixed several issues with pushblocks
|
||||
- fixed several issues with pushblocks:
|
||||
- fixed an invisible wall above stacked pushblocks if near a ceiling portal
|
||||
- fixed floor height issues with pushblocks poised to fall in various scenarios
|
||||
- fixed being unable to stack multiple pushblocks over multiple rooms
|
||||
- improved the animation of Lara's braid
|
||||
|
||||
#### Cheats
|
||||
|
|
|
@ -36,9 +36,9 @@ static int16_t m_MovableBlockBounds[12] = {
|
|||
|
||||
static bool M_TestDestination(const ITEM *item, int32_t block_height);
|
||||
static bool M_TestPush(
|
||||
const ITEM *item, int32_t block_height, uint16_t quadrant);
|
||||
const ITEM *item, int32_t block_height, DIRECTION quadrant);
|
||||
static bool M_TestPull(
|
||||
const ITEM *item, int32_t block_height, uint16_t quadrant);
|
||||
const ITEM *item, int32_t block_height, DIRECTION quadrant);
|
||||
|
||||
static void M_Setup(OBJECT *obj);
|
||||
static void M_Initialise(int16_t item_num);
|
||||
|
@ -55,12 +55,14 @@ static bool M_TestDestination(
|
|||
const SECTOR *const sector =
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
|
||||
const int16_t floor = sector->floor.height;
|
||||
const int16_t floor =
|
||||
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
|
||||
return floor == NO_HEIGHT || (floor == item->pos.y - block_height);
|
||||
}
|
||||
|
||||
static bool M_TestPush(
|
||||
const ITEM *const item, const int32_t block_height, const uint16_t quadrant)
|
||||
const ITEM *const item, const int32_t block_height,
|
||||
const DIRECTION quadrant)
|
||||
{
|
||||
if (!M_TestDestination(item, block_height)) {
|
||||
return false;
|
||||
|
@ -88,6 +90,8 @@ static bool M_TestPush(
|
|||
break;
|
||||
}
|
||||
|
||||
const SECTOR *sector = Room_GetSector(x, y, z, &room_num);
|
||||
|
||||
COLL_INFO coll = {
|
||||
.quadrant = quadrant,
|
||||
.radius = 500,
|
||||
|
@ -97,13 +101,8 @@ static bool M_TestPush(
|
|||
return false;
|
||||
}
|
||||
|
||||
const SECTOR *sector = Room_GetSector(x, y, z, &room_num);
|
||||
if (sector->floor.height != y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Room_GetHeight(sector, x, y, z);
|
||||
if (Room_GetHeightType() != HT_WALL) {
|
||||
const int16_t height = Room_GetHeight(sector, x, y, z);
|
||||
if (height != y || Room_GetHeightType() != HT_WALL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -117,7 +116,8 @@ static bool M_TestPush(
|
|||
}
|
||||
|
||||
static bool M_TestPull(
|
||||
const ITEM *const item, const int32_t block_height, const uint16_t quadrant)
|
||||
const ITEM *const item, const int32_t block_height,
|
||||
const DIRECTION quadrant)
|
||||
{
|
||||
if (!M_TestDestination(item, block_height)) {
|
||||
return false;
|
||||
|
@ -146,6 +146,7 @@ static bool M_TestPull(
|
|||
int32_t y = item->pos.y;
|
||||
int32_t z = item->pos.z + z_add;
|
||||
int16_t room_num = item->room_num;
|
||||
const SECTOR *sector = Room_GetSector(x, y, z, &room_num);
|
||||
|
||||
COLL_INFO coll = {
|
||||
.quadrant = quadrant,
|
||||
|
@ -156,14 +157,13 @@ static bool M_TestPull(
|
|||
return false;
|
||||
}
|
||||
|
||||
const SECTOR *sector = Room_GetSector(x, y, z, &room_num);
|
||||
if (sector->floor.height != y) {
|
||||
if (Room_GetHeight(sector, x, y, z) != y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int32_t y_min = y - block_height;
|
||||
sector = Room_GetSector(x, y_min, z, &room_num);
|
||||
if (sector->ceiling.height > y_min) {
|
||||
if (Room_GetCeiling(sector, x, y_min, z) > y_min) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -171,12 +171,12 @@ static bool M_TestPull(
|
|||
z += z_add;
|
||||
room_num = item->room_num;
|
||||
sector = Room_GetSector(x, y, z, &room_num);
|
||||
if (sector->floor.height != y) {
|
||||
if (Room_GetHeight(sector, x, y, z) != y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sector = Room_GetSector(x, y - LARA_HEIGHT, z, &room_num);
|
||||
if (sector->ceiling.height > y - LARA_HEIGHT) {
|
||||
if (Room_GetCeiling(sector, x, y - LARA_HEIGHT, z) > y - LARA_HEIGHT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ static bool M_TestPull(
|
|||
z = g_LaraItem->pos.z + z_add;
|
||||
y = g_LaraItem->pos.y;
|
||||
room_num = g_LaraItem->room_num;
|
||||
Room_GetSector(x, y, z, &room_num);
|
||||
sector = Room_GetSector(x, y, z, &room_num);
|
||||
coll.quadrant = (quadrant + 2) & 3;
|
||||
coll.radius = LARA_RADIUS;
|
||||
if (Collide_CollideStaticObjects(&coll, x, y, z, room_num, LARA_HEIGHT)) {
|
||||
|
@ -308,63 +308,67 @@ static void M_Collision(
|
|||
|
||||
const DIRECTION quadrant = Math_GetDirection(lara_item->rot.y);
|
||||
if (lara_item->current_anim_state == LS_STOP) {
|
||||
if (g_Lara.gun_status == LGS_ARMLESS) {
|
||||
switch (quadrant) {
|
||||
case DIR_NORTH:
|
||||
item->rot.y = 0;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
item->rot.y = DEG_90;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
item->rot.y = -DEG_180;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
item->rot.y = -DEG_90;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (g_Input.forward || g_Input.back
|
||||
|| g_Lara.gun_status != LGS_ARMLESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Item_TestPosition(m_MovableBlockBounds, item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
switch (quadrant) {
|
||||
case DIR_NORTH:
|
||||
item->rot.y = 0;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
item->rot.y = DEG_90;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
item->rot.y = -DEG_180;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
item->rot.y = -DEG_90;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int16_t room_num = lara_item->room_num;
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (room_num != item->room_num) {
|
||||
return;
|
||||
}
|
||||
if (!Item_TestPosition(m_MovableBlockBounds, item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (quadrant) {
|
||||
case DIR_NORTH:
|
||||
lara_item->pos.z = ROUND_TO_SECTOR(lara_item->pos.z);
|
||||
lara_item->pos.z += WALL_L - LARA_RADIUS;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
lara_item->pos.x = ROUND_TO_SECTOR(lara_item->pos.x);
|
||||
lara_item->pos.x += WALL_L - LARA_RADIUS;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
lara_item->pos.z = ROUND_TO_SECTOR(lara_item->pos.z);
|
||||
lara_item->pos.z += LARA_RADIUS;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
lara_item->pos.x = ROUND_TO_SECTOR(lara_item->pos.x);
|
||||
lara_item->pos.x += LARA_RADIUS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
int16_t room_num = lara_item->room_num;
|
||||
Room_GetSector(
|
||||
item->pos.x, item->pos.y - STEP_L / 2, item->pos.z, &room_num);
|
||||
if (room_num != item->room_num) {
|
||||
return;
|
||||
}
|
||||
|
||||
lara_item->rot.y = item->rot.y;
|
||||
lara_item->goal_anim_state = LS_PP_READY;
|
||||
switch (quadrant) {
|
||||
case DIR_NORTH:
|
||||
lara_item->pos.z = ROUND_TO_SECTOR(lara_item->pos.z);
|
||||
lara_item->pos.z += WALL_L - LARA_RADIUS;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
lara_item->pos.x = ROUND_TO_SECTOR(lara_item->pos.x);
|
||||
lara_item->pos.x += WALL_L - LARA_RADIUS;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
lara_item->pos.z = ROUND_TO_SECTOR(lara_item->pos.z);
|
||||
lara_item->pos.z += LARA_RADIUS;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
lara_item->pos.x = ROUND_TO_SECTOR(lara_item->pos.x);
|
||||
lara_item->pos.x += LARA_RADIUS;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Lara_Animate(lara_item);
|
||||
lara_item->rot.y = item->rot.y;
|
||||
lara_item->goal_anim_state = LS_PP_READY;
|
||||
|
||||
if (lara_item->current_anim_state == LS_PP_READY) {
|
||||
g_Lara.gun_status = LGS_HANDS_BUSY;
|
||||
}
|
||||
Lara_Animate(lara_item);
|
||||
|
||||
if (lara_item->current_anim_state == LS_PP_READY) {
|
||||
g_Lara.gun_status = LGS_HANDS_BUSY;
|
||||
}
|
||||
} else if (
|
||||
Item_TestAnimEqual(lara_item, LA_PUSHABLE_GRAB)
|
||||
|
|
|
@ -558,21 +558,47 @@ void Room_TestTriggers(const ITEM *const item)
|
|||
|
||||
void Room_AlterFloorHeight(const ITEM *const item, const int32_t height)
|
||||
{
|
||||
int16_t room_num = item->room_num;
|
||||
if (height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SECTOR *const sector =
|
||||
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
const SECTOR *ceiling = Room_GetSector(
|
||||
item->pos.x, item->pos.y + height - WALL_L, item->pos.z, &room_num);
|
||||
int16_t portal_room;
|
||||
SECTOR *sector;
|
||||
const ROOM *room = Room_Get(item->room_num);
|
||||
|
||||
if (sector->floor.height == NO_HEIGHT) {
|
||||
sector->floor.height = ceiling->ceiling.height + ROUND_TO_CLICK(height);
|
||||
} else {
|
||||
do {
|
||||
int32_t z_sector = (item->pos.z - room->pos.z) >> WALL_SHIFT;
|
||||
int32_t x_sector = (item->pos.x - room->pos.x) >> WALL_SHIFT;
|
||||
|
||||
if (z_sector <= 0) {
|
||||
z_sector = 0;
|
||||
CLAMP(x_sector, 1, room->size.x - 2);
|
||||
} else if (z_sector >= room->size.z - 1) {
|
||||
z_sector = room->size.z - 1;
|
||||
CLAMP(x_sector, 1, room->size.x - 2);
|
||||
} else {
|
||||
CLAMP(x_sector, 0, room->size.x - 1);
|
||||
}
|
||||
|
||||
sector = Room_GetUnitSector(room, x_sector, z_sector);
|
||||
portal_room = sector->portal_room.wall;
|
||||
if (portal_room != NO_ROOM) {
|
||||
room = Room_Get(portal_room);
|
||||
}
|
||||
} while (portal_room != NO_ROOM);
|
||||
|
||||
const SECTOR *const sky_sector =
|
||||
Room_GetSkySector(sector, item->pos.x, item->pos.z);
|
||||
sector = Room_GetPitSector(sector, item->pos.x, item->pos.z);
|
||||
|
||||
if (sector->floor.height != NO_HEIGHT) {
|
||||
sector->floor.height += ROUND_TO_CLICK(height);
|
||||
if (sector->floor.height == ceiling->ceiling.height
|
||||
&& sector->portal_room.sky == NO_ROOM) {
|
||||
if (sector->floor.height == sky_sector->ceiling.height) {
|
||||
sector->floor.height = NO_HEIGHT;
|
||||
}
|
||||
} else {
|
||||
sector->floor.height =
|
||||
sky_sector->ceiling.height + ROUND_TO_CLICK(height);
|
||||
}
|
||||
|
||||
BOX_INFO *const box = Box_GetBox(sector->box);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue