Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rooms: move height vars and functions to TRX #2542

Merged
merged 6 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/GAME_FLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ default game flow for examples.
</td>
</tr>
<tr valign="top">
<td><code>disable_floor</code><strong>²</strong></td>
<td><code>disable_floor</code></td>
<td><code>value</code></td>
<td>Integer</td>
<td>
Expand Down
1 change: 1 addition & 0 deletions docs/tr1/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr1-4.8.3...develop) - ××××-××-××
- added support for custom levels to use `disable_floor` in the gameflow, similar to TR2's Floating Islands (#2541)

## [4.8.3](https://github.com/LostArtefacts/TRX/compare/tr1-4.8.2...tr1-4.8.3) - 2025-02-17
- fixed some of Lara's speech in the gym not playing in response to player action (#2514, regression from 4.8)
Expand Down
1 change: 1 addition & 0 deletions docs/tr1/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ Not all options are turned on by default. Refer to `TR1X_ConfigTool.exe` for det
- added a photo mode feature
- added optional automatic key/puzzle inventory item pre-selection
- added ability for falling pushblocks to kill Lara outright if one lands directly on her
- added support for custom levels to define "no floor", to create an abyss like in TR2's Floating Islands
- changed weapon pickup behavior when unarmed to set any weapon as the default weapon, not just pistols
- fixed keys and items not working when drawing guns immediately after using them
- fixed counting the secret in The Great Pyramid
Expand Down
1 change: 1 addition & 0 deletions src/libtrx/game/game_flow/reader_tr1.def.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static M_SEQUENCE_EVENT_HANDLER m_SequenceEventHandlers[] = {
{ GFS_PLAY_MUSIC, M_HandleIntEvent, "music_track" },
{ GFS_SET_CAMERA_ANGLE, M_HandleIntEvent, "value" },
{ GFS_SETUP_BACON_LARA, M_HandleIntEvent, "anchor_room" },
{ GFS_DISABLE_FLOOR, M_HandleIntEvent, "height" },

// Special cases with custom handlers
{ GFS_LOADING_SCREEN, M_HandlePictureEvent, nullptr },
Expand Down
175 changes: 175 additions & 0 deletions src/libtrx/game/rooms/common.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "game/rooms/common.h"

#include "debug.h"
#include "game/camera.h"
#include "game/const.h"
#include "game/game_buf.h"
#include "game/items.h"
Expand Down Expand Up @@ -32,11 +33,17 @@ static bool m_FlipStatus = false;
static int32_t m_FlipEffect = -1;
static int32_t m_FlipTimer = 0;
static int32_t m_FlipSlotFlags[MAX_FLIP_MAPS] = {};
static int16_t m_AbyssMinHeight = 0;
static int32_t m_AbyssMaxHeight = 0;
static HEIGHT_TYPE m_HeightType = HT_WALL;

static const int16_t *M_ReadTrigger(
const int16_t *data, int16_t fd_entry, SECTOR *sector);
static void M_AddFlipItems(const ROOM *room);
static void M_RemoveFlipItems(const ROOM *room);
static int16_t M_GetFloorTiltHeight(const SECTOR *sector, int32_t x, int32_t z);
static int16_t M_GetCeilingTiltHeight(
const SECTOR *sector, int32_t x, int32_t z);

static const int16_t *M_ReadTrigger(
const int16_t *data, const int16_t fd_entry, SECTOR *const sector)
Expand Down Expand Up @@ -145,6 +152,70 @@ static void M_RemoveFlipItems(const ROOM *const room)
}
}

static int16_t M_GetFloorTiltHeight(
const SECTOR *const sector, const int32_t x, const int32_t z)
{
int16_t height = sector->floor.height;
if (sector->floor.tilt == 0) {
return height;
}

const int32_t z_off = sector->floor.tilt >> 8;
const int32_t x_off = (int8_t)sector->floor.tilt;

const HEIGHT_TYPE slope_type =
(ABS(z_off) > 2 || ABS(x_off) > 2) ? HT_BIG_SLOPE : HT_SMALL_SLOPE;
if (Camera_IsChunky() && slope_type == HT_BIG_SLOPE) {
return height;
}

m_HeightType = slope_type;

if (z_off < 0) {
height -= (int16_t)NEG_TILT(z_off, z);
} else {
height += (int16_t)POS_TILT(z_off, z);
}

if (x_off < 0) {
height -= (int16_t)NEG_TILT(x_off, x);
} else {
height += (int16_t)POS_TILT(x_off, x);
}

return height;
}

