tr2/movable_block: fix falling pushblock height issues

This resolves falling pushblocks causing various floor height issues
depending on where they are placed above the floor.
This commit is contained in:
lahm86 2025-02-21 14:25:15 +00:00
parent 8621b05dd8
commit e89d6932bf
6 changed files with 37 additions and 7 deletions

View file

@ -8,6 +8,7 @@
- fixed flare pickups only adding one flare to Lara's inventory rather than six (#2551, regression from 0.9)
- 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 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)

View file

@ -82,6 +82,7 @@ game with new enhancements and features.
- 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 an invisible wall above stacked pushblocks if near a ceiling portal
- fixed floor height issues with pushblocks poised to fall in various scenarios
- improved the animation of Lara's braid
#### Cheats

View file

@ -44,8 +44,8 @@ typedef struct {
SHADE shade;
void *data;
#if TR_VERSION == 1
void *priv;
#if TR_VERSION == 1
CARRIED_ITEM *carried_item;
bool enable_shadow;
#elif TR_VERSION == 2

View file

@ -82,6 +82,7 @@ void Item_Initialise(const int16_t item_num)
item->mesh_bits = 0xFFFFFFFF;
item->touch_bits = 0;
item->data = nullptr;
item->priv = nullptr;
item->active = 0;
item->status = IS_INACTIVE;
@ -170,6 +171,17 @@ void Item_UpdateRoom(ITEM *const item, const int32_t height)
}
}
int16_t Item_GetHeight(const ITEM *const item)
{
int16_t room_num = item->room_num;
const SECTOR *const sector =
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
const int32_t height =
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
return height;
}
int32_t Item_TestBoundsCollide(
const ITEM *const src_item, const ITEM *const dst_item,
const int32_t radius)

View file

@ -6,6 +6,7 @@ void Item_Control(void);
void Item_ClearKilled(void);
void Item_ShiftCol(ITEM *item, COLL_INFO *coll);
void Item_UpdateRoom(ITEM *item, int32_t height);
int16_t Item_GetHeight(const ITEM *item);
int32_t Item_TestBoundsCollide(
const ITEM *src_item, const ITEM *dst_item, int32_t radius);
int32_t Item_TestPosition(

View file

@ -197,7 +197,7 @@ static bool M_TestPull(
static void M_Initialise(const int16_t item_num)
{
ITEM *const item = Item_Get(item_num);
if (item->status != IS_INVISIBLE) {
if (item->status != IS_INVISIBLE && item->pos.y >= Item_GetHeight(item)) {
Room_AlterFloorHeight(item, -WALL_L);
}
}
@ -228,10 +228,14 @@ static void M_HandleSave(ITEM *const item, const SAVEGAME_STAGE stage)
{
switch (stage) {
case SAVEGAME_STAGE_BEFORE_LOAD:
Room_AlterFloorHeight(item, WALL_L);
if (item->status != IS_INVISIBLE
&& item->pos.y >= Item_GetHeight(item)) {
Room_AlterFloorHeight(item, WALL_L);
}
break;
case SAVEGAME_STAGE_AFTER_LOAD:
item->priv = item->status == IS_ACTIVE ? (void *)true : (void *)false;
if (item->status == IS_INACTIVE) {
Room_AlterFloorHeight(item, -WALL_L);
}
@ -255,10 +259,10 @@ static void M_Control(const int16_t item_num)
Item_Animate(item);
int16_t room_num = item->room_num;
const SECTOR *const sector =
Room_GetSector(item->pos.x, item->pos.y, item->pos.z, &room_num);
const int32_t height =
Room_GetHeight(sector, item->pos.x, item->pos.y, item->pos.z);
const SECTOR *const sector = Room_GetSector(
item->pos.x, item->pos.y - STEP_L / 2, item->pos.z, &room_num);
const int32_t height = Room_GetHeight(
sector, item->pos.x, item->pos.y - STEP_L / 2, item->pos.z);
if (item->pos.y < height) {
item->gravity = 1;
@ -268,6 +272,11 @@ static void M_Control(const int16_t item_num)
item->status = IS_DEACTIVATED;
ItemAction_Run(ITEM_ACTION_FLOOR_SHAKE, item);
Sound_Effect(SFX_ENEMY_GRUNT, &item->pos, SPM_ALWAYS);
} else if (
item->pos.y >= height && !item->gravity
&& !(bool)(intptr_t)item->priv) {
item->status = IS_INACTIVE;
Item_RemoveActive(item_num);
}
if (item->room_num != room_num) {
@ -286,6 +295,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 (item->current_anim_state == MOVABLE_BLOCK_STATE_STILL) {
item->priv = (void *)false;
}
if (!g_Input.action || item->status == IS_ACTIVE || lara_item->gravity
|| lara_item->pos.y != item->pos.y) {
@ -380,6 +394,7 @@ static void M_Collision(
item->status = IS_ACTIVE;
Item_Animate(item);
Lara_Animate(lara_item);
item->priv = (void *)true;
}
}