diff --git a/docs/GAME_FLOW.md b/docs/GAME_FLOW.md
index fe25e2ea1..24226714a 100644
--- a/docs/GAME_FLOW.md
+++ b/docs/GAME_FLOW.md
@@ -841,7 +841,7 @@ default game flow for examples.
- disable_floor ² |
+ disable_floor |
value |
Integer |
diff --git a/docs/tr1/CHANGELOG.md b/docs/tr1/CHANGELOG.md
index dea5a5b2d..228644cee 100644
--- a/docs/tr1/CHANGELOG.md
+++ b/docs/tr1/CHANGELOG.md
@@ -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)
diff --git a/docs/tr1/README.md b/docs/tr1/README.md
index da3a70707..d1570c335 100644
--- a/docs/tr1/README.md
+++ b/docs/tr1/README.md
@@ -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
diff --git a/src/libtrx/game/game_flow/reader_tr1.def.c b/src/libtrx/game/game_flow/reader_tr1.def.c
index 4ae7d8191..34944fe87 100644
--- a/src/libtrx/game/game_flow/reader_tr1.def.c
+++ b/src/libtrx/game/game_flow/reader_tr1.def.c
@@ -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 },
diff --git a/src/libtrx/game/rooms/common.c b/src/libtrx/game/rooms/common.c
index 7bb107ba6..a2fd63f9d 100644
--- a/src/libtrx/game/rooms/common.c
+++ b/src/libtrx/game/rooms/common.c
@@ -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"
@@ -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)
@@ -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;
@@ -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;
+}
diff --git a/src/libtrx/include/libtrx/game/enum_map.def b/src/libtrx/include/libtrx/game/enum_map.def
index 6d37d0ec5..48b3ac199 100644
--- a/src/libtrx/include/libtrx/game/enum_map.def
+++ b/src/libtrx/include/libtrx/game/enum_map.def
@@ -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")
@@ -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
diff --git a/src/libtrx/include/libtrx/game/game_flow/enum.h b/src/libtrx/include/libtrx/game/game_flow/enum.h
index 02e5bd561..4c51c5963 100644
--- a/src/libtrx/include/libtrx/game/game_flow/enum.h
+++ b/src/libtrx/include/libtrx/game/game_flow/enum.h
@@ -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,
@@ -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
diff --git a/src/libtrx/include/libtrx/game/rooms/common.h b/src/libtrx/include/libtrx/game/rooms/common.h
index be704fe11..43f483665 100644
--- a/src/libtrx/include/libtrx/game/rooms/common.h
+++ b/src/libtrx/include/libtrx/game/rooms/common.h
@@ -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);
diff --git a/src/libtrx/include/libtrx/game/rooms/enum.h b/src/libtrx/include/libtrx/game/rooms/enum.h
index 0f85e8799..8dcbab259 100644
--- a/src/libtrx/include/libtrx/game/rooms/enum.h
+++ b/src/libtrx/include/libtrx/game/rooms/enum.h
@@ -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,
diff --git a/src/tr1/game/collide.c b/src/tr1/game/collide.c
index b21f04adf..35c64fb16 100644
--- a/src/tr1/game/collide.c
+++ b/src/tr1/game/collide.c
@@ -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)) {
@@ -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)) {
@@ -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)) {
@@ -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)) {
diff --git a/src/tr1/game/game_flow/sequencer_events.c b/src/tr1/game/game_flow/sequencer_events.c
index d0ff9fc9d..00f66fced 100644
--- a/src/tr1/game/game_flow/sequencer_events.c
+++ b/src/tr1/game/game_flow/sequencer_events.c
@@ -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);
@@ -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,
@@ -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) {
@@ -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;
diff --git a/src/tr1/game/lara/common.c b/src/tr1/game/lara/common.c
index f5b91ac86..7897a9fab 100644
--- a/src/tr1/game/lara/common.c
+++ b/src/tr1/game/lara/common.c
@@ -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();
diff --git a/src/tr1/game/room.c b/src/tr1/game/room.c
index f223afa9e..56784c9e0 100644
--- a/src/tr1/game/room.c
+++ b/src/tr1/game/room.c
@@ -21,11 +21,6 @@
static void M_TriggerMusicTrack(int16_t track, const TRIGGER *const trigger);
-static int16_t M_GetFloorTiltHeight(
- const SECTOR *sector, const int32_t x, const int32_t z);
-static int16_t M_GetCeilingTiltHeight(
- const SECTOR *sector, const int32_t x, const int32_t z);
-static SECTOR *M_GetSkySector(const SECTOR *sector, int32_t x, int32_t z);
static bool M_TestLava(const ITEM *const item);
static void M_TriggerMusicTrack(int16_t track, const TRIGGER *const trigger)
@@ -162,28 +157,6 @@ void Room_GetNewRoom(int32_t x, int32_t y, int32_t z, int16_t room_num)
Room_MarkToBeDrawn(room_num);
}
-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;
-}
-
-static SECTOR *M_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;
-}
-
SECTOR *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num)
{
int16_t portal_room;
@@ -246,127 +219,6 @@ SECTOR *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num)
return sector;
}
-int16_t Room_GetCeiling(const SECTOR *sector, int32_t x, int32_t y, int32_t z)
-{
- int16_t *data;
- int16_t type;
- int16_t trigger;
-
- const SECTOR *const sky_sector = M_GetSkySector(sector, x, z);
- int16_t height = M_GetCeilingTiltHeight(sky_sector, x, z);
-
- sector = Room_GetPitSector(sector, x, z);
- if (sector->trigger == nullptr) {
- return height;
- }
-
- const TRIGGER_CMD *cmd = 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;
-}
-
-int16_t Room_GetHeight(const SECTOR *sector, int32_t x, int32_t y, int32_t z)
-{
- g_HeightType = HT_WALL;
- sector = Room_GetPitSector(sector, x, z);
-
- int16_t height = M_GetFloorTiltHeight(sector, x, z);
-
- if (sector->trigger == nullptr) {
- return height;
- }
-
- const TRIGGER_CMD *cmd = 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;
-}
-
-static int16_t M_GetFloorTiltHeight(
- const SECTOR *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;
- }
-
- g_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;
-}
-
int16_t Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num)
{
const ROOM *room = Room_Get(room_num);
@@ -459,7 +311,7 @@ void Room_AlterFloorHeight(const ITEM *const item, const int32_t height)
} while (portal_room != NO_ROOM);
const SECTOR *const sky_sector =
- M_GetSkySector(sector, item->pos.x, item->pos.z);
+ 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) {
diff --git a/src/tr1/game/room.h b/src/tr1/game/room.h
index c12aeb3d0..ab41fb4d7 100644
--- a/src/tr1/game/room.h
+++ b/src/tr1/game/room.h
@@ -13,9 +13,6 @@ void Room_GetNewRoom(int32_t x, int32_t y, int32_t z, int16_t room_num);
void Room_GetNearByRooms(
int32_t x, int32_t y, int32_t z, int32_t r, int32_t h, int16_t room_num);
SECTOR *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
-SECTOR *Room_GetPitSector(const SECTOR *sector, int32_t x, int32_t z);
-int16_t Room_GetCeiling(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
-int16_t Room_GetHeight(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
int16_t Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
void Room_TestTriggers(const ITEM *item);
diff --git a/src/tr1/global/types.h b/src/tr1/global/types.h
index 09505a9c4..316a4cdd8 100644
--- a/src/tr1/global/types.h
+++ b/src/tr1/global/types.h
@@ -58,12 +58,6 @@ typedef enum {
COLL_CLAMP = 32,
} COLL_TYPE;
-typedef enum {
- HT_WALL = 0,
- HT_SMALL_SLOPE = 1,
- HT_BIG_SLOPE = 2,
-} HEIGHT_TYPE;
-
typedef enum {
IC_BLACK = 0,
IC_GREY = 1,
diff --git a/src/tr1/global/vars.c b/src/tr1/global/vars.c
index 8d914491d..d15f20fdb 100644
--- a/src/tr1/global/vars.c
+++ b/src/tr1/global/vars.c
@@ -19,7 +19,6 @@ int32_t g_SavedGamesCount = 0;
int32_t g_SaveCounter = 0;
bool g_LevelComplete = false;
int32_t g_OverlayFlag = 0;
-int32_t g_HeightType = 0;
INVENTORY_MODE g_InvMode;
diff --git a/src/tr1/global/vars.h b/src/tr1/global/vars.h
index a2ee2ca45..b0d83e4e5 100644
--- a/src/tr1/global/vars.h
+++ b/src/tr1/global/vars.h
@@ -27,7 +27,6 @@ extern int32_t g_SavedGamesCount;
extern int32_t g_SaveCounter;
extern bool g_LevelComplete;
extern int32_t g_OverlayFlag;
-extern int32_t g_HeightType;
extern REQUEST_INFO g_SavegameRequester;
diff --git a/src/tr2/decomp/skidoo.c b/src/tr2/decomp/skidoo.c
index 045340d7a..5b511397f 100644
--- a/src/tr2/decomp/skidoo.c
+++ b/src/tr2/decomp/skidoo.c
@@ -559,7 +559,7 @@ int32_t Skidoo_CheckGetOffOK(int32_t direction)
const SECTOR *const sector = Room_GetSector(x, y, z, &room_num);
const int32_t height = Room_GetHeight(sector, x, y, z);
- if (g_HeightType == HT_BIG_SLOPE || height == NO_HEIGHT) {
+ if (Room_GetHeightType() == HT_BIG_SLOPE || height == NO_HEIGHT) {
return false;
}
diff --git a/src/tr2/game/collide.c b/src/tr2/game/collide.c
index 568e1b383..1aeeb5ae8 100644
--- a/src/tr2/game/collide.c
+++ b/src/tr2/game/collide.c
@@ -40,7 +40,7 @@ void Collide_GetCollisionInfo(
coll->side_mid.floor = height;
coll->side_mid.ceiling = ceiling;
- coll->side_mid.type = g_HeightType;
+ coll->side_mid.type = Room_GetHeightType();
const int16_t tilt = Room_GetTiltType(sector, x, g_LaraItem->pos.y, z);
coll->z_tilt = tilt >> 8;
@@ -113,7 +113,7 @@ void Collide_GetCollisionInfo(
coll->side_front.floor = height;
coll->side_front.ceiling = ceiling;
- coll->side_front.type = g_HeightType;
+ coll->side_front.type = Room_GetHeightType();
if (coll->slopes_are_walls && coll->side_front.type == HT_BIG_SLOPE
&& coll->side_front.floor < 0) {
coll->side_front.floor = -32767;
@@ -141,7 +141,7 @@ void Collide_GetCollisionInfo(
coll->side_left.floor = height;
coll->side_left.ceiling = ceiling;
- coll->side_left.type = g_HeightType;
+ coll->side_left.type = Room_GetHeightType();
if (coll->slopes_are_walls && coll->side_left.type == HT_BIG_SLOPE
&& coll->side_left.floor < 0) {
coll->side_left.floor = -32767;
@@ -169,7 +169,7 @@ void Collide_GetCollisionInfo(
coll->side_right.floor = height;
coll->side_right.ceiling = ceiling;
- coll->side_right.type = g_HeightType;
+ coll->side_right.type = Room_GetHeightType();
if (coll->slopes_are_walls && coll->side_right.type == HT_BIG_SLOPE
&& coll->side_right.floor < 0) {
coll->side_right.floor = -32767;
diff --git a/src/tr2/game/game_flow/sequencer_events.c b/src/tr2/game/game_flow/sequencer_events.c
index b8d1ca9e2..595a5b609 100644
--- a/src/tr2/game/game_flow/sequencer_events.c
+++ b/src/tr2/game/game_flow/sequencer_events.c
@@ -31,7 +31,7 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleSetNumSecrets);
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_ENABLE_SUNSET] = M_HandleEnableSunset,
@@ -200,7 +200,7 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleDisableFloor)
{
GF_COMMAND gf_cmd = { .action = GF_NOOP };
if (seq_ctx != GFSC_STORY) {
- g_GF_NoFloor = (int16_t)(intptr_t)event->data;
+ Room_SetAbyssHeight((int16_t)(intptr_t)event->data);
}
return gf_cmd;
}
@@ -262,7 +262,7 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleSetNumSecrets)
void GF_PreSequenceHook(
const GF_SEQUENCE_CONTEXT seq_ctx, void *const seq_ctx_arg)
{
- g_GF_NoFloor = 0;
+ Room_SetAbyssHeight(0);
Output_SetSunsetEnabled(false);
g_GF_LaraStartAnim = 0;
g_GF_RemoveAmmo = false;
diff --git a/src/tr2/game/lara/control.c b/src/tr2/game/lara/control.c
index 0d9e53592..702445db1 100644
--- a/src/tr2/game/lara/control.c
+++ b/src/tr2/game/lara/control.c
@@ -633,7 +633,7 @@ void Lara_Control(const int16_t item_num)
g_Lara.death_timer++;
return;
}
- } else if (g_GF_NoFloor && item->pos.y >= g_GF_NoFloor) {
+ } else if (Room_IsAbyssHeight(item->pos.y)) {
item->hit_points = -1;
g_Lara.death_timer = 9 * FRAMES_PER_SECOND;
}
diff --git a/src/tr2/game/objects/general/movable_block.c b/src/tr2/game/objects/general/movable_block.c
index 5c3a63ca8..bf48ed9a4 100644
--- a/src/tr2/game/objects/general/movable_block.c
+++ b/src/tr2/game/objects/general/movable_block.c
@@ -103,7 +103,7 @@ static bool M_TestPush(
}
Room_GetHeight(sector, x, y, z);
- if (g_HeightType != HT_WALL) {
+ if (Room_GetHeightType() != HT_WALL) {
return false;
}
diff --git a/src/tr2/game/room.c b/src/tr2/game/room.c
index e9d5f7a62..d7c6ee006 100644
--- a/src/tr2/game/room.c
+++ b/src/tr2/game/room.c
@@ -20,77 +20,10 @@
#include
void Room_MarkToBeDrawn(int16_t room_num);
-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 void M_TriggerMusicTrack(int16_t track, const TRIGGER *trigger);
static bool M_TestLava(const ITEM *item);
-static int16_t M_GetFloorTiltHeight(
- const SECTOR *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;
- }
-
- g_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;
-}
-
static void M_TriggerMusicTrack(
const int16_t track, const TRIGGER *const trigger)
{
@@ -496,28 +429,6 @@ int16_t Room_GetTiltType(
return sector->floor.tilt;
}
-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;
-}
-
SECTOR *Room_GetSector(
const int32_t x, const int32_t y, const int32_t z, int16_t *const room_num)
{
@@ -636,40 +547,6 @@ int32_t Room_GetWaterHeight(
}
}
-int32_t Room_GetHeight(
- const SECTOR *sector, const int32_t x, const int32_t y, const int32_t z)
-{
- g_HeightType = 0;
-
- const SECTOR *const pit_sector = Room_GetPitSector(sector, x, z);
- int32_t height = pit_sector->floor.height;
-
- if (g_GF_NoFloor && g_GF_NoFloor == height) {
- height = 0x4000;
- } 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;
-}
-
void Room_TestTriggers(const ITEM *const item)
{
int16_t room_num = item->room_num;
@@ -679,34 +556,6 @@ void Room_TestTriggers(const ITEM *const item)
Room_TestSectorTrigger(item, sector);
}
-int32_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);
- int32_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;
-}
-
void Room_AlterFloorHeight(const ITEM *const item, const int32_t height)
{
int16_t room_num = item->room_num;
diff --git a/src/tr2/game/room.h b/src/tr2/game/room.h
index ecdda372d..460ec9732 100644
--- a/src/tr2/game/room.h
+++ b/src/tr2/game/room.h
@@ -15,13 +15,9 @@ int16_t Room_GetTiltType(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
// TODO: poor abstraction
void Room_InitCinematic(void);
-SECTOR *Room_GetPitSector(const SECTOR *sector, int32_t x, int32_t z);
-SECTOR *Room_GetSkySector(const SECTOR *sector, int32_t x, int32_t z);
SECTOR *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
int32_t Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
-int32_t Room_GetHeight(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
-int32_t Room_GetCeiling(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
void Room_TestTriggers(const ITEM *item);
void Room_TestSectorTrigger(const ITEM *item, const SECTOR *sector);
diff --git a/src/tr2/global/types_decomp.h b/src/tr2/global/types_decomp.h
index 0ebd67542..83949787c 100644
--- a/src/tr2/global/types_decomp.h
+++ b/src/tr2/global/types_decomp.h
@@ -232,12 +232,6 @@ typedef enum {
COLL_CLAMP = 0x20,
} COLL_TYPE;
-typedef enum {
- HT_WALL = 0,
- HT_SMALL_SLOPE = 1,
- HT_BIG_SLOPE = 2,
-} HEIGHT_TYPE;
-
typedef struct {
int32_t boat_turn;
int32_t left_fallspeed;
diff --git a/src/tr2/global/vars.c b/src/tr2/global/vars.c
index d5dfc9603..bda567bfd 100644
--- a/src/tr2/global/vars.c
+++ b/src/tr2/global/vars.c
@@ -64,7 +64,6 @@ LARA_INFO g_Lara;
ITEM *g_LaraItem = nullptr;
CREATURE *g_BaddieSlots = nullptr;
-int32_t g_HeightType;
bool g_CameraUnderwater;
char g_LevelFileName[256];
@@ -265,7 +264,6 @@ REQUEST_INFO g_SaveGameRequester = {
bool g_GF_RemoveAmmo = false;
bool g_GF_RemoveWeapons = false;
-int16_t g_GF_NoFloor = 0;
int16_t g_GF_NumSecrets = 3;
int32_t g_GF_LaraStartAnim;
int32_t g_GF_ScriptVersion;
diff --git a/src/tr2/global/vars.h b/src/tr2/global/vars.h
index d966f5411..8d7b5c582 100644
--- a/src/tr2/global/vars.h
+++ b/src/tr2/global/vars.h
@@ -64,7 +64,6 @@ extern SAVEGAME_INFO g_SaveGame;
extern LARA_INFO g_Lara;
extern ITEM *g_LaraItem;
extern CREATURE *g_BaddieSlots;
-extern int32_t g_HeightType;
extern bool g_CameraUnderwater;
extern char g_LevelFileName[256];
extern WEAPON_INFO g_Weapons[];
@@ -77,7 +76,6 @@ extern REQUEST_INFO g_SaveGameRequester;
extern bool g_GF_RemoveAmmo;
extern bool g_GF_RemoveWeapons;
-extern int16_t g_GF_NoFloor;
extern int16_t g_GF_NumSecrets;
extern int32_t g_GF_LaraStartAnim;
|