static int16_t M_GetCeilingTiltHeight(
const SECTOR *sector, const int32_t x, const int32_t z)
{
int16_t height = sector->ceiling.height;
if (sector->ceiling.tilt == 0) {
return height;
}

const int32_t z_off = sector->ceiling.tilt >> 8;
const int32_t x_off = (int8_t)sector->ceiling.tilt;

if (Camera_IsChunky() && (ABS(z_off) > 2 || ABS(x_off) > 2)) {
return height;
}

if (z_off < 0) {
height += (int16_t)NEG_TILT(z_off, z);
} else {
height -= (int16_t)POS_TILT(z_off, z);
}

if (x_off < 0) {
height += (int16_t)POS_TILT(x_off, x);
} else {
height -= (int16_t)NEG_TILT(x_off, x);
}

return height;
}

void Room_InitialiseRooms(const int32_t num_rooms)
{
m_RoomCount = num_rooms;
Expand Down Expand Up @@ -416,3 +487,107 @@ SECTOR *Room_GetUnitSector(
{
return &room->sectors[z_sector + x_sector * room->size.z];
}

SECTOR *Room_GetPitSector(
const SECTOR *sector, const int32_t x, const int32_t z)
{
while (sector->portal_room.pit != NO_ROOM) {
const ROOM *const room = Room_Get(sector->portal_room.pit);
sector = Room_GetWorldSector(room, x, z);
}

return (SECTOR *)sector;
}

SECTOR *Room_GetSkySector(
const SECTOR *sector, const int32_t x, const int32_t z)
{
while (sector->portal_room.sky != NO_ROOM) {
const ROOM *const room = Room_Get(sector->portal_room.sky);
sector = Room_GetWorldSector(room, x, z);
}

return (SECTOR *)sector;
}

void Room_SetAbyssHeight(const int16_t height)
{
// Once Lara reaches the min abyss height, she will be killed; she will
// continue to fall however, so the max height is needed until the inventory
// is shown, otherwise Lara will hit the floor.
m_AbyssMinHeight = height;
m_AbyssMaxHeight = height == 0 ? 0 : m_AbyssMinHeight + 26 * STEP_L;
CLAMPG(m_AbyssMaxHeight, MAX_HEIGHT - STEP_L);
}

bool Room_IsAbyssHeight(const int16_t height)
{
return m_AbyssMinHeight != 0 && height >= m_AbyssMinHeight;
}

HEIGHT_TYPE Room_GetHeightType(void)
{
return m_HeightType;
}

int16_t Room_GetHeight(
const SECTOR *sector, const int32_t x, const int32_t y, const int32_t z)
{
m_HeightType = HT_WALL;

const SECTOR *const pit_sector = Room_GetPitSector(sector, x, z);
int32_t height = pit_sector->floor.height;

if (Room_IsAbyssHeight(height)) {
height = m_AbyssMaxHeight;
} else {
height = M_GetFloorTiltHeight(pit_sector, x, z);
}

if (pit_sector->trigger == nullptr) {
return height;
}

const TRIGGER_CMD *cmd = pit_sector->trigger->command;
for (; cmd != nullptr; cmd = cmd->next_cmd) {
if (cmd->type != TO_OBJECT) {
continue;
}

const ITEM *const item = Item_Get((int16_t)(intptr_t)cmd->parameter);
const OBJECT *const obj = Object_Get(item->object_id);
if (obj->floor_height_func != nullptr) {
height = obj->floor_height_func(item, x, y, z, height);
}
}

return height;
}

int16_t Room_GetCeiling(
const SECTOR *const sector, const int32_t x, const int32_t y,
const int32_t z)
{
const SECTOR *const sky_sector = Room_GetSkySector(sector, x, z);
int16_t height = M_GetCeilingTiltHeight(sky_sector, x, z);

const SECTOR *const pit_sector = Room_GetPitSector(sector, x, z);
if (pit_sector->trigger == nullptr) {
return height;
}

const TRIGGER_CMD *cmd = pit_sector->trigger->command;
for (; cmd != nullptr; cmd = cmd->next_cmd) {
if (cmd->type != TO_OBJECT) {
continue;
}

const ITEM *const item = Item_Get((int16_t)(intptr_t)cmd->parameter);
const OBJECT *const obj = Object_Get(item->object_id);
if (obj->ceiling_height_func != nullptr) {
height = obj->ceiling_height_func(item, x, y, z, height);
}
}

return height;
}
2 changes: 1 addition & 1 deletion src/libtrx/include/libtrx/game/enum_map.def
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_ADD_ITEM, "give_item")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_WEAPONS, "remove_weapons")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_AMMO, "remove_ammo")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_MEDIPACKS, "remove_medipacks")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_DISABLE_FLOOR, "disable_floor")
#if TR_VERSION == 1
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_SCIONS, "remove_scions")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_MESH_SWAP, "mesh_swap")
Expand All @@ -88,7 +89,6 @@ ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_REMOVE_FLARES, "remove_flares")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_ENABLE_SUNSET, "enable_sunset")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_SET_NUM_SECRETS, "set_secret_count")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_SET_START_ANIM, "set_lara_start_anim")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_DISABLE_FLOOR, "disable_floor")
ENUM_MAP_DEFINE(GF_SEQUENCE_EVENT_TYPE, GFS_ADD_SECRET_REWARD, "add_secret_reward")
#endif

Expand Down
2 changes: 1 addition & 1 deletion src/libtrx/include/libtrx/game/game_flow/enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ typedef enum {
GFS_REMOVE_WEAPONS,
GFS_REMOVE_AMMO,
GFS_REMOVE_MEDIPACKS,
GFS_DISABLE_FLOOR,
#if TR_VERSION == 1
GFS_REMOVE_SCIONS,
GFS_FLIP_MAP,
Expand All @@ -82,7 +83,6 @@ typedef enum {
GFS_REMOVE_FLARES,
GFS_SET_START_ANIM,
GFS_SET_NUM_SECRETS,
GFS_DISABLE_FLOOR,
GFS_ENABLE_SUNSET,
GFS_ADD_SECRET_REWARD,
#endif
Expand Down
8 changes: 8 additions & 0 deletions src/libtrx/include/libtrx/game/rooms/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ BOUNDS_32 Room_GetWorldBounds(void);
SECTOR *Room_GetWorldSector(const ROOM *room, int32_t x_pos, int32_t z_pos);
SECTOR *Room_GetUnitSector(
const ROOM *room, int32_t x_sector, int32_t z_sector);
SECTOR *Room_GetPitSector(const SECTOR *sector, int32_t x, int32_t z);
SECTOR *Room_GetSkySector(const SECTOR *sector, int32_t x, int32_t z);

void Room_SetAbyssHeight(int16_t height);
bool Room_IsAbyssHeight(int16_t height);
HEIGHT_TYPE Room_GetHeightType(void);
int16_t Room_GetHeight(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
int16_t Room_GetCeiling(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
6 changes: 6 additions & 0 deletions src/libtrx/include/libtrx/game/rooms/enum.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#pragma once

typedef enum {
HT_WALL = 0,
HT_SMALL_SLOPE = 1,
HT_BIG_SLOPE = 2,
} HEIGHT_TYPE;

typedef enum {
RF_UNDERWATER = 0x01,
RF_OUTSIDE = 0x08,
Expand Down
8 changes: 4 additions & 4 deletions src/tr1/game/collide.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void Collide_GetCollisionInfo(

coll->mid_floor = height;
coll->mid_ceiling = ceiling;
coll->mid_type = g_HeightType;
coll->mid_type = Room_GetHeightType();

if (!g_Config.gameplay.fix_bridge_collision
|| !Room_IsOnWalkable(sector, x, ytop, z, room_height)) {
Expand Down Expand Up @@ -123,7 +123,7 @@ void Collide_GetCollisionInfo(

coll->front_floor = height;
coll->front_ceiling = ceiling;
coll->front_type = g_HeightType;
coll->front_type = Room_GetHeightType();

if (!g_Config.gameplay.fix_bridge_collision
|| !Room_IsOnWalkable(sector, x, ytop, z, room_height)) {
Expand Down Expand Up @@ -158,7 +158,7 @@ void Collide_GetCollisionInfo(

coll->left_floor = height;
coll->left_ceiling = ceiling;
coll->left_type = g_HeightType;
coll->left_type = Room_GetHeightType();

if (!g_Config.gameplay.fix_bridge_collision
|| !Room_IsOnWalkable(sector, x, ytop, z, room_height)) {
Expand Down Expand Up @@ -193,7 +193,7 @@ void Collide_GetCollisionInfo(

coll->right_floor = height;
coll->right_ceiling = ceiling;
coll->right_type = g_HeightType;
coll->right_type = Room_GetHeightType();

if (!g_Config.gameplay.fix_bridge_collision
|| !Room_IsOnWalkable(sector, x, ytop, z, room_height)) {
Expand Down
14 changes: 13 additions & 1 deletion src/tr1/game/game_flow/sequencer_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ static DECLARE_GF_EVENT_HANDLER(M_HandlePlayMusic);
static DECLARE_GF_EVENT_HANDLER(M_HandleLevelComplete);
static DECLARE_GF_EVENT_HANDLER(M_HandleSetCameraPos);
static DECLARE_GF_EVENT_HANDLER(M_HandleSetCameraAngle);
static DECLARE_GF_EVENT_HANDLER(M_HandleDisableFloor);
static DECLARE_GF_EVENT_HANDLER(M_HandleFlipMap);
static DECLARE_GF_EVENT_HANDLER(M_HandleAddItem);
static DECLARE_GF_EVENT_HANDLER(M_HandleRemoveWeapons);
Expand All @@ -33,11 +34,12 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleSetupBaconLara);

static DECLARE_GF_EVENT_HANDLER((*m_EventHandlers[GFS_NUMBER_OF])) = {
// clang-format off
[GFS_LOOP_GAME] = M_HandlePlayLevel,
[GFS_LOOP_GAME] = M_HandlePlayLevel,
[GFS_PLAY_MUSIC] = M_HandlePlayMusic,
[GFS_LEVEL_COMPLETE] = M_HandleLevelComplete,
[GFS_SET_CAMERA_POS] = M_HandleSetCameraPos,
[GFS_SET_CAMERA_ANGLE] = M_HandleSetCameraAngle,
[GFS_DISABLE_FLOOR] = M_HandleDisableFloor,
[GFS_FLIP_MAP] = M_HandleFlipMap,
[GFS_ADD_ITEM] = M_HandleAddItem,
[GFS_REMOVE_WEAPONS] = M_HandleRemoveWeapons,
Expand Down Expand Up @@ -272,6 +274,15 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleSetCameraAngle)
return (GF_COMMAND) { .action = GF_NOOP };
}

static DECLARE_GF_EVENT_HANDLER(M_HandleDisableFloor)
{
GF_COMMAND gf_cmd = { .action = GF_NOOP };
if (seq_ctx != GFSC_STORY) {
Room_SetAbyssHeight((int16_t)(intptr_t)event->data);
}
return gf_cmd;
}

static DECLARE_GF_EVENT_HANDLER(M_HandleFlipMap)
{
if (seq_ctx != GFSC_STORY) {
Expand Down Expand Up @@ -349,6 +360,7 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleSetupBaconLara)
void GF_PreSequenceHook(
const GF_SEQUENCE_CONTEXT seq_ctx, void *const seq_ctx_arg)
{
Room_SetAbyssHeight(0);
g_GameInfo.remove_guns = false;
g_GameInfo.remove_scions = false;
g_GameInfo.remove_ammo = false;
Expand Down
3 changes: 3 additions & 0 deletions src/tr1/game/lara/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ void Lara_Control(void)
if (g_LaraItem->flags & IF_INVISIBLE) {
return;
}
} else if (Room_IsAbyssHeight(item->pos.y)) {
item->hit_points = -1;
g_Lara.death_timer = 9 * LOGIC_FPS;
}

Camera_MoveManual();
Expand Down
Loading