From 5de236b76e6e2f43fc1cc9a3c15816886f141f5f Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 14 Aug 2023 02:20:41 +1000 Subject: [PATCH 001/410] Prototype PointCollision class --- TombEngine/Game/collision/PointCollision.cpp | 266 +++++++++++++++++++ TombEngine/Game/collision/PointCollision.h | 67 +++++ TombEngine/Game/collision/collide_room.cpp | 230 +++++++++------- TombEngine/Game/collision/collide_room.h | 4 + TombEngine/TombEngine.vcxproj | 2 + 5 files changed, 477 insertions(+), 92 deletions(-) create mode 100644 TombEngine/Game/collision/PointCollision.cpp create mode 100644 TombEngine/Game/collision/PointCollision.h diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp new file mode 100644 index 000000000..6b95ec912 --- /dev/null +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -0,0 +1,266 @@ +#include "framework.h" +#include "Game/collision/PointCollision.h" + +#include "Game/collision/collide_room.h" +#include "Game/collision/floordata.h" +#include "Game/items.h" +#include "Game/room.h" +#include "Math/Math.h" +#include "Specific/level.h" + +using namespace TEN::Collision::Floordata; +using namespace TEN::Math; + +namespace TEN::Collision +{ + PointCollision::PointCollision(const Vector3i& pos, int roomNumber) : + Position(pos), + RoomNumber(roomNumber) + { + } + + FloorInfo& PointCollision::nGetSector() + { + if (SectorPtr != nullptr) + return *SectorPtr; + + // Set current sector pointer. + short probedRoomNumber = RoomNumber; + auto* sectorPtr = GetFloor(Position.x, Position.y, Position.z, &probedRoomNumber); + SectorPtr = sectorPtr; + + return *SectorPtr; + } + + FloorInfo& PointCollision::GetTopSector() + { + if (TopSectorPtr != nullptr) + return *TopSectorPtr; + + // Set top sector pointer. + auto* topSectorPtr = &nGetSector(); + while (topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z).has_value()) + { + auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); + auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->Room)]; + + topSectorPtr = GetSector(&room, Position.x - room.x, Position.z - room.z); + } + TopSectorPtr = topSectorPtr; + + return *TopSectorPtr; + } + + FloorInfo& PointCollision::GetBottomSector() + { + if (BottomSectorPtr != nullptr) + return *BottomSectorPtr; + + // Set bottom sector pointer. + auto* bottomSectorPtr = &nGetSector(); + while (bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z).has_value()) + { + auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); + auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->Room)]; + + bottomSectorPtr = GetSector(&room, Position.x - room.x, Position.z - room.z); + } + BottomSectorPtr = bottomSectorPtr; + + return *BottomSectorPtr; + } + + int PointCollision::nGetFloorHeight() + { + if (FloorHeight.has_value()) + return *FloorHeight; + + // Set floor height. + auto roomVector = ROOM_VECTOR{ SectorPtr->Room, Position.y }; + FloorHeight = GetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + + return *FloorHeight; + } + + int PointCollision::nGetCeilingHeight() + { + if (CeilingHeight.has_value()) + return *CeilingHeight; + + // Set ceiling height. + auto roomVector = ROOM_VECTOR{ SectorPtr->Room, Position.y }; + CeilingHeight = GetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + + return *CeilingHeight; + } + + Vector3 PointCollision::GetFloorNormal() + { + if (FloorNormal.has_value()) + return *FloorNormal; + + // Set floor normal. + auto floorTilt = GetBottomSector().GetSurfaceTilt(Position.x, Position.z, true); + auto floorNormal = GetSurfaceNormal(floorTilt, true); + FloorNormal = floorNormal; + + return *FloorNormal; + } + + Vector3 PointCollision::GetCeilingNormal() + { + if (CeilingNormal.has_value()) + return *CeilingNormal; + + // Set ceiling normal. + auto ceilingTilt = GetTopSector().GetSurfaceTilt(Position.x, Position.z, false); // TODO: Check GetTopSector(). + auto ceilingNormal = GetSurfaceNormal(ceilingTilt, false); + CeilingNormal = ceilingNormal; + + return *CeilingNormal; + } + + int PointCollision::GetBridgeItemNumber() + { + if (BridgeItemNumber.has_value()) + return *BridgeItemNumber; + + // Set bridge item number. + int floorHeight = nGetFloorHeight(); + int bridgItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false); + BridgeItemNumber = bridgItemNumber; + + return *BridgeItemNumber; + } + + float PointCollision::GetSplitAngle() + { + return GetBottomSector().FloorCollision.SplitAngle; + } + + int PointCollision::GetWaterSurfaceHeight() + { + if (WaterSurfaceHeight.has_value()) + return *WaterSurfaceHeight; + + // Set water surface height. + WaterSurfaceHeight = GetWaterSurface(Position.x, Position.y, Position.z, RoomNumber); + + return *WaterSurfaceHeight; + } + + int PointCollision::GetWaterTopHeight() + { + if (WaterTopHeight.has_value()) + return *WaterTopHeight; + + // Set water top height. + WaterTopHeight = GetWaterHeight(Position.x, Position.y, Position.z, RoomNumber); + + return *WaterTopHeight; + } + + int PointCollision::GetWaterBottomHeight() + { + if (WaterBottomHeight.has_value()) + return *WaterBottomHeight; + + // Set water bottom height. + WaterBottomHeight = GetWaterDepth(Position.x, Position.y, Position.z, RoomNumber); + + return *WaterBottomHeight; + } + + bool PointCollision::IsWall() + { + return ((nGetFloorHeight() == NO_HEIGHT) || (nGetCeilingHeight() == NO_HEIGHT)); + } + + bool PointCollision::IsFloorSlope() + { + // Get floor slope angle. + auto floorNormal = GetFloorNormal(); + auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); + + return (GetBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= SLIPPERY_FLOOR_SLOPE_ANGLE); + } + + bool PointCollision::IsCeilingSlope() + { + // Get ceiling slope angle. + auto ceilingNormal = GetCeilingNormal(); + auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); + + return (abs(slopeAngle) >= SLIPPERY_CEILING_SLOPE_ANGLE); + } + + bool PointCollision::IsDiagonalStep() + { + return GetBottomSector().IsSurfaceDiagonalStep(true); + } + + bool PointCollision::HasDiagonalSplit() + { + constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; + constexpr auto DIAGONAL_SPLIT_1 = 135.0f * RADIAN; + + return ((GetSplitAngle() == DIAGONAL_SPLIT_0) || (GetSplitAngle() == DIAGONAL_SPLIT_1)); + } + + bool PointCollision::HasFlippedDiagonalSplit() + { + constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; + + return (HasDiagonalSplit() && (GetSplitAngle() != DIAGONAL_SPLIT_0)); + } + + bool PointCollision::HasEnvironmentFlag(RoomEnvFlags envFlag) + { + const auto& room = g_Level.Rooms[RoomNumber]; + return ((room.flags & envFlag) == envFlag); + } + + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber) + { + return PointCollision(pos, roomNumber); + } + + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) + { + short tempRoomNumber = roomNumber; + const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); + + auto roomVector = ROOM_VECTOR{ sector.Room, pos.y }; + + auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); + int adjacentRoomNumber = GetRoom(roomVector, pos.x, probePos.y, pos.z).roomNumber; + return PointCollision(probePos, adjacentRoomNumber); + } + + PointCollision GetPointCollision(const ItemInfo& item) + { + return PointCollision(item.Pose.Position, item.RoomNumber); + } + + // TODO: Find cleaner solution. Constructing a room vector (sometimes dubbed "Location") + // on the spot for the player can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 + static ROOM_VECTOR GetEntityRoomVector(const ItemInfo& item) + { + if (item.IsLara()) + return item.Location; + + short tempRoomNumber = item.RoomNumber; + const auto& sector = *GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &tempRoomNumber); + + return ROOM_VECTOR{ sector.Room, item.Pose.Position.y }; + } + + PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) + { + auto roomVector = GetEntityRoomVector(item); + + auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); + int adjacentRoomNumber = GetRoom(roomVector, item.Pose.Position.x, probePos.y, item.Pose.Position.z).roomNumber; + return PointCollision(probePos, adjacentRoomNumber); + } +} diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h new file mode 100644 index 000000000..cf6b76c3b --- /dev/null +++ b/TombEngine/Game/collision/PointCollision.h @@ -0,0 +1,67 @@ +#pragma once +#include "Math/Math.h" + +enum RoomEnvFlags; +class FloorInfo; + +using namespace TEN::Math; + +namespace TEN::Collision +{ + class PointCollision + { + public: + // Members + const Vector3i Position = Vector3i::Zero; + const int RoomNumber = 0; + + private: + FloorInfo* SectorPtr = nullptr; + FloorInfo* TopSectorPtr = nullptr; + FloorInfo* BottomSectorPtr = nullptr; + + std::optional FloorHeight = std::nullopt; + std::optional CeilingHeight = std::nullopt; + std::optional FloorNormal = std::nullopt; + std::optional CeilingNormal = std::nullopt; + std::optional BridgeItemNumber = std::nullopt; + + std::optional WaterSurfaceHeight = std::nullopt; + std::optional WaterTopHeight = std::nullopt; + std::optional WaterBottomHeight = std::nullopt; + + public: + // Constructors + PointCollision(const Vector3i& pos, int roomNumber); + + // Getters + FloorInfo& nGetSector(); + FloorInfo& GetTopSector(); + FloorInfo& GetBottomSector(); + + int nGetFloorHeight(); + int nGetCeilingHeight(); + Vector3 GetFloorNormal(); + Vector3 GetCeilingNormal(); + int GetBridgeItemNumber(); + float GetSplitAngle(); + + int GetWaterSurfaceHeight(); + int GetWaterTopHeight(); + int GetWaterBottomHeight(); + + // Inquirers + bool IsWall(); + bool IsFloorSlope(); + bool IsCeilingSlope(); + bool IsDiagonalStep(); + bool HasDiagonalSplit(); + bool HasFlippedDiagonalSplit(); + bool HasEnvironmentFlag(RoomEnvFlags envFlag); + }; + + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber); + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); + PointCollision GetPointCollision(const ItemInfo& item); + PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); +} diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index f7b5f82da..3979e6ec9 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -4,6 +4,7 @@ #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/animation.h" #include "Game/Lara/lara.h" #include "Game/items.h" @@ -12,6 +13,7 @@ #include "Sound/sound.h" #include "Renderer/Renderer11.h" +using namespace TEN::Collision; using namespace TEN::Collision::Floordata; using namespace TEN::Math; using namespace TEN::Renderer; @@ -180,11 +182,26 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber) // Deprecated. CollisionResult GetCollision(int x, int y, int z, short roomNumber) { - auto room = roomNumber; - auto floor = GetFloor(x, y, z, &room); - auto result = GetCollision(floor, x, y, z); + auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); + + auto result = CollisionResult{}; + + result.Coordinates = pointColl.Position; + result.RoomNumber = pointColl.RoomNumber; + result.Block = &pointColl.nGetSector(); + result.BottomBlock = &pointColl.GetBottomSector(); + + result.Position.Floor = pointColl.nGetFloorHeight(); + result.Position.Ceiling = pointColl.nGetCeilingHeight(); + result.Position.Bridge = pointColl.GetBridgeItemNumber(); + result.Position.SplitAngle = pointColl.GetSplitAngle(); + result.Position.FloorSlope = pointColl.IsFloorSlope(); + result.Position.CeilingSlope = pointColl.IsCeilingSlope(); + result.Position.DiagonalStep = pointColl.IsDiagonalStep(); + + result.FloorTilt = result.BottomBlock->GetSurfaceTilt(x, z, true); + result.CeilingTilt = result.BottomBlock->GetSurfaceTilt(x, z, false); - result.RoomNumber = room; return result; } @@ -207,7 +224,7 @@ CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) // Return provided collision block into result as itself. result.Block = floor; - + // Floor and ceiling heights are borrowed directly from floordata. result.Position.Floor = GetFloorHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT); result.Position.Ceiling = GetCeilingHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT); @@ -1193,31 +1210,31 @@ void AlterFloorHeight(ItemInfo* item, int height) int GetWaterSurface(int x, int y, int z, short roomNumber) { - auto* room = &g_Level.Rooms[roomNumber]; - FloorInfo* floor = GetSector(room, x - room->x, z - room->z); + auto* roomPtr = &g_Level.Rooms[roomNumber]; + auto* sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); - if (TestEnvironment(ENV_FLAG_WATER, room)) + if (TestEnvironment(ENV_FLAG_WATER, roomPtr)) { - while (floor->GetRoomNumberAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetRoomNumberAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - room = &g_Level.Rooms[floor->GetRoomNumberAbove(x, y, z).value_or(floor->Room)]; - if (!TestEnvironment(ENV_FLAG_WATER, room)) - return (floor->GetSurfaceHeight(x, z, false)); + roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberAbove(x, y, z).value_or(sectorPtr->Room)]; + if (!TestEnvironment(ENV_FLAG_WATER, roomPtr)) + return (sectorPtr->GetSurfaceHeight(x, z, false)); - floor = GetSector(room, x - room->x, z - room->z); + sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); } return NO_HEIGHT; } else { - while (floor->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - room = &g_Level.Rooms[floor->GetRoomNumberBelow(x, y, z).value_or(floor->Room)]; - if (TestEnvironment(ENV_FLAG_WATER, room)) - return (floor->GetSurfaceHeight(x, z, true)); + roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberBelow(x, y, z).value_or(sectorPtr->Room)]; + if (TestEnvironment(ENV_FLAG_WATER, roomPtr)) + return (sectorPtr->GetSurfaceHeight(x, z, true)); - floor = GetSector(room, x - room->x, z - room->z); + sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); } } @@ -1231,81 +1248,93 @@ int GetWaterSurface(ItemInfo* item) int GetWaterDepth(int x, int y, int z, short roomNumber) { - FloorInfo* floor; - auto* room = &g_Level.Rooms[roomNumber]; + FloorInfo* sectorPtr = nullptr; + auto* roomPtr = &g_Level.Rooms[roomNumber]; - short roomIndex = NO_ROOM; + int adjoiningRoomNumber = NO_ROOM; do { - int zFloor = (z - room->z) / BLOCK(1); - int xFloor = (x - room->x) / BLOCK(1); + int xFloor = (x - roomPtr->x) / BLOCK(1); + int zFloor = (z - roomPtr->z) / BLOCK(1); if (zFloor <= 0) { zFloor = 0; if (xFloor < 1) + { xFloor = 1; - else if (xFloor > room->xSize - 2) - xFloor = room->xSize - 2; + } + else if (xFloor > (roomPtr->xSize - 2)) + { + xFloor = roomPtr->xSize - 2; + } } - else if (zFloor >= room->zSize - 1) + else if (zFloor >= (roomPtr->zSize - 1)) { - zFloor = room->zSize - 1; + zFloor = roomPtr->zSize - 1; if (xFloor < 1) + { xFloor = 1; - else if (xFloor > room->xSize - 2) - xFloor = room->xSize - 2; + } + else if (xFloor > (roomPtr->xSize - 2)) + { + xFloor = roomPtr->xSize - 2; + } } else if (xFloor < 0) - xFloor = 0; - else if (xFloor >= room->xSize) - xFloor = room->xSize - 1; - - floor = &room->floor[zFloor + xFloor * room->zSize]; - roomIndex = floor->WallPortal; - if (roomIndex != NO_ROOM) { - roomNumber = roomIndex; - room = &g_Level.Rooms[roomIndex]; + xFloor = 0; + } + else if (xFloor >= roomPtr->xSize) + { + xFloor = roomPtr->xSize - 1; + } + + sectorPtr = &roomPtr->floor[zFloor + (xFloor * roomPtr->zSize)]; + adjoiningRoomNumber = sectorPtr->WallPortal; + if (adjoiningRoomNumber != NO_ROOM) + { + roomNumber = adjoiningRoomNumber; + roomPtr = &g_Level.Rooms[adjoiningRoomNumber]; } } - while (roomIndex != NO_ROOM); + while (adjoiningRoomNumber != NO_ROOM); - if (TestEnvironment(ENV_FLAG_WATER, room) || - TestEnvironment(ENV_FLAG_SWAMP, room)) + if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || + TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { - while (floor->GetRoomNumberAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetRoomNumberAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - room = &g_Level.Rooms[floor->GetRoomNumberAbove(x, y, z).value_or(floor->Room)]; + roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberAbove(x, y, z).value_or(sectorPtr->Room)]; - if (!TestEnvironment(ENV_FLAG_WATER, room) && - !TestEnvironment(ENV_FLAG_SWAMP, room)) + if (!TestEnvironment(ENV_FLAG_WATER, roomPtr) && + !TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { - int waterHeight = floor->GetSurfaceHeight(x, z, false); - int floorHeight = GetCollision(floor, x, y, z).BottomBlock->GetSurfaceHeight(x, z, true); + int waterHeight = sectorPtr->GetSurfaceHeight(x, z, false); + int floorHeight = GetCollision(sectorPtr, x, y, z).BottomBlock->GetSurfaceHeight(x, z, true); return (floorHeight - waterHeight); } - floor = GetSector(room, x - room->x, z - room->z); + sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); } return DEEP_WATER; } else { - while (floor->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - room = &g_Level.Rooms[floor->GetRoomNumberBelow(x, y, z).value_or(floor->Room)]; + roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberBelow(x, y, z).value_or(sectorPtr->Room)]; - if (TestEnvironment(ENV_FLAG_WATER, room) || - TestEnvironment(ENV_FLAG_SWAMP, room)) + if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || + TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { - int waterHeight = floor->GetSurfaceHeight(x, z, true); - floor = GetFloor(x, y, z, &roomNumber); - return (GetFloorHeight(floor, x, y, z) - waterHeight); + int waterHeight = sectorPtr->GetSurfaceHeight(x, z, true); + sectorPtr = GetFloor(x, y, z, &roomNumber); + return (GetFloorHeight(sectorPtr, x, y, z) - waterHeight); } - floor = GetSector(room, x - room->x, z - room->z); + sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); } return NO_HEIGHT; @@ -1319,79 +1348,96 @@ int GetWaterDepth(ItemInfo* item) int GetWaterHeight(int x, int y, int z, short roomNumber) { - auto* room = &g_Level.Rooms[roomNumber]; - FloorInfo* floor; + FloorInfo* sectorPtr = nullptr; + auto* roomPtr = &g_Level.Rooms[roomNumber]; - short adjoiningRoom = NO_ROOM; + int adjoiningRoomNumber = NO_ROOM; do { - int xBlock = (x - room->x) / BLOCK(1); - int zBlock = (z - room->z) / BLOCK(1); + int xBlock = (x - roomPtr->x) / BLOCK(1); + int zBlock = (z - roomPtr->z) / BLOCK(1); if (zBlock <= 0) { zBlock = 0; if (xBlock < 1) + { xBlock = 1; - else if (xBlock > room->xSize - 2) - xBlock = room->xSize - 2; + } + else if (xBlock > (roomPtr->xSize - 2)) + { + xBlock = roomPtr->xSize - 2; + } } - else if (zBlock >= room->zSize - 1) + else if (zBlock >= (roomPtr->zSize - 1)) { - zBlock = room->zSize - 1; + zBlock = roomPtr->zSize - 1; if (xBlock < 1) + { xBlock = 1; - else if (xBlock > room->xSize - 2) - xBlock = room->xSize - 2; + } + else if (xBlock > (roomPtr->xSize - 2)) + { + xBlock = roomPtr->xSize - 2; + } } else if (xBlock < 0) - xBlock = 0; - else if (xBlock >= room->xSize) - xBlock = room->xSize - 1; - - floor = &room->floor[zBlock + xBlock * room->zSize]; - adjoiningRoom = floor->WallPortal; - - if (adjoiningRoom != NO_ROOM) { - roomNumber = adjoiningRoom; - room = &g_Level.Rooms[adjoiningRoom]; + xBlock = 0; + } + else if (xBlock >= roomPtr->xSize) + { + xBlock = roomPtr->xSize - 1; } - } while (adjoiningRoom != NO_ROOM); - if (floor->IsWall(x, z)) + sectorPtr = &roomPtr->floor[zBlock + (xBlock * roomPtr->zSize)]; + adjoiningRoomNumber = sectorPtr->WallPortal; + + if (adjoiningRoomNumber != NO_ROOM) + { + roomNumber = adjoiningRoomNumber; + roomPtr = &g_Level.Rooms[adjoiningRoomNumber]; + } + } + while (adjoiningRoomNumber != NO_ROOM); + + if (sectorPtr->IsWall(x, z)) return NO_HEIGHT; - if (TestEnvironment(ENV_FLAG_WATER, room) || - TestEnvironment(ENV_FLAG_SWAMP, room)) + if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || + TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { - while (floor->GetRoomNumberAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetRoomNumberAbove(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - auto* room = &g_Level.Rooms[floor->GetRoomNumberAbove(x, y, z).value_or(floor->Room)]; + auto* room = &g_Level.Rooms[sectorPtr->GetRoomNumberAbove(x, y, z).value_or(sectorPtr->Room)]; if (!TestEnvironment(ENV_FLAG_WATER, room) && !TestEnvironment(ENV_FLAG_SWAMP, room)) + { break; + } - floor = GetSector(room, x - room->x, z - room->z); + sectorPtr = GetSector(room, x - room->x, z - room->z); } - return GetCollision(floor, x, y, z).Block->GetSurfaceHeight(x, y, z, false); + return GetCollision(sectorPtr, x, y, z).Block->GetSurfaceHeight(x, y, z, false); } - else if (floor->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) + else if (sectorPtr->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - while (floor->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) { - auto* room2 = &g_Level.Rooms[floor->GetRoomNumberBelow(x, y, z).value_or(floor->Room)]; + auto* roomPtr2 = &g_Level.Rooms[sectorPtr->GetRoomNumberBelow(x, y, z).value_or(sectorPtr->Room)]; - if (TestEnvironment(ENV_FLAG_WATER, room2) || - TestEnvironment(ENV_FLAG_SWAMP, room2)) + if (TestEnvironment(ENV_FLAG_WATER, roomPtr2) || + TestEnvironment(ENV_FLAG_SWAMP, roomPtr2)) + { break; + } - floor = GetSector(room2, x - room2->x, z - room2->z); + sectorPtr = GetSector(roomPtr2, x - roomPtr2->x, z - roomPtr2->z); } - return GetCollision(floor, x, y, z).Block->GetSurfaceHeight(x, y, z, true); + return GetCollision(sectorPtr, x, y, z).Block->GetSurfaceHeight(x, y, z, true); } return NO_HEIGHT; diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index e13c8c6f3..5f286d8b9 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -13,6 +13,9 @@ constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBou constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound. constexpr auto COLLISION_CHECK_DISTANCE = BLOCK(8); +constexpr auto SLIPPERY_FLOOR_SLOPE_ANGLE = short(ANGLE(45.0f) * 0.75f); +constexpr auto SLIPPERY_CEILING_SLOPE_ANGLE = ANGLE(45.0f); + enum CollisionType { CT_NONE = 0, @@ -126,6 +129,7 @@ struct CollisionInfo [[nodiscard]] bool TestItemRoomCollisionAABB(ItemInfo* item); +// All deprecated. Use GetPointCollision() instead. CollisionResult GetCollision(const ItemInfo& item); CollisionResult GetCollision(ItemInfo* item); CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 0d5ad7b92..90c5d8dc8 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -323,6 +323,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -786,6 +787,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From de3ef5137863d916edc512dbcb54d493b6b16746 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 14 Aug 2023 02:28:54 +1000 Subject: [PATCH 002/410] Remove unneeded method --- TombEngine/Game/collision/PointCollision.cpp | 11 ++++------- TombEngine/Game/collision/PointCollision.h | 1 - 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 6b95ec912..1902b48e3 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -133,11 +133,6 @@ namespace TEN::Collision return *BridgeItemNumber; } - float PointCollision::GetSplitAngle() - { - return GetBottomSector().FloorCollision.SplitAngle; - } - int PointCollision::GetWaterSurfaceHeight() { if (WaterSurfaceHeight.has_value()) @@ -204,14 +199,16 @@ namespace TEN::Collision constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; constexpr auto DIAGONAL_SPLIT_1 = 135.0f * RADIAN; - return ((GetSplitAngle() == DIAGONAL_SPLIT_0) || (GetSplitAngle() == DIAGONAL_SPLIT_1)); + float splitAngle = GetBottomSector().FloorCollision.SplitAngle; + return ((splitAngle == DIAGONAL_SPLIT_0) || (splitAngle == DIAGONAL_SPLIT_1)); } bool PointCollision::HasFlippedDiagonalSplit() { constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; - return (HasDiagonalSplit() && (GetSplitAngle() != DIAGONAL_SPLIT_0)); + float splitAngle = GetBottomSector().FloorCollision.SplitAngle; + return (HasDiagonalSplit() && (splitAngle != DIAGONAL_SPLIT_0)); } bool PointCollision::HasEnvironmentFlag(RoomEnvFlags envFlag) diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index cf6b76c3b..327868692 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -44,7 +44,6 @@ namespace TEN::Collision Vector3 GetFloorNormal(); Vector3 GetCeilingNormal(); int GetBridgeItemNumber(); - float GetSplitAngle(); int GetWaterSurfaceHeight(); int GetWaterTopHeight(); From a0aa4548b3837399ff6cea6705fad9db615dc948 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 14 Aug 2023 02:52:30 +1000 Subject: [PATCH 003/410] Move function into namespace to avoid name clash --- TombEngine/Game/collision/PointCollision.cpp | 38 ++++++++++++------- TombEngine/Game/collision/PointCollision.h | 6 +-- TombEngine/Game/collision/collide_room.cpp | 1 + TombEngine/Game/control/box.cpp | 1 + TombEngine/Game/control/lot.cpp | 2 + TombEngine/Game/items.cpp | 3 +- TombEngine/Game/room.cpp | 19 ++++++---- TombEngine/Game/room.h | 6 ++- .../Objects/Generic/Doors/generic_doors.cpp | 1 + .../Objects/TR5/Entity/tr5_gladiator.cpp | 1 + .../Objects/TR5/Entity/tr5_roman_statue.cpp | 1 + .../Objects/TR5/Object/tr5_pushableblock.cpp | 1 + .../Objects/TR5/Shatter/tr5_smashobject.cpp | 2 + 13 files changed, 56 insertions(+), 26 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 1902b48e3..a3f140079 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -10,16 +10,28 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Math; +using namespace TEN::Room; namespace TEN::Collision { + // TEMP: Wrappers to avoid name clashes. + static std::optional WrapGetFloorHeight(const ROOM_VECTOR& roomVector, int x, int z) + { + return GetFloorHeight(roomVector, x, z); + } + + static std::optional WrapGetCeilingHeight(const ROOM_VECTOR& roomVector, int x, int z) + { + return GetCeilingHeight(roomVector, x, z); + } + PointCollision::PointCollision(const Vector3i& pos, int roomNumber) : Position(pos), RoomNumber(roomNumber) { } - FloorInfo& PointCollision::nGetSector() + FloorInfo& PointCollision::GetSector() { if (SectorPtr != nullptr) return *SectorPtr; @@ -38,13 +50,13 @@ namespace TEN::Collision return *TopSectorPtr; // Set top sector pointer. - auto* topSectorPtr = &nGetSector(); + auto* topSectorPtr = &GetSector(); while (topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z).has_value()) { auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->Room)]; - topSectorPtr = GetSector(&room, Position.x - room.x, Position.z - room.z); + topSectorPtr = TEN::Room::GetSector(&room, Position.x - room.x, Position.z - room.z); } TopSectorPtr = topSectorPtr; @@ -57,39 +69,39 @@ namespace TEN::Collision return *BottomSectorPtr; // Set bottom sector pointer. - auto* bottomSectorPtr = &nGetSector(); + auto* bottomSectorPtr = &GetSector(); while (bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z).has_value()) { auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->Room)]; - bottomSectorPtr = GetSector(&room, Position.x - room.x, Position.z - room.z); + bottomSectorPtr = TEN::Room::GetSector(&room, Position.x - room.x, Position.z - room.z); } BottomSectorPtr = bottomSectorPtr; return *BottomSectorPtr; } - int PointCollision::nGetFloorHeight() + int PointCollision::GetFloorHeight() { if (FloorHeight.has_value()) return *FloorHeight; // Set floor height. - auto roomVector = ROOM_VECTOR{ SectorPtr->Room, Position.y }; - FloorHeight = GetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + auto roomVector = ROOM_VECTOR{ GetSector().Room, Position.y }; + FloorHeight = WrapGetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); return *FloorHeight; } - int PointCollision::nGetCeilingHeight() + int PointCollision::GetCeilingHeight() { if (CeilingHeight.has_value()) return *CeilingHeight; // Set ceiling height. - auto roomVector = ROOM_VECTOR{ SectorPtr->Room, Position.y }; - CeilingHeight = GetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + auto roomVector = ROOM_VECTOR{ GetSector().Room, Position.y}; + CeilingHeight = WrapGetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); return *CeilingHeight; } @@ -126,7 +138,7 @@ namespace TEN::Collision return *BridgeItemNumber; // Set bridge item number. - int floorHeight = nGetFloorHeight(); + int floorHeight = GetFloorHeight(); int bridgItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false); BridgeItemNumber = bridgItemNumber; @@ -168,7 +180,7 @@ namespace TEN::Collision bool PointCollision::IsWall() { - return ((nGetFloorHeight() == NO_HEIGHT) || (nGetCeilingHeight() == NO_HEIGHT)); + return ((GetFloorHeight() == NO_HEIGHT) || (GetCeilingHeight() == NO_HEIGHT)); } bool PointCollision::IsFloorSlope() diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 327868692..fef3952d8 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -35,12 +35,12 @@ namespace TEN::Collision PointCollision(const Vector3i& pos, int roomNumber); // Getters - FloorInfo& nGetSector(); + FloorInfo& GetSector(); FloorInfo& GetTopSector(); FloorInfo& GetBottomSector(); - int nGetFloorHeight(); - int nGetCeilingHeight(); + int GetFloorHeight(); + int GetCeilingHeight(); Vector3 GetFloorNormal(); Vector3 GetCeilingNormal(); int GetBridgeItemNumber(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 3979e6ec9..bfc959d44 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -17,6 +17,7 @@ using namespace TEN::Collision; using namespace TEN::Collision::Floordata; using namespace TEN::Math; using namespace TEN::Renderer; +using namespace TEN::Room; void ShiftItem(ItemInfo* item, CollisionInfo* coll) { diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 37b44690d..e265e53eb 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -23,6 +23,7 @@ #include "Renderer/Renderer11.h" using namespace TEN::Effects::Smoke; +using namespace TEN::Room; constexpr auto ESCAPE_DIST = BLOCK(5); constexpr auto STALK_DIST = BLOCK(3); diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 66e06c183..373d70a76 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -10,6 +10,8 @@ #include "Game/Setup.h" #include "Specific/level.h" +using namespace TEN::Room; + #define DEFAULT_FLY_UPDOWN_SPEED 16 #define DEFAULT_SWIM_UPDOWN_SPEED 32 diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index e574205be..7bd42c6f7 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -21,11 +21,12 @@ #include "Specific/level.h" #include "Scripting/Internal/TEN/Objects/ObjectIDs.h" +using namespace TEN::Collision::Floordata; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Items; -using namespace TEN::Collision::Floordata; using namespace TEN::Input; using namespace TEN::Math; +using namespace TEN::Room; constexpr int ITEM_DEATH_TIMEOUT = 4 * FPS; diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index ebc8f615b..aef5da31e 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -159,16 +159,19 @@ int IsRoomOutside(int x, int y, int z) return NO_ROOM; } -FloorInfo* GetSector(ROOM_INFO* room, int x, int z) +namespace TEN::Room { - int sectorX = std::clamp(x / BLOCK(1), 0, room->xSize - 1); - int sectorZ = std::clamp(z / BLOCK(1), 0, room->zSize - 1); + FloorInfo* GetSector(ROOM_INFO* room, int x, int z) + { + int sectorX = std::clamp(x / BLOCK(1), 0, room->xSize - 1); + int sectorZ = std::clamp(z / BLOCK(1), 0, room->zSize - 1); - int index = sectorZ + sectorX * room->zSize; - if (index > room->floor.size()) - return nullptr; - - return &room->floor[index]; + int index = sectorZ + sectorX * room->zSize; + if (index > room->floor.size()) + return nullptr; + + return &room->floor[index]; + } } GameBoundingBox& GetBoundsAccurate(const MESH_INFO& mesh, bool visibility) diff --git a/TombEngine/Game/room.h b/TombEngine/Game/room.h index bb11ddc96..81a0570d0 100644 --- a/TombEngine/Game/room.h +++ b/TombEngine/Game/room.h @@ -155,4 +155,8 @@ std::set GetRoomList(int roomNumber); void InitializeNeighborRoomList(); GameBoundingBox& GetBoundsAccurate(const MESH_INFO& mesh, bool visibility); -FloorInfo* GetSector(ROOM_INFO* room, int x, int z); + +namespace TEN::Room +{ + FloorInfo* GetSector(ROOM_INFO* room, int x, int z); +} diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index ec0fd8d29..94f6f3769 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -25,6 +25,7 @@ using namespace TEN::Gui; using namespace TEN::Input; +using namespace TEN::Room; namespace TEN::Entities::Doors { diff --git a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp index 8b56bacc2..62efd7a60 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp @@ -16,6 +16,7 @@ #include "Specific/level.h" using namespace TEN::Math; +using namespace TEN::Room; namespace TEN::Entities::Creatures::TR5 { diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index 73be0c039..e94e48405 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -23,6 +23,7 @@ using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Spark; using namespace TEN::Math; +using namespace TEN::Room; namespace TEN::Entities::Creatures::TR5 { diff --git a/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp b/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp index fa4ecb2ae..aa629e109 100644 --- a/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp @@ -17,6 +17,7 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Input; +using namespace TEN::Room; namespace TEN::Entities::Generic { diff --git a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp index 8ff5953de..4ed96e273 100644 --- a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp +++ b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp @@ -6,6 +6,8 @@ #include "Game/effects/tomb4fx.h" #include "Game/items.h" +using namespace TEN::Room; + void InitializeSmashObject(short itemNumber) { auto* item = &g_Level.Items[itemNumber]; From cf4429f7d72c0959f17fbfe0b38c0972be0e13b0 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 14 Aug 2023 03:01:04 +1000 Subject: [PATCH 004/410] Update collide_room.cpp --- TombEngine/Game/collision/collide_room.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index bfc959d44..0be68e1e2 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -189,13 +189,13 @@ CollisionResult GetCollision(int x, int y, int z, short roomNumber) result.Coordinates = pointColl.Position; result.RoomNumber = pointColl.RoomNumber; - result.Block = &pointColl.nGetSector(); + result.Block = &pointColl.GetSector(); result.BottomBlock = &pointColl.GetBottomSector(); - result.Position.Floor = pointColl.nGetFloorHeight(); - result.Position.Ceiling = pointColl.nGetCeilingHeight(); + result.Position.Floor = pointColl.GetFloorHeight(); + result.Position.Ceiling = pointColl.GetCeilingHeight(); result.Position.Bridge = pointColl.GetBridgeItemNumber(); - result.Position.SplitAngle = pointColl.GetSplitAngle(); + result.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; result.Position.FloorSlope = pointColl.IsFloorSlope(); result.Position.CeilingSlope = pointColl.IsCeilingSlope(); result.Position.DiagonalStep = pointColl.IsDiagonalStep(); From ffe819e4a68bf5890d1a55c6dbedda74132a9c70 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 14 Aug 2023 18:39:02 +1000 Subject: [PATCH 005/410] Update methods --- TombEngine/Game/collision/PointCollision.cpp | 31 +++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index a3f140079..7531bb10a 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -112,9 +112,17 @@ namespace TEN::Collision return *FloorNormal; // Set floor normal. - auto floorTilt = GetBottomSector().GetSurfaceTilt(Position.x, Position.z, true); - auto floorNormal = GetSurfaceNormal(floorTilt, true); - FloorNormal = floorNormal; + if (GetBridgeItemNumber() != NO_ITEM) + { + // TODO: Get bridge normal. + FloorNormal = -Vector3::UnitY; + } + else + { + auto floorTilt = GetBottomSector().GetSurfaceTilt(Position.x, Position.z, true); + auto floorNormal = GetSurfaceNormal(floorTilt, true); + FloorNormal = floorNormal; + } return *FloorNormal; } @@ -125,9 +133,18 @@ namespace TEN::Collision return *CeilingNormal; // Set ceiling normal. - auto ceilingTilt = GetTopSector().GetSurfaceTilt(Position.x, Position.z, false); // TODO: Check GetTopSector(). - auto ceilingNormal = GetSurfaceNormal(ceilingTilt, false); - CeilingNormal = ceilingNormal; + if (GetBridgeItemNumber() != NO_ITEM) + { + // TODO: Get bridge normal. + CeilingNormal = Vector3::UnitY; + } + else + { + // TODO: Check GetTopSector(). + auto ceilingTilt = GetTopSector().GetSurfaceTilt(Position.x, Position.z, false); + auto ceilingNormal = GetSurfaceNormal(ceilingTilt, false); + CeilingNormal = ceilingNormal; + } return *CeilingNormal; } @@ -189,7 +206,7 @@ namespace TEN::Collision auto floorNormal = GetFloorNormal(); auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); - return (GetBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= SLIPPERY_FLOOR_SLOPE_ANGLE); + return ((GetBridgeItemNumber() == NO_ITEM) && (abs(slopeAngle) >= SLIPPERY_FLOOR_SLOPE_ANGLE)); } bool PointCollision::IsCeilingSlope() From 5433a11297a70355cd06796f5844f7a158713a7f Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 14 Aug 2023 19:26:59 +1000 Subject: [PATCH 006/410] Move RoomVector struct --- TombEngine/Game/Lara/lara.cpp | 4 +- TombEngine/Game/Lara/lara_helpers.cpp | 4 +- TombEngine/Game/Lara/lara_initialise.cpp | 4 +- TombEngine/Game/Lara/lara_tests.cpp | 8 +- TombEngine/Game/collision/PointCollision.cpp | 18 +-- TombEngine/Game/collision/collide_room.cpp | 40 +++---- TombEngine/Game/collision/collide_room.h | 1 - TombEngine/Game/collision/floordata.cpp | 110 +++++++++--------- TombEngine/Game/collision/floordata.h | 24 +++- TombEngine/Game/effects/bubble.cpp | 4 +- TombEngine/Game/items.h | 2 +- TombEngine/Game/savegame.cpp | 4 +- TombEngine/Renderer/Renderer11DrawMenu.cpp | 2 +- .../TEN/Objects/Moveable/MoveableObject.cpp | 2 +- TombEngine/Specific/newtypes.h | 6 - 15 files changed, 120 insertions(+), 113 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 0f95a18df..9608309f1 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -1186,9 +1186,9 @@ bool UpdateLaraRoom(ItemInfo* item, int height, int xOffset, int zOffset) item->Location = GetRoom(item->Location, item->Pose.Position.x, point.y, item->Pose.Position.z); item->Floor = GetFloorHeight(item->Location, item->Pose.Position.x, item->Pose.Position.z).value_or(NO_HEIGHT); - if (item->RoomNumber != item->Location.roomNumber) + if (item->RoomNumber != item->Location.RoomNumber) { - ItemNewRoom(item->Index, item->Location.roomNumber); + ItemNewRoom(item->Index, item->Location.RoomNumber); return true; } diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index ffd2da09f..75ed0e3d5 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -534,7 +534,7 @@ void HandlePlayerWetnessDrips(ItemInfo& item) for (auto& node : player.Effect.DripNodes) { auto pos = GetJointPosition(&item, jointIndex).ToVector3(); - int roomNumber = GetRoom(item.Location, pos.x, pos.y, pos.z).roomNumber; + int roomNumber = GetRoom(item.Location, pos.x, pos.y, pos.z).RoomNumber; jointIndex++; // Node underwater; set max wetness value. @@ -571,7 +571,7 @@ void HandlePlayerDiveBubbles(ItemInfo& item) for (auto& node : player.Effect.BubbleNodes) { auto pos = GetJointPosition(&item, jointIndex).ToVector3(); - int roomNumber = GetRoom(item.Location, pos.x, pos.y, pos.z).roomNumber; + int roomNumber = GetRoom(item.Location, pos.x, pos.y, pos.z).RoomNumber; jointIndex++; // Node inactive; continue. diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index e6cef9199..752b3a615 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -33,8 +33,8 @@ void InitializeLara(bool restore) LaraItem->Data = &Lara; LaraItem->Collidable = false; - LaraItem->Location.roomNumber = LaraItem->RoomNumber; - LaraItem->Location.yNumber = LaraItem->Pose.Position.y; + LaraItem->Location.RoomNumber = LaraItem->RoomNumber; + LaraItem->Location.Height = LaraItem->Pose.Position.y; Lara.Status.Air = LARA_AIR_MAX; Lara.Status.Exposure = LARA_EXPOSURE_MAX; diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 6e172c83c..6e3ab8e27 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -43,8 +43,8 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo int y = item->Pose.Position.y - coll->Setup.Height; // Get frontal collision data - auto frontLeft = GetCollision(item->Pose.Position.x + xl, y, item->Pose.Position.z + zl, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).roomNumber); - auto frontRight = GetCollision(item->Pose.Position.x + xr, y, item->Pose.Position.z + zr, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).roomNumber); + auto frontLeft = GetCollision(item->Pose.Position.x + xl, y, item->Pose.Position.z + zl, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).RoomNumber); + auto frontRight = GetCollision(item->Pose.Position.x + xr, y, item->Pose.Position.z + zr, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).RoomNumber); // If any of the frontal collision results intersects item bounds, return false, because there is material intersection. // This check helps to filter out cases when Lara is formally facing corner but ledge check returns true because probe distance is fixed. @@ -63,8 +63,8 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo int zf = phd_cos(coll->NearestLedgeAngle) * (coll->Setup.Radius * 1.2f); // Get floor heights at both points - auto left = GetCollision(item->Pose.Position.x + xf + xl, y, item->Pose.Position.z + zf + zl, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).roomNumber).Position.Floor; - auto right = GetCollision(item->Pose.Position.x + xf + xr, y, item->Pose.Position.z + zf + zr, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).roomNumber).Position.Floor; + auto left = GetCollision(item->Pose.Position.x + xf + xl, y, item->Pose.Position.z + zf + zl, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).RoomNumber).Position.Floor; + auto right = GetCollision(item->Pose.Position.x + xf + xr, y, item->Pose.Position.z + zf + zr, GetRoom(item->Location, item->Pose.Position.x, y, item->Pose.Position.z).RoomNumber).Position.Floor; // If specified, limit vertical search zone only to nearest height if (heightLimit && (abs(left - y) > CLICK(0.5f) || abs(right - y) > CLICK(0.5f))) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 7531bb10a..24709da29 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -15,12 +15,12 @@ using namespace TEN::Room; namespace TEN::Collision { // TEMP: Wrappers to avoid name clashes. - static std::optional WrapGetFloorHeight(const ROOM_VECTOR& roomVector, int x, int z) + static std::optional WrapGetFloorHeight(const RoomVector& roomVector, int x, int z) { return GetFloorHeight(roomVector, x, z); } - static std::optional WrapGetCeilingHeight(const ROOM_VECTOR& roomVector, int x, int z) + static std::optional WrapGetCeilingHeight(const RoomVector& roomVector, int x, int z) { return GetCeilingHeight(roomVector, x, z); } @@ -88,7 +88,7 @@ namespace TEN::Collision return *FloorHeight; // Set floor height. - auto roomVector = ROOM_VECTOR{ GetSector().Room, Position.y }; + auto roomVector = RoomVector(GetSector().Room, Position.y); FloorHeight = WrapGetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); return *FloorHeight; @@ -100,7 +100,7 @@ namespace TEN::Collision return *CeilingHeight; // Set ceiling height. - auto roomVector = ROOM_VECTOR{ GetSector().Room, Position.y}; + auto roomVector = RoomVector(GetSector().Room, Position.y); CeilingHeight = WrapGetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); return *CeilingHeight; @@ -256,10 +256,10 @@ namespace TEN::Collision short tempRoomNumber = roomNumber; const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); - auto roomVector = ROOM_VECTOR{ sector.Room, pos.y }; + auto roomVector = RoomVector(sector.Room, pos.y); auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(roomVector, pos.x, probePos.y, pos.z).roomNumber; + int adjacentRoomNumber = GetRoom(roomVector, pos.x, probePos.y, pos.z).RoomNumber; return PointCollision(probePos, adjacentRoomNumber); } @@ -270,7 +270,7 @@ namespace TEN::Collision // TODO: Find cleaner solution. Constructing a room vector (sometimes dubbed "Location") // on the spot for the player can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 - static ROOM_VECTOR GetEntityRoomVector(const ItemInfo& item) + static RoomVector GetEntityRoomVector(const ItemInfo& item) { if (item.IsLara()) return item.Location; @@ -278,7 +278,7 @@ namespace TEN::Collision short tempRoomNumber = item.RoomNumber; const auto& sector = *GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &tempRoomNumber); - return ROOM_VECTOR{ sector.Room, item.Pose.Position.y }; + return RoomVector(sector.Room, item.Pose.Position.y); } PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) @@ -286,7 +286,7 @@ namespace TEN::Collision auto roomVector = GetEntityRoomVector(item); auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(roomVector, item.Pose.Position.x, probePos.y, item.Pose.Position.z).roomNumber; + int adjacentRoomNumber = GetRoom(roomVector, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; return PointCollision(probePos, adjacentRoomNumber); } } diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 0be68e1e2..0b91a8356 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -142,10 +142,10 @@ CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, // TODO: Find cleaner solution. Constructing a Location for Lara on the spot can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 auto location = item->IsLara() ? item->Location : - ROOM_VECTOR{ GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &tempRoomNumber)->Room, item->Pose.Position.y }; + RoomVector(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &tempRoomNumber)->Room, item->Pose.Position.y); auto point = Geometry::TranslatePoint(item->Pose.Position, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(location, item->Pose.Position.x, point.y, item->Pose.Position.z).roomNumber; + int adjacentRoomNumber = GetRoom(location, item->Pose.Position.x, point.y, item->Pose.Position.z).RoomNumber; return GetCollision(point.x, point.y, point.z, adjacentRoomNumber); } @@ -153,10 +153,10 @@ CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { short tempRoomNumber = roomNumber; - auto location = ROOM_VECTOR{ GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y }; + auto location = RoomVector(GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y); auto point = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).roomNumber; + int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; return GetCollision(point.x, point.y, point.z, adjacentRoomNumber); } @@ -165,8 +165,8 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const EulerAng auto point = Geometry::TranslatePoint(pos, orient, dist); short tempRoomNumber = roomNumber; - auto location = ROOM_VECTOR{ GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y }; - int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).roomNumber; + auto location = RoomVector{ GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y }; + int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; return GetCollision(point.x, point.y, point.z, adjacentRoomNumber); } @@ -227,8 +227,8 @@ CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) result.Block = floor; // Floor and ceiling heights are borrowed directly from floordata. - result.Position.Floor = GetFloorHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT); - result.Position.Ceiling = GetCeilingHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT); + result.Position.Floor = GetFloorHeight(RoomVector(floor->Room, y), x, z).value_or(NO_HEIGHT); + result.Position.Ceiling = GetCeilingHeight(RoomVector(floor->Room, y), x, z).value_or(NO_HEIGHT); // Probe bottom collision block through portals. while (floor->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) @@ -377,19 +377,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } // Define generic variables used for later object-specific position test shifts. - ROOM_VECTOR tfLocation{}, tcLocation{}, lrfLocation{}, lrcLocation{}; + RoomVector tfLocation, tcLocation, lrfLocation, lrcLocation; int height, ceiling; // Parameter definition ends here, now process to actual collision tests... // HACK: when using SetPosition animcommand, item->RoomNumber does not immediately // update, but only at the end of control loop. This may cause bugs when Lara is - // climbing or vaulting ledges under slopes. Using Location->roomNumber solves - // these bugs, as it is updated immediately. But since Location->roomNumber is ONLY + // climbing or vaulting ledges under slopes. Using Location->RoomNumber solves + // these bugs, as it is updated immediately. But since Location->RoomNumber is ONLY // updated for Lara, we can't use it for all objects for now. In future, we should // either update Location field for all objects or use this value as it is now. - int realRoomNumber = doPlayerCollision ? item->Location.roomNumber : item->RoomNumber; + int realRoomNumber = doPlayerCollision ? item->Location.RoomNumber : item->RoomNumber; // TEST 1: TILT AND NEAREST LEDGE CALCULATION @@ -921,12 +921,12 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) float maxZ = ceil(ffpZ / BLOCK(1)) * BLOCK(1) + 1.0f; // Get front floor block - auto room = GetRoom(item->Location, ffpX, y, ffpZ).roomNumber; + auto room = GetRoom(item->Location, ffpX, y, ffpZ).RoomNumber; auto block = GetCollision(ffpX, y, ffpZ, room).Block; // Get front floor surface heights - auto floorHeight = GetFloorHeight(ROOM_VECTOR{ block->Room, y }, ffpX, ffpZ).value_or(NO_HEIGHT); - auto ceilingHeight = GetCeilingHeight(ROOM_VECTOR{ block->Room, y }, ffpX, ffpZ).value_or(NO_HEIGHT); + auto floorHeight = GetFloorHeight(RoomVector(block->Room, y), ffpX, ffpZ).value_or(NO_HEIGHT); + auto ceilingHeight = GetCeilingHeight(RoomVector(block->Room, y), ffpX, ffpZ).value_or(NO_HEIGHT); // If probe landed inside wall (i.e. both floor/ceiling heights are NO_HEIGHT), make a fake // ledge for algorithm to further succeed. @@ -951,7 +951,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) // g_Renderer.AddDebugSphere(Vector3(fpX, y, fpZ), 16, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); // Get true room number and block, based on derived height - room = GetRoom(item->Location, fpX, height, fpZ).roomNumber; + room = GetRoom(item->Location, fpX, height, fpZ).RoomNumber; block = GetCollision(fpX, height, fpZ, room).Block; // We don't need actual corner heights to build planes, so just use normalized value here. @@ -1150,19 +1150,19 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) FloorInfo* GetFloor(int x, int y, int z, short* roomNumber) { - const auto location = GetRoom(ROOM_VECTOR{ *roomNumber, y }, x, y, z); - *roomNumber = location.roomNumber; + const auto location = GetRoom(RoomVector{ *roomNumber, y }, x, y, z); + *roomNumber = location.RoomNumber; return &GetFloor(*roomNumber, x, z); } int GetFloorHeight(FloorInfo* floor, int x, int y, int z) { - return GetFloorHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT); + return GetFloorHeight(RoomVector(floor->Room, y), x, z).value_or(NO_HEIGHT); } int GetCeiling(FloorInfo* floor, int x, int y, int z) { - return GetCeilingHeight(ROOM_VECTOR{ floor->Room, y }, x, z).value_or(NO_HEIGHT); + return GetCeilingHeight(RoomVector(floor->Room, y), x, z).value_or(NO_HEIGHT); } int GetDistanceToFloor(int itemNumber, bool precise) diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 5f286d8b9..74cd6fd0e 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -172,4 +172,3 @@ bool TestEnvironment(RoomEnvFlags environmentType, ItemInfo* item); bool TestEnvironment(RoomEnvFlags environmentType, int roomNumber); bool TestEnvironment(RoomEnvFlags environmentType, ROOM_INFO* room); bool TestEnvironmentFlags(RoomEnvFlags environmentType, int flags); - diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index cbe2cdbbc..b03d921d3 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -484,15 +484,15 @@ namespace TEN::Collision::Floordata return pos.y; } - std::optional GetFloorHeight(const ROOM_VECTOR& location, int x, int z) + std::optional GetFloorHeight(const RoomVector& location, int x, int z) { - auto floor = &GetFloorSide(location.roomNumber, x, z); - auto y = location.yNumber; + auto floor = &GetFloorSide(location.RoomNumber, x, z); + auto y = location.Height; auto direction = 0; if (floor->IsWall(x, z)) { - floor = &GetTopFloor(location.roomNumber, x, z); + floor = &GetTopFloor(location.RoomNumber, x, z); if (!floor->IsWall(x, z)) { @@ -501,7 +501,7 @@ namespace TEN::Collision::Floordata } else { - floor = &GetBottomFloor(location.roomNumber, x, z); + floor = &GetBottomFloor(location.RoomNumber, x, z); if (!floor->IsWall(x, z)) { @@ -550,15 +550,15 @@ namespace TEN::Collision::Floordata return std::optional{floor->GetSurfaceHeight(x, y, z, true)}; } - std::optional GetCeilingHeight(const ROOM_VECTOR& location, int x, int z) + std::optional GetCeilingHeight(const RoomVector& location, int x, int z) { - auto floor = &GetFloorSide(location.roomNumber, x, z); - auto y = location.yNumber; + auto floor = &GetFloorSide(location.RoomNumber, x, z); + auto y = location.Height; auto direction = 0; if (floor->IsWall(x, z)) { - floor = &GetBottomFloor(location.roomNumber, x, z); + floor = &GetBottomFloor(location.RoomNumber, x, z); if (!floor->IsWall(x, z)) { @@ -567,7 +567,7 @@ namespace TEN::Collision::Floordata } else { - floor = &GetTopFloor(location.roomNumber, x, z); + floor = &GetTopFloor(location.RoomNumber, x, z); if (!floor->IsWall(x, z)) { @@ -616,131 +616,131 @@ namespace TEN::Collision::Floordata return std::optional{floor->GetSurfaceHeight(x, y, z, false)}; } - std::optional GetBottomRoom(ROOM_VECTOR location, int x, int y, int z) + std::optional GetBottomRoom(RoomVector location, int x, int y, int z) { - auto floor = &GetFloorSide(location.roomNumber, x, z, &location.roomNumber); + auto floor = &GetFloorSide(location.RoomNumber, x, z, &location.RoomNumber); if (floor->IsWall(x, z)) { - floor = &GetBottomFloor(location.roomNumber, x, z, &location.roomNumber); + floor = &GetBottomFloor(location.RoomNumber, x, z, &location.RoomNumber); if (floor->IsWall(x, z)) return std::nullopt; - location.yNumber = floor->GetSurfaceHeight(x, z, false); + location.Height = floor->GetSurfaceHeight(x, z, false); } - auto floorHeight = floor->GetSurfaceHeight(x, location.yNumber, z, true); - auto ceilingHeight = floor->GetSurfaceHeight(x, location.yNumber, z, false); + auto floorHeight = floor->GetSurfaceHeight(x, location.Height, z, true); + auto ceilingHeight = floor->GetSurfaceHeight(x, location.Height, z, false); - location.yNumber = std::clamp(location.yNumber, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); + location.Height = std::clamp(location.Height, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); - if (floor->GetInsideBridgeItemNumber(x, location.yNumber, z, location.yNumber == ceilingHeight, location.yNumber == floorHeight) >= 0) + if (floor->GetInsideBridgeItemNumber(x, location.Height, z, location.Height == ceilingHeight, location.Height == floorHeight) >= 0) { - const auto height = GetBottomHeight(*floor, Vector3i(x, location.yNumber, z), &location.roomNumber, &floor); + const auto height = GetBottomHeight(*floor, Vector3i(x, location.Height, z), &location.RoomNumber, &floor); if (!height) return std::nullopt; - location.yNumber = *height; + location.Height = *height; } - floorHeight = floor->GetSurfaceHeight(x, location.yNumber, z, true); - ceilingHeight = floor->GetSurfaceHeight(x, location.yNumber, z, false); + floorHeight = floor->GetSurfaceHeight(x, location.Height, z, true); + ceilingHeight = floor->GetSurfaceHeight(x, location.Height, z, false); - if (y < ceilingHeight && floor->GetRoomNumberAbove(x, location.yNumber, z)) + if (y < ceilingHeight && floor->GetRoomNumberAbove(x, location.Height, z)) return std::nullopt; if (y <= floorHeight) { - location.yNumber = std::max(y, ceilingHeight); + location.Height = std::max(y, ceilingHeight); return std::optional{location}; } - auto roomBelow = floor->GetRoomNumberBelow(x, location.yNumber, z); + auto roomBelow = floor->GetRoomNumberBelow(x, location.Height, z); while (roomBelow) { - floor = &GetFloorSide(*roomBelow, x, z, &location.roomNumber); - location.yNumber = floor->GetSurfaceHeight(x, z, false); + floor = &GetFloorSide(*roomBelow, x, z, &location.RoomNumber); + location.Height = floor->GetSurfaceHeight(x, z, false); - floorHeight = floor->GetSurfaceHeight(x, location.yNumber, z, true); - ceilingHeight = floor->GetSurfaceHeight(x, location.yNumber, z, false); + floorHeight = floor->GetSurfaceHeight(x, location.Height, z, true); + ceilingHeight = floor->GetSurfaceHeight(x, location.Height, z, false); - if (y < ceilingHeight && floor->GetRoomNumberAbove(x, location.yNumber, z)) + if (y < ceilingHeight && floor->GetRoomNumberAbove(x, location.Height, z)) return std::nullopt; if (y <= floorHeight) { - location.yNumber = std::max(y, ceilingHeight); + location.Height = std::max(y, ceilingHeight); return std::optional{location}; } - roomBelow = floor->GetRoomNumberBelow(x, location.yNumber, z); + roomBelow = floor->GetRoomNumberBelow(x, location.Height, z); } return std::nullopt; } - std::optional GetTopRoom(ROOM_VECTOR location, int x, int y, int z) + std::optional GetTopRoom(RoomVector location, int x, int y, int z) { - auto floor = &GetFloorSide(location.roomNumber, x, z, &location.roomNumber); + auto floor = &GetFloorSide(location.RoomNumber, x, z, &location.RoomNumber); if (floor->IsWall(x, z)) { - floor = &GetTopFloor(location.roomNumber, x, z, &location.roomNumber); + floor = &GetTopFloor(location.RoomNumber, x, z, &location.RoomNumber); if (floor->IsWall(x, z)) return std::nullopt; - location.yNumber = floor->GetSurfaceHeight(x, z, true); + location.Height = floor->GetSurfaceHeight(x, z, true); } - auto floorHeight = floor->GetSurfaceHeight(x, location.yNumber, z, true); - auto ceilingHeight = floor->GetSurfaceHeight(x, location.yNumber, z, false); + auto floorHeight = floor->GetSurfaceHeight(x, location.Height, z, true); + auto ceilingHeight = floor->GetSurfaceHeight(x, location.Height, z, false); - location.yNumber = std::clamp(location.yNumber, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); + location.Height = std::clamp(location.Height, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); - if (floor->GetInsideBridgeItemNumber(x, location.yNumber, z, location.yNumber == ceilingHeight, location.yNumber == floorHeight) >= 0) + if (floor->GetInsideBridgeItemNumber(x, location.Height, z, location.Height == ceilingHeight, location.Height == floorHeight) >= 0) { - const auto height = GetTopHeight(*floor, Vector3i(x, location.yNumber, z), &location.roomNumber, &floor); + const auto height = GetTopHeight(*floor, Vector3i(x, location.Height, z), &location.RoomNumber, &floor); if (!height) return std::nullopt; - location.yNumber = *height; + location.Height = *height; } - floorHeight = floor->GetSurfaceHeight(x, location.yNumber, z, true); - ceilingHeight = floor->GetSurfaceHeight(x, location.yNumber, z, false); + floorHeight = floor->GetSurfaceHeight(x, location.Height, z, true); + ceilingHeight = floor->GetSurfaceHeight(x, location.Height, z, false); - if (y > floorHeight && floor->GetRoomNumberBelow(x, location.yNumber, z)) + if (y > floorHeight && floor->GetRoomNumberBelow(x, location.Height, z)) return std::nullopt; if (y >= ceilingHeight) { - location.yNumber = std::min(y, floorHeight); + location.Height = std::min(y, floorHeight); return std::optional{location}; } - auto roomAbove = floor->GetRoomNumberAbove(x, location.yNumber, z); + auto roomAbove = floor->GetRoomNumberAbove(x, location.Height, z); while (roomAbove) { - floor = &GetFloorSide(*roomAbove, x, z, &location.roomNumber); - location.yNumber = floor->GetSurfaceHeight(x, z, true); + floor = &GetFloorSide(*roomAbove, x, z, &location.RoomNumber); + location.Height = floor->GetSurfaceHeight(x, z, true); - floorHeight = floor->GetSurfaceHeight(x, location.yNumber, z, true); - ceilingHeight = floor->GetSurfaceHeight(x, location.yNumber, z, false); + floorHeight = floor->GetSurfaceHeight(x, location.Height, z, true); + ceilingHeight = floor->GetSurfaceHeight(x, location.Height, z, false); - if (y > floorHeight && floor->GetRoomNumberBelow(x, location.yNumber, z)) + if (y > floorHeight && floor->GetRoomNumberBelow(x, location.Height, z)) return std::nullopt; if (y >= ceilingHeight) { - location.yNumber = std::min(y, floorHeight); + location.Height = std::min(y, floorHeight); return std::optional{location}; } - roomAbove = floor->GetRoomNumberAbove(x, location.yNumber, z); + roomAbove = floor->GetRoomNumberAbove(x, location.Height, z); } return std::nullopt; } - ROOM_VECTOR GetRoom(ROOM_VECTOR location, int x, int y, int z) + RoomVector GetRoom(RoomVector location, int x, int y, int z) { const auto locationBelow = GetBottomRoom(location, x, y, z); if (locationBelow) diff --git a/TombEngine/Game/collision/floordata.h b/TombEngine/Game/collision/floordata.h index 90ba4f368..77ee59ebc 100644 --- a/TombEngine/Game/collision/floordata.h +++ b/TombEngine/Game/collision/floordata.h @@ -55,6 +55,20 @@ enum class ClimbDirectionFlags West = (1 << 11) }; +struct RoomVector +{ + int RoomNumber = 0; + int Height = 0; + + RoomVector() {}; + + RoomVector(int roomNumber, int height) + { + RoomNumber = roomNumber; + Height = height; + } +}; + struct SurfaceCollisionData { private: @@ -174,12 +188,12 @@ namespace TEN::Collision::Floordata std::optional GetTopHeight(FloorInfo& startSector, Vector3i pos, int* topRoomNumberPtr = nullptr, FloorInfo** topSectorPtr = nullptr); std::optional GetBottomHeight(FloorInfo& startSector, Vector3i pos, int* bottomRoomNumberPtr = nullptr, FloorInfo** bottomSectorPtr = nullptr); - std::optional GetFloorHeight(const ROOM_VECTOR& location, int x, int z); - std::optional GetCeilingHeight(const ROOM_VECTOR& location, int x, int z); + std::optional GetFloorHeight(const RoomVector& location, int x, int z); + std::optional GetCeilingHeight(const RoomVector& location, int x, int z); - std::optional GetBottomRoom(ROOM_VECTOR location, int x, int y, int z); - std::optional GetTopRoom(ROOM_VECTOR location, int x, int y, int z); - ROOM_VECTOR GetRoom(ROOM_VECTOR location, int x, int y, int z); + std::optional GetBottomRoom(RoomVector location, int x, int y, int z); + std::optional GetTopRoom(RoomVector location, int x, int y, int z); + RoomVector GetRoom(RoomVector location, int x, int y, int z); void AddBridge(int itemNumber, int x = 0, int z = 0); void RemoveBridge(int itemNumber, int x = 0, int z = 0); diff --git a/TombEngine/Game/effects/bubble.cpp b/TombEngine/Game/effects/bubble.cpp index a8d78e761..3bf53d479 100644 --- a/TombEngine/Game/effects/bubble.cpp +++ b/TombEngine/Game/effects/bubble.cpp @@ -148,8 +148,8 @@ namespace TEN::Effects::Bubble continue; // Update room number. TODO: Should use GetCollision(), but calling it for each bubble is very inefficient. - auto roomVector = ROOM_VECTOR{ bubble.RoomNumber, int(bubble.Position.y - bubble.Gravity) }; - int roomNumber = GetRoom(roomVector, bubble.Position.x, bubble.Position.y - bubble.Gravity, bubble.Position.z).roomNumber; + auto roomVector = RoomVector(bubble.RoomNumber, int(bubble.Position.y - bubble.Gravity)); + int roomNumber = GetRoom(roomVector, bubble.Position.x, bubble.Position.y - bubble.Gravity, bubble.Position.z).RoomNumber; int prevRoomNumber = bubble.RoomNumber; bubble.RoomNumber = roomNumber; diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index 2ac0bd5d7..a76821d15 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -125,7 +125,7 @@ struct ItemInfo Pose StartPose; Pose Pose; - ROOM_VECTOR Location; + RoomVector Location; short RoomNumber; int Floor; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index ebfe02372..ec8133a49 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -1555,8 +1555,8 @@ bool SaveGame::Load(int slot) { LaraItem->Data = nullptr; LaraItem = item; - LaraItem->Location.roomNumber = savedItem->room_number(); - LaraItem->Location.yNumber = item->Pose.Position.y; + LaraItem->Location.RoomNumber = savedItem->room_number(); + LaraItem->Location.Height = item->Pose.Position.y; LaraItem->Data = &Lara; } diff --git a/TombEngine/Renderer/Renderer11DrawMenu.cpp b/TombEngine/Renderer/Renderer11DrawMenu.cpp index 35f47267e..531c5e116 100644 --- a/TombEngine/Renderer/Renderer11DrawMenu.cpp +++ b/TombEngine/Renderer/Renderer11DrawMenu.cpp @@ -1125,7 +1125,7 @@ namespace TEN::Renderer PrintDebugMessage("Pos: %d %d %d", LaraItem->Pose.Position.x, LaraItem->Pose.Position.y, LaraItem->Pose.Position.z); PrintDebugMessage("Orient: %d %d %d", LaraItem->Pose.Orientation.x, LaraItem->Pose.Orientation.y, LaraItem->Pose.Orientation.z); PrintDebugMessage("RoomNumber: %d", LaraItem->RoomNumber); - PrintDebugMessage("Location: %d %d", LaraItem->Location.roomNumber, LaraItem->Location.yNumber); + PrintDebugMessage("Location: %d %d", LaraItem->Location.RoomNumber, LaraItem->Location.Height); PrintDebugMessage("BoxNumber: %d", LaraItem->BoxNumber); PrintDebugMessage("WaterSurfaceDist: %d", Lara.Context.WaterSurfaceDist); PrintDebugMessage("Room: %d %d %d %d", r->x, r->z, r->x + r->xSize * BLOCK(1), r->z + r->zSize * BLOCK(1)); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 05568ed8e..71a4bf970 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -920,7 +920,7 @@ void Moveable::SetRoomNumber(int roomNumber) // or else camera won't be updated properly. if (m_item->IsLara()) - m_item->Location.roomNumber = roomNumber; + m_item->Location.RoomNumber = roomNumber; } } diff --git a/TombEngine/Specific/newtypes.h b/TombEngine/Specific/newtypes.h index 6881ae985..46712f3d0 100644 --- a/TombEngine/Specific/newtypes.h +++ b/TombEngine/Specific/newtypes.h @@ -2,12 +2,6 @@ #include "framework.h" #include "Renderer/Renderer11Enums.h" -struct ROOM_VECTOR -{ - int roomNumber; - int yNumber; -}; - struct POLYGON { int shape; From 210b24fb6d446c840a965d9a3cc3274ca819996b Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 15 Aug 2023 14:36:03 +1000 Subject: [PATCH 007/410] Remove wrappers; simplify --- TombEngine/Game/collision/PointCollision.cpp | 29 +++++--------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 24709da29..82c379234 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -14,17 +14,6 @@ using namespace TEN::Room; namespace TEN::Collision { - // TEMP: Wrappers to avoid name clashes. - static std::optional WrapGetFloorHeight(const RoomVector& roomVector, int x, int z) - { - return GetFloorHeight(roomVector, x, z); - } - - static std::optional WrapGetCeilingHeight(const RoomVector& roomVector, int x, int z) - { - return GetCeilingHeight(roomVector, x, z); - } - PointCollision::PointCollision(const Vector3i& pos, int roomNumber) : Position(pos), RoomNumber(roomNumber) @@ -56,7 +45,7 @@ namespace TEN::Collision auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->Room)]; - topSectorPtr = TEN::Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + topSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); } TopSectorPtr = topSectorPtr; @@ -75,7 +64,7 @@ namespace TEN::Collision auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->Room)]; - bottomSectorPtr = TEN::Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + bottomSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); } BottomSectorPtr = bottomSectorPtr; @@ -89,7 +78,7 @@ namespace TEN::Collision // Set floor height. auto roomVector = RoomVector(GetSector().Room, Position.y); - FloorHeight = WrapGetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + FloorHeight = Floordata::GetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); return *FloorHeight; } @@ -101,7 +90,7 @@ namespace TEN::Collision // Set ceiling height. auto roomVector = RoomVector(GetSector().Room, Position.y); - CeilingHeight = WrapGetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + CeilingHeight = Floordata::GetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); return *CeilingHeight; } @@ -120,8 +109,7 @@ namespace TEN::Collision else { auto floorTilt = GetBottomSector().GetSurfaceTilt(Position.x, Position.z, true); - auto floorNormal = GetSurfaceNormal(floorTilt, true); - FloorNormal = floorNormal; + FloorNormal = GetSurfaceNormal(floorTilt, true); } return *FloorNormal; @@ -140,10 +128,8 @@ namespace TEN::Collision } else { - // TODO: Check GetTopSector(). auto ceilingTilt = GetTopSector().GetSurfaceTilt(Position.x, Position.z, false); - auto ceilingNormal = GetSurfaceNormal(ceilingTilt, false); - CeilingNormal = ceilingNormal; + CeilingNormal = GetSurfaceNormal(ceilingTilt, false); } return *CeilingNormal; @@ -156,8 +142,7 @@ namespace TEN::Collision // Set bridge item number. int floorHeight = GetFloorHeight(); - int bridgItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false); - BridgeItemNumber = bridgItemNumber; + BridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; return *BridgeItemNumber; } From 102d317b08fc8e2a3132148178411109db171d26 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 15 Aug 2023 14:41:19 +1000 Subject: [PATCH 008/410] Organise --- TombEngine/Game/collision/PointCollision.cpp | 15 +++++++-------- TombEngine/Game/collision/floordata.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 82c379234..02432df46 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -240,11 +240,10 @@ namespace TEN::Collision { short tempRoomNumber = roomNumber; const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); - - auto roomVector = RoomVector(sector.Room, pos.y); + auto location = RoomVector(sector.Room, pos.y); auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(roomVector, pos.x, probePos.y, pos.z).RoomNumber; + int adjacentRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; return PointCollision(probePos, adjacentRoomNumber); } @@ -253,9 +252,9 @@ namespace TEN::Collision return PointCollision(item.Pose.Position, item.RoomNumber); } - // TODO: Find cleaner solution. Constructing a room vector (sometimes dubbed "Location") - // on the spot for the player can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 - static RoomVector GetEntityRoomVector(const ItemInfo& item) + // TODO: Find cleaner solution. Constructing a "location" on the spot for the player + // can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 + static RoomVector GetEntityLocation(const ItemInfo& item) { if (item.IsLara()) return item.Location; @@ -268,10 +267,10 @@ namespace TEN::Collision PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) { - auto roomVector = GetEntityRoomVector(item); + auto location = GetEntityLocation(item); auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(roomVector, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; + int adjacentRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; return PointCollision(probePos, adjacentRoomNumber); } } diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index b03d921d3..f7e25a9f3 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -742,12 +742,12 @@ namespace TEN::Collision::Floordata RoomVector GetRoom(RoomVector location, int x, int y, int z) { - const auto locationBelow = GetBottomRoom(location, x, y, z); - if (locationBelow) + auto locationBelow = GetBottomRoom(location, x, y, z); + if (locationBelow.has_value()) return *locationBelow; - const auto locationAbove = GetTopRoom(location, x, y, z); - if (locationAbove) + auto locationAbove = GetTopRoom(location, x, y, z); + if (locationAbove.has_value()) return *locationAbove; return location; From d9e8275ca32adbb9a4b23bdc994e6e1d85a2b711 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 15 Aug 2023 14:48:11 +1000 Subject: [PATCH 009/410] Update namespace --- TombEngine/Game/collision/PointCollision.cpp | 2 +- TombEngine/Game/collision/collide_room.cpp | 2 +- TombEngine/Game/control/box.cpp | 2 +- TombEngine/Game/control/lot.cpp | 2 +- TombEngine/Game/items.cpp | 2 +- TombEngine/Game/room.cpp | 2 +- TombEngine/Game/room.h | 2 +- TombEngine/Objects/Generic/Doors/generic_doors.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp | 2 +- TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp | 2 +- TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 02432df46..f3cc63462 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -9,8 +9,8 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::Room; using namespace TEN::Math; -using namespace TEN::Room; namespace TEN::Collision { diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 0b91a8356..0af378f3c 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -15,9 +15,9 @@ using namespace TEN::Collision; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::Room; using namespace TEN::Math; using namespace TEN::Renderer; -using namespace TEN::Room; void ShiftItem(ItemInfo* item, CollisionInfo* coll) { diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index e265e53eb..9969554b5 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -22,8 +22,8 @@ #include "Objects/TR5/Object/tr5_pushableblock.h" #include "Renderer/Renderer11.h" +using namespace TEN::Collision::Room; using namespace TEN::Effects::Smoke; -using namespace TEN::Room; constexpr auto ESCAPE_DIST = BLOCK(5); constexpr auto STALK_DIST = BLOCK(3); diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 373d70a76..9f125f49d 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -10,7 +10,7 @@ #include "Game/Setup.h" #include "Specific/level.h" -using namespace TEN::Room; +using namespace TEN::Collision::Room; #define DEFAULT_FLY_UPDOWN_SPEED 16 #define DEFAULT_SWIM_UPDOWN_SPEED 32 diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 7bd42c6f7..4b579c43e 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -22,11 +22,11 @@ #include "Scripting/Internal/TEN/Objects/ObjectIDs.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::Room; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Items; using namespace TEN::Input; using namespace TEN::Math; -using namespace TEN::Room; constexpr int ITEM_DEATH_TIMEOUT = 4 * FPS; diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index aef5da31e..d15a0d242 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -159,7 +159,7 @@ int IsRoomOutside(int x, int y, int z) return NO_ROOM; } -namespace TEN::Room +namespace TEN::Collision::Room { FloorInfo* GetSector(ROOM_INFO* room, int x, int z) { diff --git a/TombEngine/Game/room.h b/TombEngine/Game/room.h index 81a0570d0..1e40f19da 100644 --- a/TombEngine/Game/room.h +++ b/TombEngine/Game/room.h @@ -156,7 +156,7 @@ void InitializeNeighborRoomList(); GameBoundingBox& GetBoundsAccurate(const MESH_INFO& mesh, bool visibility); -namespace TEN::Room +namespace TEN::Collision::Room { FloorInfo* GetSector(ROOM_INFO* room, int x, int z); } diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index 94f6f3769..8df4c601d 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -23,9 +23,9 @@ #include "Game/collision/collide_item.h" #include "Game/itemdata/itemdata.h" +using namespace TEN::Collision::Room; using namespace TEN::Gui; using namespace TEN::Input; -using namespace TEN::Room; namespace TEN::Entities::Doors { diff --git a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp index 62efd7a60..ce611c676 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp @@ -15,8 +15,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Room; using namespace TEN::Math; -using namespace TEN::Room; namespace TEN::Entities::Creatures::TR5 { diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index e94e48405..7c192fdb0 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -20,10 +20,10 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Room; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Spark; using namespace TEN::Math; -using namespace TEN::Room; namespace TEN::Entities::Creatures::TR5 { diff --git a/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp b/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp index aa629e109..ccc538fa2 100644 --- a/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_pushableblock.cpp @@ -16,8 +16,8 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::Room; using namespace TEN::Input; -using namespace TEN::Room; namespace TEN::Entities::Generic { diff --git a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp index 4ed96e273..bb75a6201 100644 --- a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp +++ b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp @@ -6,7 +6,7 @@ #include "Game/effects/tomb4fx.h" #include "Game/items.h" -using namespace TEN::Room; +using namespace TEN::Collision::Room; void InitializeSmashObject(short itemNumber) { From 433f877d82e97d16f15de951b567830d4c77df37 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 15 Aug 2023 23:44:22 +1000 Subject: [PATCH 010/410] Fix room number probing; Wrap GetPointCollision() calls in old GetCollision() --- TombEngine/Game/camera.cpp | 6 +- TombEngine/Game/collision/PointCollision.cpp | 68 ++++++++++-- TombEngine/Game/collision/PointCollision.h | 2 + TombEngine/Game/collision/collide_room.cpp | 103 +++++++++---------- 4 files changed, 115 insertions(+), 64 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index db2c95cdb..88951d2a6 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/los.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -21,6 +22,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision; using TEN::Renderer::g_Renderer; using namespace TEN::Effects::Environment; @@ -175,8 +177,8 @@ void LookCamera(ItemInfo& item, const CollisionInfo& coll) auto lookAtPos = Geometry::TranslatePoint(pivotPos, orient, LOOK_AT_DIST); // Determine best position. - auto origin = GameVector(pivotPos, GetCollision(&item, item.Pose.Orientation.y, pivotOffset.z, pivotOffset.y).RoomNumber); - auto target = GameVector(idealPos, GetCollision(origin.ToVector3i(), origin.RoomNumber, orient, idealDist).RoomNumber); + auto origin = GameVector(pivotPos, GetPointCollision(item, item.Pose.Orientation.y, pivotOffset.z, pivotOffset.y).RoomNumber); + auto target = GameVector(idealPos, GetPointCollision(origin.ToVector3i(), origin.RoomNumber, orient.ToDirection(), idealDist).RoomNumber); // Handle room and object collisions. LOSAndReturnTarget(&origin, &target, 0); diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index f3cc63462..221438c18 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -27,8 +27,7 @@ namespace TEN::Collision // Set current sector pointer. short probedRoomNumber = RoomNumber; - auto* sectorPtr = GetFloor(Position.x, Position.y, Position.z, &probedRoomNumber); - SectorPtr = sectorPtr; + SectorPtr = GetFloor(Position.x, Position.y, Position.z, &probedRoomNumber); return *SectorPtr; } @@ -233,18 +232,48 @@ namespace TEN::Collision PointCollision GetPointCollision(const Vector3i& pos, int roomNumber) { - return PointCollision(pos, roomNumber); + // HACK: This function takes arguments for a *current* position and room number. + // However, since some calls to the previous implementation (GetCollision()) had *projected* + // positions passed to it, for now the room number must be corrected to account for such cases. + // They are primarily found in camera.cpp. + short correctedRoomNumber = roomNumber; + GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + + return PointCollision(pos, correctedRoomNumber); } - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) { + // Get "location". short tempRoomNumber = roomNumber; const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); auto location = RoomVector(sector.Room, pos.y); + // Calculate probe position. + auto probePos = Geometry::TranslatePoint(pos, dir, dist); + + // Get probe position's room number. + short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; + GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + + return PointCollision(probePos, probeRoomNumber); + } + + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) + { + // Get "location". + short tempRoomNumber = roomNumber; + const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); + auto location = RoomVector(sector.Room, pos.y); + + // Calculate probe position. auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; - return PointCollision(probePos, adjacentRoomNumber); + + // Get probe position's room number. + short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; + GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + + return PointCollision(probePos, probeRoomNumber); } PointCollision GetPointCollision(const ItemInfo& item) @@ -265,12 +294,33 @@ namespace TEN::Collision return RoomVector(sector.Room, item.Pose.Position.y); } - PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) + PointCollision GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist) { + // Get "location". auto location = GetEntityLocation(item); + // Calculate probe position. + auto probePos = Geometry::TranslatePoint(item.Pose.Position, dir, dist); + + // Get probe position's room number. + short probeRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; + GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + + return PointCollision(probePos, probeRoomNumber); + } + + PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) + { + // Get "location". + auto location = GetEntityLocation(item); + + // Calculate probe position. auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; - return PointCollision(probePos, adjacentRoomNumber); + + // Get probe position's room number. + short probeRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; + GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + + return PointCollision(probePos, probeRoomNumber); } } diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index fef3952d8..9b504cd52 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -60,7 +60,9 @@ namespace TEN::Collision }; PointCollision GetPointCollision(const Vector3i& pos, int roomNumber); + PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist); PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); PointCollision GetPointCollision(const ItemInfo& item); + PointCollision GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist); PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); } diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 0af378f3c..e0bb0c125 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -117,47 +117,51 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) return collided; } -// Overload used to quickly get point collision parameters at a given item's position. +static CollisionResult ConvertPointCollisionToCollisionResult(PointCollision& pointColl) +{ + auto collResult = CollisionResult{}; + + collResult.Coordinates = pointColl.Position; + collResult.RoomNumber = pointColl.RoomNumber; + collResult.Block = &pointColl.GetSector(); + collResult.BottomBlock = &pointColl.GetBottomSector(); + + collResult.Position.Floor = pointColl.GetFloorHeight(); + collResult.Position.Ceiling = pointColl.GetCeilingHeight(); + collResult.Position.Bridge = pointColl.GetBridgeItemNumber(); + collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; + collResult.Position.FloorSlope = pointColl.IsFloorSlope(); + collResult.Position.CeilingSlope = pointColl.IsCeilingSlope(); + collResult.Position.DiagonalStep = pointColl.IsDiagonalStep(); + + collResult.FloorTilt = collResult.BottomBlock->GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, true); + collResult.CeilingTilt = collResult.BottomBlock->GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, false); + + return collResult; +} + CollisionResult GetCollision(const ItemInfo& item) { - auto newRoomNumber = item.RoomNumber; - auto floor = GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &newRoomNumber); - auto probe = GetCollision(floor, item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z); - - probe.RoomNumber = newRoomNumber; - return probe; + auto pointColl = GetPointCollision(item); + return ConvertPointCollisionToCollisionResult(pointColl); } -// Deprecated. CollisionResult GetCollision(ItemInfo* item) { - return GetCollision(*item); + auto pointColl = GetPointCollision(*item); + return ConvertPointCollisionToCollisionResult(pointColl); } -// Overload used to probe point collision parameters from a given item's position. CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down, float right) { - short tempRoomNumber = item->RoomNumber; - - // TODO: Find cleaner solution. Constructing a Location for Lara on the spot can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 - auto location = item->IsLara() ? - item->Location : - RoomVector(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &tempRoomNumber)->Room, item->Pose.Position.y); - - auto point = Geometry::TranslatePoint(item->Pose.Position, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(location, item->Pose.Position.x, point.y, item->Pose.Position.z).RoomNumber; - return GetCollision(point.x, point.y, point.z, adjacentRoomNumber); + auto pointColl = GetPointCollision(*item, headingAngle, forward, down, right); + return ConvertPointCollisionToCollisionResult(pointColl); } -// Overload used to probe point collision parameters from a given position. CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { - short tempRoomNumber = roomNumber; - auto location = RoomVector(GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y); - - auto point = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); - int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; - return GetCollision(point.x, point.y, point.z, adjacentRoomNumber); + auto pointColl = GetPointCollision(pos, roomNumber, headingAngle, forward, down, right); + return ConvertPointCollisionToCollisionResult(pointColl); } CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const EulerAngles& orient, float dist) @@ -165,9 +169,15 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const EulerAng auto point = Geometry::TranslatePoint(pos, orient, dist); short tempRoomNumber = roomNumber; - auto location = RoomVector{ GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y }; + auto location = RoomVector(GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y); int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; - return GetCollision(point.x, point.y, point.z, adjacentRoomNumber); + + // Get probe position's room number. + short probeRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; + GetFloor(point.x, point.y, point.z, &probeRoomNumber); + + auto pointColl = GetPointCollision(point, roomNumber); + return ConvertPointCollisionToCollisionResult(pointColl); } // Overload used as universal wrapper across collisional code replacing @@ -177,39 +187,26 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const EulerAng // This way, no external variables are modified as output arguments. CollisionResult GetCollision(const Vector3i& pos, int roomNumber) { - return GetCollision(pos.x, pos.y, pos.z, roomNumber); + auto pointColl = GetPointCollision(pos, roomNumber); + return ConvertPointCollisionToCollisionResult(pointColl); } -// Deprecated. CollisionResult GetCollision(int x, int y, int z, short roomNumber) { + /*auto room = roomNumber; + auto floor = GetFloor(x, y, z, &room); + auto result = GetCollision(floor, x, y, z); + result.RoomNumber = room; + return result;*/ + auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); - - auto result = CollisionResult{}; - - result.Coordinates = pointColl.Position; - result.RoomNumber = pointColl.RoomNumber; - result.Block = &pointColl.GetSector(); - result.BottomBlock = &pointColl.GetBottomSector(); - - result.Position.Floor = pointColl.GetFloorHeight(); - result.Position.Ceiling = pointColl.GetCeilingHeight(); - result.Position.Bridge = pointColl.GetBridgeItemNumber(); - result.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; - result.Position.FloorSlope = pointColl.IsFloorSlope(); - result.Position.CeilingSlope = pointColl.IsCeilingSlope(); - result.Position.DiagonalStep = pointColl.IsDiagonalStep(); - - result.FloorTilt = result.BottomBlock->GetSurfaceTilt(x, z, true); - result.CeilingTilt = result.BottomBlock->GetSurfaceTilt(x, z, false); - - return result; + return ConvertPointCollisionToCollisionResult(pointColl); } -// NOTE: To be used only when absolutely necessary. CollisionResult GetCollision(const GameVector& pos) { - return GetCollision(pos.x, pos.y, pos.z, pos.RoomNumber); + auto pointColl = GetPointCollision(pos.ToVector3i(), pos.RoomNumber); + return ConvertPointCollisionToCollisionResult(pointColl); } // A reworked legacy GetFloorHeight() function which writes data From bc212b041da3dedacd22ca2755af1a6f7ce8b2a7 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 15 Aug 2023 23:59:34 +1000 Subject: [PATCH 011/410] Remove deprecated GetCollision() overload --- TombEngine/Game/collision/PointCollision.cpp | 2 +- TombEngine/Game/collision/collide_room.cpp | 16 ---------------- TombEngine/Game/collision/collide_room.h | 1 - 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 221438c18..8ac20b67d 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -233,7 +233,7 @@ namespace TEN::Collision PointCollision GetPointCollision(const Vector3i& pos, int roomNumber) { // HACK: This function takes arguments for a *current* position and room number. - // However, since some calls to the previous implementation (GetCollision()) had *projected* + // However, since some calls to the previous implementation (GetCollision()) had *vertically projected* // positions passed to it, for now the room number must be corrected to account for such cases. // They are primarily found in camera.cpp. short correctedRoomNumber = roomNumber; diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index e0bb0c125..321795e46 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -164,22 +164,6 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingA return ConvertPointCollisionToCollisionResult(pointColl); } -CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const EulerAngles& orient, float dist) -{ - auto point = Geometry::TranslatePoint(pos, orient, dist); - - short tempRoomNumber = roomNumber; - auto location = RoomVector(GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y); - int adjacentRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; - - // Get probe position's room number. - short probeRoomNumber = GetRoom(location, pos.x, point.y, pos.z).RoomNumber; - GetFloor(point.x, point.y, point.z, &probeRoomNumber); - - auto pointColl = GetPointCollision(point, roomNumber); - return ConvertPointCollisionToCollisionResult(pointColl); -} - // Overload used as universal wrapper across collisional code replacing // triads of roomNumber-GetFloor()-GetFloorHeight() calls. // Advantage is that it does NOT modify incoming roomNumber argument, diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 74cd6fd0e..761b7f16e 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -134,7 +134,6 @@ CollisionResult GetCollision(const ItemInfo& item); CollisionResult GetCollision(ItemInfo* item); CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); -CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const EulerAngles& orient, float dist); CollisionResult GetCollision(const Vector3i& pos, int roomNumber); CollisionResult GetCollision(int x, int y, int z, short roomNumber); CollisionResult GetCollision(const GameVector& pos); From 14af4269e1be673278ac90489498ee1ed30515cd Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 00:50:11 +1000 Subject: [PATCH 012/410] Update slope query methods --- TombEngine/Game/collision/PointCollision.cpp | 12 +++++++----- TombEngine/Game/collision/PointCollision.h | 5 +++-- TombEngine/Game/collision/collide_room.cpp | 10 ++-------- TombEngine/Game/collision/collide_room.h | 4 ++-- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 8ac20b67d..be2ba8b11 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -184,22 +184,24 @@ namespace TEN::Collision return ((GetFloorHeight() == NO_HEIGHT) || (GetCeilingHeight() == NO_HEIGHT)); } - bool PointCollision::IsFloorSlope() + bool PointCollision::IsSlipperyFloor(short slopeAngleMin) { // Get floor slope angle. auto floorNormal = GetFloorNormal(); auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); - return ((GetBridgeItemNumber() == NO_ITEM) && (abs(slopeAngle) >= SLIPPERY_FLOOR_SLOPE_ANGLE)); + // TODO: Slippery bridges. + return ((GetBridgeItemNumber() == NO_ITEM) && (abs(slopeAngle) >= slopeAngleMin)); } - bool PointCollision::IsCeilingSlope() + bool PointCollision::IsSlipperyCeiling(short slopeAngleMin) { // Get ceiling slope angle. auto ceilingNormal = GetCeilingNormal(); auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); - - return (abs(slopeAngle) >= SLIPPERY_CEILING_SLOPE_ANGLE); + + // TODO: Slippery bridges. + return (abs(slopeAngle) >= slopeAngleMin); } bool PointCollision::IsDiagonalStep() diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 9b504cd52..31ef6df92 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -1,4 +1,5 @@ #pragma once +#include "Game/collision/collide_room.h" #include "Math/Math.h" enum RoomEnvFlags; @@ -51,8 +52,8 @@ namespace TEN::Collision // Inquirers bool IsWall(); - bool IsFloorSlope(); - bool IsCeilingSlope(); + bool IsSlipperyFloor(short slopeAngleMin = DEFAULT_SLIPPERY_FLOOR_SLOPE_ANGLE); + bool IsSlipperyCeiling(short slopeAngleMin = DEFAULT_SLIPPERY_CEILING_SLOPE_ANGLE); bool IsDiagonalStep(); bool HasDiagonalSplit(); bool HasFlippedDiagonalSplit(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 321795e46..58c212e3b 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -130,8 +130,8 @@ static CollisionResult ConvertPointCollisionToCollisionResult(PointCollision& po collResult.Position.Ceiling = pointColl.GetCeilingHeight(); collResult.Position.Bridge = pointColl.GetBridgeItemNumber(); collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; - collResult.Position.FloorSlope = pointColl.IsFloorSlope(); - collResult.Position.CeilingSlope = pointColl.IsCeilingSlope(); + collResult.Position.FloorSlope = pointColl.IsSlipperyFloor(); + collResult.Position.CeilingSlope = pointColl.IsSlipperyCeiling(); collResult.Position.DiagonalStep = pointColl.IsDiagonalStep(); collResult.FloorTilt = collResult.BottomBlock->GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, true); @@ -177,12 +177,6 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber) CollisionResult GetCollision(int x, int y, int z, short roomNumber) { - /*auto room = roomNumber; - auto floor = GetFloor(x, y, z, &room); - auto result = GetCollision(floor, x, y, z); - result.RoomNumber = room; - return result;*/ - auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); return ConvertPointCollisionToCollisionResult(pointColl); } diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 761b7f16e..1ac8a1633 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -13,8 +13,8 @@ constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBou constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound. constexpr auto COLLISION_CHECK_DISTANCE = BLOCK(8); -constexpr auto SLIPPERY_FLOOR_SLOPE_ANGLE = short(ANGLE(45.0f) * 0.75f); -constexpr auto SLIPPERY_CEILING_SLOPE_ANGLE = ANGLE(45.0f); +constexpr auto DEFAULT_SLIPPERY_FLOOR_SLOPE_ANGLE = short(ANGLE(45.0f) * 0.75f); +constexpr auto DEFAULT_SLIPPERY_CEILING_SLOPE_ANGLE = ANGLE(45.0f); enum CollisionType { From 7da15230eebad8ea0894a4e01e23dd6400aae97a Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 01:41:44 +1000 Subject: [PATCH 013/410] Update collide_room.cpp --- TombEngine/Game/collision/collide_room.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 58c212e3b..f0a9d1113 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -1125,7 +1125,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) FloorInfo* GetFloor(int x, int y, int z, short* roomNumber) { - const auto location = GetRoom(RoomVector{ *roomNumber, y }, x, y, z); + auto location = GetRoom(RoomVector(*roomNumber, y), x, y, z); *roomNumber = location.RoomNumber; return &GetFloor(*roomNumber, x, z); } From 70ffe72e1fc60e1adf545e4f3dd55f1ab4643552 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 16:58:43 +1000 Subject: [PATCH 014/410] Rename class --- TombEngine/Game/collision/PointCollision.cpp | 62 ++++++++++---------- TombEngine/Game/collision/PointCollision.h | 16 ++--- TombEngine/Game/collision/collide_room.cpp | 2 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index be2ba8b11..1c84e0918 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -14,13 +14,13 @@ using namespace TEN::Math; namespace TEN::Collision { - PointCollision::PointCollision(const Vector3i& pos, int roomNumber) : + PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) : Position(pos), RoomNumber(roomNumber) { } - FloorInfo& PointCollision::GetSector() + FloorInfo& PointCollisionData::GetSector() { if (SectorPtr != nullptr) return *SectorPtr; @@ -32,7 +32,7 @@ namespace TEN::Collision return *SectorPtr; } - FloorInfo& PointCollision::GetTopSector() + FloorInfo& PointCollisionData::GetTopSector() { if (TopSectorPtr != nullptr) return *TopSectorPtr; @@ -51,7 +51,7 @@ namespace TEN::Collision return *TopSectorPtr; } - FloorInfo& PointCollision::GetBottomSector() + FloorInfo& PointCollisionData::GetBottomSector() { if (BottomSectorPtr != nullptr) return *BottomSectorPtr; @@ -70,7 +70,7 @@ namespace TEN::Collision return *BottomSectorPtr; } - int PointCollision::GetFloorHeight() + int PointCollisionData::GetFloorHeight() { if (FloorHeight.has_value()) return *FloorHeight; @@ -82,7 +82,7 @@ namespace TEN::Collision return *FloorHeight; } - int PointCollision::GetCeilingHeight() + int PointCollisionData::GetCeilingHeight() { if (CeilingHeight.has_value()) return *CeilingHeight; @@ -94,7 +94,7 @@ namespace TEN::Collision return *CeilingHeight; } - Vector3 PointCollision::GetFloorNormal() + Vector3 PointCollisionData::GetFloorNormal() { if (FloorNormal.has_value()) return *FloorNormal; @@ -114,7 +114,7 @@ namespace TEN::Collision return *FloorNormal; } - Vector3 PointCollision::GetCeilingNormal() + Vector3 PointCollisionData::GetCeilingNormal() { if (CeilingNormal.has_value()) return *CeilingNormal; @@ -134,7 +134,7 @@ namespace TEN::Collision return *CeilingNormal; } - int PointCollision::GetBridgeItemNumber() + int PointCollisionData::GetBridgeItemNumber() { if (BridgeItemNumber.has_value()) return *BridgeItemNumber; @@ -146,7 +146,7 @@ namespace TEN::Collision return *BridgeItemNumber; } - int PointCollision::GetWaterSurfaceHeight() + int PointCollisionData::GetWaterSurfaceHeight() { if (WaterSurfaceHeight.has_value()) return *WaterSurfaceHeight; @@ -157,7 +157,7 @@ namespace TEN::Collision return *WaterSurfaceHeight; } - int PointCollision::GetWaterTopHeight() + int PointCollisionData::GetWaterTopHeight() { if (WaterTopHeight.has_value()) return *WaterTopHeight; @@ -168,7 +168,7 @@ namespace TEN::Collision return *WaterTopHeight; } - int PointCollision::GetWaterBottomHeight() + int PointCollisionData::GetWaterBottomHeight() { if (WaterBottomHeight.has_value()) return *WaterBottomHeight; @@ -179,12 +179,12 @@ namespace TEN::Collision return *WaterBottomHeight; } - bool PointCollision::IsWall() + bool PointCollisionData::IsWall() { return ((GetFloorHeight() == NO_HEIGHT) || (GetCeilingHeight() == NO_HEIGHT)); } - bool PointCollision::IsSlipperyFloor(short slopeAngleMin) + bool PointCollisionData::IsSlipperyFloor(short slopeAngleMin) { // Get floor slope angle. auto floorNormal = GetFloorNormal(); @@ -194,7 +194,7 @@ namespace TEN::Collision return ((GetBridgeItemNumber() == NO_ITEM) && (abs(slopeAngle) >= slopeAngleMin)); } - bool PointCollision::IsSlipperyCeiling(short slopeAngleMin) + bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) { // Get ceiling slope angle. auto ceilingNormal = GetCeilingNormal(); @@ -204,12 +204,12 @@ namespace TEN::Collision return (abs(slopeAngle) >= slopeAngleMin); } - bool PointCollision::IsDiagonalStep() + bool PointCollisionData::IsDiagonalStep() { return GetBottomSector().IsSurfaceDiagonalStep(true); } - bool PointCollision::HasDiagonalSplit() + bool PointCollisionData::HasDiagonalSplit() { constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; constexpr auto DIAGONAL_SPLIT_1 = 135.0f * RADIAN; @@ -218,7 +218,7 @@ namespace TEN::Collision return ((splitAngle == DIAGONAL_SPLIT_0) || (splitAngle == DIAGONAL_SPLIT_1)); } - bool PointCollision::HasFlippedDiagonalSplit() + bool PointCollisionData::HasFlippedDiagonalSplit() { constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; @@ -226,13 +226,13 @@ namespace TEN::Collision return (HasDiagonalSplit() && (splitAngle != DIAGONAL_SPLIT_0)); } - bool PointCollision::HasEnvironmentFlag(RoomEnvFlags envFlag) + bool PointCollisionData::HasEnvironmentFlag(RoomEnvFlags envFlag) { const auto& room = g_Level.Rooms[RoomNumber]; return ((room.flags & envFlag) == envFlag); } - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber) + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) { // HACK: This function takes arguments for a *current* position and room number. // However, since some calls to the previous implementation (GetCollision()) had *vertically projected* @@ -241,10 +241,10 @@ namespace TEN::Collision short correctedRoomNumber = roomNumber; GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); - return PointCollision(pos, correctedRoomNumber); + return PointCollisionData(pos, correctedRoomNumber); } - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) { // Get "location". short tempRoomNumber = roomNumber; @@ -258,10 +258,10 @@ namespace TEN::Collision short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); - return PointCollision(probePos, probeRoomNumber); + return PointCollisionData(probePos, probeRoomNumber); } - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { // Get "location". short tempRoomNumber = roomNumber; @@ -275,12 +275,12 @@ namespace TEN::Collision short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); - return PointCollision(probePos, probeRoomNumber); + return PointCollisionData(probePos, probeRoomNumber); } - PointCollision GetPointCollision(const ItemInfo& item) + PointCollisionData GetPointCollision(const ItemInfo& item) { - return PointCollision(item.Pose.Position, item.RoomNumber); + return PointCollisionData(item.Pose.Position, item.RoomNumber); } // TODO: Find cleaner solution. Constructing a "location" on the spot for the player @@ -296,7 +296,7 @@ namespace TEN::Collision return RoomVector(sector.Room, item.Pose.Position.y); } - PointCollision GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist) + PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist) { // Get "location". auto location = GetEntityLocation(item); @@ -308,10 +308,10 @@ namespace TEN::Collision short probeRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); - return PointCollision(probePos, probeRoomNumber); + return PointCollisionData(probePos, probeRoomNumber); } - PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) + PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) { // Get "location". auto location = GetEntityLocation(item); @@ -323,6 +323,6 @@ namespace TEN::Collision short probeRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); - return PointCollision(probePos, probeRoomNumber); + return PointCollisionData(probePos, probeRoomNumber); } } diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 31ef6df92..d69dcc831 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -9,7 +9,7 @@ using namespace TEN::Math; namespace TEN::Collision { - class PointCollision + class PointCollisionData { public: // Members @@ -33,7 +33,7 @@ namespace TEN::Collision public: // Constructors - PointCollision(const Vector3i& pos, int roomNumber); + PointCollisionData(const Vector3i& pos, int roomNumber); // Getters FloorInfo& GetSector(); @@ -60,10 +60,10 @@ namespace TEN::Collision bool HasEnvironmentFlag(RoomEnvFlags envFlag); }; - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber); - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist); - PointCollision GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); - PointCollision GetPointCollision(const ItemInfo& item); - PointCollision GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist); - PointCollision GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber); + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist); + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); + PointCollisionData GetPointCollision(const ItemInfo& item); + PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist); + PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); } diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index f0a9d1113..8c4bfa446 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -117,7 +117,7 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) return collided; } -static CollisionResult ConvertPointCollisionToCollisionResult(PointCollision& pointColl) +static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData& pointColl) { auto collResult = CollisionResult{}; From b2da3a9d03929a438cda3355c523466246e8fa72 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 20:23:28 +1000 Subject: [PATCH 015/410] Optimise --- TombEngine/Game/collision/PointCollision.cpp | 26 +++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 1c84e0918..f2745450f 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -26,8 +26,8 @@ namespace TEN::Collision return *SectorPtr; // Set current sector pointer. - short probedRoomNumber = RoomNumber; - SectorPtr = GetFloor(Position.x, Position.y, Position.z, &probedRoomNumber); + short probeRoomNumber = RoomNumber; + SectorPtr = GetFloor(Position.x, Position.y, Position.z, &probeRoomNumber); return *SectorPtr; } @@ -39,12 +39,13 @@ namespace TEN::Collision // Set top sector pointer. auto* topSectorPtr = &GetSector(); - while (topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z).has_value()) + auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); + while (roomNumberAbove.has_value()) { - auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->Room)]; - topSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + + roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); } TopSectorPtr = topSectorPtr; @@ -58,12 +59,13 @@ namespace TEN::Collision // Set bottom sector pointer. auto* bottomSectorPtr = &GetSector(); - while (bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z).has_value()) + auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); + while (roomNumberBelow.has_value()) { - auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->Room)]; - bottomSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + + roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); } BottomSectorPtr = bottomSectorPtr; @@ -181,7 +183,7 @@ namespace TEN::Collision bool PointCollisionData::IsWall() { - return ((GetFloorHeight() == NO_HEIGHT) || (GetCeilingHeight() == NO_HEIGHT)); + return (GetFloorHeight() == NO_HEIGHT || GetCeilingHeight() == NO_HEIGHT); } bool PointCollisionData::IsSlipperyFloor(short slopeAngleMin) @@ -191,7 +193,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); // TODO: Slippery bridges. - return ((GetBridgeItemNumber() == NO_ITEM) && (abs(slopeAngle) >= slopeAngleMin)); + return (GetBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) @@ -215,7 +217,7 @@ namespace TEN::Collision constexpr auto DIAGONAL_SPLIT_1 = 135.0f * RADIAN; float splitAngle = GetBottomSector().FloorCollision.SplitAngle; - return ((splitAngle == DIAGONAL_SPLIT_0) || (splitAngle == DIAGONAL_SPLIT_1)); + return (splitAngle == DIAGONAL_SPLIT_0 || splitAngle == DIAGONAL_SPLIT_1); } bool PointCollisionData::HasFlippedDiagonalSplit() @@ -223,7 +225,7 @@ namespace TEN::Collision constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; float splitAngle = GetBottomSector().FloorCollision.SplitAngle; - return (HasDiagonalSplit() && (splitAngle != DIAGONAL_SPLIT_0)); + return (HasDiagonalSplit() && splitAngle != DIAGONAL_SPLIT_0); } bool PointCollisionData::HasEnvironmentFlag(RoomEnvFlags envFlag) From 23efb49677338f5fcd8d24c496dcae0ae4033607 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 21:46:16 +1000 Subject: [PATCH 016/410] Add GetCeilingBridgeItemID(); consider bridges above when checking for slippery ceiling --- TombEngine/Game/Lara/lara.cpp | 8 ++++- TombEngine/Game/collision/PointCollision.cpp | 32 ++++++++++++++------ TombEngine/Game/collision/PointCollision.h | 14 +++++---- TombEngine/Game/collision/collide_room.cpp | 6 ++-- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 9608309f1..eac7789bd 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -25,6 +25,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/flipeffect.h" #include "Game/control/volume.h" #include "Game/effects/Hair.h" @@ -40,10 +41,11 @@ #include "Sound/sound.h" #include "Specific/winmain.h" +using namespace TEN::Collision; +using namespace TEN::Collision::Floordata; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Hair; using namespace TEN::Effects::Items; -using namespace TEN::Collision::Floordata; using namespace TEN::Input; using namespace TEN::Math; @@ -445,6 +447,10 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) { auto* lara = GetLaraInfo(item); + auto pointColl = GetPointCollision(*item); + g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeItemID()); + g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeItemID()); + if (lara->Control.Weapon.HasFired) { AlertNearbyGuards(item); diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index f2745450f..9f739501f 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -102,7 +102,7 @@ namespace TEN::Collision return *FloorNormal; // Set floor normal. - if (GetBridgeItemNumber() != NO_ITEM) + if (GetFloorBridgeItemID() != NO_ITEM) { // TODO: Get bridge normal. FloorNormal = -Vector3::UnitY; @@ -122,7 +122,7 @@ namespace TEN::Collision return *CeilingNormal; // Set ceiling normal. - if (GetBridgeItemNumber() != NO_ITEM) + if (GetCeilingBridgeItemID() != NO_ITEM) { // TODO: Get bridge normal. CeilingNormal = Vector3::UnitY; @@ -136,16 +136,28 @@ namespace TEN::Collision return *CeilingNormal; } - int PointCollisionData::GetBridgeItemNumber() + int PointCollisionData::GetFloorBridgeItemID() { - if (BridgeItemNumber.has_value()) - return *BridgeItemNumber; + if (FloorBridgeItemID.has_value()) + return *FloorBridgeItemID; - // Set bridge item number. + // Set floor bridge item ID. int floorHeight = GetFloorHeight(); - BridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; + FloorBridgeItemID = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; - return *BridgeItemNumber; + return *FloorBridgeItemID; + } + + int PointCollisionData::GetCeilingBridgeItemID() + { + if (CeilingBridgeItemID.has_value()) + return *CeilingBridgeItemID; + + // Set ceiling bridge item ID. + int ceilingHeight = GetCeilingHeight(); + CeilingBridgeItemID = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; + + return *CeilingBridgeItemID; } int PointCollisionData::GetWaterSurfaceHeight() @@ -193,7 +205,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); // TODO: Slippery bridges. - return (GetBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (GetFloorBridgeItemID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) @@ -203,7 +215,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); // TODO: Slippery bridges. - return (abs(slopeAngle) >= slopeAngleMin); + return (GetCeilingBridgeItemID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsDiagonalStep() diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index d69dcc831..ea0893dbe 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -21,11 +21,12 @@ namespace TEN::Collision FloorInfo* TopSectorPtr = nullptr; FloorInfo* BottomSectorPtr = nullptr; - std::optional FloorHeight = std::nullopt; - std::optional CeilingHeight = std::nullopt; - std::optional FloorNormal = std::nullopt; - std::optional CeilingNormal = std::nullopt; - std::optional BridgeItemNumber = std::nullopt; + std::optional FloorHeight = std::nullopt; + std::optional CeilingHeight = std::nullopt; + std::optional FloorNormal = std::nullopt; + std::optional CeilingNormal = std::nullopt; + std::optional FloorBridgeItemID = std::nullopt; + std::optional CeilingBridgeItemID = std::nullopt; std::optional WaterSurfaceHeight = std::nullopt; std::optional WaterTopHeight = std::nullopt; @@ -44,7 +45,8 @@ namespace TEN::Collision int GetCeilingHeight(); Vector3 GetFloorNormal(); Vector3 GetCeilingNormal(); - int GetBridgeItemNumber(); + int GetFloorBridgeItemID(); + int GetCeilingBridgeItemID(); int GetWaterSurfaceHeight(); int GetWaterTopHeight(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 8c4bfa446..33c9294cb 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -128,14 +128,14 @@ static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData collResult.Position.Floor = pointColl.GetFloorHeight(); collResult.Position.Ceiling = pointColl.GetCeilingHeight(); - collResult.Position.Bridge = pointColl.GetBridgeItemNumber(); + collResult.Position.Bridge = pointColl.GetFloorBridgeItemID(); collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; collResult.Position.FloorSlope = pointColl.IsSlipperyFloor(); collResult.Position.CeilingSlope = pointColl.IsSlipperyCeiling(); collResult.Position.DiagonalStep = pointColl.IsDiagonalStep(); - collResult.FloorTilt = collResult.BottomBlock->GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, true); - collResult.CeilingTilt = collResult.BottomBlock->GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, false); + collResult.FloorTilt = pointColl.GetBottomSector().GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, true); + collResult.CeilingTilt = pointColl.GetTopSector().GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, false); return collResult; } From 426b99d75dc590fc4b861e42fd022a8a8119b58a Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 22:27:23 +1000 Subject: [PATCH 017/410] Update methods --- TombEngine/Game/Lara/lara.cpp | 4 +-- TombEngine/Game/collision/PointCollision.cpp | 28 ++++++++++---------- TombEngine/Game/collision/PointCollision.h | 16 +++++------ TombEngine/Game/collision/collide_room.cpp | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index eac7789bd..2c4f3198d 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -448,8 +448,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) auto* lara = GetLaraInfo(item); auto pointColl = GetPointCollision(*item); - g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeItemID()); - g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeItemID()); + g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeEntityID()); + g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeEntityID()); if (lara->Control.Weapon.HasFired) { diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 9f739501f..45e513ea3 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -102,7 +102,7 @@ namespace TEN::Collision return *FloorNormal; // Set floor normal. - if (GetFloorBridgeItemID() != NO_ITEM) + if (GetFloorBridgeEntityID() != NO_ITEM) { // TODO: Get bridge normal. FloorNormal = -Vector3::UnitY; @@ -122,7 +122,7 @@ namespace TEN::Collision return *CeilingNormal; // Set ceiling normal. - if (GetCeilingBridgeItemID() != NO_ITEM) + if (GetCeilingBridgeEntityID() != NO_ITEM) { // TODO: Get bridge normal. CeilingNormal = Vector3::UnitY; @@ -136,28 +136,28 @@ namespace TEN::Collision return *CeilingNormal; } - int PointCollisionData::GetFloorBridgeItemID() + int PointCollisionData::GetFloorBridgeEntityID() { - if (FloorBridgeItemID.has_value()) - return *FloorBridgeItemID; + if (FloorBridgeEntityID.has_value()) + return *FloorBridgeEntityID; // Set floor bridge item ID. int floorHeight = GetFloorHeight(); - FloorBridgeItemID = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; + FloorBridgeEntityID = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; - return *FloorBridgeItemID; + return *FloorBridgeEntityID; } - int PointCollisionData::GetCeilingBridgeItemID() + int PointCollisionData::GetCeilingBridgeEntityID() { - if (CeilingBridgeItemID.has_value()) - return *CeilingBridgeItemID; + if (CeilingBridgeEntityID.has_value()) + return *CeilingBridgeEntityID; // Set ceiling bridge item ID. int ceilingHeight = GetCeilingHeight(); - CeilingBridgeItemID = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; + CeilingBridgeEntityID = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; - return *CeilingBridgeItemID; + return *CeilingBridgeEntityID; } int PointCollisionData::GetWaterSurfaceHeight() @@ -205,7 +205,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); // TODO: Slippery bridges. - return (GetFloorBridgeItemID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (GetFloorBridgeEntityID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) @@ -215,7 +215,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); // TODO: Slippery bridges. - return (GetCeilingBridgeItemID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (GetCeilingBridgeEntityID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsDiagonalStep() diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index ea0893dbe..2b05afb97 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -21,12 +21,12 @@ namespace TEN::Collision FloorInfo* TopSectorPtr = nullptr; FloorInfo* BottomSectorPtr = nullptr; - std::optional FloorHeight = std::nullopt; - std::optional CeilingHeight = std::nullopt; - std::optional FloorNormal = std::nullopt; - std::optional CeilingNormal = std::nullopt; - std::optional FloorBridgeItemID = std::nullopt; - std::optional CeilingBridgeItemID = std::nullopt; + std::optional FloorHeight = std::nullopt; + std::optional CeilingHeight = std::nullopt; + std::optional FloorNormal = std::nullopt; + std::optional CeilingNormal = std::nullopt; + std::optional FloorBridgeEntityID = std::nullopt; + std::optional CeilingBridgeEntityID = std::nullopt; std::optional WaterSurfaceHeight = std::nullopt; std::optional WaterTopHeight = std::nullopt; @@ -45,8 +45,8 @@ namespace TEN::Collision int GetCeilingHeight(); Vector3 GetFloorNormal(); Vector3 GetCeilingNormal(); - int GetFloorBridgeItemID(); - int GetCeilingBridgeItemID(); + int GetFloorBridgeEntityID(); + int GetCeilingBridgeEntityID(); int GetWaterSurfaceHeight(); int GetWaterTopHeight(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 33c9294cb..f3bb4f838 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -128,7 +128,7 @@ static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData collResult.Position.Floor = pointColl.GetFloorHeight(); collResult.Position.Ceiling = pointColl.GetCeilingHeight(); - collResult.Position.Bridge = pointColl.GetFloorBridgeItemID(); + collResult.Position.Bridge = pointColl.GetFloorBridgeEntityID(); collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; collResult.Position.FloorSlope = pointColl.IsSlipperyFloor(); collResult.Position.CeilingSlope = pointColl.IsSlipperyCeiling(); From 8c47b067211061f91f36dceab9656d8fee8cc56d Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 16 Aug 2023 23:01:23 +1000 Subject: [PATCH 018/410] Update comments --- TombEngine/Game/collision/PointCollision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 45e513ea3..f43e69c9b 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -141,7 +141,7 @@ namespace TEN::Collision if (FloorBridgeEntityID.has_value()) return *FloorBridgeEntityID; - // Set floor bridge item ID. + // Set floor bridge entity ID. int floorHeight = GetFloorHeight(); FloorBridgeEntityID = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; @@ -153,7 +153,7 @@ namespace TEN::Collision if (CeilingBridgeEntityID.has_value()) return *CeilingBridgeEntityID; - // Set ceiling bridge item ID. + // Set ceiling bridge entity ID. int ceilingHeight = GetCeilingHeight(); CeilingBridgeEntityID = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; From a97f5954ce5b520e52bd45b51c866891c2462a29 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 17 Aug 2023 20:05:24 +1000 Subject: [PATCH 019/410] Update comment --- TombEngine/Game/collision/PointCollision.cpp | 4 ++-- TombEngine/Game/collision/PointCollision.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index f43e69c9b..5a0858936 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -249,8 +249,8 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) { // HACK: This function takes arguments for a *current* position and room number. - // However, since some calls to the previous implementation (GetCollision()) had *vertically projected* - // positions passed to it, for now the room number must be corrected to account for such cases. + // However, since some calls to the previous implementation (GetCollision()) had *projected* + // positions passed to it, the room number must be corrected to account for such cases for now. // They are primarily found in camera.cpp. short correctedRoomNumber = roomNumber; GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 2b05afb97..0b604f3fe 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -65,6 +65,7 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber); PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist); PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); + PointCollisionData GetPointCollision(const ItemInfo& item); PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist); PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); From be03784ddac75c16e189ab706713c901c0d9c394 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 20 Aug 2023 17:52:08 +1000 Subject: [PATCH 020/410] Add helper functions to simplify --- TombEngine/Game/collision/PointCollision.cpp | 84 ++++++++++---------- TombEngine/Game/collision/PointCollision.h | 18 +++-- TombEngine/Game/collision/collide_room.cpp | 2 +- 3 files changed, 54 insertions(+), 50 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 5a0858936..03ab3f7a0 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -102,7 +102,7 @@ namespace TEN::Collision return *FloorNormal; // Set floor normal. - if (GetFloorBridgeEntityID() != NO_ITEM) + if (GetFloorBridgeItemNumber() != NO_ITEM) { // TODO: Get bridge normal. FloorNormal = -Vector3::UnitY; @@ -122,7 +122,7 @@ namespace TEN::Collision return *CeilingNormal; // Set ceiling normal. - if (GetCeilingBridgeEntityID() != NO_ITEM) + if (GetCeilingBridgeItemNumber() != NO_ITEM) { // TODO: Get bridge normal. CeilingNormal = Vector3::UnitY; @@ -136,28 +136,28 @@ namespace TEN::Collision return *CeilingNormal; } - int PointCollisionData::GetFloorBridgeEntityID() + int PointCollisionData::GetFloorBridgeItemNumber() { - if (FloorBridgeEntityID.has_value()) - return *FloorBridgeEntityID; + if (FloorBridgeItemNumber.has_value()) + return *FloorBridgeItemNumber; - // Set floor bridge entity ID. + // Set floor bridge item number. int floorHeight = GetFloorHeight(); - FloorBridgeEntityID = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; + FloorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; - return *FloorBridgeEntityID; + return *FloorBridgeItemNumber; } - int PointCollisionData::GetCeilingBridgeEntityID() + int PointCollisionData::GetCeilingBridgeItemNumber() { - if (CeilingBridgeEntityID.has_value()) - return *CeilingBridgeEntityID; + if (CeilingBridgeItemNumber.has_value()) + return *CeilingBridgeItemNumber; - // Set ceiling bridge entity ID. + // Set ceiling bridge item number. int ceilingHeight = GetCeilingHeight(); - CeilingBridgeEntityID = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; + CeilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; - return *CeilingBridgeEntityID; + return *CeilingBridgeItemNumber; } int PointCollisionData::GetWaterSurfaceHeight() @@ -205,7 +205,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); // TODO: Slippery bridges. - return (GetFloorBridgeEntityID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (GetFloorBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) @@ -215,7 +215,7 @@ namespace TEN::Collision auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); // TODO: Slippery bridges. - return (GetCeilingBridgeEntityID() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (GetCeilingBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsDiagonalStep() @@ -250,7 +250,7 @@ namespace TEN::Collision { // HACK: This function takes arguments for a *current* position and room number. // However, since some calls to the previous implementation (GetCollision()) had *projected* - // positions passed to it, the room number must be corrected to account for such cases for now. + // positions passed to it, the room number must be corrected to account for such cases. // They are primarily found in camera.cpp. short correctedRoomNumber = roomNumber; GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); @@ -258,19 +258,31 @@ namespace TEN::Collision return PointCollisionData(pos, correctedRoomNumber); } + static int GetProbeRoomNumber(const Vector3i& pos, const RoomVector& location, const Vector3i& probePos) + { + // Conduct L-shaped room traversal. + short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; + GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + + return probeRoomNumber; + } + + static RoomVector GetPositionLocation(const Vector3i& pos, int roomNumber) + { + short tempRoomNumber = roomNumber; + const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); + + return RoomVector(sector.Room, pos.y); + } + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) { // Get "location". - short tempRoomNumber = roomNumber; - const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); - auto location = RoomVector(sector.Room, pos.y); + auto location = GetPositionLocation(pos, roomNumber); // Calculate probe position. auto probePos = Geometry::TranslatePoint(pos, dir, dist); - - // Get probe position's room number. - short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; - GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + short probeRoomNumber = GetProbeRoomNumber(pos, location, probePos); return PointCollisionData(probePos, probeRoomNumber); } @@ -278,16 +290,11 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { // Get "location". - short tempRoomNumber = roomNumber; - const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); - auto location = RoomVector(sector.Room, pos.y); + auto location = GetPositionLocation(pos, roomNumber); // Calculate probe position. auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); - - // Get probe position's room number. - short probeRoomNumber = GetRoom(location, pos.x, probePos.y, pos.z).RoomNumber; - GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + short probeRoomNumber = GetProbeRoomNumber(pos, location, probePos); return PointCollisionData(probePos, probeRoomNumber); } @@ -297,10 +304,11 @@ namespace TEN::Collision return PointCollisionData(item.Pose.Position, item.RoomNumber); } - // TODO: Find cleaner solution. Constructing a "location" on the spot for the player - // can result in a stumble when climbing onto thin platforms. -- Sezz 2022.06.14 static RoomVector GetEntityLocation(const ItemInfo& item) { + // TODO: Find cleaner solution. Constructing a "location" for the player on the spot + // can result in stumbles when climbing onto thin platforms. + // May have to do with player's room number being updated at half-height? -- Sezz 2022.06.14 if (item.IsLara()) return item.Location; @@ -317,10 +325,7 @@ namespace TEN::Collision // Calculate probe position. auto probePos = Geometry::TranslatePoint(item.Pose.Position, dir, dist); - - // Get probe position's room number. - short probeRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; - GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + short probeRoomNumber = GetProbeRoomNumber(item.Pose.Position, location, probePos); return PointCollisionData(probePos, probeRoomNumber); } @@ -332,10 +337,7 @@ namespace TEN::Collision // Calculate probe position. auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); - - // Get probe position's room number. - short probeRoomNumber = GetRoom(location, item.Pose.Position.x, probePos.y, item.Pose.Position.z).RoomNumber; - GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); + short probeRoomNumber = GetProbeRoomNumber(item.Pose.Position, location, probePos); return PointCollisionData(probePos, probeRoomNumber); } diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 0b604f3fe..7869e690f 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -4,6 +4,8 @@ enum RoomEnvFlags; class FloorInfo; +struct ItemInfo; +struct RoomVector; using namespace TEN::Math; @@ -21,12 +23,12 @@ namespace TEN::Collision FloorInfo* TopSectorPtr = nullptr; FloorInfo* BottomSectorPtr = nullptr; - std::optional FloorHeight = std::nullopt; - std::optional CeilingHeight = std::nullopt; - std::optional FloorNormal = std::nullopt; - std::optional CeilingNormal = std::nullopt; - std::optional FloorBridgeEntityID = std::nullopt; - std::optional CeilingBridgeEntityID = std::nullopt; + std::optional FloorHeight = std::nullopt; + std::optional CeilingHeight = std::nullopt; + std::optional FloorNormal = std::nullopt; + std::optional CeilingNormal = std::nullopt; + std::optional FloorBridgeItemNumber = std::nullopt; + std::optional CeilingBridgeItemNumber = std::nullopt; std::optional WaterSurfaceHeight = std::nullopt; std::optional WaterTopHeight = std::nullopt; @@ -45,8 +47,8 @@ namespace TEN::Collision int GetCeilingHeight(); Vector3 GetFloorNormal(); Vector3 GetCeilingNormal(); - int GetFloorBridgeEntityID(); - int GetCeilingBridgeEntityID(); + int GetFloorBridgeItemNumber(); + int GetCeilingBridgeItemNumber(); int GetWaterSurfaceHeight(); int GetWaterTopHeight(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index f3bb4f838..d62d17f5d 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -128,7 +128,7 @@ static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData collResult.Position.Floor = pointColl.GetFloorHeight(); collResult.Position.Ceiling = pointColl.GetCeilingHeight(); - collResult.Position.Bridge = pointColl.GetFloorBridgeEntityID(); + collResult.Position.Bridge = pointColl.GetFloorBridgeItemNumber(); collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; collResult.Position.FloorSlope = pointColl.IsSlipperyFloor(); collResult.Position.CeilingSlope = pointColl.IsSlipperyCeiling(); From bacb5c99ce2f05fe75227b40a28e71004b58e706 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 20 Aug 2023 17:56:53 +1000 Subject: [PATCH 021/410] Get location --- TombEngine/Game/collision/PointCollision.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 03ab3f7a0..3ac69ddf0 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -267,7 +267,7 @@ namespace TEN::Collision return probeRoomNumber; } - static RoomVector GetPositionLocation(const Vector3i& pos, int roomNumber) + static RoomVector GetLocation(const Vector3i& pos, int roomNumber) { short tempRoomNumber = roomNumber; const auto& sector = *GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber); @@ -278,7 +278,7 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) { // Get "location". - auto location = GetPositionLocation(pos, roomNumber); + auto location = GetLocation(pos, roomNumber); // Calculate probe position. auto probePos = Geometry::TranslatePoint(pos, dir, dist); @@ -290,7 +290,7 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { // Get "location". - auto location = GetPositionLocation(pos, roomNumber); + auto location = GetLocation(pos, roomNumber); // Calculate probe position. auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); @@ -304,7 +304,7 @@ namespace TEN::Collision return PointCollisionData(item.Pose.Position, item.RoomNumber); } - static RoomVector GetEntityLocation(const ItemInfo& item) + static RoomVector GetLocation(const ItemInfo& item) { // TODO: Find cleaner solution. Constructing a "location" for the player on the spot // can result in stumbles when climbing onto thin platforms. @@ -321,7 +321,7 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist) { // Get "location". - auto location = GetEntityLocation(item); + auto location = GetLocation(item); // Calculate probe position. auto probePos = Geometry::TranslatePoint(item.Pose.Position, dir, dist); @@ -333,7 +333,7 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) { // Get "location". - auto location = GetEntityLocation(item); + auto location = GetLocation(item); // Calculate probe position. auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); From 104066b91519f6d2efc9b8449f987e5c37185f81 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 20 Aug 2023 23:43:55 +1000 Subject: [PATCH 022/410] Get bridge surface normals --- TombEngine/Game/Lara/lara.cpp | 9 +- TombEngine/Game/collision/PointCollision.cpp | 96 +++++++++++++------- TombEngine/Game/collision/PointCollision.h | 4 + TombEngine/Game/collision/collide_room.cpp | 15 +-- 4 files changed, 78 insertions(+), 46 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 2c4f3198d..2ecc32754 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -448,8 +448,13 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) auto* lara = GetLaraInfo(item); auto pointColl = GetPointCollision(*item); - g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeEntityID()); - g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeEntityID()); + + auto origin = item->Pose.Position + Vector3i(0, -BLOCK(1), 0); + g_Renderer.AddLine3D(origin.ToVector3(), Geometry::TranslatePoint(origin, pointColl.GetFloorNormal(), BLOCK(0.5f)).ToVector3(), Vector4(0, 1, 0, 1)); + g_Renderer.AddLine3D(origin.ToVector3(), Geometry::TranslatePoint(origin, pointColl.GetCeilingNormal(), BLOCK(0.5f)).ToVector3(), Vector4(1, 0, 0, 1)); + + g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeItemNumber()); + g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeItemNumber()); if (lara->Control.Weapon.HasFired) { diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 3ac69ddf0..79cdc780a 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -5,7 +5,9 @@ #include "Game/collision/floordata.h" #include "Game/items.h" #include "Game/room.h" +#include "Game/Setup.h" #include "Math/Math.h" +#include "Objects/game_object_ids.h" #include "Specific/level.h" using namespace TEN::Collision::Floordata; @@ -104,8 +106,7 @@ namespace TEN::Collision // Set floor normal. if (GetFloorBridgeItemNumber() != NO_ITEM) { - // TODO: Get bridge normal. - FloorNormal = -Vector3::UnitY; + FloorNormal = GetBridgeNormal(true); } else { @@ -124,8 +125,7 @@ namespace TEN::Collision // Set ceiling normal. if (GetCeilingBridgeItemNumber() != NO_ITEM) { - // TODO: Get bridge normal. - CeilingNormal = Vector3::UnitY; + CeilingNormal = GetBridgeNormal(false); } else { @@ -195,7 +195,8 @@ namespace TEN::Collision bool PointCollisionData::IsWall() { - return (GetFloorHeight() == NO_HEIGHT || GetCeilingHeight() == NO_HEIGHT); + return (GetFloorHeight() == NO_HEIGHT || GetCeilingHeight() == NO_HEIGHT || + GetFloorHeight() < GetCeilingHeight()); } bool PointCollisionData::IsSlipperyFloor(short slopeAngleMin) @@ -204,8 +205,7 @@ namespace TEN::Collision auto floorNormal = GetFloorNormal(); auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); - // TODO: Slippery bridges. - return (GetFloorBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) @@ -214,8 +214,7 @@ namespace TEN::Collision auto ceilingNormal = GetCeilingNormal(); auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); - // TODO: Slippery bridges. - return (GetCeilingBridgeItemNumber() == NO_ITEM && abs(slopeAngle) >= slopeAngleMin); + return (abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsDiagonalStep() @@ -246,16 +245,39 @@ namespace TEN::Collision return ((room.flags & envFlag) == envFlag); } - PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) + // HACK. + Vector3 PointCollisionData::GetBridgeNormal(bool isFloor) { - // HACK: This function takes arguments for a *current* position and room number. - // However, since some calls to the previous implementation (GetCollision()) had *projected* - // positions passed to it, the room number must be corrected to account for such cases. - // They are primarily found in camera.cpp. - short correctedRoomNumber = roomNumber; - GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + constexpr auto ANGLE_STEP = ANGLE(11.25f); - return PointCollisionData(pos, correctedRoomNumber); + int itemNumber = isFloor ? GetFloorBridgeItemNumber() : GetCeilingBridgeItemNumber(); + const auto& item = g_Level.Items[itemNumber]; + + auto orient = item.Pose.Orientation; + switch (item.ObjectNumber) + { + default: + case ID_BRIDGE_FLAT: + break; + + case ID_BRIDGE_TILT1: + orient.z -= ANGLE_STEP; + break; + + case ID_BRIDGE_TILT2: + orient.z -= ANGLE_STEP * 2; + break; + + case ID_BRIDGE_TILT3: + orient.z -= ANGLE_STEP * 3; + break; + + case ID_BRIDGE_TILT4: + orient.z -= ANGLE_STEP * 4; + break; + } + + return Vector3::Transform(isFloor ? -Vector3::UnitY : Vector3::UnitY, orient.ToRotationMatrix()); } static int GetProbeRoomNumber(const Vector3i& pos, const RoomVector& location, const Vector3i& probePos) @@ -275,6 +297,32 @@ namespace TEN::Collision return RoomVector(sector.Room, pos.y); } + static RoomVector GetLocation(const ItemInfo& item) + { + // TODO: Find cleaner solution. Constructing a "location" for the player on the spot + // can result in stumbles when climbing onto thin platforms. + // May have to do with player's room number being updated at half-height? -- Sezz 2022.06.14 + if (item.IsLara()) + return item.Location; + + short tempRoomNumber = item.RoomNumber; + const auto& sector = *GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &tempRoomNumber); + + return RoomVector(sector.Room, item.Pose.Position.y); + } + + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) + { + // HACK: This function takes arguments for a *current* position and room number. + // However, since some calls to the previous implementation (GetCollision()) had *projected* + // positions passed to it, the room number must be corrected to account for such cases. + // They are primarily found in camera.cpp. + short correctedRoomNumber = roomNumber; + GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + + return PointCollisionData(pos, correctedRoomNumber); + } + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) { // Get "location". @@ -304,20 +352,6 @@ namespace TEN::Collision return PointCollisionData(item.Pose.Position, item.RoomNumber); } - static RoomVector GetLocation(const ItemInfo& item) - { - // TODO: Find cleaner solution. Constructing a "location" for the player on the spot - // can result in stumbles when climbing onto thin platforms. - // May have to do with player's room number being updated at half-height? -- Sezz 2022.06.14 - if (item.IsLara()) - return item.Location; - - short tempRoomNumber = item.RoomNumber; - const auto& sector = *GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &tempRoomNumber); - - return RoomVector(sector.Room, item.Pose.Position.y); - } - PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist) { // Get "location". diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 7869e690f..a61e78656 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -62,6 +62,10 @@ namespace TEN::Collision bool HasDiagonalSplit(); bool HasFlippedDiagonalSplit(); bool HasEnvironmentFlag(RoomEnvFlags envFlag); + + private: + // Helpers + Vector3 GetBridgeNormal(bool isFloor); }; PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index d62d17f5d..535262702 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -187,32 +187,21 @@ CollisionResult GetCollision(const GameVector& pos) return ConvertPointCollisionToCollisionResult(pointColl); } -// A reworked legacy GetFloorHeight() function which writes data -// into a special CollisionResult struct instead of global variables. -// It writes for both floor and ceiling heights at the same coordinates, meaning it should be used -// in place of successive GetFloorHeight() and GetCeilingHeight() calls to increase readability. +// Deprecated. CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) { auto result = CollisionResult{}; - // Record coordinates. result.Coordinates = Vector3i(x, y, z); - - // Return provided collision block into result as itself. - result.Block = floor; - - // Floor and ceiling heights are borrowed directly from floordata. result.Position.Floor = GetFloorHeight(RoomVector(floor->Room, y), x, z).value_or(NO_HEIGHT); result.Position.Ceiling = GetCeilingHeight(RoomVector(floor->Room, y), x, z).value_or(NO_HEIGHT); - // Probe bottom collision block through portals. + result.Block = floor; while (floor->GetRoomNumberBelow(x, y, z).value_or(NO_ROOM) != NO_ROOM) { auto* room = &g_Level.Rooms[floor->GetRoomNumberBelow(x, y, z).value_or(floor->Room)]; floor = GetSector(room, x - room->x, z - room->z); } - - // Return probed bottom collision block into result. result.BottomBlock = floor; // Get tilts. From 7acff7d9125d50dcbf157a56d7289e5c77deed51 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 22 Aug 2023 16:45:43 +1000 Subject: [PATCH 023/410] Update constant --- TombEngine/Game/collision/PointCollision.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 79cdc780a..7f05df2e1 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -248,7 +248,7 @@ namespace TEN::Collision // HACK. Vector3 PointCollisionData::GetBridgeNormal(bool isFloor) { - constexpr auto ANGLE_STEP = ANGLE(11.25f); + constexpr auto ANGLE_STEP = short(ANGLE(45.0f) / 4); int itemNumber = isFloor ? GetFloorBridgeItemNumber() : GetCeilingBridgeItemNumber(); const auto& item = g_Level.Items[itemNumber]; From 666fe3e60500cf45d8c5295de3dbff7b78faba06 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 27 Aug 2023 17:41:37 +1000 Subject: [PATCH 024/410] Simplify --- TombEngine/Game/collision/PointCollision.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 7f05df2e1..34c27c0a1 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -80,8 +80,8 @@ namespace TEN::Collision return *FloorHeight; // Set floor height. - auto roomVector = RoomVector(GetSector().Room, Position.y); - FloorHeight = Floordata::GetFloorHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + auto location = RoomVector(GetSector().Room, Position.y); + FloorHeight = Floordata::GetFloorHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); return *FloorHeight; } @@ -92,8 +92,8 @@ namespace TEN::Collision return *CeilingHeight; // Set ceiling height. - auto roomVector = RoomVector(GetSector().Room, Position.y); - CeilingHeight = Floordata::GetCeilingHeight(roomVector, Position.x, Position.z).value_or(NO_HEIGHT); + auto location = RoomVector(GetSector().Room, Position.y); + CeilingHeight = Floordata::GetCeilingHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); return *CeilingHeight; } @@ -277,7 +277,8 @@ namespace TEN::Collision break; } - return Vector3::Transform(isFloor ? -Vector3::UnitY : Vector3::UnitY, orient.ToRotationMatrix()); + int sign = isFloor ? -1 : 1; + return Vector3::Transform(Vector3::UnitY * sign, orient.ToRotationMatrix()); } static int GetProbeRoomNumber(const Vector3i& pos, const RoomVector& location, const Vector3i& probePos) From a8b1f6575ac25a92523dd9f7e2c72c5f3248eb87 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 27 Aug 2023 18:45:44 +1000 Subject: [PATCH 025/410] Update comments; make parameters const --- TombEngine/Game/collision/collide_room.cpp | 23 +++++++++++++--------- TombEngine/Game/collision/collide_room.h | 6 +++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 535262702..bdfa12a09 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -140,54 +140,56 @@ static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData return collResult; } +// NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo& item) { auto pointColl = GetPointCollision(item); return ConvertPointCollisionToCollisionResult(pointColl); } -CollisionResult GetCollision(ItemInfo* item) +// NOTE: Deprecated. Use GetPointCollision(). +CollisionResult GetCollision(const ItemInfo* item) { auto pointColl = GetPointCollision(*item); return ConvertPointCollisionToCollisionResult(pointColl); } -CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down, float right) +// NOTE: Deprecated. Use GetPointCollision(). +CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down, float right) { auto pointColl = GetPointCollision(*item, headingAngle, forward, down, right); return ConvertPointCollisionToCollisionResult(pointColl); } +// NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { auto pointColl = GetPointCollision(pos, roomNumber, headingAngle, forward, down, right); return ConvertPointCollisionToCollisionResult(pointColl); } -// Overload used as universal wrapper across collisional code replacing -// triads of roomNumber-GetFloor()-GetFloorHeight() calls. -// Advantage is that it does NOT modify incoming roomNumber argument, -// instead storing one modified by GetFloor() within a returned CollisionResult struct. -// This way, no external variables are modified as output arguments. +// NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber) { auto pointColl = GetPointCollision(pos, roomNumber); return ConvertPointCollisionToCollisionResult(pointColl); } +// NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(int x, int y, int z, short roomNumber) { auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); return ConvertPointCollisionToCollisionResult(pointColl); } +// NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const GameVector& pos) { auto pointColl = GetPointCollision(pos.ToVector3i(), pos.RoomNumber); return ConvertPointCollisionToCollisionResult(pointColl); } -// Deprecated. +// NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) { auto result = CollisionResult{}; @@ -213,7 +215,10 @@ CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) result.Position.SplitAngle = floor->FloorCollision.SplitAngle; result.Position.Bridge = result.BottomBlock->GetInsideBridgeItemNumber(x, result.Position.Floor, z, true, false); result.Position.FloorSlope = result.Position.Bridge < 0 && (abs(result.FloorTilt.x) >= 3 || (abs(result.FloorTilt.y) >= 3)); - result.Position.CeilingSlope = abs(result.CeilingTilt.x) >= 4 || abs(result.CeilingTilt.y) >= 4; // TODO: Fix on bridges placed beneath ceiling slopes. @Sezz 2022.01.29 + + // TODO: Fix on bridges placed beneath ceiling slopes. @Sezz 2022.01.29 + // NOTE: Already fixed if using GetPointCollision(). + result.Position.CeilingSlope = abs(result.CeilingTilt.x) >= 4 || abs(result.CeilingTilt.y) >= 4; return result; } diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 1ac8a1633..09558c0d7 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -129,10 +129,10 @@ struct CollisionInfo [[nodiscard]] bool TestItemRoomCollisionAABB(ItemInfo* item); -// All deprecated. Use GetPointCollision() instead. +// NOTE: All overloads deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo& item); -CollisionResult GetCollision(ItemInfo* item); -CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); +CollisionResult GetCollision(const ItemInfo* item); +CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); CollisionResult GetCollision(const Vector3i& pos, int roomNumber); CollisionResult GetCollision(int x, int y, int z, short roomNumber); From a286dbdd0309cccd32100a4d6bb19ccb72006b8f Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 27 Aug 2023 18:51:30 +1000 Subject: [PATCH 026/410] Update collide_room.cpp --- TombEngine/Game/collision/collide_room.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index bdfa12a09..646f9120e 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -117,7 +117,7 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) return collided; } -static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData& pointColl) +static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& pointColl) { auto collResult = CollisionResult{}; @@ -144,49 +144,49 @@ static CollisionResult ConvertPointCollisionToCollisionResult(PointCollisionData CollisionResult GetCollision(const ItemInfo& item) { auto pointColl = GetPointCollision(item); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo* item) { auto pointColl = GetPointCollision(*item); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down, float right) { auto pointColl = GetPointCollision(*item, headingAngle, forward, down, right); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) { auto pointColl = GetPointCollision(pos, roomNumber, headingAngle, forward, down, right); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber) { auto pointColl = GetPointCollision(pos, roomNumber); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(int x, int y, int z, short roomNumber) { auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const GameVector& pos) { auto pointColl = GetPointCollision(pos.ToVector3i(), pos.RoomNumber); - return ConvertPointCollisionToCollisionResult(pointColl); + return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). From fde6c2827be22e5012e500465272997e112bd905 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 27 Aug 2023 18:58:34 +1000 Subject: [PATCH 027/410] Add comment --- TombEngine/Game/collision/collide_room.h | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 09558c0d7..33365e2f7 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -55,6 +55,7 @@ struct CollisionPosition bool HasFlippedDiagonalSplit() { return (HasDiagonalSplit() && (SplitAngle != (45.0f * RADIAN))); } }; +// Deprecated. Use PointCollisionData. struct CollisionResult { Vector3i Coordinates; From 0d2d22fa8db7e0cfb97aedbb2270abaa81d067d4 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 29 Aug 2023 19:57:32 +1000 Subject: [PATCH 028/410] Add comment --- TombEngine/Game/collision/collide_room.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 646f9120e..4675bfc51 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -134,6 +134,7 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin collResult.Position.CeilingSlope = pointColl.IsSlipperyCeiling(); collResult.Position.DiagonalStep = pointColl.IsDiagonalStep(); + // NOTE: Bridge tilts ignored by old method. collResult.FloorTilt = pointColl.GetBottomSector().GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, true); collResult.CeilingTilt = pointColl.GetTopSector().GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, false); From 2833c35ac9561e91a046f4c345204418d2222832 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 29 Aug 2023 23:41:07 +1000 Subject: [PATCH 029/410] Add stub function for object intersections --- TombEngine/Game/collision/PointCollision.cpp | 11 +++++++++++ TombEngine/Game/collision/PointCollision.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 34c27c0a1..6715dd38b 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -193,6 +193,17 @@ namespace TEN::Collision return *WaterBottomHeight; } + Vector3 PointCollisionData::GetObjectIntersectPoint() + { + if (ObjectIntersectPoint.has_value()) + return *ObjectIntersectPoint; + + // Set object intersect point. + ObjectIntersectPoint = Vector3::Zero; + + return *ObjectIntersectPoint; + } + bool PointCollisionData::IsWall() { return (GetFloorHeight() == NO_HEIGHT || GetCeilingHeight() == NO_HEIGHT || diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index a61e78656..d9f8f1f7f 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -34,6 +34,8 @@ namespace TEN::Collision std::optional WaterTopHeight = std::nullopt; std::optional WaterBottomHeight = std::nullopt; + std::optional ObjectIntersectPoint = std::nullopt; + public: // Constructors PointCollisionData(const Vector3i& pos, int roomNumber); @@ -54,6 +56,9 @@ namespace TEN::Collision int GetWaterTopHeight(); int GetWaterBottomHeight(); + // TODO: Above and below. Also return reference to object itself? May need std::variant. + Vector3 GetObjectIntersectPoint(); + // Inquirers bool IsWall(); bool IsSlipperyFloor(short slopeAngleMin = DEFAULT_SLIPPERY_FLOOR_SLOPE_ANGLE); From 0d62bbb823d15c8d0806d0eb015b089ff140aaa8 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 3 Sep 2023 21:59:19 +1000 Subject: [PATCH 030/410] Remove dummy method to keep it simple for now --- TombEngine/Game/collision/PointCollision.cpp | 11 ----------- TombEngine/Game/collision/PointCollision.h | 3 --- 2 files changed, 14 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 6715dd38b..34c27c0a1 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -193,17 +193,6 @@ namespace TEN::Collision return *WaterBottomHeight; } - Vector3 PointCollisionData::GetObjectIntersectPoint() - { - if (ObjectIntersectPoint.has_value()) - return *ObjectIntersectPoint; - - // Set object intersect point. - ObjectIntersectPoint = Vector3::Zero; - - return *ObjectIntersectPoint; - } - bool PointCollisionData::IsWall() { return (GetFloorHeight() == NO_HEIGHT || GetCeilingHeight() == NO_HEIGHT || diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index d9f8f1f7f..3686fe7af 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -56,9 +56,6 @@ namespace TEN::Collision int GetWaterTopHeight(); int GetWaterBottomHeight(); - // TODO: Above and below. Also return reference to object itself? May need std::variant. - Vector3 GetObjectIntersectPoint(); - // Inquirers bool IsWall(); bool IsSlipperyFloor(short slopeAngleMin = DEFAULT_SLIPPERY_FLOOR_SLOPE_ANGLE); From 53ad627f7243642882053afffdb3a76714ecc2fb Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 7 Sep 2023 23:04:33 +1000 Subject: [PATCH 031/410] Update PointCollision.cpp --- TombEngine/Game/collision/PointCollision.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 34c27c0a1..3c932488f 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -143,7 +143,7 @@ namespace TEN::Collision // Set floor bridge item number. int floorHeight = GetFloorHeight(); - FloorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false);; + FloorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false); return *FloorBridgeItemNumber; } @@ -155,7 +155,7 @@ namespace TEN::Collision // Set ceiling bridge item number. int ceilingHeight = GetCeilingHeight(); - CeilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true);; + CeilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true); return *CeilingBridgeItemNumber; } @@ -196,7 +196,7 @@ namespace TEN::Collision bool PointCollisionData::IsWall() { return (GetFloorHeight() == NO_HEIGHT || GetCeilingHeight() == NO_HEIGHT || - GetFloorHeight() < GetCeilingHeight()); + GetFloorHeight() <= GetCeilingHeight()); } bool PointCollisionData::IsSlipperyFloor(short slopeAngleMin) From 2a19651480a7b12c8cbd804661220cb03a3c9ae0 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 7 Sep 2023 23:47:31 +1000 Subject: [PATCH 032/410] Update PointCollision.h --- TombEngine/Game/collision/PointCollision.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 3686fe7af..a61e78656 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -34,8 +34,6 @@ namespace TEN::Collision std::optional WaterTopHeight = std::nullopt; std::optional WaterBottomHeight = std::nullopt; - std::optional ObjectIntersectPoint = std::nullopt; - public: // Constructors PointCollisionData(const Vector3i& pos, int roomNumber); From a0eea51fbfae943253860db074b865f2e7fbdbee Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 8 Sep 2023 00:23:52 +1000 Subject: [PATCH 033/410] Move hack to deprecated functions. --- TombEngine/Game/collision/PointCollision.cpp | 9 +-------- TombEngine/Game/collision/collide_room.cpp | 21 +++++++++++++++++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 3c932488f..0b42afb25 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -314,14 +314,7 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) { - // HACK: This function takes arguments for a *current* position and room number. - // However, since some calls to the previous implementation (GetCollision()) had *projected* - // positions passed to it, the room number must be corrected to account for such cases. - // They are primarily found in camera.cpp. - short correctedRoomNumber = roomNumber; - GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); - - return PointCollisionData(pos, correctedRoomNumber); + return PointCollisionData(pos, roomNumber); } PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 4675bfc51..ac5bbffe4 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -172,21 +172,36 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingA // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber) { - auto pointColl = GetPointCollision(pos, roomNumber); + // HACK: GetPointCollision() takes arguments for a *current* position and room number. + // However, since some calls to this deprecated function had *projected* + // positions passed to it, the room number must be corrected to account for such cases. + // They are primarily found in camera.cpp. + short correctedRoomNumber = roomNumber; + GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + + auto pointColl = GetPointCollision(pos, correctedRoomNumber); return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(int x, int y, int z, short roomNumber) { - auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); + // HACK: Explained above. + short correctedRoomNumber = roomNumber; + GetFloor(x, y, z, &correctedRoomNumber); + + auto pointColl = GetPointCollision(Vector3i(x, y, z), correctedRoomNumber); return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const GameVector& pos) { - auto pointColl = GetPointCollision(pos.ToVector3i(), pos.RoomNumber); + // HACK: Explained above. + short correctedRoomNumber = pos.RoomNumber; + GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + + auto pointColl = GetPointCollision(pos.ToVector3i(), correctedRoomNumber); return ConvertPointCollDataToCollResult(pointColl); } From cb78e08d89c32adef9cd276102e3f92698dd8c2d Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 8 Sep 2023 00:29:41 +1000 Subject: [PATCH 034/410] Fix compile error --- TombEngine/Game/Lara/lara_overhang.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index 5a47625bf..b10fde0ee 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -960,7 +960,7 @@ void SlopeClimbExtra(ItemInfo* item, CollisionInfo* coll) // Extends LS_LADDER_IDLE (56) bool LadderMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { - auto probe = GetCollision(item); + auto probe = GetCollision(*item); if (probe.Position.CeilingSlope) return false; From ba3bd0b1d33afdea081eeba8494234401349d1db Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 13 Oct 2023 12:41:36 +1100 Subject: [PATCH 035/410] Include files --- TombEngine/TombEngine.vcxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index eb5f54535..75c2f5f68 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -323,6 +323,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -794,6 +795,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From b38d9754d741fe47f55ab5151aada30073f7f8f9 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 16 Oct 2023 16:20:52 +1100 Subject: [PATCH 036/410] Add error handling; don't duplicate constants --- TombEngine/Game/collision/PointCollision.cpp | 25 ++++++++------------ 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 0b42afb25..64290a100 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -201,19 +201,13 @@ namespace TEN::Collision bool PointCollisionData::IsSlipperyFloor(short slopeAngleMin) { - // Get floor slope angle. - auto floorNormal = GetFloorNormal(); - auto slopeAngle = Geometry::GetSurfaceSlopeAngle(floorNormal); - + auto slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); return (abs(slopeAngle) >= slopeAngleMin); } bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) { - // Get ceiling slope angle. - auto ceilingNormal = GetCeilingNormal(); - auto slopeAngle = Geometry::GetSurfaceSlopeAngle(ceilingNormal, -Vector3::UnitY); - + auto slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); return (abs(slopeAngle) >= slopeAngleMin); } @@ -224,19 +218,14 @@ namespace TEN::Collision bool PointCollisionData::HasDiagonalSplit() { - constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; - constexpr auto DIAGONAL_SPLIT_1 = 135.0f * RADIAN; - float splitAngle = GetBottomSector().FloorCollision.SplitAngle; - return (splitAngle == DIAGONAL_SPLIT_0 || splitAngle == DIAGONAL_SPLIT_1); + return (splitAngle == SurfaceCollisionData::SPLIT_ANGLE_0 || splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); } bool PointCollisionData::HasFlippedDiagonalSplit() { - constexpr auto DIAGONAL_SPLIT_0 = 45.0f * RADIAN; - float splitAngle = GetBottomSector().FloorCollision.SplitAngle; - return (HasDiagonalSplit() && splitAngle != DIAGONAL_SPLIT_0); + return (HasDiagonalSplit() && splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); } bool PointCollisionData::HasEnvironmentFlag(RoomEnvFlags envFlag) @@ -251,6 +240,12 @@ namespace TEN::Collision constexpr auto ANGLE_STEP = short(ANGLE(45.0f) / 4); int itemNumber = isFloor ? GetFloorBridgeItemNumber() : GetCeilingBridgeItemNumber(); + if (itemNumber == NO_ITEM) + { + TENLog("PointCollisionData error: invalid bridge item number in GetBridgeNormal().", LogLevel::Warning); + return -Vector3::UnitY; + } + const auto& item = g_Level.Items[itemNumber]; auto orient = item.Pose.Orientation; From b35367339ea7e1867d5d280ee5aec544f2343ecf Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 28 Oct 2023 16:49:02 +1100 Subject: [PATCH 037/410] Formatting --- TombEngine/Game/collision/PointCollision.cpp | 146 +++++++++---------- TombEngine/Game/collision/PointCollision.h | 28 ++-- 2 files changed, 87 insertions(+), 87 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 64290a100..32a912b0d 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -24,40 +24,20 @@ namespace TEN::Collision FloorInfo& PointCollisionData::GetSector() { - if (SectorPtr != nullptr) - return *SectorPtr; + if (_sectorPtr != nullptr) + return *_sectorPtr; // Set current sector pointer. short probeRoomNumber = RoomNumber; - SectorPtr = GetFloor(Position.x, Position.y, Position.z, &probeRoomNumber); + _sectorPtr = GetFloor(Position.x, Position.y, Position.z, &probeRoomNumber); - return *SectorPtr; - } - - FloorInfo& PointCollisionData::GetTopSector() - { - if (TopSectorPtr != nullptr) - return *TopSectorPtr; - - // Set top sector pointer. - auto* topSectorPtr = &GetSector(); - auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); - while (roomNumberAbove.has_value()) - { - auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->Room)]; - topSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); - - roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); - } - TopSectorPtr = topSectorPtr; - - return *TopSectorPtr; + return *_sectorPtr; } FloorInfo& PointCollisionData::GetBottomSector() { - if (BottomSectorPtr != nullptr) - return *BottomSectorPtr; + if (_bottomSectorPtr != nullptr) + return *_bottomSectorPtr; // Set bottom sector pointer. auto* bottomSectorPtr = &GetSector(); @@ -69,128 +49,148 @@ namespace TEN::Collision roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position.x, Position.y, Position.z); } - BottomSectorPtr = bottomSectorPtr; + _bottomSectorPtr = bottomSectorPtr; - return *BottomSectorPtr; + return *_bottomSectorPtr; + } + + FloorInfo& PointCollisionData::GetTopSector() + { + if (_topSectorPtr != nullptr) + return *_topSectorPtr; + + // Set top sector pointer. + auto* topSectorPtr = &GetSector(); + auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); + while (roomNumberAbove.has_value()) + { + auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->Room)]; + topSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + + roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position.x, Position.y, Position.z); + } + _topSectorPtr = topSectorPtr; + + return *_topSectorPtr; } int PointCollisionData::GetFloorHeight() { - if (FloorHeight.has_value()) - return *FloorHeight; + if (_floorHeight.has_value()) + return *_floorHeight; // Set floor height. auto location = RoomVector(GetSector().Room, Position.y); - FloorHeight = Floordata::GetFloorHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); + _floorHeight = Floordata::GetFloorHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); - return *FloorHeight; + return *_floorHeight; } int PointCollisionData::GetCeilingHeight() { - if (CeilingHeight.has_value()) - return *CeilingHeight; + if (_ceilingHeight.has_value()) + return *_ceilingHeight; // Set ceiling height. auto location = RoomVector(GetSector().Room, Position.y); - CeilingHeight = Floordata::GetCeilingHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); + _ceilingHeight = Floordata::GetCeilingHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); - return *CeilingHeight; + return *_ceilingHeight; } Vector3 PointCollisionData::GetFloorNormal() { - if (FloorNormal.has_value()) - return *FloorNormal; + if (_floorNormal.has_value()) + return *_floorNormal; // Set floor normal. if (GetFloorBridgeItemNumber() != NO_ITEM) { - FloorNormal = GetBridgeNormal(true); + _floorNormal = GetBridgeNormal(true); } else { auto floorTilt = GetBottomSector().GetSurfaceTilt(Position.x, Position.z, true); - FloorNormal = GetSurfaceNormal(floorTilt, true); + _floorNormal = GetSurfaceNormal(floorTilt, true); } - return *FloorNormal; + return *_floorNormal; } Vector3 PointCollisionData::GetCeilingNormal() { - if (CeilingNormal.has_value()) - return *CeilingNormal; + if (_ceilingNormal.has_value()) + return *_ceilingNormal; // Set ceiling normal. if (GetCeilingBridgeItemNumber() != NO_ITEM) { - CeilingNormal = GetBridgeNormal(false); + _ceilingNormal = GetBridgeNormal(false); } else { auto ceilingTilt = GetTopSector().GetSurfaceTilt(Position.x, Position.z, false); - CeilingNormal = GetSurfaceNormal(ceilingTilt, false); + _ceilingNormal = GetSurfaceNormal(ceilingTilt, false); } - return *CeilingNormal; + return *_ceilingNormal; } int PointCollisionData::GetFloorBridgeItemNumber() { - if (FloorBridgeItemNumber.has_value()) - return *FloorBridgeItemNumber; + if (_floorBridgeItemNumber.has_value()) + return *_floorBridgeItemNumber; // Set floor bridge item number. int floorHeight = GetFloorHeight(); - FloorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false); + _floorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Position.x, floorHeight, Position.z, true, false); - return *FloorBridgeItemNumber; + return *_floorBridgeItemNumber; } int PointCollisionData::GetCeilingBridgeItemNumber() { - if (CeilingBridgeItemNumber.has_value()) - return *CeilingBridgeItemNumber; + if (_ceilingBridgeItemNumber.has_value()) + return *_ceilingBridgeItemNumber; // Set ceiling bridge item number. int ceilingHeight = GetCeilingHeight(); - CeilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true); + _ceilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(Position.x, ceilingHeight, Position.z, false, true); - return *CeilingBridgeItemNumber; + return *_ceilingBridgeItemNumber; } int PointCollisionData::GetWaterSurfaceHeight() { - if (WaterSurfaceHeight.has_value()) - return *WaterSurfaceHeight; + if (_waterSurfaceHeight.has_value()) + return *_waterSurfaceHeight; // Set water surface height. - WaterSurfaceHeight = GetWaterSurface(Position.x, Position.y, Position.z, RoomNumber); + _waterSurfaceHeight = GetWaterSurface(Position.x, Position.y, Position.z, RoomNumber); - return *WaterSurfaceHeight; - } - - int PointCollisionData::GetWaterTopHeight() - { - if (WaterTopHeight.has_value()) - return *WaterTopHeight; - - // Set water top height. - WaterTopHeight = GetWaterHeight(Position.x, Position.y, Position.z, RoomNumber); - - return *WaterTopHeight; + return *_waterSurfaceHeight; } int PointCollisionData::GetWaterBottomHeight() { - if (WaterBottomHeight.has_value()) - return *WaterBottomHeight; + if (_waterBottomHeight.has_value()) + return *_waterBottomHeight; // Set water bottom height. - WaterBottomHeight = GetWaterDepth(Position.x, Position.y, Position.z, RoomNumber); + _waterBottomHeight = GetWaterDepth(Position.x, Position.y, Position.z, RoomNumber); - return *WaterBottomHeight; + return *_waterBottomHeight; + } + + int PointCollisionData::GetWaterTopHeight() + { + if (_waterTopHeight.has_value()) + return *_waterTopHeight; + + // Set water top height. + _waterTopHeight = GetWaterHeight(Position.x, Position.y, Position.z, RoomNumber); + + return *_waterTopHeight; } bool PointCollisionData::IsWall() diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index a61e78656..d8271d0d5 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -19,20 +19,20 @@ namespace TEN::Collision const int RoomNumber = 0; private: - FloorInfo* SectorPtr = nullptr; - FloorInfo* TopSectorPtr = nullptr; - FloorInfo* BottomSectorPtr = nullptr; + FloorInfo* _sectorPtr = nullptr; + FloorInfo* _bottomSectorPtr = nullptr; + FloorInfo* _topSectorPtr = nullptr; - std::optional FloorHeight = std::nullopt; - std::optional CeilingHeight = std::nullopt; - std::optional FloorNormal = std::nullopt; - std::optional CeilingNormal = std::nullopt; - std::optional FloorBridgeItemNumber = std::nullopt; - std::optional CeilingBridgeItemNumber = std::nullopt; + std::optional _floorHeight = std::nullopt; + std::optional _ceilingHeight = std::nullopt; + std::optional _floorNormal = std::nullopt; + std::optional _ceilingNormal = std::nullopt; + std::optional _floorBridgeItemNumber = std::nullopt; + std::optional _ceilingBridgeItemNumber = std::nullopt; - std::optional WaterSurfaceHeight = std::nullopt; - std::optional WaterTopHeight = std::nullopt; - std::optional WaterBottomHeight = std::nullopt; + std::optional _waterSurfaceHeight = std::nullopt; + std::optional _waterBottomHeight = std::nullopt; + std::optional _waterTopHeight = std::nullopt; public: // Constructors @@ -40,8 +40,8 @@ namespace TEN::Collision // Getters FloorInfo& GetSector(); - FloorInfo& GetTopSector(); FloorInfo& GetBottomSector(); + FloorInfo& GetTopSector(); int GetFloorHeight(); int GetCeilingHeight(); @@ -51,8 +51,8 @@ namespace TEN::Collision int GetCeilingBridgeItemNumber(); int GetWaterSurfaceHeight(); - int GetWaterTopHeight(); int GetWaterBottomHeight(); + int GetWaterTopHeight(); // Inquirers bool IsWall(); From 7aa1a8338b88c1a7779d2c06d626f839f5e85e55 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 28 Oct 2023 16:50:41 +1100 Subject: [PATCH 038/410] Update PointCollision.cpp --- TombEngine/Game/collision/PointCollision.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 32a912b0d..11a9c4138 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -237,19 +237,19 @@ namespace TEN::Collision // HACK. Vector3 PointCollisionData::GetBridgeNormal(bool isFloor) { - constexpr auto ANGLE_STEP = short(ANGLE(45.0f) / 4); + constexpr auto ANGLE_STEP = ANGLE(45.0f / 4); - int itemNumber = isFloor ? GetFloorBridgeItemNumber() : GetCeilingBridgeItemNumber(); - if (itemNumber == NO_ITEM) + int bridgeItemNumber = isFloor ? GetFloorBridgeItemNumber() : GetCeilingBridgeItemNumber(); + if (bridgeItemNumber == NO_ITEM) { TENLog("PointCollisionData error: invalid bridge item number in GetBridgeNormal().", LogLevel::Warning); return -Vector3::UnitY; } - const auto& item = g_Level.Items[itemNumber]; + const auto& bridgeItem = g_Level.Items[bridgeItemNumber]; - auto orient = item.Pose.Orientation; - switch (item.ObjectNumber) + auto orient = bridgeItem.Pose.Orientation; + switch (bridgeItem.ObjectNumber) { default: case ID_BRIDGE_FLAT: From fb20bf535509f1a7ac42837abd1d03c92e56e9af Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 4 Nov 2023 23:08:32 +1100 Subject: [PATCH 039/410] Complete method set --- TombEngine/Game/collision/PointCollision.cpp | 35 +++++++++++++++----- TombEngine/Game/collision/PointCollision.h | 16 +++++---- TombEngine/Game/collision/collide_room.cpp | 6 ++-- TombEngine/Game/collision/collide_room.h | 4 +-- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 11a9c4138..166d07657 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -199,36 +199,53 @@ namespace TEN::Collision GetFloorHeight() <= GetCeilingHeight()); } - bool PointCollisionData::IsSlipperyFloor(short slopeAngleMin) + bool PointCollisionData::IsIllegalFloor(short slopeAngleMin) { auto slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); return (abs(slopeAngle) >= slopeAngleMin); } - bool PointCollisionData::IsSlipperyCeiling(short slopeAngleMin) + bool PointCollisionData::IsIllegalCeiling(short slopeAngleMin) { auto slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); return (abs(slopeAngle) >= slopeAngleMin); } - bool PointCollisionData::IsDiagonalStep() + bool PointCollisionData::IsDiagonalFloorStep() { return GetBottomSector().IsSurfaceDiagonalStep(true); } + + bool PointCollisionData::IsDiagonalCeilingStep() + { + return GetTopSector().IsSurfaceDiagonalStep(false); + } - bool PointCollisionData::HasDiagonalSplit() + bool PointCollisionData::IsFloorDiagonalSplit() { float splitAngle = GetBottomSector().FloorCollision.SplitAngle; return (splitAngle == SurfaceCollisionData::SPLIT_ANGLE_0 || splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); } - - bool PointCollisionData::HasFlippedDiagonalSplit() + + bool PointCollisionData::IsCeilingDiagonalSplit() { - float splitAngle = GetBottomSector().FloorCollision.SplitAngle; - return (HasDiagonalSplit() && splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); + float splitAngle = GetTopSector().CeilingCollision.SplitAngle; + return (splitAngle == SurfaceCollisionData::SPLIT_ANGLE_0 || splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); } - bool PointCollisionData::HasEnvironmentFlag(RoomEnvFlags envFlag) + bool PointCollisionData::IsFloorFlippedDiagonalSplit() + { + float splitAngle = GetBottomSector().FloorCollision.SplitAngle; + return (IsDiagonalFloorStep() && splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); + } + + bool PointCollisionData::IsCeilingFlippedDiagonalSplit() + { + float splitAngle = GetTopSector().CeilingCollision.SplitAngle; + return (IsDiagonalCeilingStep() && splitAngle == SurfaceCollisionData::SPLIT_ANGLE_1); + } + + bool PointCollisionData::TestEnvironmentFlag(RoomEnvFlags envFlag) { const auto& room = g_Level.Rooms[RoomNumber]; return ((room.flags & envFlag) == envFlag); diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index d8271d0d5..92b56723a 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -56,12 +56,16 @@ namespace TEN::Collision // Inquirers bool IsWall(); - bool IsSlipperyFloor(short slopeAngleMin = DEFAULT_SLIPPERY_FLOOR_SLOPE_ANGLE); - bool IsSlipperyCeiling(short slopeAngleMin = DEFAULT_SLIPPERY_CEILING_SLOPE_ANGLE); - bool IsDiagonalStep(); - bool HasDiagonalSplit(); - bool HasFlippedDiagonalSplit(); - bool HasEnvironmentFlag(RoomEnvFlags envFlag); + bool IsIllegalFloor(short slopeAngleMin = DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE); + bool IsIllegalCeiling(short slopeAngleMin = DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE); + bool IsDiagonalFloorStep(); + bool IsDiagonalCeilingStep(); + bool IsFloorDiagonalSplit(); + bool IsCeilingDiagonalSplit(); + bool IsFloorFlippedDiagonalSplit(); + bool IsCeilingFlippedDiagonalSplit(); + + bool TestEnvironmentFlag(RoomEnvFlags envFlag); private: // Helpers diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index ac5bbffe4..2187f30ea 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -130,9 +130,9 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin collResult.Position.Ceiling = pointColl.GetCeilingHeight(); collResult.Position.Bridge = pointColl.GetFloorBridgeItemNumber(); collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorCollision.SplitAngle; - collResult.Position.FloorSlope = pointColl.IsSlipperyFloor(); - collResult.Position.CeilingSlope = pointColl.IsSlipperyCeiling(); - collResult.Position.DiagonalStep = pointColl.IsDiagonalStep(); + collResult.Position.FloorSlope = pointColl.IsIllegalFloor(); + collResult.Position.CeilingSlope = pointColl.IsIllegalCeiling(); + collResult.Position.DiagonalStep = pointColl.IsDiagonalFloorStep(); // NOTE: Bridge tilts ignored by old method. collResult.FloorTilt = pointColl.GetBottomSector().GetSurfaceTilt(pointColl.Position.x, pointColl.Position.z, true); diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 33365e2f7..2ef86555a 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -13,8 +13,8 @@ constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBou constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound. constexpr auto COLLISION_CHECK_DISTANCE = BLOCK(8); -constexpr auto DEFAULT_SLIPPERY_FLOOR_SLOPE_ANGLE = short(ANGLE(45.0f) * 0.75f); -constexpr auto DEFAULT_SLIPPERY_CEILING_SLOPE_ANGLE = ANGLE(45.0f); +constexpr auto DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE = ANGLE(45.0f * 0.75f); +constexpr auto DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE = ANGLE(45.0f); enum CollisionType { From bb21ea285ef32fdeb71b6d70f948b28f076f15d7 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 25 Nov 2023 20:03:02 +1100 Subject: [PATCH 040/410] Update collide_room.cpp --- TombEngine/Game/collision/collide_room.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 44a8af74e..5f07dafbf 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -134,13 +134,13 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin collResult.Position.Ceiling = pointColl.GetCeilingHeight(); collResult.Position.Bridge = pointColl.GetFloorBridgeItemNumber(); collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorSurface.SplitAngle; - collResult.Position.FloorSlope = pointColl.IsIllegalFloor(); + collResult.Position.FloorSlope = collResult.Position.Bridge == NO_ITEM && pointColl.IsIllegalFloor(); collResult.Position.CeilingSlope = pointColl.IsIllegalCeiling(); collResult.Position.DiagonalStep = pointColl.IsDiagonalFloorStep(); // NOTE: Bridge tilts ignored by old method. - collResult.FloorTilt = GetSurfaceTilt(pointColl.GetBottomSector().GetSurfaceNormal(pointColl.Position.x, pointColl.Position.z, true), true).ToVector2(); - collResult.CeilingTilt = GetSurfaceTilt(pointColl.GetTopSector().GetSurfaceNormal(pointColl.Position.x, pointColl.Position.z, false), false).ToVector2(); + collResult.FloorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true).ToVector2(); + collResult.CeilingTilt = GetSurfaceTilt(pointColl.GetCeilingNormal(), false).ToVector2(); return collResult; } @@ -219,12 +219,15 @@ CollisionResult GetCollision(const GameVector& pos) // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) { + auto pointColl = GetPointCollision(Vector3i(x, y, z), floor->RoomNumber); + return ConvertPointCollDataToCollResult(pointColl); + auto result = CollisionResult{}; result.Coordinates = Vector3i(x, y, z); result.Position.Floor = GetFloorHeight(RoomVector(floor->RoomNumber, y), x, z).value_or(NO_HEIGHT); result.Position.Ceiling = GetCeilingHeight(RoomVector(floor->RoomNumber, y), x, z).value_or(NO_HEIGHT); - + result.Block = floor; while (floor->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) { From 26a54e211c5bd9ada40dcfd309f557075949549c Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 25 Nov 2023 20:10:04 +1100 Subject: [PATCH 041/410] Fix slopes --- TombEngine/Game/collision/PointCollision.cpp | 8 ++++---- TombEngine/Game/collision/collide_room.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index f417d0951..0bf6ece89 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -199,14 +199,14 @@ namespace TEN::Collision bool PointCollisionData::IsIllegalFloor(short slopeAngleMin) { - auto slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); - return (abs(slopeAngle) >= FROM_RAD(GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true))); + short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); + return (abs(slopeAngle) >= GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true)); } bool PointCollisionData::IsIllegalCeiling(short slopeAngleMin) { - auto slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); - return (abs(slopeAngle) >= FROM_RAD(GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false))); + short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); + return (abs(slopeAngle) >= GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false)); } bool PointCollisionData::IsDiagonalFloorStep() diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 5f07dafbf..a4263d6cc 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -137,10 +137,12 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin collResult.Position.FloorSlope = collResult.Position.Bridge == NO_ITEM && pointColl.IsIllegalFloor(); collResult.Position.CeilingSlope = pointColl.IsIllegalCeiling(); collResult.Position.DiagonalStep = pointColl.IsDiagonalFloorStep(); + collResult.FloorNormal = pointColl.GetFloorNormal(); + collResult.CeilingNormal = pointColl.GetCeilingNormal(); // NOTE: Bridge tilts ignored by old method. - collResult.FloorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true).ToVector2(); - collResult.CeilingTilt = GetSurfaceTilt(pointColl.GetCeilingNormal(), false).ToVector2(); + collResult.FloorTilt = GetSurfaceTilt(collResult.FloorNormal, true).ToVector2(); + collResult.CeilingTilt = GetSurfaceTilt(collResult.CeilingNormal, false).ToVector2(); return collResult; } From 3533d49d9df03edf7ae98a3d6ad80686453c5199 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 25 Nov 2023 20:19:27 +1100 Subject: [PATCH 042/410] Fix monkey swing bridges below illegal ceilings --- TombEngine/Game/collision/PointCollision.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 0bf6ece89..04317e0ea 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -199,14 +199,22 @@ namespace TEN::Collision bool PointCollisionData::IsIllegalFloor(short slopeAngleMin) { + if (GetFloorBridgeItemNumber() != NO_ITEM) + return false; + short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); - return (abs(slopeAngle) >= GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true)); + short illegalSlopeAngle = GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true); + return (abs(slopeAngle) >= illegalSlopeAngle); } bool PointCollisionData::IsIllegalCeiling(short slopeAngleMin) { + if (GetCeilingBridgeItemNumber() != NO_ITEM) + return false; + short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); - return (abs(slopeAngle) >= GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false)); + short illegalSlopeAngle = GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false); + return (abs(slopeAngle) >= illegalSlopeAngle); } bool PointCollisionData::IsDiagonalFloorStep() From d5ac711da4f6dded97249a82d4ee7b208e094a80 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 21 Jan 2024 23:40:06 +1100 Subject: [PATCH 043/410] Extend GetPointCollision(); fix merge errors --- TombEngine/Game/collision/PointCollision.cpp | 21 ++++++++++---------- TombEngine/Game/collision/PointCollision.h | 6 ++++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 04317e0ea..c019096c9 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -81,7 +81,7 @@ namespace TEN::Collision // Set floor height. auto location = RoomVector(GetSector().RoomNumber, Position.y); - _floorHeight = Floordata::GetFloorHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); + _floorHeight = Floordata::GetSurfaceHeight(location, Position.x, Position.z, true).value_or(NO_HEIGHT); return *_floorHeight; } @@ -93,7 +93,7 @@ namespace TEN::Collision // Set ceiling height. auto location = RoomVector(GetSector().RoomNumber, Position.y); - _ceilingHeight = Floordata::GetCeilingHeight(location, Position.x, Position.z).value_or(NO_HEIGHT); + _ceilingHeight = Floordata::GetSurfaceHeight(location, Position.x, Position.z, false).value_or(NO_HEIGHT); return *_ceilingHeight; } @@ -141,7 +141,8 @@ namespace TEN::Collision // Set floor bridge item number. int floorHeight = GetFloorHeight(); - _floorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(Vector3i(Position.x, floorHeight, Position.z), true, false); + auto pos = Vector3i(Position.x, floorHeight, Position.z); + _floorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(pos, true, false); return *_floorBridgeItemNumber; } @@ -153,7 +154,8 @@ namespace TEN::Collision // Set ceiling bridge item number. int ceilingHeight = GetCeilingHeight(); - _ceilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(Vector3i(Position.x, ceilingHeight, Position.z), false, true); + auto pos = Vector3i(Position.x, ceilingHeight, Position.z); + _ceilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(pos, false, true); return *_ceilingBridgeItemNumber; } @@ -312,8 +314,7 @@ namespace TEN::Collision static RoomVector GetLocation(const ItemInfo& item) { - // TODO: Find cleaner solution. Constructing a "location" for the player on the spot - // can result in stumbles when climbing onto thin platforms. + // TODO: Find cleaner solution. Manually constructing a player "location" can result in stumbles when climbing onto thin platforms. // May have to do with player's room number being updated at half-height? -- Sezz 2022.06.14 if (item.IsLara()) return item.Location; @@ -341,13 +342,13 @@ namespace TEN::Collision return PointCollisionData(probePos, probeRoomNumber); } - PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right, const Vector3& axis) { // Get "location". auto location = GetLocation(pos, roomNumber); // Calculate probe position. - auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right); + auto probePos = Geometry::TranslatePoint(pos, headingAngle, forward, down, right, axis); short probeRoomNumber = GetProbeRoomNumber(pos, location, probePos); return PointCollisionData(probePos, probeRoomNumber); @@ -370,13 +371,13 @@ namespace TEN::Collision return PointCollisionData(probePos, probeRoomNumber); } - PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right) + PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down, float right, const Vector3& axis) { // Get "location". auto location = GetLocation(item); // Calculate probe position. - auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right); + auto probePos = Geometry::TranslatePoint(item.Pose.Position, headingAngle, forward, down, right, axis); short probeRoomNumber = GetProbeRoomNumber(item.Pose.Position, location, probePos); return PointCollisionData(probePos, probeRoomNumber); diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 447e75f50..be315cb6f 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -73,9 +73,11 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber); PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist); - PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); + PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f, + const Vector3& axis = Vector3::UnitY); PointCollisionData GetPointCollision(const ItemInfo& item); PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist); - PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); + PointCollisionData GetPointCollision(const ItemInfo& item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f, + const Vector3& axis = Vector3::UnitY); } From 7c21558f18805b518938789c883f1e58dcb2bae4 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 31 Jan 2024 18:19:59 +1100 Subject: [PATCH 044/410] Implement missing method --- TombEngine/Game/collision/PointCollision.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index c019096c9..65ae7628d 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -235,6 +235,12 @@ namespace TEN::Collision return (splitAngle == SectorSurfaceData::SPLIT_ANGLE_0 || splitAngle == SectorSurfaceData::SPLIT_ANGLE_1); } + bool PointCollisionData::IsCeilingDiagonalSplit() + { + float splitAngle = GetTopSector().CeilingSurface.SplitAngle; + return (splitAngle == SectorSurfaceData::SPLIT_ANGLE_0 || splitAngle == SectorSurfaceData::SPLIT_ANGLE_1); + } + bool PointCollisionData::IsFloorFlippedDiagonalSplit() { float splitAngle = GetBottomSector().FloorSurface.SplitAngle; From 85c35e4eb3d9b48eb64bc808b92901c0bcb04eac Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 31 Jan 2024 18:35:45 +1100 Subject: [PATCH 045/410] Remove warning --- TombEngine/Game/collision/PointCollision.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 65ae7628d..dcfdb7277 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -265,12 +265,6 @@ namespace TEN::Collision constexpr auto ANGLE_STEP = ANGLE(45.0f / 4); int bridgeItemNumber = isFloor ? GetFloorBridgeItemNumber() : GetCeilingBridgeItemNumber(); - if (bridgeItemNumber == NO_ITEM) - { - TENLog("PointCollisionData error: invalid bridge item number in GetBridgeNormal().", LogLevel::Warning); - return -Vector3::UnitY; - } - const auto& bridgeItem = g_Level.Items[bridgeItemNumber]; auto orient = bridgeItem.Pose.Orientation; From bedc4ee37ad44876e00701795ed68b706a5f700a Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 1 Feb 2024 16:45:26 +1100 Subject: [PATCH 046/410] Update bridge parenting; let bridge orientation influence collision --- TombEngine/Game/Lara/lara.cpp | 60 ++++++++++++++++++++ TombEngine/Game/collision/PointCollision.cpp | 16 +++--- TombEngine/Game/collision/collide_item.cpp | 33 +++++------ TombEngine/Game/collision/collide_item.h | 2 +- TombEngine/Game/collision/collide_room.cpp | 36 +----------- TombEngine/Game/collision/floordata.cpp | 2 +- 6 files changed, 88 insertions(+), 61 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 45d1ce32c..02f5b9cd1 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -63,10 +63,68 @@ LaraInfo Lara = {}; ItemInfo* LaraItem; CollisionInfo LaraCollision = {}; +//---------debug +#include +#include "Specific/Input/Input.h" +//---------- + void LaraControl(ItemInfo* item, CollisionInfo* coll) { auto& player = GetLaraInfo(*item); + //---------debug + + static int bridgeItemNumber = NO_ITEM; + if (coll->LastBridgeItemNumber != NO_ITEM) + bridgeItemNumber = coll->LastBridgeItemNumber; + + if (bridgeItemNumber != NO_ITEM) + { + constexpr auto TRANSLATE_STEP = BLOCK(0.1f); + + auto& bridgeItem = g_Level.Items[bridgeItemNumber]; + + // Move bridge. + if (KeyMap[OIS::KeyCode::KC_K]) + { + auto rotMatrix = EulerAngles(0, Camera.actualAngle, 0).ToRotationMatrix(); + auto offset = Vector3(AxisMap[(int)InputAxis::Mouse].x, 0.0f, -AxisMap[(int)InputAxis::Mouse].y) * 1000; + bridgeItem.Pose.Position += Vector3::Transform(offset, rotMatrix); + + UpdateItemRoom(bridgeItem.Index); + UpdateBridgeItem(bridgeItem); + } + else if (KeyMap[OIS::KeyCode::KC_L]) + { + auto offset = Vector3(0.0f, AxisMap[(int)InputAxis::Mouse].y, 0.0f) * 1000; + bridgeItem.Pose.Position += offset; + + UpdateItemRoom(bridgeItem.Index); + UpdateBridgeItem(bridgeItem); + } + // Rotate bridge. + else if (KeyMap[OIS::KeyCode::KC_H]) + { + auto rotMatrix = EulerAngles(0, Camera.actualAngle, 0).ToRotationMatrix(); + auto offset = Vector3(AxisMap[(int)InputAxis::Mouse].x, 0.0f, -AxisMap[(int)InputAxis::Mouse].y) * 10000; + offset = Vector3::Transform(offset, rotMatrix); + + auto rot = EulerAngles(-AxisMap[(int)InputAxis::Mouse].x * 10000, 0.0f, -AxisMap[(int)InputAxis::Mouse].y * 10000); + bridgeItem.Pose.Orientation += rot; + + UpdateItemRoom(bridgeItem.Index); + UpdateBridgeItem(bridgeItem); + } + else if (KeyMap[OIS::KeyCode::KC_J]) + { + auto rot = EulerAngles(0.0f, AxisMap[(int)InputAxis::Mouse].y * 10000, 0.0f); + bridgeItem.Pose.Orientation += rot; + + UpdateItemRoom(bridgeItem.Index); + UpdateBridgeItem(bridgeItem); + } + } + auto pointColl = GetPointCollision(*item); auto origin = item->Pose.Position + Vector3i(0, -BLOCK(1), 0); @@ -76,6 +134,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeItemNumber()); g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeItemNumber()); + //---------- + // Alert nearby creatures. if (player.Control.Weapon.HasFired) { diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index dcfdb7277..918f6ad06 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -201,21 +201,21 @@ namespace TEN::Collision bool PointCollisionData::IsIllegalFloor(short slopeAngleMin) { - if (GetFloorBridgeItemNumber() != NO_ITEM) - return false; - short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); - short illegalSlopeAngle = GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true); + short illegalSlopeAngle = (GetFloorBridgeItemNumber() != NO_ITEM) ? + DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE : + GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true); + return (abs(slopeAngle) >= illegalSlopeAngle); } bool PointCollisionData::IsIllegalCeiling(short slopeAngleMin) { - if (GetCeilingBridgeItemNumber() != NO_ITEM) - return false; - short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); - short illegalSlopeAngle = GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false); + short illegalSlopeAngle = (GetCeilingBridgeItemNumber() != NO_ITEM) ? + DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE : + GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false); + return (abs(slopeAngle) >= illegalSlopeAngle); } diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 534194a3d..d6ac72700 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -898,22 +898,20 @@ void ItemPushBridge(ItemInfo& item, CollisionInfo& coll) ShiftItem(&item, &coll); } -void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResult& collResult) +void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResult& pointColl) { - // Store an offset for a bridge item into shifts, if exists. - if (coll.LastBridgeItemNumber == collResult.Position.Bridge && coll.LastBridgeItemNumber != NO_ITEM) + // Store offset for bridge item into shifts if it exists. + if (coll.LastBridgeItemNumber == pointColl.Position.Bridge && + coll.LastBridgeItemNumber != NO_ITEM) { - auto& bridgeItem = g_Level.Items[collResult.Position.Bridge]; + auto& bridgeItem = g_Level.Items[pointColl.Position.Bridge]; auto deltaPos = bridgeItem.Pose.Position - coll.LastBridgeItemPose.Position; auto deltaOrient = bridgeItem.Pose.Orientation - coll.LastBridgeItemPose.Orientation; auto deltaPose = Pose(deltaPos, deltaOrient); - int absDeltaHeight = item.Pose.Position.y - collResult.Position.Floor; - int relDeltaHeight = absDeltaHeight + GameBoundingBox(&item).Y2; - - if (deltaPose != Pose::Zero && - (abs(absDeltaHeight) <= CLICK(1 / 8.0f) || abs(relDeltaHeight) <= CLICK(1 / 8.0f))) + // Item is grounded and bridge position changed; set shift. + if (deltaPose != Pose::Zero && !item.Animation.IsAirborne) { const auto& bridgePos = bridgeItem.Pose.Position; @@ -923,15 +921,18 @@ void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResu auto offset = bridgePos.ToVector3() + Vector3::Transform(relOffset, rotMatrix); deltaPose.Position -= item.Pose.Position - Vector3i(offset); - - // Don't update shifts if difference is too big (possibly bridge was teleported or just entered bridge). - if (deltaPose.Position.ToVector3().Length() <= coll.Setup.Radius * 2) + + // Don't update shifts if difference is too big (bridge was possibly teleported or just entered). + if (Vector2(deltaPose.Position.x, deltaPose.Position.z).Length() <= (coll.Setup.Radius * 2)) + { + deltaPose.Orientation = EulerAngles(0, deltaPose.Orientation.y, 0); coll.Shift = deltaPose; + } } - else if (deltaPos.ToVector3().Length() <= coll.Setup.Radius && relDeltaHeight > 0 && - (deltaPos != Vector3i::Zero || deltaOrient != EulerAngles::Identity)) + // Push item. + else if (Vector2(deltaPose.Position.x, deltaPose.Position.z).Length() <= coll.Setup.Radius && + (deltaPos != Vector3i::Zero || deltaOrient != EulerAngles::Identity)) { - // Push item away if not directly above bridge, and bridge position was changed. ItemPushItem(&bridgeItem, &item); } @@ -943,7 +944,7 @@ void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResu coll.LastBridgeItemNumber = NO_ITEM; } - coll.LastBridgeItemNumber = collResult.Position.Bridge; + coll.LastBridgeItemNumber = pointColl.Position.Bridge; } void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll) diff --git a/TombEngine/Game/collision/collide_item.h b/TombEngine/Game/collision/collide_item.h index 68f02bbe2..31a275928 100644 --- a/TombEngine/Game/collision/collide_item.h +++ b/TombEngine/Game/collision/collide_item.h @@ -45,7 +45,7 @@ void ItemPushBridge(ItemInfo& item, CollisionInfo& coll); bool CollideSolidBounds(ItemInfo* item, const GameBoundingBox& box, const Pose& pose, CollisionInfo* coll); void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll); -void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResult& collResult); +void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResult& pointColl); void AIPickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void ObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index ab1f055a0..61d0a3286 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -143,7 +143,7 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin // NOTE: Bridge tilts ignored by old method. collResult.FloorTilt = GetSurfaceTilt(collResult.FloorNormal, true).ToVector2(); collResult.CeilingTilt = GetSurfaceTilt(collResult.CeilingNormal, false).ToVector2(); - + return collResult; } @@ -223,40 +223,6 @@ CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) { auto pointColl = GetPointCollision(Vector3i(x, y, z), floor->RoomNumber); return ConvertPointCollDataToCollResult(pointColl); - - auto result = CollisionResult{}; - - result.Coordinates = Vector3i(x, y, z); - result.Position.Floor = GetFloorHeight(RoomVector(floor->RoomNumber, y), x, z).value_or(NO_HEIGHT); - result.Position.Ceiling = GetCeilingHeight(RoomVector(floor->RoomNumber, y), x, z).value_or(NO_HEIGHT); - - result.Block = floor; - while (floor->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) - { - auto* room = &g_Level.Rooms[floor->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(floor->RoomNumber)]; - floor = Room::GetSector(room, x - room->x, z - room->z); - } - result.BottomBlock = floor; - - // Get surface noramls. - result.FloorNormal = floor->GetSurfaceNormal(x, z, true); - result.CeilingNormal = floor->GetSurfaceNormal(x, z, false); - - // Backport surface normals to tilts. - result.FloorTilt = GetSurfaceTilt(result.FloorNormal, true).ToVector2(); - result.CeilingTilt = GetSurfaceTilt(result.CeilingNormal, false).ToVector2(); - - // Split, bridge and slope data. - result.Position.DiagonalStep = floor->IsSurfaceDiagonalStep(true); - result.Position.SplitAngle = TO_RAD(floor->FloorSurface.SplitAngle); - result.Position.Bridge = result.BottomBlock->GetInsideBridgeItemNumber(Vector3i(x, result.Position.Floor, z), true, false); - result.Position.FloorSlope = result.Position.Bridge < 0 && (abs(result.FloorTilt.x) >= 3 || (abs(result.FloorTilt.y) >= 3)); - - // TODO: Fix on bridges placed beneath ceiling slopes. @Sezz 2022.01.29 - // NOTE: Already fixed if using GetPointCollision(). - result.Position.CeilingSlope = abs(result.CeilingTilt.x) >= 4 || abs(result.CeilingTilt.y) >= 4; - - return result; } void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index be7a49f2a..01e386268 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -925,7 +925,7 @@ namespace TEN::Collision::Floordata // Ray intersects box; return bridge box height. float dist = 0.0f; if (box.Intersects(origin, dir, dist)) - return (item.Pose.Position.y + (useBottomHeight ? bounds.Y2 : bounds.Y1)); + return Geometry::TranslatePoint(origin, dir, dist).y; return std::nullopt; } From 68899231f49e593b404dafcf7eba5105982c2324 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 1 Feb 2024 17:23:36 +1100 Subject: [PATCH 047/410] Update PointCollisionData class; adopt PointCollisionData in camera.cpp --- TombEngine/Game/camera.cpp | 278 +++++++++---------- TombEngine/Game/collision/PointCollision.cpp | 70 +++-- TombEngine/Game/collision/PointCollision.h | 12 +- TombEngine/Game/collision/collide_room.cpp | 25 +- 4 files changed, 195 insertions(+), 190 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 4c74ce093..c07b395b9 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -134,8 +134,8 @@ static int GetLookCameraVerticalOffset(const ItemInfo& item, const CollisionInfo } // Get floor-to-ceiling height. - auto pointColl = GetCollision(item); - int floorToCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + auto pointColl = GetPointCollision(item); + int floorToCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); // Return appropriate vertical offset. return -((verticalOffset < floorToCeilHeight) ? verticalOffset : floorToCeilHeight); @@ -175,8 +175,8 @@ void LookCamera(ItemInfo& item, const CollisionInfo& coll) auto lookAtPos = Geometry::TranslatePoint(pivotPos, orient, LOOK_AT_DIST); // Determine best position. - auto origin = GameVector(pivotPos, GetPointCollision(item, item.Pose.Orientation.y, pivotOffset.z, pivotOffset.y).RoomNumber); - auto target = GameVector(idealPos, GetPointCollision(origin.ToVector3i(), origin.RoomNumber, orient.ToDirection(), idealDist).RoomNumber); + auto origin = GameVector(pivotPos, GetPointCollision(item, item.Pose.Orientation.y, pivotOffset.z, pivotOffset.y).GetRoomNumber()); + auto target = GameVector(idealPos, GetPointCollision(origin.ToVector3i(), origin.RoomNumber, orient.ToDirection(), idealDist).GetRoomNumber()); // Handle room and object collisions. LOSAndReturnTarget(&origin, &target, 0); @@ -345,9 +345,9 @@ void MoveCamera(GameVector* ideal, int speed) if (TestEnvironment(ENV_FLAG_SWAMP, Camera.pos.RoomNumber)) y = g_Level.Rooms[Camera.pos.RoomNumber].y - CLICK(1); - auto probe = GetCollision(Camera.pos.x, y, Camera.pos.z, Camera.pos.RoomNumber); - if (y < probe.Position.Ceiling || - y > probe.Position.Floor) + auto pointColl = GetPointCollision(Vector3i(Camera.pos.x, y, Camera.pos.z), Camera.pos.RoomNumber); + if (y < pointColl.GetCeilingHeight() || + y > pointColl.GetFloorHeight()) { LOSAndReturnTarget(&Camera.target, &Camera.pos, 0); @@ -366,41 +366,41 @@ void MoveCamera(GameVector* ideal, int speed) } } - probe = GetCollision(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber); + pointColl = GetPointCollision(Camera.pos.ToVector3i(), Camera.pos.RoomNumber); int buffer = CLICK(1) - 1; - if ((Camera.pos.y - buffer) < probe.Position.Ceiling && - (Camera.pos.y + buffer) > probe.Position.Floor && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + if ((Camera.pos.y - buffer) < pointColl.GetCeilingHeight() && + (Camera.pos.y + buffer) > pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - Camera.pos.y = (probe.Position.Floor + probe.Position.Ceiling) / 2; + Camera.pos.y = (pointColl.GetFloorHeight() + pointColl.GetCeilingHeight()) / 2; } - else if ((Camera.pos.y + buffer) > probe.Position.Floor && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + else if ((Camera.pos.y + buffer) > pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - Camera.pos.y = probe.Position.Floor - buffer; + Camera.pos.y = pointColl.GetFloorHeight() - buffer; } - else if ((Camera.pos.y - buffer) < probe.Position.Ceiling && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + else if ((Camera.pos.y - buffer) < pointColl.GetCeilingHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - Camera.pos.y = probe.Position.Ceiling + buffer; + Camera.pos.y = pointColl.GetCeilingHeight() + buffer; } - else if (probe.Position.Ceiling >= probe.Position.Floor || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT) + else if (pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT) { Camera.pos = *ideal; } ItemsCollideCamera(); - Camera.pos.RoomNumber = GetCollision(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber).RoomNumber; + Camera.pos.RoomNumber = GetPointCollision(Camera.pos.ToVector3i(), Camera.pos.RoomNumber).GetRoomNumber(); LookAt(&Camera, 0); UpdateMikePos(*LaraItem); Camera.oldType = Camera.type; @@ -467,7 +467,7 @@ void MoveObjCamera(GameVector* ideal, ItemInfo* camSlotId, int camMeshId, ItemIn } Camera.pos += (ideal->ToVector3i() - Camera.pos.ToVector3i()) / speed; - Camera.pos.RoomNumber = GetCollision(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber).RoomNumber; + Camera.pos.RoomNumber = GetPointCollision(Camera.pos.ToVector3i(), Camera.pos.RoomNumber).GetRoomNumber(); LookAt(&Camera, 0); auto angle = Camera.target.ToVector3i() - Camera.pos.ToVector3i(); @@ -531,21 +531,23 @@ void ChaseCamera(ItemInfo* item) int distance = Camera.targetDistance * phd_cos(Camera.actualElevation); - auto probe = GetCollision(Camera.target.x, Camera.target.y + CLICK(1), Camera.target.z, Camera.target.RoomNumber); + auto pointColl = GetPointCollision(Vector3i(Camera.target.x, Camera.target.y + CLICK(1), Camera.target.z), Camera.target.RoomNumber); - if (TestEnvironment(ENV_FLAG_SWAMP, probe.RoomNumber)) - Camera.target.y = g_Level.Rooms[probe.RoomNumber].maxceiling - CLICK(1); + if (TestEnvironment(ENV_FLAG_SWAMP, pointColl.GetRoomNumber())) + Camera.target.y = g_Level.Rooms[pointColl.GetRoomNumber()].maxceiling - CLICK(1); int y = Camera.target.y; - probe = GetCollision(Camera.target.x, y, Camera.target.z, Camera.target.RoomNumber); - if (((y < probe.Position.Ceiling || probe.Position.Floor < y) || probe.Position.Floor <= probe.Position.Ceiling) || - (probe.Position.Floor == NO_HEIGHT || probe.Position.Ceiling == NO_HEIGHT)) + pointColl = GetPointCollision(Vector3i(Camera.target.x, y, Camera.target.z), Camera.target.RoomNumber); + if (((y < pointColl.GetCeilingHeight() || pointColl.GetFloorHeight() < y) || pointColl.GetFloorHeight() <= pointColl.GetCeilingHeight()) || + (pointColl.GetFloorHeight() == NO_HEIGHT || pointColl.GetCeilingHeight() == NO_HEIGHT)) { TargetSnaps++; Camera.target = LastTarget; } else + { TargetSnaps = 0; + } for (int i = 0; i < maxSwivelSteps; i++) Ideals[i].y = Camera.target.y + (Camera.targetDistance * phd_sin(Camera.actualElevation)); @@ -648,43 +650,43 @@ void CombatCamera(ItemInfo* item) Camera.targetElevation = player.ExtraHeadRot.x + player.ExtraTorsoRot.x + item->Pose.Orientation.x - ANGLE(15.0f); } - auto probe = GetCollision(Camera.target.x, Camera.target.y + CLICK(1), Camera.target.z, Camera.target.RoomNumber); - if (TestEnvironment(ENV_FLAG_SWAMP, probe.RoomNumber)) - Camera.target.y = g_Level.Rooms[probe.RoomNumber].y - CLICK(1); + auto pointColl = GetPointCollision(Vector3i(Camera.target.x, Camera.target.y + CLICK(1), Camera.target.z), Camera.target.RoomNumber); + if (TestEnvironment(ENV_FLAG_SWAMP, pointColl.GetRoomNumber())) + Camera.target.y = g_Level.Rooms[pointColl.GetRoomNumber()].y - CLICK(1); - probe = GetCollision(Camera.target.x, Camera.target.y, Camera.target.z, Camera.target.RoomNumber); - Camera.target.RoomNumber = probe.RoomNumber; + pointColl = GetPointCollision(Camera.target.ToVector3i(), Camera.target.RoomNumber); + Camera.target.RoomNumber = pointColl.GetRoomNumber(); int buffer = CLICK(0.25f); - if ((probe.Position.Ceiling + buffer) > (probe.Position.Floor - buffer) && - probe.Position.Floor != NO_HEIGHT && - probe.Position.Ceiling != NO_HEIGHT) + if ((pointColl.GetCeilingHeight() + buffer) > (pointColl.GetFloorHeight() - buffer) && + pointColl.GetFloorHeight() != NO_HEIGHT && + pointColl.GetCeilingHeight() != NO_HEIGHT) { - Camera.target.y = (probe.Position.Ceiling + probe.Position.Floor) / 2; + Camera.target.y = (pointColl.GetCeilingHeight() + pointColl.GetFloorHeight()) / 2; Camera.targetElevation = 0; } - else if (Camera.target.y > (probe.Position.Floor - buffer) && - probe.Position.Floor != NO_HEIGHT) + else if (Camera.target.y > (pointColl.GetFloorHeight() - buffer) && + pointColl.GetFloorHeight() != NO_HEIGHT) { - Camera.target.y = probe.Position.Floor - buffer; + Camera.target.y = pointColl.GetFloorHeight() - buffer; Camera.targetElevation = 0; } - else if (Camera.target.y < (probe.Position.Ceiling + buffer) && - probe.Position.Ceiling != NO_HEIGHT) + else if (Camera.target.y < (pointColl.GetCeilingHeight() + buffer) && + pointColl.GetCeilingHeight() != NO_HEIGHT) { - Camera.target.y = probe.Position.Ceiling + buffer; + Camera.target.y = pointColl.GetCeilingHeight() + buffer; Camera.targetElevation = 0; } int y = Camera.target.y; - probe = GetCollision(Camera.target.x, y, Camera.target.z, Camera.target.RoomNumber); - Camera.target.RoomNumber = probe.RoomNumber; + pointColl = GetPointCollision(Vector3i(Camera.target.x, y, Camera.target.z), Camera.target.RoomNumber); + Camera.target.RoomNumber = pointColl.GetRoomNumber(); - if (y < probe.Position.Ceiling || - y > probe.Position.Floor || - probe.Position.Ceiling >= probe.Position.Floor || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT) + if (y < pointColl.GetCeilingHeight() || + y > pointColl.GetFloorHeight() || + pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT) { TargetSnaps++; Camera.target = LastTarget; @@ -770,116 +772,114 @@ bool CameraCollisionBounds(GameVector* ideal, int push, bool yFirst) int y = ideal->y; int z = ideal->z; - CollisionResult probe = {}; + auto pointColl = GetPointCollision(Vector3i(x, y, z), ideal->RoomNumber); if (yFirst) { - probe = GetCollision(x, y, z, ideal->RoomNumber); - int buffer = CLICK(1) - 1; - if ((y - buffer) < probe.Position.Ceiling && - (y + buffer) > probe.Position.Floor && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + if ((y - buffer) < pointColl.GetCeilingHeight() && + (y + buffer) > pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - y = (probe.Position.Floor + probe.Position.Ceiling) / 2; + y = (pointColl.GetFloorHeight() + pointColl.GetCeilingHeight()) / 2; } - else if ((y + buffer) > probe.Position.Floor && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + else if ((y + buffer) > pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - y = probe.Position.Floor - buffer; + y = pointColl.GetFloorHeight() - buffer; } - else if ((y - buffer) < probe.Position.Ceiling && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + else if ((y - buffer) < pointColl.GetCeilingHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - y = probe.Position.Ceiling + buffer; + y = pointColl.GetCeilingHeight() + buffer; } } - probe = GetCollision(x - push, y, z, ideal->RoomNumber); - if (y > probe.Position.Floor || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT || - probe.Position.Ceiling >= probe.Position.Floor || - y < probe.Position.Ceiling) + pointColl = GetPointCollision(Vector3i(x - push, y, z), ideal->RoomNumber); + if (y > pointColl.GetFloorHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight() || + y < pointColl.GetCeilingHeight()) { x = (x & (~1023)) + push; } - probe = GetCollision(x, y, z - push, ideal->RoomNumber); - if (y > probe.Position.Floor || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT || - probe.Position.Ceiling >= probe.Position.Floor || - y < probe.Position.Ceiling) + pointColl = GetPointCollision(Vector3i(x, y, z - push), ideal->RoomNumber); + if (y > pointColl.GetFloorHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight() || + y < pointColl.GetCeilingHeight()) { z = (z & (~1023)) + push; } - probe = GetCollision(x + push, y, z, ideal->RoomNumber); - if (y > probe.Position.Floor || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT || - probe.Position.Ceiling >= probe.Position.Floor || - y < probe.Position.Ceiling) + pointColl = GetPointCollision(Vector3i(x + push, y, z), ideal->RoomNumber); + if (y > pointColl.GetFloorHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight() || + y < pointColl.GetCeilingHeight()) { x = (x | 1023) - push; } - probe = GetCollision(x, y, z + push, ideal->RoomNumber); - if (y > probe.Position.Floor || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT || - probe.Position.Ceiling >= probe.Position.Floor || - y < probe.Position.Ceiling) + pointColl = GetPointCollision(Vector3i(x, y, z + push), ideal->RoomNumber); + if (y > pointColl.GetFloorHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight() || + y < pointColl.GetCeilingHeight()) { z = (z | 1023) - push; } if (!yFirst) { - probe = GetCollision(x, y, z, ideal->RoomNumber); + pointColl = GetPointCollision(Vector3i(x, y, z), ideal->RoomNumber); int buffer = CLICK(1) - 1; - if ((y - buffer) < probe.Position.Ceiling && - (y + buffer) > probe.Position.Floor && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + if ((y - buffer) < pointColl.GetCeilingHeight() && + (y + buffer) > pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - y = (probe.Position.Floor + probe.Position.Ceiling) / 2; + y = (pointColl.GetFloorHeight() + pointColl.GetCeilingHeight()) / 2; } - else if ((y + buffer) > probe.Position.Floor && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + else if ((y + buffer) > pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - y = probe.Position.Floor - buffer; + y = pointColl.GetFloorHeight() - buffer; } - else if ((y - buffer) < probe.Position.Ceiling && - probe.Position.Ceiling < probe.Position.Floor && - probe.Position.Ceiling != NO_HEIGHT && - probe.Position.Floor != NO_HEIGHT) + else if ((y - buffer) < pointColl.GetCeilingHeight() && + pointColl.GetCeilingHeight() < pointColl.GetFloorHeight() && + pointColl.GetCeilingHeight() != NO_HEIGHT && + pointColl.GetFloorHeight() != NO_HEIGHT) { - y = probe.Position.Ceiling + buffer; + y = pointColl.GetCeilingHeight() + buffer; } } - probe = GetCollision(x, y, z, ideal->RoomNumber); - if (y > probe.Position.Floor || - y < probe.Position.Ceiling || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT || - probe.Position.Ceiling >= probe.Position.Floor) + pointColl = GetPointCollision(Vector3i(x, y, z), ideal->RoomNumber); + if (y > pointColl.GetFloorHeight() || + y < pointColl.GetCeilingHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() >= pointColl.GetFloorHeight()) { return true; } - ideal->RoomNumber = probe.RoomNumber; + ideal->RoomNumber = pointColl.GetRoomNumber(); ideal->x = x; ideal->y = y; ideal->z = z; @@ -963,20 +963,20 @@ void BinocularCamera(ItemInfo* item) int y = item->Pose.Position.y - CLICK(2); int z = item->Pose.Position.z; - auto probe = GetCollision(x, y, z, item->RoomNumber); - if (probe.Position.Ceiling <= (y - CLICK(1))) + auto pointColl = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); + if (pointColl.GetCeilingHeight() <= (y - CLICK(1))) { y -= CLICK(1); } else { - y = probe.Position.Ceiling + CLICK(0.25f); + y = pointColl.GetCeilingHeight() + CLICK(0.25f); } Camera.pos.x = x; Camera.pos.y = y; Camera.pos.z = z; - Camera.pos.RoomNumber = probe.RoomNumber; + Camera.pos.RoomNumber = pointColl.GetRoomNumber(); float l = BLOCK(20.25f) * phd_cos(player.Control.Look.Orientation.x); float tx = x + l * phd_sin(item->Pose.Orientation.y + player.Control.Look.Orientation.y); @@ -1016,7 +1016,7 @@ void BinocularCamera(ItemInfo* item) } } - Camera.target.RoomNumber = GetCollision(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.target.RoomNumber).RoomNumber; + Camera.target.RoomNumber = GetPointCollision(Camera.pos.ToVector3i(), Camera.target.RoomNumber).GetRoomNumber(); LookAt(&Camera, 0); UpdateMikePos(*item); Camera.oldType = Camera.type; @@ -1052,12 +1052,12 @@ void ConfirmCameraTargetPos() } int y = Camera.target.y; - auto probe = GetCollision(Camera.target.x, y, Camera.target.z, Camera.target.RoomNumber); - if (y < probe.Position.Ceiling || - probe.Position.Floor < y || - probe.Position.Floor <= probe.Position.Ceiling || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT) + auto pointColl = GetPointCollision(Vector3i(Camera.target.x, y, Camera.target.z), Camera.target.RoomNumber); + if (y < pointColl.GetCeilingHeight() || + pointColl.GetFloorHeight() < y || + pointColl.GetFloorHeight() <= pointColl.GetCeilingHeight() || + pointColl.GetFloorHeight() == NO_HEIGHT || + pointColl.GetCeilingHeight() == NO_HEIGHT) { Camera.target.x = pos.x; Camera.target.y = pos.y; @@ -1268,7 +1268,7 @@ void CalculateCamera(const CollisionInfo& coll) Camera.speed = 1; } - Camera.target.RoomNumber = GetCollision(x, y, z, Camera.target.RoomNumber).RoomNumber; + Camera.target.RoomNumber = GetPointCollision(Vector3i(x, y, z), Camera.target.RoomNumber).GetRoomNumber(); if (abs(LastTarget.x - Camera.target.x) < 4 && abs(LastTarget.y - Camera.target.y) < 4 && @@ -1361,9 +1361,9 @@ void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius) Camera.pos.x = pos->Position.x + ((x * cosY) + (z * sinY)); Camera.pos.z = pos->Position.z + ((z * cosY) - (x * sinY)); - auto pointColl = GetCollision(Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber); - if (pointColl.Position.Floor == NO_HEIGHT || Camera.pos.y > pointColl.Position.Floor || Camera.pos.y < pointColl.Position.Ceiling) - Camera.pos = GameVector(CamOldPos, pointColl.RoomNumber); + auto pointColl = GetPointCollision(Camera.pos.ToVector3i(), Camera.pos.RoomNumber); + if (pointColl.GetFloorHeight() == NO_HEIGHT || Camera.pos.y > pointColl.GetFloorHeight() || Camera.pos.y < pointColl.GetCeilingHeight()) + Camera.pos = GameVector(CamOldPos, pointColl.GetRoomNumber()); } bool CheckItemCollideCamera(ItemInfo* item) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 918f6ad06..6765df0c6 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -16,10 +16,20 @@ using namespace TEN::Math; namespace TEN::Collision { - PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) : - Position(pos), - RoomNumber(roomNumber) + PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) { + _position = pos; + _roomNumber = roomNumber; + } + + Vector3i PointCollisionData::GetPosition() const + { + return _position; + } + + int PointCollisionData::GetRoomNumber() const + { + return _roomNumber; } FloorInfo& PointCollisionData::GetSector() @@ -28,8 +38,8 @@ namespace TEN::Collision return *_sectorPtr; // Set current sector pointer. - short probeRoomNumber = RoomNumber; - _sectorPtr = GetFloor(Position.x, Position.y, Position.z, &probeRoomNumber); + short probeRoomNumber = _roomNumber; + _sectorPtr = GetFloor(_position.x, _position.y, _position.z, &probeRoomNumber); return *_sectorPtr; } @@ -41,13 +51,13 @@ namespace TEN::Collision // Set bottom sector pointer. auto* bottomSectorPtr = &GetSector(); - auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position); + auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(_position); while (roomNumberBelow.has_value()) { auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->RoomNumber)]; - bottomSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + bottomSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); - roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(Position); + roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(_position); } _bottomSectorPtr = bottomSectorPtr; @@ -61,13 +71,13 @@ namespace TEN::Collision // Set top sector pointer. auto* topSectorPtr = &GetSector(); - auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position); + auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(_position); while (roomNumberAbove.has_value()) { auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->RoomNumber)]; - topSectorPtr = Room::GetSector(&room, Position.x - room.x, Position.z - room.z); + topSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); - roomNumberAbove = topSectorPtr->GetRoomNumberAbove(Position); + roomNumberAbove = topSectorPtr->GetRoomNumberAbove(_position); } _topSectorPtr = topSectorPtr; @@ -80,8 +90,8 @@ namespace TEN::Collision return *_floorHeight; // Set floor height. - auto location = RoomVector(GetSector().RoomNumber, Position.y); - _floorHeight = Floordata::GetSurfaceHeight(location, Position.x, Position.z, true).value_or(NO_HEIGHT); + auto location = RoomVector(GetSector().RoomNumber, _position.y); + _floorHeight = Floordata::GetSurfaceHeight(location, _position.x, _position.z, true).value_or(NO_HEIGHT); return *_floorHeight; } @@ -92,8 +102,8 @@ namespace TEN::Collision return *_ceilingHeight; // Set ceiling height. - auto location = RoomVector(GetSector().RoomNumber, Position.y); - _ceilingHeight = Floordata::GetSurfaceHeight(location, Position.x, Position.z, false).value_or(NO_HEIGHT); + auto location = RoomVector(GetSector().RoomNumber, _position.y); + _ceilingHeight = Floordata::GetSurfaceHeight(location, _position.x, _position.z, false).value_or(NO_HEIGHT); return *_ceilingHeight; } @@ -110,7 +120,7 @@ namespace TEN::Collision } else { - _floorNormal = GetBottomSector().GetSurfaceNormal(Position.x, Position.z, true); + _floorNormal = GetBottomSector().GetSurfaceNormal(_position.x, _position.z, true); } return *_floorNormal; @@ -128,7 +138,7 @@ namespace TEN::Collision } else { - _ceilingNormal = GetTopSector().GetSurfaceNormal(Position.x, Position.z, false); + _ceilingNormal = GetTopSector().GetSurfaceNormal(_position.x, _position.z, false); } return *_ceilingNormal; @@ -141,7 +151,7 @@ namespace TEN::Collision // Set floor bridge item number. int floorHeight = GetFloorHeight(); - auto pos = Vector3i(Position.x, floorHeight, Position.z); + auto pos = Vector3i(_position.x, floorHeight, _position.z); _floorBridgeItemNumber = GetBottomSector().GetInsideBridgeItemNumber(pos, true, false); return *_floorBridgeItemNumber; @@ -154,7 +164,7 @@ namespace TEN::Collision // Set ceiling bridge item number. int ceilingHeight = GetCeilingHeight(); - auto pos = Vector3i(Position.x, ceilingHeight, Position.z); + auto pos = Vector3i(_position.x, ceilingHeight, _position.z); _ceilingBridgeItemNumber = GetTopSector().GetInsideBridgeItemNumber(pos, false, true); return *_ceilingBridgeItemNumber; @@ -166,7 +176,7 @@ namespace TEN::Collision return *_waterSurfaceHeight; // Set water surface height. - _waterSurfaceHeight = GetWaterSurface(Position.x, Position.y, Position.z, RoomNumber); + _waterSurfaceHeight = GetWaterSurface(_position.x, _position.y, _position.z, _roomNumber); return *_waterSurfaceHeight; } @@ -177,7 +187,7 @@ namespace TEN::Collision return *_waterBottomHeight; // Set water bottom height. - _waterBottomHeight = GetWaterDepth(Position.x, Position.y, Position.z, RoomNumber); + _waterBottomHeight = GetWaterDepth(_position.x, _position.y, _position.z, _roomNumber); return *_waterBottomHeight; } @@ -188,7 +198,7 @@ namespace TEN::Collision return *_waterTopHeight; // Set water top height. - _waterTopHeight = GetWaterHeight(Position.x, Position.y, Position.z, RoomNumber); + _waterTopHeight = GetWaterHeight(_position.x, _position.y, _position.z, _roomNumber); return *_waterTopHeight; } @@ -204,7 +214,7 @@ namespace TEN::Collision short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); short illegalSlopeAngle = (GetFloorBridgeItemNumber() != NO_ITEM) ? DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE : - GetBottomSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, true); + GetBottomSector().GetSurfaceIllegalSlopeAngle(_position.x, _position.z, true); return (abs(slopeAngle) >= illegalSlopeAngle); } @@ -214,7 +224,7 @@ namespace TEN::Collision short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); short illegalSlopeAngle = (GetCeilingBridgeItemNumber() != NO_ITEM) ? DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE : - GetTopSector().GetSurfaceIllegalSlopeAngle(Position.x, Position.z, false); + GetTopSector().GetSurfaceIllegalSlopeAngle(_position.x, _position.z, false); return (abs(slopeAngle) >= illegalSlopeAngle); } @@ -255,7 +265,7 @@ namespace TEN::Collision bool PointCollisionData::TestEnvironmentFlag(RoomEnvFlags envFlag) { - const auto& room = g_Level.Rooms[RoomNumber]; + const auto& room = g_Level.Rooms[_roomNumber]; return ((room.flags & envFlag) == envFlag); } @@ -327,7 +337,15 @@ namespace TEN::Collision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) { - return PointCollisionData(pos, roomNumber); + // TEMP HACK + // GetPointCollision() takes arguments for a *current* position and room number. + // However, since some calls to the equivalent deprecated function had *projected* + // positions passed to it, the room number had be corrected to account for such cases. + // These are primarily found in camera.cpp. + short correctedRoomNumber = roomNumber; + GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + + return PointCollisionData(pos, correctedRoomNumber); } PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index be315cb6f..b6ec8da81 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -12,12 +12,11 @@ namespace TEN::Collision { class PointCollisionData { - public: - // Members - const Vector3i Position = Vector3i::Zero; - const int RoomNumber = 0; - private: + // Members + Vector3i _position = Vector3i::Zero; + int _roomNumber = 0; + FloorInfo* _sectorPtr = nullptr; FloorInfo* _bottomSectorPtr = nullptr; FloorInfo* _topSectorPtr = nullptr; @@ -38,6 +37,9 @@ namespace TEN::Collision PointCollisionData(const Vector3i& pos, int roomNumber); // Getters + Vector3i GetPosition() const; + int GetRoomNumber() const; + FloorInfo& GetSector(); FloorInfo& GetBottomSector(); FloorInfo& GetTopSector(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 61d0a3286..d10facb25 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -125,8 +125,8 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin { auto collResult = CollisionResult{}; - collResult.Coordinates = pointColl.Position; - collResult.RoomNumber = pointColl.RoomNumber; + collResult.Coordinates = pointColl.GetPosition(); + collResult.RoomNumber = pointColl.GetRoomNumber(); collResult.Block = &pointColl.GetSector(); collResult.BottomBlock = &pointColl.GetBottomSector(); @@ -185,36 +185,21 @@ CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const Vector3& // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber) { - // HACK: GetPointCollision() takes arguments for a *current* position and room number. - // However, since some calls to this deprecated function had *projected* - // positions passed to it, the room number must be corrected to account for such cases. - // They are primarily found in camera.cpp. - short correctedRoomNumber = roomNumber; - GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); - - auto pointColl = GetPointCollision(pos, correctedRoomNumber); + auto pointColl = GetPointCollision(pos, roomNumber); return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(int x, int y, int z, short roomNumber) { - // HACK: Explained above. - short correctedRoomNumber = roomNumber; - GetFloor(x, y, z, &correctedRoomNumber); - - auto pointColl = GetPointCollision(Vector3i(x, y, z), correctedRoomNumber); + auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); return ConvertPointCollDataToCollResult(pointColl); } // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const GameVector& pos) { - // HACK: Explained above. - short correctedRoomNumber = pos.RoomNumber; - GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); - - auto pointColl = GetPointCollision(pos.ToVector3i(), correctedRoomNumber); + auto pointColl = GetPointCollision(pos.ToVector3i(), pos.RoomNumber); return ConvertPointCollDataToCollResult(pointColl); } From e9012c619e0eaa35cceb05c99048665ef5b53908 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 1 Feb 2024 17:30:31 +1100 Subject: [PATCH 048/410] Remove parameters --- TombEngine/Game/collision/PointCollision.cpp | 4 ++-- TombEngine/Game/collision/PointCollision.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 6765df0c6..6abc6d33d 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -209,7 +209,7 @@ namespace TEN::Collision GetFloorHeight() <= GetCeilingHeight()); } - bool PointCollisionData::IsIllegalFloor(short slopeAngleMin) + bool PointCollisionData::IsIllegalFloor() { short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); short illegalSlopeAngle = (GetFloorBridgeItemNumber() != NO_ITEM) ? @@ -219,7 +219,7 @@ namespace TEN::Collision return (abs(slopeAngle) >= illegalSlopeAngle); } - bool PointCollisionData::IsIllegalCeiling(short slopeAngleMin) + bool PointCollisionData::IsIllegalCeiling() { short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); short illegalSlopeAngle = (GetCeilingBridgeItemNumber() != NO_ITEM) ? diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index b6ec8da81..71b90e2d3 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -57,8 +57,8 @@ namespace TEN::Collision // Inquirers bool IsWall(); - bool IsIllegalFloor(short slopeAngleMin = DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE); - bool IsIllegalCeiling(short slopeAngleMin = DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE); + bool IsIllegalFloor(); + bool IsIllegalCeiling(); bool IsDiagonalFloorStep(); bool IsDiagonalCeilingStep(); bool IsFloorDiagonalSplit(); From 923790041df614ace139d65c4e70da80c917de1b Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 1 Feb 2024 23:43:41 +1100 Subject: [PATCH 049/410] Process tilts correctly for bridges rotated on X and Z axes --- .../Objects/Generic/Object/generic_bridge.cpp | 37 +++++++++---------- .../Objects/Generic/Object/generic_bridge.h | 1 - 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/generic_bridge.cpp b/TombEngine/Objects/Generic/Object/generic_bridge.cpp index 05826f823..c5fdcedb4 100644 --- a/TombEngine/Objects/Generic/Object/generic_bridge.cpp +++ b/TombEngine/Objects/Generic/Object/generic_bridge.cpp @@ -10,15 +10,28 @@ using namespace TEN::Collision::Floordata; namespace TEN::Entities::Generic { + static int GetTiltOffset(const ItemInfo& item, const Vector3i& pos, int tiltGrade, bool isFloor) + { + // Calculate delta position. + auto deltaPos = (item.Pose.Position - pos).ToVector3(); + + // Calculate tilt normal. + int sign = isFloor ? -1 : 1; + auto rotMatrix = EulerAngles(0, item.Pose.Orientation.y, 0).ToRotationMatrix(); + auto normal = Vector3::Transform(Vector3(-tiltGrade, 1.0f, 0.0f) * sign, rotMatrix); + normal.Normalize(); + + // Calculate and return tilt offset. + float relPlaneHeight = -((normal.x * deltaPos.x) + (normal.z * deltaPos.z)) / normal.y; + return ((relPlaneHeight / 4) + CLICK(tiltGrade * 0.5f)); // TODO: Wrong when walking near some bridge edges? + } + template static std::optional GetBridgeFloorHeight(const ItemInfo& item, const Vector3i& pos) { auto boxHeight = GetBridgeItemIntersect(item, pos, false); if (boxHeight.has_value() && tiltGrade != 0) - { - int height = item.Pose.Position.y + (tiltGrade * ((GetOffset(item.Pose.Orientation.y, pos.x, pos.z) / 4) + (BLOCK(1 / 8.0f)))); - return height; - } + return (*boxHeight + GetTiltOffset(item, pos, tiltGrade, true)); return boxHeight; } @@ -28,10 +41,7 @@ namespace TEN::Entities::Generic { auto boxHeight = GetBridgeItemIntersect(item, pos, true); if (boxHeight.has_value() && tiltGrade != 0) - { - int height = item.Pose.Position.y + (tiltGrade * ((GetOffset(item.Pose.Orientation.y, pos.x, pos.z) / 4) + (BLOCK(1 / 8.0f)))); - return (height + CLICK(1)); - } + return ((item.Pose.Position.y + GetTiltOffset(item, pos, tiltGrade, false)) + CLICK(1)); return boxHeight; } @@ -96,15 +106,4 @@ namespace TEN::Entities::Generic UpdateBridgeItem(bridgeItem); } - - int GetOffset(short angle, int x, int z) - { - // Get rotated sector point. - auto sectorPoint = GetSectorPoint(x, z).ToVector2(); - auto rotMatrix = Matrix::CreateRotationZ(TO_RAD(angle)); - Vector2::Transform(sectorPoint, rotMatrix, sectorPoint); - - // Return offset. - return -sectorPoint.x; - } } diff --git a/TombEngine/Objects/Generic/Object/generic_bridge.h b/TombEngine/Objects/Generic/Object/generic_bridge.h index 3830ecd23..12dfee101 100644 --- a/TombEngine/Objects/Generic/Object/generic_bridge.h +++ b/TombEngine/Objects/Generic/Object/generic_bridge.h @@ -3,5 +3,4 @@ namespace TEN::Entities::Generic { void InitializeBridge(short itemNumber); - int GetOffset(short angle, int x, int z); } From 4d6f22a948f9fa81b87700807d009278ad1b576b Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 1 Feb 2024 23:44:09 +1100 Subject: [PATCH 050/410] Remove comment --- TombEngine/Objects/Generic/Object/generic_bridge.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Objects/Generic/Object/generic_bridge.cpp b/TombEngine/Objects/Generic/Object/generic_bridge.cpp index c5fdcedb4..81abfa392 100644 --- a/TombEngine/Objects/Generic/Object/generic_bridge.cpp +++ b/TombEngine/Objects/Generic/Object/generic_bridge.cpp @@ -23,7 +23,7 @@ namespace TEN::Entities::Generic // Calculate and return tilt offset. float relPlaneHeight = -((normal.x * deltaPos.x) + (normal.z * deltaPos.z)) / normal.y; - return ((relPlaneHeight / 4) + CLICK(tiltGrade * 0.5f)); // TODO: Wrong when walking near some bridge edges? + return ((relPlaneHeight / 4) + CLICK(tiltGrade * 0.5f)); } template From 75c8ff2601c955dc9fc0152eb8b32c150e82983e Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 2 Feb 2024 00:07:05 +1100 Subject: [PATCH 051/410] Simplify --- TombEngine/Game/collision/floordata.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 01e386268..8a24dbba4 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -916,8 +916,7 @@ namespace TEN::Collision::Floordata { constexpr auto VERTICAL_MARGIN = 4; - auto bounds = GameBoundingBox(&item); - auto box = bounds.ToBoundingOrientedBox(item.Pose); + auto box = GameBoundingBox(&item).ToBoundingOrientedBox(item.Pose); auto origin = Vector3(pos.x, pos.y + (useBottomHeight ? VERTICAL_MARGIN : -VERTICAL_MARGIN), pos.z); auto dir = useBottomHeight ? -Vector3::UnitY : Vector3::UnitY; From 253aa3816d4e6d062d90bc60015a4b560e1e7bc7 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 2 Feb 2024 00:44:52 +1100 Subject: [PATCH 052/410] Remove 3 GetCollision() overloads --- TombEngine/Game/Lara/lara.cpp | 2 +- TombEngine/Game/Lara/lara_helpers.cpp | 6 ++- TombEngine/Game/Lara/lara_overhang.cpp | 10 +++-- TombEngine/Game/camera.cpp | 4 +- TombEngine/Game/collision/PointCollision.cpp | 2 +- TombEngine/Game/collision/PointCollision.h | 2 +- TombEngine/Game/collision/collide_room.cpp | 23 +--------- TombEngine/Game/collision/collide_room.h | 3 -- TombEngine/Game/collision/floordata.cpp | 25 ++++++----- TombEngine/Game/missile.cpp | 14 +++--- .../Object/Pushable/PushableCollision.cpp | 14 +++--- .../Generic/Object/Pushable/PushableSound.cpp | 7 ++- .../Generic/Traps/crumblingPlatform.cpp | 14 +++--- TombEngine/Objects/TR1/Entity/tr1_bear.cpp | 6 ++- .../Objects/TR3/Trap/ElectricCleaner.cpp | 45 +++++++++++-------- TombEngine/Objects/TR5/Entity/tr5_guard.cpp | 4 +- 16 files changed, 92 insertions(+), 89 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 02f5b9cd1..7eec415d2 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -47,8 +47,8 @@ #include "Specific/Input/Input.h" #include "Specific/winmain.h" -using namespace TEN::Collision; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Hair; using namespace TEN::Effects::Items; diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 584391b80..d6bb58a65 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -7,6 +7,7 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/control/volume.h" #include "Game/items.h" @@ -37,6 +38,7 @@ #include "Objects/TR4/Vehicles/motorbike.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Drip; @@ -1257,8 +1259,8 @@ PlayerWaterData GetPlayerWaterData(ItemInfo& item) int waterDepth = GetWaterDepth(&item); int waterHeight = GetWaterHeight(&item); - auto pointColl = GetCollision(item); - int heightFromWater = (waterHeight == NO_HEIGHT) ? NO_HEIGHT : (std::min(item.Pose.Position.y, pointColl.Position.Floor) - waterHeight); + auto pointColl = GetPointCollision(item); + int heightFromWater = (waterHeight == NO_HEIGHT) ? NO_HEIGHT : (std::min(item.Pose.Position.y, pointColl.GetFloorHeight()) - waterHeight); return PlayerWaterData { diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index b398a0fb1..72e93f579 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -2,8 +2,9 @@ #include "Game/Lara/lara_overhang.h" #include "Game/camera.h" -#include "Game/collision/floordata.h" #include "Game/collision/collide_room.h" +#include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_climb.h" @@ -16,6 +17,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Generic; using namespace TEN::Input; @@ -967,12 +969,12 @@ void SlopeClimbExtra(ItemInfo* item, CollisionInfo* coll) // Extends LS_LADDER_IDLE (56) bool LadderMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { - auto probe = GetCollision(*item); + auto probe = GetPointCollision(*item); - if (probe.Position.CeilingSlope) + if (probe.IsIllegalCeiling()) return false; - if (probe.BottomBlock->Flags.Monkeyswing && (item->Pose.Position.y - coll->Setup.Height - CLICK(0.5f) <= probe.Position.Ceiling)) + if (probe.GetBottomSector().Flags.Monkeyswing && (item->Pose.Position.y - coll->Setup.Height - CLICK(0.5f) <= probe.GetCeilingHeight())) { item->Animation.TargetState = LS_MONKEY_IDLE; return true; diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index c07b395b9..9e13f0bd7 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -22,13 +22,13 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision; -using TEN::Renderer::g_Renderer; +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Environment; using namespace TEN::Entities::Generic; using namespace TEN::Input; using namespace TEN::Math; +using TEN::Renderer::g_Renderer; constexpr auto PARTICLE_FADE_THRESHOLD = BLOCK(14); constexpr auto COLL_CHECK_THRESHOLD = BLOCK(4); diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 6abc6d33d..652a47af5 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -14,7 +14,7 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Room; using namespace TEN::Math; -namespace TEN::Collision +namespace TEN::Collision::PointCollision { PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) { diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index 71b90e2d3..cc031d4ab 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -8,7 +8,7 @@ struct ItemInfo; using namespace TEN::Math; -namespace TEN::Collision +namespace TEN::Collision::PointCollision { class PointCollisionData { diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index d10facb25..4ecd49296 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -13,8 +13,8 @@ #include "Sound/sound.h" #include "Renderer/Renderer.h" -using namespace TEN::Collision; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Collision::Room; using namespace TEN::Math; using namespace TEN::Renderer; @@ -147,13 +147,6 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin return collResult; } -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const ItemInfo& item) -{ - auto pointColl = GetPointCollision(item); - return ConvertPointCollDataToCollResult(pointColl); -} - // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo* item) { @@ -168,20 +161,6 @@ CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float for return ConvertPointCollDataToCollResult(pointColl); } -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right) -{ - auto pointColl = GetPointCollision(pos, roomNumber, headingAngle, forward, down, right); - return ConvertPointCollDataToCollResult(pointColl); -} - -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) -{ - auto pointColl = GetPointCollision(pos, roomNumber, dir, dist); - return ConvertPointCollDataToCollResult(pointColl); -} - // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(const Vector3i& pos, int roomNumber) { diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 755a2eb85..99a94bd35 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -136,11 +136,8 @@ struct CollisionInfo [[nodiscard]] bool TestItemRoomCollisionAABB(ItemInfo* item); // NOTE: All overloads deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const ItemInfo& item); CollisionResult GetCollision(const ItemInfo* item); CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); -CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); -CollisionResult GetCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist); CollisionResult GetCollision(const Vector3i& pos, int roomNumber); CollisionResult GetCollision(int x, int y, int z, short roomNumber); CollisionResult GetCollision(const GameVector& pos); diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 8a24dbba4..0303e233c 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -1,6 +1,8 @@ #include "framework.h" #include "Game/collision/floordata.h" + #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/items.h" #include "Game/room.h" #include "Game/Setup.h" @@ -11,6 +13,7 @@ #include "Specific/trutils.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Generic; using namespace TEN::Math; using namespace TEN::Utils; @@ -1036,7 +1039,7 @@ namespace TEN::Collision::Floordata constexpr auto MINECART_STOP_COLOR = Vector4(0.4f, 1.0f, 1.0f, 1.0f); // Get point collision. - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(item); auto pos = item.Pose.Position.ToVector3(); // Run through neighboring rooms. @@ -1052,50 +1055,50 @@ namespace TEN::Collision::Floordata pos.x = BLOCK(roomGridCoord.x) + neighborRoom.x; pos.z = BLOCK(roomGridCoord.y) + neighborRoom.z; - pointColl = GetCollision(pos, neighborRoomNumber); - pos.y = pointColl.Position.Floor; + pointColl = GetPointCollision(pos, neighborRoomNumber); + pos.y = pointColl.GetFloorHeight(); float verticalOffset = STRING_SPACING; // Stopper - if (pointColl.Block->Stopper) + if (pointColl.GetSector().Stopper) { DrawSectorFlagLabel(pos, "Stopper", STOPPER_COLOR, verticalOffset); verticalOffset += STRING_SPACING; } // Death - if (pointColl.Block->Flags.Death) + if (pointColl.GetSector().Flags.Death) { DrawSectorFlagLabel(pos, "Death", DEATH_COLOR, verticalOffset); verticalOffset += STRING_SPACING; } // Monkey Swing - if (pointColl.Block->Flags.Monkeyswing) + if (pointColl.GetSector().Flags.Monkeyswing) { DrawSectorFlagLabel(pos, "Monkey Swing", MONKEY_SWING_COLOR, verticalOffset); verticalOffset += STRING_SPACING; } // Beetle / Minecart Right - if (pointColl.Block->Flags.MarkBeetle) + if (pointColl.GetSector().Flags.MarkBeetle) { - auto labelString = std::string("Beetle") + (!pointColl.Block->Flags.MinecartStop() ? " / Minecart Right" : ""); + auto labelString = std::string("Beetle") + (!pointColl.GetSector().Flags.MinecartStop() ? " / Minecart Right" : ""); DrawSectorFlagLabel(pos, labelString, BEETLE_MINECART_RIGHT_COLOR, verticalOffset); verticalOffset += STRING_SPACING; } // Activator / Minecart Left - if (pointColl.Block->Flags.MarkTriggerer) + if (pointColl.GetSector().Flags.MarkTriggerer) { - auto labelString = std::string("Activator") + (!pointColl.Block->Flags.MinecartStop() ? " / Minecart Left" : ""); + auto labelString = std::string("Activator") + (!pointColl.GetSector().Flags.MinecartStop() ? " / Minecart Left" : ""); DrawSectorFlagLabel(pos, labelString, ACTIVATOR_MINECART_LEFT_COLOR, verticalOffset); verticalOffset += STRING_SPACING; } // Minecart Stop - if (pointColl.Block->Flags.MinecartStop()) + if (pointColl.GetSector().Flags.MinecartStop()) { DrawSectorFlagLabel(pos, "Minecart Stop", MINECART_STOP_COLOR, verticalOffset); verticalOffset += STRING_SPACING; diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index e0655c903..b1449629b 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/effects.h" #include "Game/effects/explosion.h" @@ -15,6 +16,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision;; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Explosion; using namespace TEN::Math; @@ -142,23 +144,23 @@ void ControlNatlaGun(short fxNumber) // If first frame, start another explosion at next position. if (fx.frameNumber == -1) { - auto pointColl = GetCollision(fx.pos.Position, fx.roomNumber, fx.pos.Orientation.y, fx.speed); + auto pointColl = GetPointCollision(fx.pos.Position, fx.roomNumber, fx.pos.Orientation.y, fx.speed); // Don't create one if hit a wall. - if (pointColl.Coordinates.y >= pointColl.Position.Floor || - pointColl.Coordinates.y <= pointColl.Position.Ceiling) + if (pointColl.GetPosition().y >= pointColl.GetFloorHeight() || + pointColl.GetPosition().y <= pointColl.GetCeilingHeight()) { return; } - fxNumber = CreateNewEffect(pointColl.RoomNumber); + fxNumber = CreateNewEffect(pointColl.GetRoomNumber()); if (fxNumber != NO_ITEM) { auto& fxNew = EffectList[fxNumber]; - fxNew.pos.Position = pointColl.Coordinates; + fxNew.pos.Position = pointColl.GetPosition(); fxNew.pos.Orientation.y = fx.pos.Orientation.y; - fxNew.roomNumber = pointColl.RoomNumber; + fxNew.roomNumber = pointColl.GetRoomNumber(); fxNew.speed = fx.speed; fxNew.frameNumber = 0; fxNew.objectNumber = ID_PROJ_BOMB; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 5a96b5ce2..4e9634660 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/Lara/lara.h" #include "Game/Setup.h" #include "Objects/Generic/Object/BridgeObject.h" @@ -12,6 +13,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Collision::Floordata; using namespace TEN::Entities::Generic; using namespace TEN::Input; @@ -309,14 +311,14 @@ namespace TEN::Entities::Generic { auto& pushable = GetPushableInfo(item); - auto pointColl = CollisionResult{}; + auto pointColl = GetPointCollision(item); int waterHeight = NO_HEIGHT; if (pushable.UseBridgeCollision) { RemovePushableBridge(item); - pointColl = GetCollision(item); + pointColl = GetPointCollision(item); waterHeight = GetWaterSurface(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber); if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) @@ -326,7 +328,7 @@ namespace TEN::Entities::Generic } else { - pointColl = GetCollision(item); + pointColl = GetPointCollision(item); waterHeight = GetWaterSurface(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber); if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) @@ -334,8 +336,8 @@ namespace TEN::Entities::Generic } auto pushableColl = PushableCollisionData{}; - pushableColl.FloorHeight = pointColl.Position.Floor; - pushableColl.CeilingHeight = pointColl.Position.Ceiling; + pushableColl.FloorHeight = pointColl.GetFloorHeight(); + pushableColl.CeilingHeight = pointColl.GetCeilingHeight(); // Above water. if (TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) || @@ -367,7 +369,7 @@ namespace TEN::Entities::Generic // Grounded. else { - auto floorSlopeAngle = Geometry::GetSurfaceSlopeAngle(pointColl.FloorNormal); + auto floorSlopeAngle = Geometry::GetSurfaceSlopeAngle(pointColl.GetFloorNormal()); if (floorSlopeAngle == 0) { diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp index 4509c346f..b28869af2 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp @@ -1,10 +1,13 @@ #include "framework.h" #include "Objects/Generic/Object/Pushable/PushableSound.h" +#include "Game/collision/PointCollision.h" #include "Objects/Generic/Object/Pushable/PushableObject.h" #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::Generic { enum PushableSoundType @@ -64,8 +67,8 @@ namespace TEN::Entities::Generic static std::optional GetPushableSoundID(const ItemInfo& pushableItem, PushableSoundType soundType) { // Get floor material. - auto pointColl = GetCollision(pushableItem); - auto material = pointColl.BottomBlock->GetSurfaceMaterial(pointColl.Coordinates.x, pointColl.Coordinates.z, true); + auto pointColl = GetPointCollision(pushableItem); + auto material = pointColl.GetBottomSector().GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true); switch (soundType) { diff --git a/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp b/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp index 4af04c235..406262f9f 100644 --- a/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp +++ b/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" #include "Game/setup.h" @@ -11,6 +12,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Generic; // NOTES: @@ -139,8 +141,8 @@ namespace TEN::Entities::Traps item.Animation.TargetState = CRUMBLING_PLATFORM_STATE_FALL; item.ItemFlags[1] = CRUMBLING_PLATFORM_VELOCITY_MIN; - auto pointColl = GetCollision(item); - pointColl.Block->RemoveBridge(itemNumber); + auto pointColl = GetPointCollision(item); + pointColl.GetSector().RemoveBridge(itemNumber); } } @@ -152,8 +154,8 @@ namespace TEN::Entities::Traps // Get point collision. auto box = GameBoundingBox(&item); - auto pointColl = GetCollision(item); - int relFloorHeight = (item.Pose.Position.y - pointColl.Position.Floor) - box.Y1 ; + auto pointColl = GetPointCollision(item); + int relFloorHeight = (item.Pose.Position.y - pointColl.GetFloorHeight()) - box.Y1 ; // Airborne. if (relFloorHeight <= fallVel) @@ -168,11 +170,11 @@ namespace TEN::Entities::Traps else { item.Animation.TargetState = CRUMBLING_PLATFORM_STATE_LAND; - item.Pose.Position.y = pointColl.Position.Floor; + item.Pose.Position.y = pointColl.GetFloorHeight(); } // Update room number. - int probedRoomNumber = pointColl.RoomNumber; + int probedRoomNumber = pointColl.GetRoomNumber(); if (item.RoomNumber != probedRoomNumber) ItemNewRoom(itemNumber, probedRoomNumber); } diff --git a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp index 01b67ec76..fce60b3eb 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp @@ -2,6 +2,7 @@ #include "Objects/TR1/Entity/tr1_bear.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -13,6 +14,7 @@ #include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR1 @@ -146,8 +148,8 @@ namespace TEN::Entities::Creatures::TR1 bool isPlayerDead = LaraItem->HitPoints <= 0; - auto pointColl = GetCollision(item); - int floorToCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + auto pointColl = GetPointCollision(item); + int floorToCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); switch (item.Animation.ActiveState) { diff --git a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp index f99da99eb..3f88cdc9d 100644 --- a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp +++ b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp @@ -2,6 +2,8 @@ #include "Objects/TR3/Trap/ElectricCleaner.h" #include "Game/collision/collide_item.h" +#include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/effects/item_fx.h" #include "Game/effects/spark.h" @@ -9,6 +11,8 @@ #include "Game/Lara/lara_helpers.h" #include "Game/Setup.h" +using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Floordata; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; @@ -72,21 +76,24 @@ namespace TEN::Entities::Traps static bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir) { auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, BLOCK(1)); - auto pointColl = GetCollision(item.Pose.Position, item.RoomNumber, dir, BLOCK(1)); + auto pointColl = GetPointCollision(item.Pose.Position, item.RoomNumber, dir, BLOCK(1)); + + // TODO: Use floor normal directly. + auto floorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true); // Test for wall. - if (pointColl.Block->IsWall(projectedPos.x, projectedPos.z)) + if (pointColl.GetSector().IsWall(projectedPos.x, projectedPos.z)) return false; // Test for slippery slope. - if (pointColl.Position.FloorSlope) + if (pointColl.IsIllegalFloor()) return false; // Flat floor. - if (abs(pointColl.FloorTilt.x) == 0 && abs(pointColl.FloorTilt.y) == 0) + if (abs(floorTilt.x) == 0 && abs(floorTilt.y) == 0) { // Test for step. - int relFloorHeight = abs(pointColl.Position.Floor - item.Pose.Position.y); + int relFloorHeight = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); if (relFloorHeight >= CLICK(1)) return false; } @@ -94,25 +101,25 @@ namespace TEN::Entities::Traps else { // Half block. - int relFloorHeight = abs(pointColl.Position.Floor - item.Pose.Position.y); + int relFloorHeight = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); if (relFloorHeight > CLICK(2)) return false; short slopeAngle = ANGLE(0.0f); - if (pointColl.FloorTilt.x > 0) + if (floorTilt.x > 0) { slopeAngle = ANGLE(-90.0f); } - else if (pointColl.FloorTilt.x < 0) + else if (floorTilt.x < 0) { slopeAngle = ANGLE(90.0f); } - if (pointColl.FloorTilt.y > 0 && pointColl.FloorTilt.y > abs(pointColl.FloorTilt.x)) + if (floorTilt.y > 0 && floorTilt.y > abs(floorTilt.x)) { slopeAngle = ANGLE(180.0f); } - else if (pointColl.FloorTilt.y < 0 && -pointColl.FloorTilt.y > abs(pointColl.FloorTilt.x)) + else if (floorTilt.y < 0 && -floorTilt.y > abs(floorTilt.x)) { slopeAngle = ANGLE(0.0f); } @@ -126,28 +133,28 @@ namespace TEN::Entities::Traps } // Check for diagonal split. - if (pointColl.Position.DiagonalStep) + if (pointColl.IsDiagonalFloorStep()) return false; // Test ceiling height. - int relCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + int relCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); int cleanerHeight = BLOCK(1); if (relCeilHeight < cleanerHeight) return false; // Check for inaccessible sector. - if (pointColl.Block->Box == NO_BOX) + if (pointColl.GetSector().Box == NO_BOX) return false; // Check for blocked grey box. - if (g_Level.Boxes[pointColl.Block->Box].flags & BLOCKABLE) + if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKABLE) { - if (g_Level.Boxes[pointColl.Block->Box].flags& BLOCKED) + if (g_Level.Boxes[pointColl.GetSector().Box].flags& BLOCKED) return false; } // Check for stopper flag. - if (pointColl.Block->Stopper) + if (pointColl.GetSector().Stopper) return false; return true; @@ -309,8 +316,8 @@ namespace TEN::Entities::Traps case ElectricCleanerState::MOVE: { - auto pointColl = GetCollision(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber); - item.Pose.Position.y = pointColl.Position.Floor; + auto pointColl = GetPointCollision(item); + item.Pose.Position.y = pointColl.GetFloorHeight(); auto forwardDir = EulerAngles(0, item.Pose.Orientation.y, 0).ToDirection(); @@ -321,7 +328,7 @@ namespace TEN::Entities::Traps (item.Pose.Position.z & WALL_MASK) == BLOCK(0.5f)) { // Only turn on flat floor. - if (abs(pointColl.FloorTilt.x) == 0 && abs(pointColl.FloorTilt.y) == 0) + if (pointColl.GetFloorNormal() == -Vector3::UnitY) activeState = ElectricCleanerState::CHOOSE_PATH; } } diff --git a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp index f00c6eacb..e02a89ca0 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/effects.h" @@ -17,6 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR5 @@ -262,7 +264,7 @@ namespace TEN::Entities::Creatures::TR5 case GuardOcb::RopeDownFast: SetAnimation(item, GUARD_ANIM_ROPE_DOWN_FAST); - item->Pose.Position.y = GetCollision(*item).Position.Ceiling - BLOCK(2); + item->Pose.Position.y = GetPointCollision(*item).GetCeilingHeight() - BLOCK(2); break; case GuardOcb::WaitOnWall: From b72766b46041c60842cb34767434989362b52136 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 2 Feb 2024 00:58:59 +1100 Subject: [PATCH 053/410] Remove 2 GetCollision() overloads --- TombEngine/Game/Lara/lara.cpp | 2 +- TombEngine/Game/collision/PointCollision.cpp | 2 +- TombEngine/Game/collision/collide_room.cpp | 14 -------- TombEngine/Game/collision/collide_room.h | 2 -- .../Object/Pushable/PushableCollision.cpp | 36 +++++++++---------- .../Object/Pushable/PushableObject.cpp | 6 ++-- 6 files changed, 24 insertions(+), 38 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 7eec415d2..1c256a84a 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -125,7 +125,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) } } - auto pointColl = GetPointCollision(*item); + auto pointColl = GetPointCollision(*item, -Vector3::UnitY, coll->Setup.Height / 2); auto origin = item->Pose.Position + Vector3i(0, -BLOCK(1), 0); g_Renderer.AddDebugLine(origin.ToVector3(), Geometry::TranslatePoint(origin, pointColl.GetFloorNormal(), BLOCK(0.5f)).ToVector3(), Vector4(0, 1, 0, 1)); diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 652a47af5..22869a549 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -339,7 +339,7 @@ namespace TEN::Collision::PointCollision { // TEMP HACK // GetPointCollision() takes arguments for a *current* position and room number. - // However, since some calls to the equivalent deprecated function had *projected* + // However, since some calls to the old GetCollision() function had *projected* // positions passed to it, the room number had be corrected to account for such cases. // These are primarily found in camera.cpp. short correctedRoomNumber = roomNumber; diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 4ecd49296..0ca7e52bc 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -161,13 +161,6 @@ CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float for return ConvertPointCollDataToCollResult(pointColl); } -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const Vector3i& pos, int roomNumber) -{ - auto pointColl = GetPointCollision(pos, roomNumber); - return ConvertPointCollDataToCollResult(pointColl); -} - // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(int x, int y, int z, short roomNumber) { @@ -175,13 +168,6 @@ CollisionResult GetCollision(int x, int y, int z, short roomNumber) return ConvertPointCollDataToCollResult(pointColl); } -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const GameVector& pos) -{ - auto pointColl = GetPointCollision(pos.ToVector3i(), pos.RoomNumber); - return ConvertPointCollDataToCollResult(pointColl); -} - // NOTE: Deprecated. Use GetPointCollision(). CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) { diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 99a94bd35..b597a119a 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -138,9 +138,7 @@ struct CollisionInfo // NOTE: All overloads deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo* item); CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); -CollisionResult GetCollision(const Vector3i& pos, int roomNumber); CollisionResult GetCollision(int x, int y, int z, short roomNumber); -CollisionResult GetCollision(const GameVector& pos); CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z); void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false); diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 4e9634660..d2eac7afb 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -30,24 +30,24 @@ namespace TEN::Entities::Generic if (pushableItem.Status == ITEM_INVISIBLE || pushableItem.TriggerFlags < 0) return false; - auto pointColl = CollisionResult{}; + auto pointColl = GetPointCollision(pushableItem); if (pushable.UseRoomCollision) { RemovePushableBridge(pushableItem); - pointColl = GetCollision(&pushableItem); + pointColl = GetPointCollision(pushableItem); AddPushableBridge(pushableItem); } else { - pointColl = GetCollision(&pushableItem); + pointColl = GetPointCollision(pushableItem); } // 1) Check for wall. - if (pointColl.Block->IsWall(pushableItem.Pose.Position.x, pushableItem.Pose.Position.z)) + if (pointColl.GetSector().IsWall(pushableItem.Pose.Position.x, pushableItem.Pose.Position.z)) return false; // 2) Test height from floor. - int heightFromFloor = abs(pointColl.Position.Floor - pushableItem.Pose.Position.y); + int heightFromFloor = abs(pointColl.GetFloorHeight() - pushableItem.Pose.Position.y); if (heightFromFloor >= PUSHABLE_FLOOR_HEIGHT_TOLERANCE) return false; @@ -65,18 +65,18 @@ namespace TEN::Entities::Generic pushable.IsOnEdge = false; - auto pointColl = GetCollision(targetPos, targetRoomNumber); + auto pointColl = GetPointCollision(targetPos, targetRoomNumber); // 1) Check for wall. - if (pointColl.Block->IsWall(targetPos.x, targetPos.z)) + if (pointColl.GetSector().IsWall(targetPos.x, targetPos.z)) return false; // 2) Check for gaps or steps. - int heightFromFloor = abs(pointColl.Position.Floor - pushableItem.Pose.Position.y); + int heightFromFloor = abs(pointColl.GetFloorHeight() - pushableItem.Pose.Position.y); if (heightFromFloor >= PUSHABLE_FLOOR_HEIGHT_TOLERANCE) { // Step. - if (pointColl.Position.Floor < pushableItem.Pose.Position.y) + if (pointColl.GetFloorHeight() < pushableItem.Pose.Position.y) { return false; } @@ -90,15 +90,15 @@ namespace TEN::Entities::Generic } // 3) Check for slippery floor slope. - if (pointColl.Position.FloorSlope) + if (pointColl.IsIllegalFloor()) return false; // 4) Check for diagonal floor step. - if (pointColl.Position.DiagonalStep) + if (pointColl.IsDiagonalFloorStep()) return false; // 5) Test floor slope. TODO: Check slope angles of normals directly. - if ((pointColl.Block->GetSurfaceNormal(0, true) != -Vector3::UnitY) || (pointColl.Block->GetSurfaceNormal(1, true) != -Vector3::UnitY)) + if ((pointColl.GetSector().GetSurfaceNormal(0, true) != -Vector3::UnitY) || (pointColl.GetSector().GetSurfaceNormal(1, true) != -Vector3::UnitY)) return false; // Check for stopper flag. @@ -109,7 +109,7 @@ namespace TEN::Entities::Generic }*/ // Is ceiling (square or diagonal) high enough? - int distFromCeil = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + int distFromCeil = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); int blockHeight = GetStackHeight(pushableItem.Index) - PUSHABLE_FLOOR_HEIGHT_TOLERANCE; if (distFromCeil < blockHeight) return false; @@ -174,25 +174,25 @@ namespace TEN::Entities::Generic } // This collisionResult is the point where Lara would be at the end of the pushable pull. - auto pointColl = GetCollision(LaraItem->Pose.Position + playerOffset, LaraItem->RoomNumber); + auto pointColl = GetPointCollision(LaraItem->Pose.Position + playerOffset, LaraItem->RoomNumber); // Test for wall. - if (pointColl.Block->IsWall(pointColl.Coordinates.x, pointColl.Coordinates.z)) + if (pointColl.GetSector().IsWall(pointColl.GetPosition().x, pointColl.GetPosition().z)) return false; // Test for flat floor. - int floorHeightDelta = abs(pointColl.Position.Floor - LaraItem->Pose.Position.y); + int floorHeightDelta = abs(pointColl.GetFloorHeight() - LaraItem->Pose.Position.y); if (floorHeightDelta >= PUSHABLE_FLOOR_HEIGHT_TOLERANCE) return false; // Test floor-to-ceiling height. - int floorToCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + int floorToCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); if (floorToCeilHeight < LARA_HEIGHT) return false; // Collide with objects. auto prevPos = LaraItem->Pose.Position; - LaraItem->Pose.Position = pointColl.Coordinates; + LaraItem->Pose.Position = pointColl.GetPosition(); GetCollidedObjects(LaraItem, LARA_RADIUS, true, &CollidedItems[0], &CollidedMeshes[0], true); LaraItem->Pose.Position = prevPos; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp index 530c29c6b..e96226e1b 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/floordata.h" #include "Game/control/box.h" #include "Game/control/flipeffect.h" @@ -22,6 +23,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; namespace TEN::Entities::Generic @@ -224,8 +226,8 @@ namespace TEN::Entities::Generic void SetPushableStopperFlag(bool isStopper, const Vector3i& pos, int roomNumber) { - auto pointColl = GetCollision(pos, roomNumber); - pointColl.Block->Stopper = isStopper; + auto pointColl = GetPointCollision(pos, roomNumber); + pointColl.GetSector().Stopper = isStopper; // TODO: There is a problem, it also has to set/reset the flag in the flipped room. // Because when flipmaps happens, it forgets about the old flag. From 0fdf829b3b0ee2c0602f6b957c6ef122d8623537 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 2 Feb 2024 01:22:28 +1100 Subject: [PATCH 054/410] Remove 1 GetCollision() overload --- TombEngine/Game/Lara/lara.cpp | 2 +- TombEngine/Game/Lara/lara_overhang.cpp | 32 +++++++++++----------- TombEngine/Game/collision/collide_room.cpp | 13 ++------- TombEngine/Game/collision/collide_room.h | 1 - TombEngine/Game/control/box.cpp | 6 ++-- TombEngine/Game/control/trigger.cpp | 4 ++- 6 files changed, 27 insertions(+), 31 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 1c256a84a..7df426cc5 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -278,7 +278,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) // pre-TR5 bug where player would keep submerged until root mesh was above water level. isWaterOnHeadspace = TestEnvironment( ENV_FLAG_WATER, item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z, - GetCollision(item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z, item->RoomNumber).RoomNumber); + GetPointCollision(*item, 0, 0, -CLICK(1)).GetRoomNumber()); if (water.WaterDepth == NO_HEIGHT || abs(water.HeightFromWater) >= CLICK(1) || isWaterOnHeadspace || item->Animation.AnimNumber == LA_UNDERWATER_RESURFACE || item->Animation.AnimNumber == LA_ONWATER_DIVE) diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index 72e93f579..d1245b90d 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -370,11 +370,11 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) if (GetClimbFlags(probeUp.BottomBlock) & slopeData.ClimbOrient && InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, CLICK(3), CLICK(4))) { - if (GetCollision(probeUp.Block, up.x, up.y, up.z).Position.Ceiling - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there. - { - AlignToEdge(item, FORWARD_ALIGNMENT); - SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONVEX_START); - } + //if (GetCollision(probeUp.Block, up.x, up.y, up.z).Position.Ceiling - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there. + //{ + // AlignToEdge(item, FORWARD_ALIGNMENT); + // SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONVEX_START); + //} } // Test for monkey at next position. @@ -415,13 +415,13 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) } else if (IsHeld(In::Back)) { - if ((GetClimbFlags(GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).BottomBlock) & slopeData.ClimbOrient) && - InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, 0, CLICK(1))) - { - AlignToEdge(item, BACKWARD_ALIGNMENT); - SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONCAVE); // Slope to underlying ladder transition (concave). - return; - } + //if ((GetClimbFlags(GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).BottomBlock) & slopeData.ClimbOrient) && + // InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, 0, CLICK(1))) + //{ + // AlignToEdge(item, BACKWARD_ALIGNMENT); + // SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONCAVE); // Slope to underlying ladder transition (concave). + // return; + //} if (probeDown.BottomBlock->Flags.Monkeyswing) { @@ -1075,8 +1075,8 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { lara->Context.NextCornerPos.Orientation.z = AlignToGrab(item); - int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).Position.Ceiling; - item->Pose.Position.y = ceiling + HEIGHT_ADJUST; + /*int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).Position.Ceiling; + item->Pose.Position.y = ceiling + HEIGHT_ADJUST;*/ SetAnimation(item, LA_OVERHANG_HANG_SWING); } @@ -1091,7 +1091,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) if (abs(OrientDelta(slopeData.GoalOrient, item->Pose.Orientation.y)) <= ANGLE(30.0f) && InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, 0, CLICK(0.5f))) { - if (probeDown.BottomBlock->Flags.Monkeyswing) + /*if (probeDown.BottomBlock->Flags.Monkeyswing) { int ceiling = GetCollision(probeDown.Block, down.x, now.y, down.z).Position.Ceiling; int yDiff = ceiling - probeNow.Position.Ceiling; @@ -1115,7 +1115,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) return; //item->Pose.Position.y = ceiling + 914; } - } + }*/ } } diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 0ca7e52bc..221e358aa 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -168,13 +168,6 @@ CollisionResult GetCollision(int x, int y, int z, short roomNumber) return ConvertPointCollDataToCollResult(pointColl); } -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z) -{ - auto pointColl = GetPointCollision(Vector3i(x, y, z), floor->RoomNumber); - return ConvertPointCollDataToCollResult(pointColl); -} - void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom) { GetCollisionInfo(coll, item, Vector3i::Zero, resetRoom); @@ -1225,7 +1218,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) !TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { int waterHeight = sectorPtr->GetSurfaceHeight(x, z, false); - int floorHeight = GetCollision(sectorPtr, x, y, z).BottomBlock->GetSurfaceHeight(x, z, true); + int floorHeight = GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetBottomSector().GetSurfaceHeight(x, z, true); return (floorHeight - waterHeight); } @@ -1334,7 +1327,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) sectorPtr = GetSector(room, x - room->x, z - room->z); } - return GetCollision(sectorPtr, x, y, z).Block->GetSurfaceHeight(Vector3i(x, y, z), false); + return GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), false); } else if (sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) { @@ -1351,7 +1344,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) sectorPtr = GetSector(roomPtr2, x - roomPtr2->x, z - roomPtr2->z); } - return GetCollision(sectorPtr, x, y, z).Block->GetSurfaceHeight(Vector3i(x, y, z), true); + return GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), true); } return NO_HEIGHT; diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index b597a119a..58936b2d8 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -139,7 +139,6 @@ struct CollisionInfo CollisionResult GetCollision(const ItemInfo* item); CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); CollisionResult GetCollision(int x, int y, int z, short roomNumber); -CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z); void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false); void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom = false); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 85555a94f..3bdc5fb3d 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -5,6 +5,7 @@ #include "Game/camera.h" #include "Game/collision/sphere.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/control/lot.h" #include "Game/effects/smoke.h" @@ -22,6 +23,7 @@ #include "Objects/Generic/Object/Pushable/PushableObject.h" #include "Renderer/Renderer.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Collision::Room; using namespace TEN::Effects::Smoke; @@ -1508,9 +1510,9 @@ int TargetReachable(ItemInfo* item, ItemInfo* enemy) } else { - auto pointColl = GetCollision(floor, enemy->Pose.Position.x, enemy->Pose.Position.y, enemy->Pose.Position.z); + auto pointColl = GetPointCollision(enemy->Pose.Position, floor->RoomNumber); auto bounds = GameBoundingBox(item); - isReachable = abs(enemy->Pose.Position.y - pointColl.Position.Floor) < bounds.GetHeight(); + isReachable = abs(enemy->Pose.Position.y - pointColl.GetFloorHeight()) < bounds.GetHeight(); } return (isReachable ? floor->Box : NO_BOX); diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 6f4f4f3aa..7a9443d12 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -3,6 +3,7 @@ #include "Game/camera.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/flipeffect.h" #include "Game/control/box.h" #include "Game/control/lot.h" @@ -24,6 +25,7 @@ #include "Sound/sound.h" #include "Specific/clock.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Entities::Switches; @@ -516,7 +518,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo case TRIGGER_TYPES::PAD: case TRIGGER_TYPES::ANTIPAD: - if (GetCollision(floor, x, y, z).Position.Floor == y) + if (GetPointCollision(Vector3i(x, y, z), floor->RoomNumber).GetFloorHeight() == y) break; return; From dbeccb885e89db1bd5b96fda762c608b1477c9cb Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 4 Feb 2024 01:05:43 +1100 Subject: [PATCH 055/410] WIP Floordata 1 --- TombEngine/Game/collision/floordata.cpp | 270 +++++++++--------------- TombEngine/Game/collision/floordata.h | 10 +- 2 files changed, 95 insertions(+), 185 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 0303e233c..307148850 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -461,6 +461,7 @@ namespace TEN::Collision::Floordata return sectorPtrs; } + // GetSector FloorInfo& GetFloor(int roomNumber, const Vector2i& roomGridCoord) { auto& room = g_Level.Rooms[roomNumber]; @@ -469,13 +470,14 @@ namespace TEN::Collision::Floordata return room.floor[sectorID]; } + // GetSector FloorInfo& GetFloor(int roomNumber, int x, int z) { auto roomGridCoord = GetRoomGridCoord(roomNumber, x, z); return GetFloor(roomNumber, roomGridCoord); } - FloorInfo& GetFloorSide(int roomNumber, int x, int z, int* sideRoomNumberPtr) + static FloorInfo& GetSideSector(int roomNumber, int x, int z, int* sideRoomNumberPtr = nullptr) { auto* sectorPtr = &GetFloor(roomNumber, x, z); @@ -494,126 +496,74 @@ namespace TEN::Collision::Floordata return *sectorPtr; } - FloorInfo& GetBottomFloor(int roomNumber, int x, int z, int* bottomRoomNumberPtr) + static FloorInfo& GetFarthestSector(int roomNumber, int x, int z, bool isBottom, int* farthestRoomNumberPtr = nullptr) { - auto* sectorPtr = &GetFloorSide(roomNumber, x, z, bottomRoomNumberPtr); + auto* sectorPtr = &GetSideSector(roomNumber, x, z, farthestRoomNumberPtr); - // Find bottom sector. + // Find bottom or top sector. bool isWall = sectorPtr->IsWall(x, z); while (isWall) { - auto roomNumberBelow = sectorPtr->GetRoomNumberBelow(x, z); - if (!roomNumberBelow.has_value()) + auto nextRoomNumber = isBottom ? sectorPtr->GetRoomNumberBelow(x, z) : sectorPtr->GetRoomNumberAbove(x, z); + if (!nextRoomNumber.has_value()) break; // TODO: Check. - sectorPtr = &GetFloorSide(*roomNumberBelow, x, z, bottomRoomNumberPtr); + sectorPtr = &GetSideSector(*nextRoomNumber, x, z, farthestRoomNumberPtr); isWall = sectorPtr->IsWall(x, z); } return *sectorPtr; } - FloorInfo& GetTopFloor(int roomNumber, int x, int z, int* topRoomNumberPtr) + static std::optional GetFarthestHeight(FloorInfo& startSector, Vector3i pos, bool isBottom, + int* farthestRoomNumberPtr = nullptr, FloorInfo** farthestSectorPtr = nullptr) { - auto* sectorPtr = &GetFloorSide(roomNumber, x, z, topRoomNumberPtr); - - // Find top sector. - bool isWall = sectorPtr->IsWall(x, z); - while (isWall) - { - auto roomNumberAbove = sectorPtr->GetRoomNumberAbove(x, z); - if (!roomNumberAbove) - break; + int roomNumber = (farthestRoomNumberPtr != nullptr) ? *farthestRoomNumberPtr : 0; - // TODO: Check. - sectorPtr = &GetFloorSide(*roomNumberAbove, x, z, topRoomNumberPtr); - isWall = sectorPtr->IsWall(x, z); - } - - return *sectorPtr; - } - - std::optional GetBottomHeight(FloorInfo& startSector, Vector3i pos, int* bottomRoomNumberPtr, FloorInfo** bottomSectorPtr) - { - int roomNumber = (bottomRoomNumberPtr != nullptr) ? *bottomRoomNumberPtr : 0; - - // Find bottom height. + // Find bottom or top height. auto* sectorPtr = &startSector; do { - // Set vertical position to lowest bridge ceiling height. - pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, false); + // Set vertical position to lowest bridge ceiling height or highest bridge floor height. + pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, !isBottom); - // Find sector at lowest bridge floor height. - while (pos.y >= sectorPtr->GetSurfaceHeight(pos.x, pos.z, true)) + // Find sector at lowest bridge floor height or highest bridge ceiling height. + while (isBottom ? + (pos.y >= sectorPtr->GetSurfaceHeight(pos.x, pos.z, true)) : + (pos.y <= sectorPtr->GetSurfaceHeight(pos.x, pos.z, false))) { - auto roomNumberBelow = sectorPtr->GetRoomNumberBelow(pos.x, pos.z); - if (!roomNumberBelow.has_value()) + auto nextRoomNumber = isBottom ? sectorPtr->GetRoomNumberBelow(pos.x, pos.z) : sectorPtr->GetRoomNumberAbove(pos.x, pos.z);; + if (!nextRoomNumber.has_value()) return std::nullopt; - sectorPtr = &GetFloorSide(*roomNumberBelow, pos.x, pos.z, &roomNumber); + sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z, &roomNumber); } } // Continue running while bridge exists(?). - while (sectorPtr->GetInsideBridgeItemNumber(pos, true, false) != NO_ITEM); + while (sectorPtr->GetInsideBridgeItemNumber(pos, isBottom, !isBottom) != NO_ITEM); - // Set output bottom room number. - if (bottomRoomNumberPtr != nullptr) - *bottomRoomNumberPtr = roomNumber; + // Set output bottom or top room number. + if (farthestRoomNumberPtr != nullptr) + *farthestRoomNumberPtr = roomNumber; - // Set output bottom sector pointer. - if (bottomSectorPtr != nullptr) - *bottomSectorPtr = sectorPtr; - - return pos.y; - } - - std::optional GetTopHeight(FloorInfo& startSector, Vector3i pos, int* topRoomNumberPtr, FloorInfo** topSectorPtr) - { - int roomNumber = (topRoomNumberPtr != nullptr) ? *topRoomNumberPtr : 0; - - // Find top height. - auto* sectorPtr = &startSector; - do - { - // Set vertical position to highest bridge floor height. - pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, true); - - // Find sector at highest bridge ceiling height. - while (pos.y <= sectorPtr->GetSurfaceHeight(pos.x, pos.z, false)) - { - auto roomNumberAbove = sectorPtr->GetRoomNumberAbove(pos.x, pos.z); - if (!roomNumberAbove.has_value()) - return std::nullopt; - - sectorPtr = &GetFloorSide(*roomNumberAbove, pos.x, pos.z, &roomNumber); - } - } - // Continue running while bridge exists(?). - while (sectorPtr->GetInsideBridgeItemNumber(pos, false, true) >= 0); - - // Set output top room number. - if (topRoomNumberPtr != nullptr) - *topRoomNumberPtr = roomNumber; - - // Set output top sector pointer. - if (topSectorPtr != nullptr) - *topSectorPtr = sectorPtr; + // Set output bottom or top sector pointer. + if (farthestSectorPtr != nullptr) + *farthestSectorPtr = sectorPtr; return pos.y; } std::optional GetSurfaceHeight(const RoomVector& location, int x, int z, bool isFloor) { - auto* sectorPtr = &GetFloorSide(location.RoomNumber, x, z); + auto* sectorPtr = &GetSideSector(location.RoomNumber, x, z); auto pos = Vector3i(x, location.Height, z); int polarity = 0; if (sectorPtr->IsWall(x, z)) { - sectorPtr = isFloor ? &GetTopFloor(location.RoomNumber, x, z) : &GetBottomFloor(location.RoomNumber, x, z); + sectorPtr = &GetFarthestSector(location.RoomNumber, x, z, isFloor); if (!sectorPtr->IsWall(x, z)) { @@ -622,7 +572,7 @@ namespace TEN::Collision::Floordata } else { - sectorPtr = isFloor ? &GetBottomFloor(location.RoomNumber, x, z) : &GetTopFloor(location.RoomNumber, x, z); + sectorPtr = &GetFarthestSector(location.RoomNumber, x, z, isFloor); if (!sectorPtr->IsWall(x, z)) { @@ -647,19 +597,16 @@ namespace TEN::Collision::Floordata if (insideBridgeItemNumber != NO_ITEM) { - if (isFloor ? (polarity <= 0) : (polarity >= 0)) + if (isFloor ? (polarity <= 0) : (polarity >= 0)) { - auto heightBound = isFloor ? GetTopHeight(*sectorPtr, pos) : GetBottomHeight(*sectorPtr, pos); + auto heightBound = GetFarthestHeight(*sectorPtr, pos, !isFloor); if (heightBound.has_value()) return heightBound; } if (isFloor ? (polarity >= 0) : (polarity <= 0)) { - auto heightBound = isFloor ? - GetBottomHeight(*sectorPtr, pos, nullptr, §orPtr) : - GetTopHeight(*sectorPtr, pos, nullptr, §orPtr); - + auto heightBound = GetFarthestHeight(*sectorPtr, pos, isFloor, nullptr, §orPtr); if (!heightBound.has_value()) return std::nullopt; @@ -672,7 +619,7 @@ namespace TEN::Collision::Floordata auto nextRoomNumber = isFloor ? sectorPtr->GetRoomNumberBelow(pos) : sectorPtr->GetRoomNumberAbove(pos); while (nextRoomNumber.has_value()) { - sectorPtr = &GetFloorSide(*nextRoomNumber, x, z); + sectorPtr = &GetSideSector(*nextRoomNumber, x, z); nextRoomNumber = isFloor ? sectorPtr->GetRoomNumberBelow(pos) : sectorPtr->GetRoomNumberAbove(pos); } } @@ -680,18 +627,17 @@ namespace TEN::Collision::Floordata return sectorPtr->GetSurfaceHeight(pos, isFloor); } - std::optional GetBottomRoom(RoomVector location, const Vector3i& pos) + static std::optional GetFarthestRoom(RoomVector location, const Vector3i& pos, bool isBottom) { - auto* sectorPtr = &GetFloorSide(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); + auto* sectorPtr = &GetSideSector(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); if (sectorPtr->IsWall(pos.x, pos.z)) { - sectorPtr = &GetBottomFloor(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); - + sectorPtr = &GetFarthestSector(location.RoomNumber, pos.x, pos.z, isBottom, &location.RoomNumber); if (sectorPtr->IsWall(pos.x, pos.z)) return std::nullopt; - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, false); + location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, !isBottom); } int floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); @@ -705,30 +651,15 @@ namespace TEN::Collision::Floordata if (insideBridgeItemNumber != NO_ITEM) { - auto bottomHeight = GetBottomHeight(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), &location.RoomNumber, §orPtr); - if (!bottomHeight.has_value()) + auto farthestHeight = GetFarthestHeight(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), isBottom, &location.RoomNumber, §orPtr); + if (!farthestHeight.has_value()) return std::nullopt; - location.Height = *bottomHeight; + location.Height = *farthestHeight; } - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); - if (pos.y < ceilingHeight && sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z))) - return std::nullopt; - - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - if (pos.y <= floorHeight) + if (isBottom) { - location.Height = std::max(pos.y, ceilingHeight); - return location; - } - - auto roomNumberBelow = sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)); - while (roomNumberBelow.has_value()) - { - sectorPtr = &GetFloorSide(*roomNumberBelow, pos.x, pos.z, &location.RoomNumber); - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, false); - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); if (pos.y < ceilingHeight && sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z))) return std::nullopt; @@ -739,62 +670,9 @@ namespace TEN::Collision::Floordata location.Height = std::max(pos.y, ceilingHeight); return location; } - - roomNumberBelow = sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)); } - - return std::nullopt; - } - - std::optional GetTopRoom(RoomVector location, const Vector3i& pos) - { - auto* sectorPtr = &GetFloorSide(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); - - if (sectorPtr->IsWall(pos.x, pos.z)) + else { - sectorPtr = &GetTopFloor(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); - - if (sectorPtr->IsWall(pos.x, pos.z)) - return std::nullopt; - - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, true); - } - - int floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - int ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); - - location.Height = std::clamp(location.Height, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); - - bool testFloorBorder = (location.Height == ceilingHeight); - bool testCeilBorder = (location.Height == floorHeight); - int insideBridgeItemNumber = sectorPtr->GetInsideBridgeItemNumber(Vector3i(pos.x, location.Height, pos.z), testFloorBorder, testCeilBorder); - - if (insideBridgeItemNumber != NO_ITEM) - { - auto topHeight = GetTopHeight(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), &location.RoomNumber, §orPtr); - if (!topHeight.has_value()) - return std::nullopt; - - location.Height = *topHeight; - } - - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - if (pos.y > floorHeight && sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z))) - return std::nullopt; - - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); - if (pos.y >= ceilingHeight) - { - location.Height = std::min(pos.y, floorHeight); - return location; - } - - auto roomNumberAbove = sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); - while (roomNumberAbove.has_value()) - { - sectorPtr = &GetFloorSide(*roomNumberAbove, pos.x, pos.z, &location.RoomNumber); - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, true); - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); if (pos.y > floorHeight && sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z))) return std::nullopt; @@ -805,20 +683,60 @@ namespace TEN::Collision::Floordata location.Height = std::min(pos.y, floorHeight); return location; } + } - roomNumberAbove = sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); + auto nextRoomNumber = isBottom ? + sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)) : + sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); + + while (nextRoomNumber.has_value()) + { + sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z, &location.RoomNumber); + location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, !isBottom); + + if (isBottom) + { + ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + if (pos.y < ceilingHeight && sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z))) + return std::nullopt; + + floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + if (pos.y <= floorHeight) + { + location.Height = std::max(pos.y, ceilingHeight); + return location; + } + } + else + { + floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + if (pos.y > floorHeight && sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z))) + return std::nullopt; + + ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + if (pos.y >= ceilingHeight) + { + location.Height = std::min(pos.y, floorHeight); + return location; + } + } + + nextRoomNumber = isBottom ? + sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)) : + sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); } return std::nullopt; } + // GetRoomVector RoomVector GetRoom(RoomVector location, const Vector3i& pos) { - auto locationBelow = GetBottomRoom(location, pos); + auto locationBelow = GetFarthestRoom(location, pos, true); if (locationBelow.has_value()) return *locationBelow; - auto locationAbove = GetTopRoom(location, pos); + auto locationAbove = GetFarthestRoom(location, pos, false); if (locationAbove.has_value()) return *locationAbove; @@ -836,7 +754,7 @@ namespace TEN::Collision::Floordata x += bridgeItem.Pose.Position.x; z += bridgeItem.Pose.Position.z; - auto* sectorPtr = &GetFloorSide(bridgeItem.RoomNumber, x, z); + auto* sectorPtr = &GetSideSector(bridgeItem.RoomNumber, x, z); sectorPtr->AddBridge(itemNumber); if (bridge.GetFloorBorder != nullptr) @@ -848,7 +766,7 @@ namespace TEN::Collision::Floordata if (!roomNumberAbove.has_value()) break; - sectorPtr = &GetFloorSide(*roomNumberAbove, x, z); + sectorPtr = &GetSideSector(*roomNumberAbove, x, z); sectorPtr->AddBridge(itemNumber); } } @@ -862,7 +780,7 @@ namespace TEN::Collision::Floordata if (!roomNumberBelow.has_value()) break; - sectorPtr = &GetFloorSide(*roomNumberBelow, x, z); + sectorPtr = &GetSideSector(*roomNumberBelow, x, z); sectorPtr->AddBridge(itemNumber); } } @@ -879,7 +797,7 @@ namespace TEN::Collision::Floordata x += bridgeItem.Pose.Position.x; z += bridgeItem.Pose.Position.z; - auto* sectorPtr = &GetFloorSide(bridgeItem.RoomNumber, x, z); + auto* sectorPtr = &GetSideSector(bridgeItem.RoomNumber, x, z); sectorPtr->RemoveBridge(itemNumber); if (bridge.GetFloorBorder != nullptr) @@ -891,7 +809,7 @@ namespace TEN::Collision::Floordata if (!roomNumberAbove.has_value()) break; - sectorPtr = &GetFloorSide(*roomNumberAbove, x, z); + sectorPtr = &GetSideSector(*roomNumberAbove, x, z); sectorPtr->RemoveBridge(itemNumber); } } @@ -905,7 +823,7 @@ namespace TEN::Collision::Floordata if (!roomNumberBelow.has_value()) break; - sectorPtr = &GetFloorSide(*roomNumberBelow, x, z); + sectorPtr = &GetSideSector(*roomNumberBelow, x, z); sectorPtr->RemoveBridge(itemNumber); } } diff --git a/TombEngine/Game/collision/floordata.h b/TombEngine/Game/collision/floordata.h index 68730cedd..33de6fd54 100644 --- a/TombEngine/Game/collision/floordata.h +++ b/TombEngine/Game/collision/floordata.h @@ -194,17 +194,9 @@ namespace TEN::Collision::Floordata FloorInfo& GetFloor(int roomNumber, const Vector2i& roomGridCoord); FloorInfo& GetFloor(int roomNumber, int x, int z); - FloorInfo& GetFloorSide(int roomNumber, int x, int z, int* sideRoomNumber = nullptr); - FloorInfo& GetBottomFloor(int roomNumber, int x, int z, int* bottomRoomNumber = nullptr); - FloorInfo& GetTopFloor(int roomNumber, int x, int z, int* topRoomNumber = nullptr); - std::optional GetBottomHeight(FloorInfo& startSector, Vector3i pos, int* bottomRoomNumberPtr = nullptr, FloorInfo** bottomSectorPtr = nullptr); - std::optional GetTopHeight(FloorInfo& startSector, Vector3i pos, int* topRoomNumberPtr = nullptr, FloorInfo** topSectorPtr = nullptr); std::optional GetSurfaceHeight(const RoomVector& location, int x, int z, bool isFloor); - - std::optional GetBottomRoom(RoomVector location, const Vector3i& pos); - std::optional GetTopRoom(RoomVector location, const Vector3i& pos); - RoomVector GetRoom(RoomVector location, const Vector3i& pos); + RoomVector GetRoom(RoomVector location, const Vector3i& pos); void AddBridge(int itemNumber, int x = 0, int z = 0); void RemoveBridge(int itemNumber, int x = 0, int z = 0); From 41508a221770bfdc95250dc53255c3443c97a146 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 4 Feb 2024 01:06:48 +1100 Subject: [PATCH 056/410] Revert "WIP Floordata 1" This reverts commit dbeccb885e89db1bd5b96fda762c608b1477c9cb. --- TombEngine/Game/collision/floordata.cpp | 270 +++++++++++++++--------- TombEngine/Game/collision/floordata.h | 10 +- 2 files changed, 185 insertions(+), 95 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 307148850..0303e233c 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -461,7 +461,6 @@ namespace TEN::Collision::Floordata return sectorPtrs; } - // GetSector FloorInfo& GetFloor(int roomNumber, const Vector2i& roomGridCoord) { auto& room = g_Level.Rooms[roomNumber]; @@ -470,14 +469,13 @@ namespace TEN::Collision::Floordata return room.floor[sectorID]; } - // GetSector FloorInfo& GetFloor(int roomNumber, int x, int z) { auto roomGridCoord = GetRoomGridCoord(roomNumber, x, z); return GetFloor(roomNumber, roomGridCoord); } - static FloorInfo& GetSideSector(int roomNumber, int x, int z, int* sideRoomNumberPtr = nullptr) + FloorInfo& GetFloorSide(int roomNumber, int x, int z, int* sideRoomNumberPtr) { auto* sectorPtr = &GetFloor(roomNumber, x, z); @@ -496,74 +494,126 @@ namespace TEN::Collision::Floordata return *sectorPtr; } - static FloorInfo& GetFarthestSector(int roomNumber, int x, int z, bool isBottom, int* farthestRoomNumberPtr = nullptr) + FloorInfo& GetBottomFloor(int roomNumber, int x, int z, int* bottomRoomNumberPtr) { - auto* sectorPtr = &GetSideSector(roomNumber, x, z, farthestRoomNumberPtr); + auto* sectorPtr = &GetFloorSide(roomNumber, x, z, bottomRoomNumberPtr); - // Find bottom or top sector. + // Find bottom sector. bool isWall = sectorPtr->IsWall(x, z); while (isWall) { - auto nextRoomNumber = isBottom ? sectorPtr->GetRoomNumberBelow(x, z) : sectorPtr->GetRoomNumberAbove(x, z); - if (!nextRoomNumber.has_value()) + auto roomNumberBelow = sectorPtr->GetRoomNumberBelow(x, z); + if (!roomNumberBelow.has_value()) break; // TODO: Check. - sectorPtr = &GetSideSector(*nextRoomNumber, x, z, farthestRoomNumberPtr); + sectorPtr = &GetFloorSide(*roomNumberBelow, x, z, bottomRoomNumberPtr); isWall = sectorPtr->IsWall(x, z); } return *sectorPtr; } - static std::optional GetFarthestHeight(FloorInfo& startSector, Vector3i pos, bool isBottom, - int* farthestRoomNumberPtr = nullptr, FloorInfo** farthestSectorPtr = nullptr) + FloorInfo& GetTopFloor(int roomNumber, int x, int z, int* topRoomNumberPtr) { - int roomNumber = (farthestRoomNumberPtr != nullptr) ? *farthestRoomNumberPtr : 0; + auto* sectorPtr = &GetFloorSide(roomNumber, x, z, topRoomNumberPtr); + + // Find top sector. + bool isWall = sectorPtr->IsWall(x, z); + while (isWall) + { + auto roomNumberAbove = sectorPtr->GetRoomNumberAbove(x, z); + if (!roomNumberAbove) + break; - // Find bottom or top height. + // TODO: Check. + sectorPtr = &GetFloorSide(*roomNumberAbove, x, z, topRoomNumberPtr); + isWall = sectorPtr->IsWall(x, z); + } + + return *sectorPtr; + } + + std::optional GetBottomHeight(FloorInfo& startSector, Vector3i pos, int* bottomRoomNumberPtr, FloorInfo** bottomSectorPtr) + { + int roomNumber = (bottomRoomNumberPtr != nullptr) ? *bottomRoomNumberPtr : 0; + + // Find bottom height. auto* sectorPtr = &startSector; do { - // Set vertical position to lowest bridge ceiling height or highest bridge floor height. - pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, !isBottom); + // Set vertical position to lowest bridge ceiling height. + pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, false); - // Find sector at lowest bridge floor height or highest bridge ceiling height. - while (isBottom ? - (pos.y >= sectorPtr->GetSurfaceHeight(pos.x, pos.z, true)) : - (pos.y <= sectorPtr->GetSurfaceHeight(pos.x, pos.z, false))) + // Find sector at lowest bridge floor height. + while (pos.y >= sectorPtr->GetSurfaceHeight(pos.x, pos.z, true)) { - auto nextRoomNumber = isBottom ? sectorPtr->GetRoomNumberBelow(pos.x, pos.z) : sectorPtr->GetRoomNumberAbove(pos.x, pos.z);; - if (!nextRoomNumber.has_value()) + auto roomNumberBelow = sectorPtr->GetRoomNumberBelow(pos.x, pos.z); + if (!roomNumberBelow.has_value()) return std::nullopt; - sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z, &roomNumber); + sectorPtr = &GetFloorSide(*roomNumberBelow, pos.x, pos.z, &roomNumber); } } // Continue running while bridge exists(?). - while (sectorPtr->GetInsideBridgeItemNumber(pos, isBottom, !isBottom) != NO_ITEM); + while (sectorPtr->GetInsideBridgeItemNumber(pos, true, false) != NO_ITEM); - // Set output bottom or top room number. - if (farthestRoomNumberPtr != nullptr) - *farthestRoomNumberPtr = roomNumber; + // Set output bottom room number. + if (bottomRoomNumberPtr != nullptr) + *bottomRoomNumberPtr = roomNumber; - // Set output bottom or top sector pointer. - if (farthestSectorPtr != nullptr) - *farthestSectorPtr = sectorPtr; + // Set output bottom sector pointer. + if (bottomSectorPtr != nullptr) + *bottomSectorPtr = sectorPtr; + + return pos.y; + } + + std::optional GetTopHeight(FloorInfo& startSector, Vector3i pos, int* topRoomNumberPtr, FloorInfo** topSectorPtr) + { + int roomNumber = (topRoomNumberPtr != nullptr) ? *topRoomNumberPtr : 0; + + // Find top height. + auto* sectorPtr = &startSector; + do + { + // Set vertical position to highest bridge floor height. + pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, true); + + // Find sector at highest bridge ceiling height. + while (pos.y <= sectorPtr->GetSurfaceHeight(pos.x, pos.z, false)) + { + auto roomNumberAbove = sectorPtr->GetRoomNumberAbove(pos.x, pos.z); + if (!roomNumberAbove.has_value()) + return std::nullopt; + + sectorPtr = &GetFloorSide(*roomNumberAbove, pos.x, pos.z, &roomNumber); + } + } + // Continue running while bridge exists(?). + while (sectorPtr->GetInsideBridgeItemNumber(pos, false, true) >= 0); + + // Set output top room number. + if (topRoomNumberPtr != nullptr) + *topRoomNumberPtr = roomNumber; + + // Set output top sector pointer. + if (topSectorPtr != nullptr) + *topSectorPtr = sectorPtr; return pos.y; } std::optional GetSurfaceHeight(const RoomVector& location, int x, int z, bool isFloor) { - auto* sectorPtr = &GetSideSector(location.RoomNumber, x, z); + auto* sectorPtr = &GetFloorSide(location.RoomNumber, x, z); auto pos = Vector3i(x, location.Height, z); int polarity = 0; if (sectorPtr->IsWall(x, z)) { - sectorPtr = &GetFarthestSector(location.RoomNumber, x, z, isFloor); + sectorPtr = isFloor ? &GetTopFloor(location.RoomNumber, x, z) : &GetBottomFloor(location.RoomNumber, x, z); if (!sectorPtr->IsWall(x, z)) { @@ -572,7 +622,7 @@ namespace TEN::Collision::Floordata } else { - sectorPtr = &GetFarthestSector(location.RoomNumber, x, z, isFloor); + sectorPtr = isFloor ? &GetBottomFloor(location.RoomNumber, x, z) : &GetTopFloor(location.RoomNumber, x, z); if (!sectorPtr->IsWall(x, z)) { @@ -597,16 +647,19 @@ namespace TEN::Collision::Floordata if (insideBridgeItemNumber != NO_ITEM) { - if (isFloor ? (polarity <= 0) : (polarity >= 0)) + if (isFloor ? (polarity <= 0) : (polarity >= 0)) { - auto heightBound = GetFarthestHeight(*sectorPtr, pos, !isFloor); + auto heightBound = isFloor ? GetTopHeight(*sectorPtr, pos) : GetBottomHeight(*sectorPtr, pos); if (heightBound.has_value()) return heightBound; } if (isFloor ? (polarity >= 0) : (polarity <= 0)) { - auto heightBound = GetFarthestHeight(*sectorPtr, pos, isFloor, nullptr, §orPtr); + auto heightBound = isFloor ? + GetBottomHeight(*sectorPtr, pos, nullptr, §orPtr) : + GetTopHeight(*sectorPtr, pos, nullptr, §orPtr); + if (!heightBound.has_value()) return std::nullopt; @@ -619,7 +672,7 @@ namespace TEN::Collision::Floordata auto nextRoomNumber = isFloor ? sectorPtr->GetRoomNumberBelow(pos) : sectorPtr->GetRoomNumberAbove(pos); while (nextRoomNumber.has_value()) { - sectorPtr = &GetSideSector(*nextRoomNumber, x, z); + sectorPtr = &GetFloorSide(*nextRoomNumber, x, z); nextRoomNumber = isFloor ? sectorPtr->GetRoomNumberBelow(pos) : sectorPtr->GetRoomNumberAbove(pos); } } @@ -627,17 +680,18 @@ namespace TEN::Collision::Floordata return sectorPtr->GetSurfaceHeight(pos, isFloor); } - static std::optional GetFarthestRoom(RoomVector location, const Vector3i& pos, bool isBottom) + std::optional GetBottomRoom(RoomVector location, const Vector3i& pos) { - auto* sectorPtr = &GetSideSector(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); + auto* sectorPtr = &GetFloorSide(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); if (sectorPtr->IsWall(pos.x, pos.z)) { - sectorPtr = &GetFarthestSector(location.RoomNumber, pos.x, pos.z, isBottom, &location.RoomNumber); + sectorPtr = &GetBottomFloor(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); + if (sectorPtr->IsWall(pos.x, pos.z)) return std::nullopt; - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, !isBottom); + location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, false); } int floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); @@ -651,15 +705,30 @@ namespace TEN::Collision::Floordata if (insideBridgeItemNumber != NO_ITEM) { - auto farthestHeight = GetFarthestHeight(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), isBottom, &location.RoomNumber, §orPtr); - if (!farthestHeight.has_value()) + auto bottomHeight = GetBottomHeight(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), &location.RoomNumber, §orPtr); + if (!bottomHeight.has_value()) return std::nullopt; - location.Height = *farthestHeight; + location.Height = *bottomHeight; } - if (isBottom) + ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + if (pos.y < ceilingHeight && sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z))) + return std::nullopt; + + floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + if (pos.y <= floorHeight) { + location.Height = std::max(pos.y, ceilingHeight); + return location; + } + + auto roomNumberBelow = sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)); + while (roomNumberBelow.has_value()) + { + sectorPtr = &GetFloorSide(*roomNumberBelow, pos.x, pos.z, &location.RoomNumber); + location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, false); + ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); if (pos.y < ceilingHeight && sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z))) return std::nullopt; @@ -670,9 +739,62 @@ namespace TEN::Collision::Floordata location.Height = std::max(pos.y, ceilingHeight); return location; } + + roomNumberBelow = sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)); } - else + + return std::nullopt; + } + + std::optional GetTopRoom(RoomVector location, const Vector3i& pos) + { + auto* sectorPtr = &GetFloorSide(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); + + if (sectorPtr->IsWall(pos.x, pos.z)) { + sectorPtr = &GetTopFloor(location.RoomNumber, pos.x, pos.z, &location.RoomNumber); + + if (sectorPtr->IsWall(pos.x, pos.z)) + return std::nullopt; + + location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, true); + } + + int floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + int ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + + location.Height = std::clamp(location.Height, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); + + bool testFloorBorder = (location.Height == ceilingHeight); + bool testCeilBorder = (location.Height == floorHeight); + int insideBridgeItemNumber = sectorPtr->GetInsideBridgeItemNumber(Vector3i(pos.x, location.Height, pos.z), testFloorBorder, testCeilBorder); + + if (insideBridgeItemNumber != NO_ITEM) + { + auto topHeight = GetTopHeight(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), &location.RoomNumber, §orPtr); + if (!topHeight.has_value()) + return std::nullopt; + + location.Height = *topHeight; + } + + floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + if (pos.y > floorHeight && sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z))) + return std::nullopt; + + ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + if (pos.y >= ceilingHeight) + { + location.Height = std::min(pos.y, floorHeight); + return location; + } + + auto roomNumberAbove = sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); + while (roomNumberAbove.has_value()) + { + sectorPtr = &GetFloorSide(*roomNumberAbove, pos.x, pos.z, &location.RoomNumber); + location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, true); + floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); if (pos.y > floorHeight && sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z))) return std::nullopt; @@ -683,60 +805,20 @@ namespace TEN::Collision::Floordata location.Height = std::min(pos.y, floorHeight); return location; } - } - auto nextRoomNumber = isBottom ? - sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)) : - sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); - - while (nextRoomNumber.has_value()) - { - sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z, &location.RoomNumber); - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, !isBottom); - - if (isBottom) - { - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); - if (pos.y < ceilingHeight && sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z))) - return std::nullopt; - - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - if (pos.y <= floorHeight) - { - location.Height = std::max(pos.y, ceilingHeight); - return location; - } - } - else - { - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - if (pos.y > floorHeight && sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z))) - return std::nullopt; - - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); - if (pos.y >= ceilingHeight) - { - location.Height = std::min(pos.y, floorHeight); - return location; - } - } - - nextRoomNumber = isBottom ? - sectorPtr->GetRoomNumberBelow(Vector3i(pos.x, location.Height, pos.z)) : - sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); + roomNumberAbove = sectorPtr->GetRoomNumberAbove(Vector3i(pos.x, location.Height, pos.z)); } return std::nullopt; } - // GetRoomVector RoomVector GetRoom(RoomVector location, const Vector3i& pos) { - auto locationBelow = GetFarthestRoom(location, pos, true); + auto locationBelow = GetBottomRoom(location, pos); if (locationBelow.has_value()) return *locationBelow; - auto locationAbove = GetFarthestRoom(location, pos, false); + auto locationAbove = GetTopRoom(location, pos); if (locationAbove.has_value()) return *locationAbove; @@ -754,7 +836,7 @@ namespace TEN::Collision::Floordata x += bridgeItem.Pose.Position.x; z += bridgeItem.Pose.Position.z; - auto* sectorPtr = &GetSideSector(bridgeItem.RoomNumber, x, z); + auto* sectorPtr = &GetFloorSide(bridgeItem.RoomNumber, x, z); sectorPtr->AddBridge(itemNumber); if (bridge.GetFloorBorder != nullptr) @@ -766,7 +848,7 @@ namespace TEN::Collision::Floordata if (!roomNumberAbove.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberAbove, x, z); + sectorPtr = &GetFloorSide(*roomNumberAbove, x, z); sectorPtr->AddBridge(itemNumber); } } @@ -780,7 +862,7 @@ namespace TEN::Collision::Floordata if (!roomNumberBelow.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberBelow, x, z); + sectorPtr = &GetFloorSide(*roomNumberBelow, x, z); sectorPtr->AddBridge(itemNumber); } } @@ -797,7 +879,7 @@ namespace TEN::Collision::Floordata x += bridgeItem.Pose.Position.x; z += bridgeItem.Pose.Position.z; - auto* sectorPtr = &GetSideSector(bridgeItem.RoomNumber, x, z); + auto* sectorPtr = &GetFloorSide(bridgeItem.RoomNumber, x, z); sectorPtr->RemoveBridge(itemNumber); if (bridge.GetFloorBorder != nullptr) @@ -809,7 +891,7 @@ namespace TEN::Collision::Floordata if (!roomNumberAbove.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberAbove, x, z); + sectorPtr = &GetFloorSide(*roomNumberAbove, x, z); sectorPtr->RemoveBridge(itemNumber); } } @@ -823,7 +905,7 @@ namespace TEN::Collision::Floordata if (!roomNumberBelow.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberBelow, x, z); + sectorPtr = &GetFloorSide(*roomNumberBelow, x, z); sectorPtr->RemoveBridge(itemNumber); } } diff --git a/TombEngine/Game/collision/floordata.h b/TombEngine/Game/collision/floordata.h index 33de6fd54..68730cedd 100644 --- a/TombEngine/Game/collision/floordata.h +++ b/TombEngine/Game/collision/floordata.h @@ -194,9 +194,17 @@ namespace TEN::Collision::Floordata FloorInfo& GetFloor(int roomNumber, const Vector2i& roomGridCoord); FloorInfo& GetFloor(int roomNumber, int x, int z); + FloorInfo& GetFloorSide(int roomNumber, int x, int z, int* sideRoomNumber = nullptr); + FloorInfo& GetBottomFloor(int roomNumber, int x, int z, int* bottomRoomNumber = nullptr); + FloorInfo& GetTopFloor(int roomNumber, int x, int z, int* topRoomNumber = nullptr); + std::optional GetBottomHeight(FloorInfo& startSector, Vector3i pos, int* bottomRoomNumberPtr = nullptr, FloorInfo** bottomSectorPtr = nullptr); + std::optional GetTopHeight(FloorInfo& startSector, Vector3i pos, int* topRoomNumberPtr = nullptr, FloorInfo** topSectorPtr = nullptr); std::optional GetSurfaceHeight(const RoomVector& location, int x, int z, bool isFloor); - RoomVector GetRoom(RoomVector location, const Vector3i& pos); + + std::optional GetBottomRoom(RoomVector location, const Vector3i& pos); + std::optional GetTopRoom(RoomVector location, const Vector3i& pos); + RoomVector GetRoom(RoomVector location, const Vector3i& pos); void AddBridge(int itemNumber, int x = 0, int z = 0); void RemoveBridge(int itemNumber, int x = 0, int z = 0); From 5a1b1c89bd0bad43ff23c246adbd7bad15969927 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 23 Feb 2024 18:12:27 +1100 Subject: [PATCH 057/410] Remove GetCollision() overload --- TombEngine/Game/Lara/lara_climb.cpp | 50 ++--- TombEngine/Game/Lara/lara_flare.cpp | 4 +- TombEngine/Game/Lara/lara_one_gun.cpp | 10 +- TombEngine/Game/Lara/lara_overhang.cpp | 155 ++++++++------- TombEngine/Game/Lara/lara_tests.cpp | 16 +- TombEngine/Game/collision/PointCollision.cpp | 10 +- TombEngine/Game/collision/collide_item.cpp | 97 ++++----- TombEngine/Game/collision/collide_item.h | 5 +- TombEngine/Game/collision/collide_room.cpp | 188 +++++++++--------- TombEngine/Game/collision/collide_room.h | 20 +- TombEngine/Game/control/box.cpp | 2 +- TombEngine/Game/control/trigger.cpp | 6 +- TombEngine/Game/effects/drip.cpp | 18 +- TombEngine/Game/effects/effects.cpp | 8 +- TombEngine/Game/effects/footprint.cpp | 30 +-- TombEngine/Game/effects/hair.cpp | 8 +- TombEngine/Game/effects/item_fx.cpp | 4 +- TombEngine/Game/effects/weather.cpp | 24 ++- TombEngine/Game/items.cpp | 9 +- TombEngine/Game/missile.cpp | 10 +- TombEngine/Game/pickup/pickup.cpp | 24 ++- TombEngine/Game/room.cpp | 10 +- TombEngine/Objects/Effects/enemy_missile.cpp | 10 +- .../Objects/Effects/tr5_electricity.cpp | 7 +- .../Objects/TR1/Entity/tr1_doppelganger.cpp | 5 +- TombEngine/Objects/TR2/Entity/Dragon.cpp | 8 +- .../Objects/TR2/Trap/tr2_spinningblade.cpp | 5 +- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 10 +- TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 66 +++--- TombEngine/Objects/TR3/Entity/Shiva.cpp | 4 +- TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp | 4 +- TombEngine/Objects/TR3/Entity/tr3_tony.cpp | 20 +- TombEngine/Objects/TR3/Trap/train.cpp | 14 +- TombEngine/Objects/TR3/Vehicles/big_gun.cpp | 8 +- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 12 +- TombEngine/Objects/TR3/Vehicles/quad_bike.cpp | 25 +-- .../Objects/TR3/Vehicles/rubber_boat.cpp | 46 +++-- TombEngine/Objects/TR3/Vehicles/upv.cpp | 34 ++-- TombEngine/Objects/TR4/Entity/tr4_baboon.cpp | 8 +- TombEngine/Objects/TR4/Entity/tr4_baddy.cpp | 32 +-- .../Objects/TR4/Entity/tr4_enemy_jeep.cpp | 20 +- .../Objects/TR4/Entity/tr4_horseman.cpp | 8 +- TombEngine/Objects/TR4/Entity/tr4_sas.cpp | 4 +- TombEngine/Objects/TR4/Entity/tr4_setha.cpp | 12 +- .../Objects/TR4/Entity/tr4_skeleton.cpp | 32 +-- TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp | 13 +- .../Objects/TR4/Entity/tr4_von_croy.cpp | 28 ++- TombEngine/Objects/TR4/Object/tr4_senet.cpp | 6 +- TombEngine/Objects/TR4/Vehicles/jeep.cpp | 12 +- TombEngine/Objects/TR4/Vehicles/motorbike.cpp | 6 +- TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp | 50 ++--- TombEngine/Objects/TR5/Entity/tr5_guard.cpp | 6 +- .../Objects/TR5/Object/tr5_bodypart.cpp | 23 ++- TombEngine/Objects/TR5/Object/tr5_missile.cpp | 10 +- .../Objects/TR5/Object/tr5_rollingball.cpp | 65 +++--- TombEngine/Objects/Utils/VehicleHelpers.cpp | 18 +- 56 files changed, 732 insertions(+), 607 deletions(-) diff --git a/TombEngine/Game/Lara/lara_climb.cpp b/TombEngine/Game/Lara/lara_climb.cpp index 483ab6b69..f944dde5c 100644 --- a/TombEngine/Game/Lara/lara_climb.cpp +++ b/TombEngine/Game/Lara/lara_climb.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/camera.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/items.h" @@ -14,6 +15,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; constexpr auto LADDER_TEST_MARGIN = 8; @@ -327,8 +329,8 @@ void lara_col_climb_idle(ItemInfo* item, CollisionInfo* coll) // HACK: Prevent climbing inside sloped ceilings. Breaks overhang even more, but that shouldn't matter since we'll be doing it over. -- Sezz 2022.05.13 int y = item->Pose.Position.y - (coll->Setup.Height + CLICK(0.5f)); - auto probe = GetCollision(item, 0, 0, -(coll->Setup.Height + CLICK(0.5f))); - if ((probe.Position.Ceiling - y) < 0) + auto probe = GetPointCollision(*item, 0, 0, -(coll->Setup.Height + CLICK(0.5f))); + if ((probe.GetCeilingHeight() - y) < 0) { item->Animation.TargetState = LS_LADDER_UP; item->Pose.Position.y += yShift; @@ -416,7 +418,7 @@ void lara_as_climb_stepoff_right(ItemInfo* item, CollisionInfo* coll) short GetClimbFlags(int x, int y, int z, short roomNumber) { - return GetClimbFlags(GetCollision(x, y, z, roomNumber).BottomBlock); + return GetClimbFlags(&GetPointCollision(Vector3i(x, y, z), roomNumber).GetBottomSector()); } short GetClimbFlags(FloorInfo* floor) @@ -787,13 +789,13 @@ int LaraTestClimb(ItemInfo* item, int xOffset, int yOffset, int zOffset, int xFr int y = item->Pose.Position.y + yOffset; int z = item->Pose.Position.z + zOffset; - auto probeUp = GetCollision(x, y - CLICK(0.5f), z, item->RoomNumber); - auto probeDown = GetCollision(x, y, z, item->RoomNumber); + auto probeUp = GetPointCollision(Vector3i(x, y - CLICK(0.5f), z), item->RoomNumber); + auto probeDown = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); - if (!lara->Control.CanClimbLadder && !TestLaraNearClimbableWall(item, probeDown.BottomBlock)) + if (!lara->Control.CanClimbLadder && !TestLaraNearClimbableWall(item, &probeDown.GetBottomSector())) return 0; - int height = probeUp.Position.Floor; + int height = probeUp.GetFloorHeight(); if (height == NO_HEIGHT) return 0; @@ -805,7 +807,7 @@ int LaraTestClimb(ItemInfo* item, int xOffset, int yOffset, int zOffset, int xFr if (height < 0) *shift = height; - int ceiling = probeDown.Position.Ceiling - y; + int ceiling = probeDown.GetCeilingHeight() - y; if (ceiling > LADDER_CLIMB_SHIFT) return 0; @@ -822,8 +824,8 @@ int LaraTestClimb(ItemInfo* item, int xOffset, int yOffset, int zOffset, int xFr int dz = zFront + z; int dx = xFront + x; - auto probeFront = GetCollision(dx, y, dz, item->RoomNumber); - height = probeFront.Position.Floor; + auto probeFront = GetPointCollision(Vector3i(dx, y, dz), item->RoomNumber); + height = probeFront.GetFloorHeight(); if (height != NO_HEIGHT) height -= y; @@ -839,9 +841,9 @@ int LaraTestClimb(ItemInfo* item, int xOffset, int yOffset, int zOffset, int xFr *shift = height; } - auto probeTop = GetCollision(x, y + itemHeight, z, item->RoomNumber); - auto probeTopFront = GetCollision(dx, y + itemHeight, dz, probeTop.RoomNumber); - ceiling = probeTopFront.Position.Ceiling; + auto probeTop = GetPointCollision(Vector3i(x, y + itemHeight, z), item->RoomNumber); + auto probeTopFront = GetPointCollision(Vector3i(dx, y + itemHeight, dz), probeTop.GetRoomNumber()); + ceiling = probeTopFront.GetCeilingHeight(); if (ceiling == NO_HEIGHT) return 1; @@ -862,7 +864,7 @@ int LaraTestClimb(ItemInfo* item, int xOffset, int yOffset, int zOffset, int xFr return 1; } - ceiling = probeFront.Position.Ceiling - y; + ceiling = probeFront.GetCeilingHeight() - y; if (ceiling >= CLICK(2)) return 1; @@ -895,16 +897,16 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le *shift = 0; // Test center. - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(*item); int vPos = item->Pose.Position.y - CLICK(4); - if ((pointColl.Position.Ceiling - vPos) > LADDER_CLIMB_SHIFT) + if ((pointColl.GetCeilingHeight() - vPos) > LADDER_CLIMB_SHIFT) return 0; - pointColl = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber); - int ceiling = (CLICK(1) - probePos.y) + pointColl.Position.Ceiling; + pointColl = GetPointCollision(probePos, item->RoomNumber); + int ceiling = (CLICK(1) - probePos.y) + pointColl.GetCeilingHeight(); - pointColl = GetCollision(probePos.x + probeOffset.x, probePos.y, probePos.z + probeOffset.z, pointColl.RoomNumber); - int height = pointColl.Position.Floor; + pointColl = GetPointCollision(Vector3i(probePos.x + probeOffset.x, probePos.y, probePos.z + probeOffset.z), pointColl.GetRoomNumber()); + int height = pointColl.GetFloorHeight(); if (height == NO_HEIGHT) { @@ -933,10 +935,10 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le if (height > 0 && height > *shift) *shift = height; - pointColl = GetCollision(probePos.x, probePos.y + CLICK(2), probePos.z, item->RoomNumber); - pointColl = GetCollision(probePos.x + probeOffset.x, probePos.y + CLICK(2), probePos.z + probeOffset.z, pointColl.RoomNumber); + pointColl = GetPointCollision(Vector3i(probePos.x, probePos.y + CLICK(2), probePos.z), item->RoomNumber); + pointColl = GetPointCollision(Vector3i(probePos.x + probeOffset.x, probePos.y + CLICK(2), probePos.z + probeOffset.z), pointColl.GetRoomNumber()); - ceiling = pointColl.Position.Ceiling - probePos.y; + ceiling = pointColl.GetCeilingHeight() - probePos.y; if (ceiling <= height) return 1; @@ -947,7 +949,7 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le } else { - ceiling = GetCollision(probePos.x + probeOffset.x, probePos.y, probePos.z + probeOffset.z, pointColl.RoomNumber).Position.Ceiling - probePos.y; + ceiling = GetPointCollision(Vector3i(probePos.x + probeOffset.x, probePos.y, probePos.z + probeOffset.z), pointColl.GetRoomNumber()).GetCeilingHeight() - probePos.y; if (ceiling < CLICK(2)) { if ((height - ceiling) <= LARA_HEIGHT) diff --git a/TombEngine/Game/Lara/lara_flare.cpp b/TombEngine/Game/Lara/lara_flare.cpp index eff32b3da..3e8402ec2 100644 --- a/TombEngine/Game/Lara/lara_flare.cpp +++ b/TombEngine/Game/Lara/lara_flare.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/chaffFX.h" @@ -18,6 +19,7 @@ #include "Specific/clock.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; constexpr auto FLARE_LIFE_MAX = 60.0f * FPS; @@ -323,7 +325,7 @@ void CreateFlare(ItemInfo& laraItem, GAME_OBJECT_ID objectID, bool isThrown) flareItem.Pose.Position = pos; - int floorHeight = GetCollision(pos.x, pos.y, pos.z, laraItem.RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(pos, laraItem.RoomNumber).GetFloorHeight(); auto hasCollided = GetCollidedObjects(&flareItem, 0, true, CollidedItems, CollidedMeshes, true); bool hasLanded = false; diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index cfea58fe5..b9917a70f 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/los.h" @@ -31,6 +32,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Drip; using namespace TEN::Effects::Environment; @@ -600,7 +602,7 @@ bool FireHarpoon(ItemInfo& laraItem, const std::optional& pose) auto jointPos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(-2, 373, 77)); harpoonItem.RoomNumber = laraItem.RoomNumber; - int floorHeight = GetCollision(jointPos.x, jointPos.y, jointPos.z, harpoonItem.RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(jointPos, harpoonItem.RoomNumber).GetFloorHeight(); if (floorHeight >= jointPos.y) { harpoonItem.Pose.Position = jointPos; @@ -693,7 +695,7 @@ void FireGrenade(ItemInfo& laraItem) grenadeItem.Pose.Position = jointPos; auto smokePos = jointPos; - int floorHeight = GetCollision(jointPos.x, jointPos.y, jointPos.z, grenadeItem.RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(jointPos, grenadeItem.RoomNumber).GetFloorHeight(); if (floorHeight < jointPos.y) { grenadeItem.Pose.Position.x = laraItem.Pose.Position.x; @@ -1027,9 +1029,11 @@ void FireCrossbow(ItemInfo& laraItem, const std::optional& pose) boltItem.RoomNumber = laraItem.RoomNumber; - int floorHeight = GetCollision(jointPos.x, jointPos.y, jointPos.z, boltItem.RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(jointPos, boltItem.RoomNumber).GetFloorHeight(); if (floorHeight >= jointPos.y) + { boltItem.Pose.Position = jointPos; + } else { boltItem.Pose.Position = Vector3i(laraItem.Pose.Position.x, jointPos.y, laraItem.Pose.Position.z); diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index 6129d45c1..a558b4035 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -17,6 +17,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::Floordata; using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Generic; using namespace TEN::Input; @@ -326,14 +327,14 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) auto up = Vector3i(item->Pose.Position.x - slopeData.Offset.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z - slopeData.Offset.z); auto down = Vector3i(item->Pose.Position.x + slopeData.Offset.x, item->Pose.Position.y + CLICK(1), item->Pose.Position.z + slopeData.Offset.z); - auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber); - auto probeUp = GetCollision(up.x, up.y, up.z, item->RoomNumber); - auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber); + auto probeNow = GetPointCollision(now, item->RoomNumber); + auto probeUp = GetPointCollision(up, item->RoomNumber); + auto probeDown = GetPointCollision(down, item->RoomNumber); if (item->Animation.AnimNumber == LA_OVERHANG_LADDER_SLOPE_CONCAVE) return; - item->Pose.Position.y = probeNow.Position.Ceiling + HEIGHT_ADJUST; + item->Pose.Position.y = probeNow.GetCeilingHeight() + HEIGHT_ADJUST; // Drop down if action not pressed. if (!IsHeld(In::Action)) @@ -353,13 +354,13 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) if (IsHeld(In::Forward)) { // Test for ledge over slope. - short tempRoom = probeUp.Block->GetNextRoomNumber(up.x, up.z, false).value_or(NO_ROOM); + short tempRoom = probeUp.GetSector().GetNextRoomNumber(up.x, up.z, false).value_or(NO_ROOM); if (tempRoom != NO_ROOM) { - auto probeLedge = GetCollision(now.x, now.y - CLICK(3), now.z, tempRoom); + auto probeLedge = GetPointCollision(Vector3i(now.x, now.y - CLICK(3), now.z), tempRoom); - if ((probeLedge.Position.Floor - probeLedge.Position.Ceiling) >= CLICK(3) && - abs((item->Pose.Position.y - (CLICK(2.5f) + 48)) - probeLedge.Position.Floor) < 64) + if ((probeLedge.GetFloorHeight() - probeLedge.GetCeilingHeight()) >= CLICK(3) && + abs((item->Pose.Position.y - (CLICK(2.5f) + 48)) - probeLedge.GetFloorHeight()) < 64) { AlignToEdge(item, FORWARD_ALIGNMENT); SetAnimation(item, LA_OVERHANG_LEDGE_VAULT_START); // Ledge climb-up from slope. @@ -367,10 +368,10 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) } // Test for slope to overhead ladder transition (convex). - if (GetClimbFlags(probeUp.BottomBlock) & slopeData.ClimbOrient && + if (GetClimbFlags(&probeUp.GetBottomSector()) & slopeData.ClimbOrient && InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, CLICK(3), CLICK(4))) { - //if (GetCollision(probeUp.Block, up.x, up.y, up.z).Position.Ceiling - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there. + //if (GetCollision(probeUp.Block, up.x, up.y, up.z).GetCeilingHeight() - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there. //{ // AlignToEdge(item, FORWARD_ALIGNMENT); // SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONVEX_START); @@ -378,21 +379,21 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) } // Test for monkey at next position. - if (probeUp.BottomBlock->Flags.Monkeyswing) + if (probeUp.GetBottomSector().Flags.Monkeyswing) { - int yDelta = probeUp.Position.Ceiling - probeNow.Position.Ceiling; + int yDelta = probeUp.GetCeilingHeight() - probeNow.GetCeilingHeight(); int height; // Height variable for bridge ceiling functions. // Test for upwards slope to climb. short bridge = FindBridge(4, item->Pose.Orientation.y, up, &height, -CLICK(2.5f), -CLICK(1.5f)); - if (yDelta >= -CLICK(1.25f) && yDelta <= -CLICK(0.75f) && (SlopeCheck(probeUp.CeilingTilt, slopeData.Goal) || bridge >= 0)) + if (yDelta >= -CLICK(1.25f) && yDelta <= -CLICK(0.75f) && (SlopeCheck(GetSurfaceTilt(probeUp.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0)) { // Do one more check for wall/ceiling step 2 * offX / Z further to avoid lara sinking her head in wall/step. - auto probeWall = GetCollision((up.x - slopeData.Offset.x), (up.y - CLICK(1)), (up.z - slopeData.Offset.z), item->RoomNumber); + auto probeWall = GetPointCollision(Vector3i((up.x - slopeData.Offset.x), (up.y - CLICK(1)), (up.z - slopeData.Offset.z)), item->RoomNumber); - if (!probeWall.Block->IsWall((up.x - slopeData.Offset.x), (up.z - slopeData.Offset.z)) && - (probeNow.Position.Ceiling - probeWall.Position.Ceiling) > CLICK(0.5f)) // No wall or downward ceiling step. + if (!probeWall.GetSector().IsWall((up.x - slopeData.Offset.x), (up.z - slopeData.Offset.z)) && + (probeNow.GetCeilingHeight() - probeWall.GetCeilingHeight()) > CLICK(0.5f)) // No wall or downward ceiling step. { TranslateItem(item, 0, -CLICK(1), -CLICK(1)); SetAnimation(item, item->Animation.AnimNumber == LA_OVERHANG_IDLE_LEFT ? LA_OVERHANG_CLIMB_UP_LEFT : LA_OVERHANG_CLIMB_UP_RIGHT); @@ -407,7 +408,7 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) // HACK: because of the different calculations of bridge height in TR4 and TEN, we need to lower yDiff tolerance to 0.9f. if (yDelta > -CLICK(0.9f) && yDelta <= -CLICK(0.5f) && - ((abs(probeUp.CeilingTilt.x) <= 2 && abs(probeUp.CeilingTilt.y) <= 2) || bridge >= 0)) + ((abs(GetSurfaceTilt(probeUp.GetCeilingNormal(), false).ToVector2().x) <= 2 && abs(GetSurfaceTilt(probeUp.GetCeilingNormal(), false).ToVector2().y) <= 2) || bridge >= 0)) { SetAnimation(item, LA_OVERHANG_SLOPE_MONKEY_CONCAVE); // Slope to overhead monkey transition (concave). } @@ -423,22 +424,22 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) // return; //} - if (probeDown.BottomBlock->Flags.Monkeyswing) + if (probeDown.GetBottomSector().Flags.Monkeyswing) { int height; - int yDiff = probeDown.Position.Ceiling - probeNow.Position.Ceiling; + int yDiff = probeDown.GetCeilingHeight() - probeNow.GetCeilingHeight(); // Test for flat monkey (abs(slope) < 2). short bridge = FindBridge(0, slopeData.GoalOrient, down, &height, -CLICK(3), -CLICK(2)); if (bridge < 0) bridge = FindBridge(1, slopeData.GoalOrient, down, &height, -CLICK(3), -CLICK(2)); - if ((abs(yDiff) < CLICK(1) && abs(probeDown.CeilingTilt.x) <= 2 && abs(probeDown.CeilingTilt.y) <= 2) || bridge >= 0) + if ((abs(yDiff) < CLICK(1) && abs(GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2().x) <= 2 && abs(GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2().y) <= 2) || bridge >= 0) SetAnimation(item, LA_OVERHANG_SLOPE_MONKEY_CONVEX); // Force slope to underlying monkey transition (convex) // Test for downward slope to climb. bridge = FindBridge(4, slopeData.GoalOrient, down, &height, -CLICK(2.5f), -CLICK(1.5f)); - if (yDiff >= CLICK(0.75f) && yDiff <= CLICK(1.25f) && (SlopeCheck(probeDown.CeilingTilt, slopeData.Goal) || bridge >= 0)) + if (yDiff >= CLICK(0.75f) && yDiff <= CLICK(1.25f) && (SlopeCheck(GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0)) { SetAnimation(item, item->Animation.AnimNumber == LA_OVERHANG_IDLE_LEFT ? LA_OVERHANG_CLIMB_DOWN_LEFT : LA_OVERHANG_CLIMB_DOWN_RIGHT); return; @@ -493,9 +494,9 @@ void lara_col_slopehang(ItemInfo* item, CollisionInfo* coll) auto now = item->Pose.Position; - auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber); + auto probeNow = GetPointCollision(now, item->RoomNumber); - item->Pose.Position.y = probeNow.Position.Ceiling + HEIGHT_ADJUST; + item->Pose.Position.y = probeNow.GetCeilingHeight() + HEIGHT_ADJUST; // Drop down if action not pressed. if (!IsHeld(In::Action)) @@ -530,16 +531,16 @@ void lara_col_slopehang(ItemInfo* item, CollisionInfo* coll) direction = ANGLE(90.0f); } - auto probeShimmy = GetCollision(shimmy.x, shimmy.y, shimmy.z, item->RoomNumber); + auto probeShimmy = GetPointCollision(shimmy, item->RoomNumber); - if (probeShimmy.BottomBlock->Flags.Monkeyswing) + if (probeShimmy.GetBottomSector().Flags.Monkeyswing) { - int yDiff = probeShimmy.Position.Ceiling - probeNow.Position.Ceiling; + int yDiff = probeShimmy.GetCeilingHeight() - probeNow.GetCeilingHeight(); int height; short bridge = FindBridge(4, slopeData.GoalOrient, shimmy, &height, -CLICK(2.5f), -CLICK(1.5f)); - if ((SlopeCheck(probeShimmy.CeilingTilt, slopeData.Goal) && abs(yDiff) < 64) || bridge >= 0) + if ((SlopeCheck(GetSurfaceTilt(probeShimmy.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) && abs(yDiff) < 64) || bridge >= 0) SetAnimation(item, direction < 0 ? LA_OVERHANG_SHIMMY_LEFT : LA_OVERHANG_SHIMMY_RIGHT); } } @@ -569,9 +570,9 @@ void lara_col_slopeshimmy(ItemInfo* item, CollisionInfo* coll) auto now = item->Pose.Position; - auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber); + auto probeNow = GetPointCollision(now, item->RoomNumber); - item->Pose.Position.y = probeNow.Position.Ceiling + HEIGHT_ADJUST; + item->Pose.Position.y = probeNow.GetCeilingHeight() + HEIGHT_ADJUST; auto shimmy = item->Pose.Position; if (item->Animation.AnimNumber == LA_OVERHANG_SHIMMY_LEFT) @@ -585,17 +586,17 @@ void lara_col_slopeshimmy(ItemInfo* item, CollisionInfo* coll) shimmy.z -= slopeData.Offset.x / 2; } - auto probeShimmy = GetCollision(shimmy.x, shimmy.y, shimmy.z, item->RoomNumber); + auto probeShimmy = GetPointCollision(shimmy, item->RoomNumber); bool cancelShimmy = true; - if (probeShimmy.BottomBlock->Flags.Monkeyswing) + if (probeShimmy.GetBottomSector().Flags.Monkeyswing) { - int yDiff = probeShimmy.Position.Ceiling - probeNow.Position.Ceiling; + int yDiff = probeShimmy.GetCeilingHeight() - probeNow.GetCeilingHeight(); int height; short bridge = FindBridge(4, slopeData.GoalOrient, shimmy, &height, -CLICK(2.5f), -CLICK(1.5f)); - if ((SlopeCheck(probeShimmy.CeilingTilt, slopeData.Goal) && abs(yDiff) < 64) || bridge >= 0) + if ((SlopeCheck(GetSurfaceTilt(probeShimmy.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) && abs(yDiff) < 64) || bridge >= 0) cancelShimmy = false; } @@ -838,16 +839,16 @@ void SlopeHangExtra(ItemInfo* item, CollisionInfo* coll) auto down = Vector3i(item->Pose.Position.x + slopeData.Offset.x, item->Pose.Position.y + CLICK(1), item->Pose.Position.z + slopeData.Offset.z); - auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber); + auto probeDown = GetPointCollision(down, item->RoomNumber); - int ceilDist = item->Pose.Position.y - probeDown.Position.Ceiling; + int ceilDist = item->Pose.Position.y - probeDown.GetCeilingHeight(); if (item->Animation.TargetState == LS_LADDER_IDLE) // Prevent going from hang to climb mode if slope is under ladder. { if (ceilDist >= CLICK(1) && ceilDist < CLICK(2)) { - if ((probeDown.CeilingTilt.x / 3) == (slopeData.Goal.x / 3) || - (probeDown.CeilingTilt.y / 3) == (slopeData.Goal.y / 3)) + if ((GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2().x / 3) == (slopeData.Goal.x / 3) || + (GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2().y / 3) == (slopeData.Goal.y / 3)) { item->Animation.TargetState = LS_HANG; if (IsHeld(In::Forward)) @@ -863,8 +864,8 @@ void SlopeHangExtra(ItemInfo* item, CollisionInfo* coll) { if (ceilDist < CLICK(1)) { - if ((probeDown.CeilingTilt.x / 3) == (goal.x / 3) || - (probeDown.CeilingTilt.z / 3) == (goal.y / 3)) + if ((GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2().x / 3) == (goal.x / 3) || + (GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2().z / 3) == (goal.y / 3)) { SetAnimation(item, LA_REACH_TO_HANG, 21); } @@ -883,19 +884,19 @@ void SlopeReachExtra(ItemInfo* item, CollisionInfo* coll) auto now = item->Pose.Position; - auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber); + auto probeNow = GetPointCollision(now, item->RoomNumber); - int ceilDist = item->Pose.Position.y - probeNow.Position.Ceiling; + int ceilDist = item->Pose.Position.y - probeNow.GetCeilingHeight(); - if (probeNow.BottomBlock->Flags.Monkeyswing && ceilDist <= CLICK(3.5f)) + if (probeNow.GetBottomSector().Flags.Monkeyswing && ceilDist <= CLICK(3.5f)) { int height; short bridge = FindBridge(4, slopeData.GoalOrient, now, &height, -CLICK(4), -CLICK(2.5f)); - if (abs(probeNow.CeilingTilt.x) > 2 || abs(probeNow.CeilingTilt.y) > 2 || bridge >= 0) + if (abs(GetSurfaceTilt(probeNow.GetCeilingNormal(), false).ToVector2().x) > 2 || abs(GetSurfaceTilt(probeNow.GetCeilingNormal(), false).ToVector2().y) > 2 || bridge >= 0) { bool disableGrab = true; - if (SlopeCheck(probeNow.CeilingTilt, slopeData.Goal) || bridge >= 0) + if (SlopeCheck(GetSurfaceTilt(probeNow.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0) { if (abs(OrientDelta(item->Pose.Orientation.y, slopeData.GoalOrient)) < ANGLE(33.75f)) disableGrab = false; @@ -918,17 +919,17 @@ void SlopeClimbExtra(ItemInfo* item, CollisionInfo* coll) auto now = item->Pose.Position; auto down = Vector3i(item->Pose.Position.x + slopeData.Offset.x, item->Pose.Position.y + CLICK(1), item->Pose.Position.z + slopeData.Offset.z); - auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber); - auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber); + auto probeNow = GetPointCollision(now, item->RoomNumber); + auto probeDown = GetPointCollision(down, item->RoomNumber); // Block for ladder to overhead slope transition. if (item->Animation.AnimNumber == LA_LADDER_IDLE) { if (IsHeld(In::Forward)) { - int ceilDist = probeNow.Position.Ceiling - item->Pose.Position.y; + int ceilDist = probeNow.GetCeilingHeight() - item->Pose.Position.y; - if (probeNow.BottomBlock->Flags.Monkeyswing && ceilDist >= -CLICK(4) && ceilDist <= -CLICK(3)) + if (probeNow.GetBottomSector().Flags.Monkeyswing && ceilDist >= -CLICK(4) && ceilDist <= -CLICK(3)) { short facing = item->Pose.Orientation.y + ANGLE(45.0f); facing &= ANGLE(270.0f); @@ -936,9 +937,9 @@ void SlopeClimbExtra(ItemInfo* item, CollisionInfo* coll) int height; short bridge = FindBridge(4, facing, now, &height, -CLICK(4), -CLICK(3)); - if (SlopeCheck(probeNow.CeilingTilt, slopeData.Goal) || bridge >= 0) + if (SlopeCheck(GetSurfaceTilt(probeNow.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0) { - item->Pose.Position.y = probeNow.Position.Ceiling + 900; + item->Pose.Position.y = probeNow.GetCeilingHeight() + 900; SetAnimation(item, LA_OVERHANG_LADDER_SLOPE_CONCAVE); // Ladder to overhead slope transition (concave). } } @@ -946,9 +947,9 @@ void SlopeClimbExtra(ItemInfo* item, CollisionInfo* coll) if (IsHeld(In::Back)) { - int ceilDist = probeDown.Position.Ceiling - item->Pose.Position.y; + int ceilDist = probeDown.GetCeilingHeight() - item->Pose.Position.y; - if (probeDown.BottomBlock->Flags.Monkeyswing && ceilDist >= 0 && ceilDist <= CLICK(1)) + if (probeDown.GetBottomSector().Flags.Monkeyswing && ceilDist >= 0 && ceilDist <= CLICK(1)) { short facing = item->Pose.Orientation.y + ANGLE(45.0f); facing &= ANGLE(270.0f); @@ -956,9 +957,9 @@ void SlopeClimbExtra(ItemInfo* item, CollisionInfo* coll) int height; short bridge = FindBridge(4, facing, down, &height, -CLICK(0.5f), -CLICK(0.25f)); - if (SlopeCheck(probeDown.CeilingTilt, slopeData.Goal) || bridge >= 0) + if (SlopeCheck(GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0) { - item->Pose.Position.y = probeDown.Position.Ceiling - 156; + item->Pose.Position.y = probeDown.GetCeilingHeight() - 156; SetAnimation(item, LA_OVERHANG_LADDER_SLOPE_CONVEX); // Ladder to underlying slope transition (convex). } } @@ -993,15 +994,15 @@ void SlopeClimbDownExtra(ItemInfo* item, CollisionInfo* coll) auto down = Vector3i(item->Pose.Position.x + slopeData.Offset.x, item->Pose.Position.y + CLICK(1), item->Pose.Position.z + slopeData.Offset.z); - auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber); + auto probeDown = GetPointCollision(down, item->RoomNumber); if (item->Animation.AnimNumber == LA_LADDER_DOWN) // Make Lara stop before underlying slope ceiling at correct height. { if (IsHeld(In::Back)) { - int ceilDist = probeDown.Position.Ceiling - item->Pose.Position.y; + int ceilDist = probeDown.GetCeilingHeight() - item->Pose.Position.y; - if (probeDown.BottomBlock->Flags.Monkeyswing && ceilDist >= 0 && ceilDist <= CLICK(1)) + if (probeDown.GetBottomSector().Flags.Monkeyswing && ceilDist >= 0 && ceilDist <= CLICK(1)) { short facing = item->Pose.Orientation.y + ANGLE(45.0f); facing &= ANGLE(270.0f); @@ -1009,9 +1010,9 @@ void SlopeClimbDownExtra(ItemInfo* item, CollisionInfo* coll) int height; short bridge = FindBridge(4, facing, down, &height, -CLICK(0.5f), -CLICK(0.25f)); - if (SlopeCheck(probeDown.CeilingTilt, slopeData.Goal) || bridge >= 0) + if (SlopeCheck(GetSurfaceTilt(probeDown.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0) { - item->Pose.Position.y = probeDown.Position.Ceiling - 156; + item->Pose.Position.y = probeDown.GetCeilingHeight() - 156; item->Animation.TargetState = LS_LADDER_IDLE; } } @@ -1056,14 +1057,14 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) auto now = item->Pose.Position; auto down = Vector3i(item->Pose.Position.x + slopeData.Offset.x, item->Pose.Position.y + CLICK(1), item->Pose.Position.z + slopeData.Offset.z); - auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber); - auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber); + auto probeNow = GetPointCollision(now, item->RoomNumber); + auto probeDown = GetPointCollision(down, item->RoomNumber); if (item->Animation.AnimNumber == LA_REACH_TO_MONKEY && !GetFrameIndex(item, 0)) // Manage proper grabbing of monkey slope on forward jump. { - int ceilDist = item->Pose.Position.y - probeNow.Position.Ceiling; + int ceilDist = item->Pose.Position.y - probeNow.GetCeilingHeight(); - if (probeNow.BottomBlock->Flags.Monkeyswing && ceilDist <= CLICK(3.5f)) + if (probeNow.GetBottomSector().Flags.Monkeyswing && ceilDist <= CLICK(3.5f)) { short facing = item->Pose.Orientation.y + ANGLE(45.0f); facing &= 0xC000; @@ -1071,11 +1072,11 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) int height; short bridge = FindBridge(4, facing, now, &height, -CLICK(3.5f), -CLICK(2.5f)); - if (SlopeCheck(probeNow.CeilingTilt, slopeData.Goal) || bridge >= 0) + if (SlopeCheck(GetSurfaceTilt(probeNow.GetCeilingNormal(), false).ToVector2(), slopeData.Goal) || bridge >= 0) { lara->Context.NextCornerPos.Orientation.z = AlignToGrab(item); - /*int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).Position.Ceiling; + /*int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).GetCeilingHeight(); item->Pose.Position.y = ceiling + HEIGHT_ADJUST;*/ SetAnimation(item, LA_OVERHANG_HANG_SWING); @@ -1085,7 +1086,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) if (IsHeld(In::Forward)) // Monkey to slope transitions. { - if (probeNow.BottomBlock->Flags.Monkeyswing && + if (probeNow.GetBottomSector().Flags.Monkeyswing && ((item->Animation.AnimNumber == LA_REACH_TO_MONKEY && GetFrameIndex(item, 0) >= 54) || item->Animation.AnimNumber == LA_MONKEY_IDLE)) { if (abs(OrientDelta(slopeData.GoalOrient, item->Pose.Orientation.y)) <= ANGLE(30.0f) && @@ -1093,8 +1094,8 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { /*if (probeDown.BottomBlock->Flags.Monkeyswing) { - int ceiling = GetCollision(probeDown.Block, down.x, now.y, down.z).Position.Ceiling; - int yDiff = ceiling - probeNow.Position.Ceiling; + int ceiling = GetCollision(probeDown.Block, down.x, now.y, down.z).GetCeilingHeight(); + int yDiff = ceiling - probeNow.GetCeilingHeight(); int height; short bridge = FindBridge(4, slopeData.GoalOrient, down, &height, -CLICK(7) >> 1, -CLICK(5) >> 1); @@ -1124,19 +1125,19 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) // Additional overhang ladder tests. int y = item->Pose.Position.y - coll->Setup.Height; - auto probe = GetCollision(down.x, item->Pose.Position.y - coll->Setup.Height, down.z, item->RoomNumber); + auto probe = GetPointCollision(Vector3i(down.x, item->Pose.Position.y - coll->Setup.Height, down.z), item->RoomNumber); - if (probe.BottomBlock->Flags.IsWallClimbable(GetClimbDirectionFlags(item->Pose.Orientation.y + ANGLE(180.0f))) && - probe.Position.Floor >= (item->Pose.Position.y - CLICK(1)) && - probe.Position.Ceiling <= (y - CLICK(1))) + if (probe.GetBottomSector().Flags.IsWallClimbable(GetClimbDirectionFlags(item->Pose.Orientation.y + ANGLE(180.0f))) && + probe.GetFloorHeight() >= (item->Pose.Position.y - CLICK(1)) && + probe.GetCeilingHeight() <= (y - CLICK(1))) { // Primary checks succeeded, now do C-shaped secondary probing. - probe = GetCollision(down.x, y, down.z, probe.RoomNumber); - probe = GetCollision(down.x, y - CLICK(2), down.z, probe.RoomNumber); - probe = GetCollision(now.x, y - CLICK(2), now.z, probe.RoomNumber); + probe = GetPointCollision(Vector3i(down.x, y, down.z), probe.GetRoomNumber()); + probe = GetPointCollision(Vector3i(down.x, y - CLICK(2), down.z), probe.GetRoomNumber()); + probe = GetPointCollision(Vector3i(now.x, y - CLICK(2), now.z), probe.GetRoomNumber()); - if (probe.Position.Floor <= (y - CLICK(1)) || - probe.Position.Ceiling >= (y - CLICK(1))) + if (probe.GetFloorHeight() <= (y - CLICK(1)) || + probe.GetCeilingHeight() >= (y - CLICK(1))) { if (item->Animation.TargetState != LS_LADDER_IDLE) { diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index a1328e0d2..ce6a61776 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -5,6 +5,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/control/los.h" #include "Game/items.h" @@ -22,6 +23,7 @@ #include "Specific/trutils.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Player; using namespace TEN::Input; using namespace TEN::Math; @@ -46,14 +48,14 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo int y = item->Pose.Position.y - coll->Setup.Height; // Get frontal collision data - auto frontLeft = GetCollision(item->Pose.Position.x + xl, y, item->Pose.Position.z + zl, GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber); - auto frontRight = GetCollision(item->Pose.Position.x + xr, y, item->Pose.Position.z + zr, GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber); + auto frontLeft = GetPointCollision(Vector3i(item->Pose.Position.x + xl, y, item->Pose.Position.z + zl), GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber); + auto frontRight = GetPointCollision(Vector3i(item->Pose.Position.x + xr, y, item->Pose.Position.z + zr), GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber); // If any of the frontal collision results intersects item bounds, return false, because there is material intersection. // This check helps to filter out cases when Lara is formally facing corner but ledge check returns true because probe distance is fixed. - if (frontLeft.Position.Floor < (item->Pose.Position.y - CLICK(0.5f)) || frontRight.Position.Floor < (item->Pose.Position.y - CLICK(0.5f))) + if (frontLeft.GetFloorHeight() < (item->Pose.Position.y - CLICK(0.5f)) || frontRight.GetFloorHeight() < (item->Pose.Position.y - CLICK(0.5f))) return false; - if (frontLeft.Position.Ceiling > (item->Pose.Position.y - coll->Setup.Height) || frontRight.Position.Ceiling > (item->Pose.Position.y - coll->Setup.Height)) + if (frontLeft.GetCeilingHeight() >(item->Pose.Position.y - coll->Setup.Height) || frontRight.GetCeilingHeight() > (item->Pose.Position.y - coll->Setup.Height)) return false; //g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xl, left, item->pos.Position.z + zl), 64, Vector4::One, RendererDebugPage::CollisionStats); @@ -66,8 +68,8 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo int zf = phd_cos(coll->NearestLedgeAngle) * (coll->Setup.Radius * 1.2f); // Get floor heights at both points - auto left = GetCollision(item->Pose.Position.x + xf + xl, y, item->Pose.Position.z + zf + zl, GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber).Position.Floor; - auto right = GetCollision(item->Pose.Position.x + xf + xr, y, item->Pose.Position.z + zf + zr, GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber).Position.Floor; + auto left = GetPointCollision(Vector3i(item->Pose.Position.x + xf + xl, y, item->Pose.Position.z + zf + zl), GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber).GetFloorHeight(); + auto right = GetPointCollision(Vector3i(item->Pose.Position.x + xf + xr, y, item->Pose.Position.z + zf + zr), GetRoomVector(item->Location, Vector3i(item->Pose.Position.x, y, item->Pose.Position.z)).RoomNumber).GetFloorHeight(); // If specified, limit vertical search zone only to nearest height if (heightLimit && (abs(left - y) > CLICK(0.5f) || abs(right - y) > CLICK(0.5f))) @@ -214,7 +216,7 @@ bool TestLaraHang(ItemInfo* item, CollisionInfo* coll) z += testShift.y; } - if (TestLaraNearClimbableWall(item, GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).BottomBlock)) + if (TestLaraNearClimbableWall(item, &GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetBottomSector())) { if (!TestLaraHangOnClimbableWall(item, coll)) verticalShift = 0; // Ignore vertical shift if ladder is encountered next block diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 22869a549..1112ed12e 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -51,13 +51,13 @@ namespace TEN::Collision::PointCollision // Set bottom sector pointer. auto* bottomSectorPtr = &GetSector(); - auto roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(_position); + auto roomNumberBelow = bottomSectorPtr->GetNextRoomNumber(_position, true); while (roomNumberBelow.has_value()) { auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->RoomNumber)]; bottomSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); - roomNumberBelow = bottomSectorPtr->GetRoomNumberBelow(_position); + roomNumberBelow = bottomSectorPtr->GetNextRoomNumber(_position, true); } _bottomSectorPtr = bottomSectorPtr; @@ -71,13 +71,13 @@ namespace TEN::Collision::PointCollision // Set top sector pointer. auto* topSectorPtr = &GetSector(); - auto roomNumberAbove = topSectorPtr->GetRoomNumberAbove(_position); + auto roomNumberAbove = topSectorPtr->GetNextRoomNumber(_position, false); while (roomNumberAbove.has_value()) { auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->RoomNumber)]; topSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); - roomNumberAbove = topSectorPtr->GetRoomNumberAbove(_position); + roomNumberAbove = topSectorPtr->GetNextRoomNumber(_position, false); } _topSectorPtr = topSectorPtr; @@ -308,7 +308,7 @@ namespace TEN::Collision::PointCollision static int GetProbeRoomNumber(const Vector3i& pos, const RoomVector& location, const Vector3i& probePos) { // Conduct L-shaped room traversal. - short probeRoomNumber = GetRoom(location, Vector3i(pos.x, probePos.y, pos.z)).RoomNumber; + short probeRoomNumber = GetRoomVector(location, Vector3i(pos.x, probePos.y, pos.z)).RoomNumber; GetFloor(probePos.x, probePos.y, probePos.z, &probeRoomNumber); return probeRoomNumber; diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index fafe69c2f..e70424c7a 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -4,6 +4,8 @@ #include "Game/animation.h" #include "Game/control/los.h" #include "Game/collision/collide_room.h" +#include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -20,6 +22,8 @@ #include "Scripting/Include/ScriptInterfaceGame.h" #include "Sound/sound.h" +using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; using namespace TEN::Renderer; @@ -413,7 +417,7 @@ bool AlignLaraPosition(const Vector3i& offset, ItemInfo* item, ItemInfo* laraIte auto pos = Vector3::Transform(offset.ToVector3(), rotMatrix); auto target = item->Pose.Position.ToVector3() + pos; - int height = GetCollision(target.x, target.y, target.z, laraItem->RoomNumber).Position.Floor; + int height = GetPointCollision(target, laraItem->RoomNumber).GetFloorHeight(); if ((laraItem->Pose.Position.y - height) <= CLICK(2)) { laraItem->Pose.Position = Vector3i(target); @@ -442,7 +446,7 @@ bool MoveLaraPosition(const Vector3i& offset, ItemInfo* item, ItemInfo* laraItem else { // Prevent picking up items which can result in so called "flare pickup bug" - int height = GetCollision(target.Position.x, target.Position.y, target.Position.z, laraItem->RoomNumber).Position.Floor; + int height = GetPointCollision(target.Position, laraItem->RoomNumber).GetFloorHeight(); if (abs(height - laraItem->Pose.Position.y) <= CLICK(2)) return Move3DPosTo3DPos(laraItem, laraItem->Pose, target, LARA_ALIGN_VELOCITY, ANGLE(2.0f)); } @@ -898,13 +902,13 @@ void ItemPushBridge(ItemInfo& item, CollisionInfo& coll) ShiftItem(&item, &coll); } -void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResult& pointColl) +void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, PointCollisionData& pointColl) { // Store offset for bridge item into shifts if it exists. - if (coll.LastBridgeItemNumber == pointColl.Position.Bridge && + if (coll.LastBridgeItemNumber == pointColl.GetFloorBridgeItemNumber() && coll.LastBridgeItemNumber != NO_ITEM) { - auto& bridgeItem = g_Level.Items[pointColl.Position.Bridge]; + auto& bridgeItem = g_Level.Items[pointColl.GetFloorBridgeItemNumber()]; auto deltaPos = bridgeItem.Pose.Position - coll.LastBridgeItemPose.Position; auto deltaOrient = bridgeItem.Pose.Orientation - coll.LastBridgeItemPose.Orientation; @@ -944,7 +948,7 @@ void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResu coll.LastBridgeItemNumber = NO_ITEM; } - coll.LastBridgeItemNumber = pointColl.Position.Bridge; + coll.LastBridgeItemNumber = pointColl.GetFloorBridgeItemNumber(); } void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll) @@ -1286,39 +1290,42 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { auto* item = &g_Level.Items[itemNumber]; - auto prevPointProbe = GetCollision(x, y, z, item->RoomNumber); - auto pointProbe = GetCollision(item); + auto prevPointColl = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); + auto pointColl = GetPointCollision(*item); + + // TODO: Use floor normal directly. + auto floorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true); auto bounds = GameBoundingBox(item); int radius = bounds.GetHeight(); item->Pose.Position.y += radius; - if (item->Pose.Position.y >= pointProbe.Position.Floor) + if (item->Pose.Position.y >= pointColl.GetFloorHeight()) { int bs = 0; - if (pointProbe.Position.FloorSlope && prevPointProbe.Position.Floor < pointProbe.Position.Floor) + if (pointColl.IsIllegalFloor() && prevPointColl.GetFloorHeight() < pointColl.GetFloorHeight()) { int yAngle = (long)((unsigned short)item->Pose.Orientation.y); - if (pointProbe.FloorTilt.x < 0) + if (floorTilt.x < 0) { if (yAngle >= ANGLE(180.0f)) bs = 1; } - else if (pointProbe.FloorTilt.x > 0) + else if (floorTilt.x > 0) { if (yAngle <= ANGLE(180.0f)) bs = 1; } - if (pointProbe.FloorTilt.y < 0) + if (floorTilt.y < 0) { if (yAngle >= ANGLE(90.0f) && yAngle <= ANGLE(270.0f)) bs = 1; } - else if (pointProbe.FloorTilt.y > 0) + else if (floorTilt.y > 0) { if (yAngle <= ANGLE(90.0f) || yAngle >= ANGLE(270.0f)) bs = 1; @@ -1327,7 +1334,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, // If last position of item was also below this floor height, we've hit a wall, else we've hit a floor. - if (y > (pointProbe.Position.Floor + 32) && bs == 0 && + if (y > (pointColl.GetFloorHeight() + 32) && bs == 0 && (((x / BLOCK(1)) != (item->Pose.Position.x / BLOCK(1))) || ((z / BLOCK(1)) != (item->Pose.Position.z / BLOCK(1))))) { @@ -1367,14 +1374,14 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, item->Pose.Position.z = z; } // Hit a steep slope? - else if (pointProbe.Position.FloorSlope) + else if (pointColl.IsIllegalFloor()) { // Need to know which direction the slope is. item->Animation.Velocity.z -= (item->Animation.Velocity.z / 4); // Hit angle = ANGLE(90.0f) - if (pointProbe.FloorTilt.x < 0 && ((abs(pointProbe.FloorTilt.x)) - (abs(pointProbe.FloorTilt.y)) >= 2)) + if (floorTilt.x < 0 && ((abs(floorTilt.x)) - (abs(floorTilt.y)) >= 2)) { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(180.0f)) { @@ -1386,7 +1393,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z -= pointProbe.FloorTilt.x * 2; + item->Animation.Velocity.z -= floorTilt.x * 2; if ((unsigned short)item->Pose.Orientation.y > ANGLE(90.0f) && (unsigned short)item->Pose.Orientation.y < ANGLE(270.0f)) { item->Pose.Orientation.y -= ANGLE(22.5f); @@ -1408,7 +1415,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } // Hit angle = ANGLE(270.0f) - else if (pointProbe.FloorTilt.x > 0 && ((abs(pointProbe.FloorTilt.x)) - (abs(pointProbe.FloorTilt.y)) >= 2)) + else if (floorTilt.x > 0 && ((abs(floorTilt.x)) - (abs(floorTilt.y)) >= 2)) { if (((unsigned short)item->Pose.Orientation.y) < ANGLE(180.0f)) { @@ -1420,7 +1427,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z += pointProbe.FloorTilt.x * 2; + item->Animation.Velocity.z += floorTilt.x * 2; if ((unsigned short)item->Pose.Orientation.y > ANGLE(270.0f) || (unsigned short)item->Pose.Orientation.y < ANGLE(90.0f)) { item->Pose.Orientation.y -= ANGLE(22.5f); @@ -1442,7 +1449,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } // Hit angle = 0 - else if (pointProbe.FloorTilt.y < 0 && ((abs(pointProbe.FloorTilt.y)) - (abs(pointProbe.FloorTilt.x)) >= 2)) + else if (floorTilt.y < 0 && ((abs(floorTilt.y)) - (abs(floorTilt.x)) >= 2)) { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(90.0f) && ((unsigned short)item->Pose.Orientation.y) < ANGLE(270.0f)) { @@ -1454,7 +1461,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z -= pointProbe.FloorTilt.y * 2; + item->Animation.Velocity.z -= floorTilt.y * 2; if ((unsigned short)item->Pose.Orientation.y < ANGLE(180.0f)) { @@ -1477,7 +1484,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } // Hit angle = ANGLE(180.0f) - else if (pointProbe.FloorTilt.y > 0 && ((abs(pointProbe.FloorTilt.y)) - (abs(pointProbe.FloorTilt.x)) >= 2)) + else if (floorTilt.y > 0 && ((abs(floorTilt.y)) - (abs(floorTilt.x)) >= 2)) { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(270.0f) || ((unsigned short)item->Pose.Orientation.y) < ANGLE(90.0f)) { @@ -1489,7 +1496,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z += pointProbe.FloorTilt.y * 2; + item->Animation.Velocity.z += floorTilt.y * 2; if ((unsigned short)item->Pose.Orientation.y > ANGLE(180.0f)) { @@ -1511,7 +1518,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, item->Animation.Velocity.y = 0; } } - else if (pointProbe.FloorTilt.x < 0 && pointProbe.FloorTilt.y < 0) // Hit angle = 0x2000 + else if (floorTilt.x < 0 && floorTilt.y < 0) // Hit angle = 0x2000 { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(135.0f) && ((unsigned short)item->Pose.Orientation.y) < ANGLE(315.0f)) { @@ -1523,7 +1530,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z += -pointProbe.FloorTilt.x + -pointProbe.FloorTilt.y; + item->Animation.Velocity.z += -floorTilt.x + -floorTilt.y; if ((unsigned short)item->Pose.Orientation.y > ANGLE(45.0f) && (unsigned short)item->Pose.Orientation.y < ANGLE(225.0f)) { item->Pose.Orientation.y -= ANGLE(22.5f); @@ -1545,7 +1552,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } // Hit angle = ANGLE(135.0f) - else if (pointProbe.FloorTilt.x < 0 && pointProbe.FloorTilt.y > 0) + else if (floorTilt.x < 0 && floorTilt.y > 0) { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(225.0f) || ((unsigned short)item->Pose.Orientation.y) < ANGLE(45.0f)) { @@ -1557,7 +1564,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z += (-pointProbe.FloorTilt.x) + pointProbe.FloorTilt.y; + item->Animation.Velocity.z += (-floorTilt.x) + floorTilt.y; if ((unsigned short)item->Pose.Orientation.y < ANGLE(315.0f) && (unsigned short)item->Pose.Orientation.y > ANGLE(135.0f)) { item->Pose.Orientation.y -= ANGLE(22.5f); @@ -1579,7 +1586,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } // Hit angle = ANGLE(225.5f) - else if (pointProbe.FloorTilt.x > 0 && pointProbe.FloorTilt.y > 0) + else if (floorTilt.x > 0 && floorTilt.y > 0) { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(315.0f) || ((unsigned short)item->Pose.Orientation.y) < ANGLE(135.0f)) { @@ -1591,7 +1598,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z += pointProbe.FloorTilt.x + pointProbe.FloorTilt.y; + item->Animation.Velocity.z += floorTilt.x + floorTilt.y; if ((unsigned short)item->Pose.Orientation.y < ANGLE(45.0f) || (unsigned short)item->Pose.Orientation.y > ANGLE(225.5f)) { item->Pose.Orientation.y -= ANGLE(22.5f); @@ -1613,7 +1620,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } // Hit angle = ANGLE(315.0f) - else if (pointProbe.FloorTilt.x > 0 && pointProbe.FloorTilt.y < 0) + else if (floorTilt.x > 0 && floorTilt.y < 0) { if (((unsigned short)item->Pose.Orientation.y) > ANGLE(45.0f) && ((unsigned short)item->Pose.Orientation.y) < ANGLE(225.5f)) { @@ -1625,7 +1632,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (item->Animation.Velocity.z < 32) { - item->Animation.Velocity.z += pointProbe.FloorTilt.x + (-pointProbe.FloorTilt.y); + item->Animation.Velocity.z += floorTilt.x + (-floorTilt.y); if ((unsigned short)item->Pose.Orientation.y < ANGLE(135.0f) || (unsigned short)item->Pose.Orientation.y > ANGLE(315.0f)) { item->Pose.Orientation.y -= ANGLE(22.5f); @@ -1686,7 +1693,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } - item->Pose.Position.y = pointProbe.Position.Floor; + item->Pose.Position.y = pointColl.GetFloorHeight(); } } // Check for on top of object. @@ -1694,8 +1701,8 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { if (yv >= 0) { - prevPointProbe = GetCollision(item->Pose.Position.x, y, item->Pose.Position.z, item->RoomNumber); - pointProbe = GetCollision(item); + prevPointColl = GetPointCollision(Vector3i(item->Pose.Position.x, y, item->Pose.Position.z), item->RoomNumber); + pointColl = GetPointCollision(*item); // Bounce off floor. @@ -1703,7 +1710,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, // was always set to 0 by GetHeight() function which was called before the check. // Possibly a mistake or unfinished feature by Core? -- Lwmte, 27.08.21 - if (item->Pose.Position.y >= prevPointProbe.Position.Floor) + if (item->Pose.Position.y >= prevPointColl.GetFloorHeight()) { // Hit the floor; bounce and slow down. if (item->Animation.Velocity.y > 0) @@ -1737,17 +1744,17 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } - item->Pose.Position.y = prevPointProbe.Position.Floor; + item->Pose.Position.y = prevPointColl.GetFloorHeight(); } } // else { // Bounce off ceiling. - pointProbe = GetCollision(item); + pointColl = GetPointCollision(*item); - if (item->Pose.Position.y < pointProbe.Position.Ceiling) + if (item->Pose.Position.y < pointColl.GetCeilingHeight()) { - if (y < pointProbe.Position.Ceiling && + if (y < pointColl.GetCeilingHeight() && (((x / BLOCK(1)) != (item->Pose.Position.x / BLOCK(1))) || ((z / BLOCK(1)) != (item->Pose.Position.z / BLOCK(1))))) { @@ -1776,7 +1783,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, item->Pose.Position.z = z; } else - item->Pose.Position.y = pointProbe.Position.Ceiling; + item->Pose.Position.y = pointColl.GetCeilingHeight(); if (item->Animation.Velocity.y < 0) item->Animation.Velocity.y = -item->Animation.Velocity.y; @@ -1784,14 +1791,14 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, } } - pointProbe = GetCollision(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); + pointColl = GetPointCollision(*item); - if (pointProbe.RoomNumber != item->RoomNumber) + if (pointColl.GetRoomNumber() != item->RoomNumber) { - if (item->ObjectNumber == ID_GRENADE && TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointProbe.RoomNumber)) + if (item->ObjectNumber == ID_GRENADE && TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointColl.GetRoomNumber())) Splash(item); - ItemNewRoom(itemNumber, pointProbe.RoomNumber); + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); } item->Pose.Position.y -= radius; diff --git a/TombEngine/Game/collision/collide_item.h b/TombEngine/Game/collision/collide_item.h index 31a275928..9f10dc584 100644 --- a/TombEngine/Game/collision/collide_item.h +++ b/TombEngine/Game/collision/collide_item.h @@ -1,12 +1,15 @@ #pragma once #include "Math/Math.h" +namespace TEN::Collision::PointCollision { class PointCollisionData; }; class FloorInfo; struct CollisionInfo; struct CollisionResult; struct ItemInfo; struct MESH_INFO; +using namespace TEN::Collision::PointCollision; + constexpr auto MAX_COLLIDED_OBJECTS = 1024; constexpr auto ITEM_RADIUS_YMAX = BLOCK(3); @@ -45,7 +48,7 @@ void ItemPushBridge(ItemInfo& item, CollisionInfo& coll); bool CollideSolidBounds(ItemInfo* item, const GameBoundingBox& box, const Pose& pose, CollisionInfo* coll); void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll); -void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, const CollisionResult& pointColl); +void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, PointCollisionData& pointColl); void AIPickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void ObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index fcc5bb7ae..f13c1881f 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -100,12 +100,12 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) auto test = [item](short x, short y, short z, bool floor) { - auto collPos = GetCollision(x, y, z, item->RoomNumber).Position; + auto pointColl = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); if (floor) - return (y > collPos.Floor); + return (y > pointColl.GetFloorHeight()); else - return (y < collPos.Ceiling); + return (y < pointColl.GetCeilingHeight()); }; bool collided = @@ -124,12 +124,10 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& pointColl) { auto collResult = CollisionResult{}; - collResult.Coordinates = pointColl.GetPosition(); collResult.RoomNumber = pointColl.GetRoomNumber(); collResult.Block = &pointColl.GetSector(); collResult.BottomBlock = &pointColl.GetBottomSector(); - collResult.Position.Floor = pointColl.GetFloorHeight(); collResult.Position.Ceiling = pointColl.GetCeilingHeight(); collResult.Position.Bridge = pointColl.GetFloorBridgeItemNumber(); @@ -139,8 +137,6 @@ static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& poin collResult.Position.DiagonalStep = pointColl.IsDiagonalFloorStep(); collResult.FloorNormal = pointColl.GetFloorNormal(); collResult.CeilingNormal = pointColl.GetCeilingNormal(); - - // NOTE: Bridge tilts ignored by old method. collResult.FloorTilt = GetSurfaceTilt(collResult.FloorNormal, true).ToVector2(); collResult.CeilingTilt = GetSurfaceTilt(collResult.CeilingNormal, false).ToVector2(); @@ -161,24 +157,26 @@ CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float for return ConvertPointCollDataToCollResult(pointColl); } -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(int x, int y, int z, short roomNumber) +static CollisionPosition GetCollisionPositionData(PointCollisionData& pointColl) { - auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); - return ConvertPointCollDataToCollResult(pointColl); + auto collPos = CollisionPosition{}; + collPos.Floor = pointColl.GetFloorHeight(); + collPos.Ceiling = pointColl.GetCeilingHeight(); + collPos.Bridge = pointColl.GetFloorBridgeItemNumber(); + collPos.SplitAngle = pointColl.GetBottomSector().FloorSurface.SplitAngle; + collPos.FloorSlope = pointColl.IsIllegalFloor(); + collPos.CeilingSlope = pointColl.IsIllegalCeiling(); + collPos.DiagonalStep = pointColl.IsDiagonalFloorStep(); + + return collPos; } -void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom) -{ - GetCollisionInfo(coll, item, Vector3i::Zero, resetRoom); -} - -static void SetSectorAttribs(CollisionPosition& sectorAttribs, const CollisionSetup& collSetup, const CollisionResult& pointColl, +static void SetSectorAttribs(CollisionPosition& sectorAttribs, const CollisionSetup& collSetup, PointCollisionData& pointColl, const Vector3i& probePos, int realRoomNumber) { constexpr auto ASPECT_ANGLE_DELTA_MAX = ANGLE(90.0f); - auto floorNormal = pointColl.FloorNormal; + auto floorNormal = pointColl.GetFloorNormal(); short aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal); short aspectAngleDelta = Geometry::GetShortestAngle(collSetup.ForwardAngle, aspectAngle); @@ -205,14 +203,14 @@ static void SetSectorAttribs(CollisionPosition& sectorAttribs, const CollisionSe } else if (collSetup.BlockDeathFloorDown && sectorAttribs.Floor >= CLICK(0.5f) && - pointColl.BottomBlock->Flags.Death) + pointColl.GetBottomSector().Flags.Death) { sectorAttribs.Floor = MAX_HEIGHT; } else if (collSetup.BlockMonkeySwingEdge) { - auto pointColl = GetCollision(probePos.x, probePos.y + collSetup.Height, probePos.z, realRoomNumber); - if (!pointColl.BottomBlock->Flags.Monkeyswing) + auto pointColl = GetPointCollision(probePos, realRoomNumber, Vector3::UnitY, collSetup.Height); + if (!pointColl.GetBottomSector().Flags.Monkeyswing) sectorAttribs.Floor = MAX_HEIGHT; } } @@ -328,12 +326,12 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse // TEST 1: TILT AND NEAREST LEDGE CALCULATION - auto collResult = GetCollision(probePos.x, item->Pose.Position.y, probePos.z, realRoomNumber); + auto pointColl = GetPointCollision(Vector3i(probePos.x, item->Pose.Position.y, probePos.z), realRoomNumber); - coll->FloorNormal = collResult.FloorNormal; - coll->CeilingNormal = collResult.CeilingNormal; - coll->FloorTilt = collResult.FloorTilt; - coll->CeilingTilt = collResult.CeilingTilt; + coll->FloorNormal = pointColl.GetFloorNormal(); + coll->CeilingNormal = pointColl.GetCeilingNormal(); + coll->FloorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true).ToVector2(); + coll->CeilingTilt = GetSurfaceTilt(pointColl.GetCeilingNormal(), false).ToVector2(); coll->NearestLedgeAngle = GetNearestLedgeAngle(item, coll, coll->NearestLedgeDistance); // Debug angle and distance @@ -342,8 +340,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse // TEST 2: CENTERPOINT PROBE - collResult = GetCollision(probePos.x, probePos.y, probePos.z, realRoomNumber); - int topRoomNumber = collResult.RoomNumber; // Keep top room number as we need it to re-probe from origin room. + pointColl = GetPointCollision(probePos, realRoomNumber); + int topRoomNumber = pointColl.GetRoomNumber(); // Keep top room number as we need it to re-probe from origin room. if (doPlayerCollision) { @@ -355,8 +353,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = collResult.Position.Floor; - ceiling = GetCeiling(collResult.Block, probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); + height = pointColl.GetFloorHeight(); + ceiling = GetCeiling(&pointColl.GetSector(), probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); } if (height != NO_HEIGHT) @@ -365,12 +363,12 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->Middle = collResult.Position; + coll->Middle = GetCollisionPositionData(pointColl); coll->Middle.Floor = height; coll->Middle.Ceiling = ceiling; - // Additionally calculate bridge shifts, if present. - CollideBridgeItems(*item, *coll, collResult); + // Additionally calculate bridge shifts if present. + CollideBridgeItems(*item, *coll, pointColl); // TEST 3: FRONTAL PROBE @@ -379,7 +377,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); - collResult = GetCollision(probePos.x, probePos.y, probePos.z, topRoomNumber); + pointColl = GetPointCollision(probePos, topRoomNumber); if (doPlayerCollision) { @@ -398,8 +396,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = collResult.Position.Floor; - ceiling = GetCeiling(collResult.Block, probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); + height = pointColl.GetFloorHeight(); + ceiling = GetCeiling(&pointColl.GetSector(), probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); } if (height != NO_HEIGHT) @@ -408,7 +406,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->Front = collResult.Position; + coll->Front = GetCollisionPositionData(pointColl); coll->Front.Floor = height; coll->Front.Ceiling = ceiling; @@ -419,13 +417,13 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = GetCollision(probePos.x + xFront, probePos.y, probePos.z + zFront, topRoomNumber).Position.Floor; + height = GetPointCollision(Vector3i(probePos.x + xFront, probePos.y, probePos.z + zFront), topRoomNumber).GetFloorHeight(); } if (height != NO_HEIGHT) height -= (doPlayerCollision ? entityPos.y : probePos.y); - SetSectorAttribs(coll->Front, coll->Setup, collResult, probePos, realRoomNumber); + SetSectorAttribs(coll->Front, coll->Setup, pointColl, probePos, realRoomNumber); // TEST 4: MIDDLE-LEFT PROBE @@ -434,7 +432,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats); - collResult = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber); + pointColl = GetPointCollision(probePos, item->RoomNumber); if (doPlayerCollision) { @@ -446,8 +444,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = collResult.Position.Floor; - ceiling = GetCeiling(collResult.Block, probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); + height = pointColl.GetFloorHeight(); + ceiling = GetCeiling(&pointColl.GetSector(), probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); } if (height != NO_HEIGHT) @@ -456,15 +454,16 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->MiddleLeft = collResult.Position; + coll->MiddleLeft = GetCollisionPositionData(pointColl); coll->MiddleLeft.Floor = height; coll->MiddleLeft.Ceiling = ceiling; - SetSectorAttribs(coll->MiddleLeft, coll->Setup, collResult, probePos, realRoomNumber); + SetSectorAttribs(coll->MiddleLeft, coll->Setup, pointColl, probePos, realRoomNumber); // TEST 5: FRONT-LEFT PROBE - collResult = GetCollision(probePos.x, probePos.y, probePos.z, topRoomNumber); // Use plain X/Z values here as proposed by Choco. + // Use plain X/Z values. + pointColl = GetPointCollision(probePos, topRoomNumber); if (doPlayerCollision) { @@ -476,8 +475,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = collResult.Position.Floor; - ceiling = GetCeiling(collResult.Block, probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); + height = pointColl.GetFloorHeight(); + ceiling = GetCeiling(&pointColl.GetSector(), probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); } if (height != NO_HEIGHT) @@ -486,11 +485,11 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->FrontLeft = collResult.Position; + coll->FrontLeft = GetCollisionPositionData(pointColl); coll->FrontLeft.Floor = height; coll->FrontLeft.Ceiling = ceiling; - SetSectorAttribs(coll->FrontLeft, coll->Setup, collResult, probePos, realRoomNumber); + SetSectorAttribs(coll->FrontLeft, coll->Setup, pointColl, probePos, realRoomNumber); // TEST 6: MIDDLE-RIGHT PROBE @@ -499,7 +498,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); - collResult = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber); + pointColl = GetPointCollision(probePos, item->RoomNumber); if (doPlayerCollision) { @@ -511,8 +510,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = collResult.Position.Floor; - ceiling = GetCeiling(collResult.Block, probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); + height = pointColl.GetFloorHeight(); + ceiling = GetCeiling(&pointColl.GetSector(), probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); } if (height != NO_HEIGHT) @@ -521,15 +520,15 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->MiddleRight = collResult.Position; + coll->MiddleRight = GetCollisionPositionData(pointColl); coll->MiddleRight.Floor = height; coll->MiddleRight.Ceiling = ceiling; - SetSectorAttribs(coll->MiddleRight, coll->Setup, collResult, probePos, realRoomNumber); + SetSectorAttribs(coll->MiddleRight, coll->Setup, pointColl, probePos, realRoomNumber); // TEST 7: FRONT-RIGHT PROBE - collResult = GetCollision(probePos.x, probePos.y, probePos.z, topRoomNumber); + pointColl = GetPointCollision(probePos, topRoomNumber); if (doPlayerCollision) { @@ -541,8 +540,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } else { - height = collResult.Position.Floor; - ceiling = GetCeiling(collResult.Block, probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); + height = pointColl.GetFloorHeight(); + ceiling = GetCeiling(&pointColl.GetSector(), probePos.x, probePos.y - item->Animation.Velocity.y, probePos.z); } if (height != NO_HEIGHT) @@ -551,11 +550,11 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->FrontRight = collResult.Position; + coll->FrontRight = GetCollisionPositionData(pointColl); coll->FrontRight.Floor = height; coll->FrontRight.Ceiling = ceiling; - SetSectorAttribs(coll->FrontRight, coll->Setup, collResult, probePos, realRoomNumber); + SetSectorAttribs(coll->FrontRight, coll->Setup, pointColl, probePos, realRoomNumber); // TEST 8: SOLID STATIC MESHES @@ -730,6 +729,11 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse } } +void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom) +{ + GetCollisionInfo(coll, item, Vector3i::Zero, resetRoom); +} + void AlignEntityToSurface(ItemInfo* item, const Vector2& ellipse, float alpha, short constraintAngle) { // Reduce ellipse axis lengths for stability. @@ -855,11 +859,11 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) // Get front floor block auto room = GetRoomVector(item->Location, Vector3i(ffpX, y, ffpZ)).RoomNumber; - auto block = GetCollision(ffpX, y, ffpZ, room).Block; + auto sectorPtr = &GetPointCollision(Vector3i(ffpX, y, ffpZ), room).GetSector(); // Get front floor surface heights - auto floorHeight = GetSurfaceHeight(RoomVector(block->RoomNumber, y), ffpX, ffpZ, true).value_or(NO_HEIGHT); - auto ceilingHeight = GetSurfaceHeight(RoomVector(block->RoomNumber, y), ffpX, ffpZ, false).value_or(NO_HEIGHT); + auto floorHeight = GetSurfaceHeight(RoomVector(sectorPtr->RoomNumber, y), ffpX, ffpZ, true).value_or(NO_HEIGHT); + auto ceilingHeight = GetSurfaceHeight(RoomVector(sectorPtr->RoomNumber, y), ffpX, ffpZ, false).value_or(NO_HEIGHT); // If probe landed inside wall (i.e. both floor/ceiling heights are NO_HEIGHT), make a fake // ledge for algorithm to further succeed. @@ -872,7 +876,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) int height = useCeilingLedge ? ceilingHeight : floorHeight; // Determine if there is a bridge in front. - auto bridge = block->GetInsideBridgeItemNumber(Vector3i(ffpX, height, ffpZ), true, y == height); + auto bridge = sectorPtr->GetInsideBridgeItemNumber(Vector3i(ffpX, height, ffpZ), true, y == height); // Determine floor probe offset. // This must be slightly in front of own coll radius so no bridge misfires occur. @@ -885,7 +889,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) // Get true room number and block, based on derived height room = GetRoomVector(item->Location, Vector3i(fpX, height, fpZ)).RoomNumber; - block = GetCollision(fpX, height, fpZ, room).Block; + sectorPtr = &GetPointCollision(Vector3i(fpX, height, fpZ), room).GetSector(); // We don't need actual corner heights to build planes, so just use normalized value here. auto fY = height - 1; @@ -943,7 +947,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) else { // Determine if we should use floor or ceiling split angle based on early tests. - auto splitAngle = (useCeilingLedge ? TO_RAD(block->CeilingSurface.SplitAngle) : TO_RAD(block->FloorSurface.SplitAngle)); + auto splitAngle = (useCeilingLedge ? TO_RAD(sectorPtr->CeilingSurface.SplitAngle) : TO_RAD(sectorPtr->FloorSurface.SplitAngle)); // Get horizontal block corner coordinates. auto fX = floor(eX / BLOCK(1)) * BLOCK(1) - 1; @@ -971,7 +975,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) }; // If split angle exists, take split plane into account too. - auto useSplitAngle = (useCeilingLedge ? block->IsSurfaceSplit(false) : block->IsSurfaceSplit(true)); + auto useSplitAngle = (useCeilingLedge ? sectorPtr->IsSurfaceSplit(false) : sectorPtr->IsSurfaceSplit(true)); // Find closest block edge plane. for (int i = 0; i < (useSplitAngle ? 5 : 4); i++) @@ -998,7 +1002,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) if (i == 4) { - auto usedSectorPlane = useCeilingLedge ? block->GetSurfaceTriangleID(eX, eZ, false) : block->GetSurfaceTriangleID(eX, eZ, true); + auto usedSectorPlane = useCeilingLedge ? sectorPtr->GetSurfaceTriangleID(eX, eZ, false) : sectorPtr->GetSurfaceTriangleID(eX, eZ, true); result[p] = FROM_RAD(splitAngle) + ANGLE(usedSectorPlane * 180.0f) + ANGLE(90.0f); } else @@ -1100,19 +1104,19 @@ int GetCeiling(FloorInfo* floor, int x, int y, int z) int GetDistanceToFloor(int itemNumber, bool precise) { - auto* item = &g_Level.Items[itemNumber]; + const auto& item = g_Level.Items[itemNumber]; - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(item); // HACK: Remove item from bridge objects temporarily. - pointColl.Block->RemoveBridge(itemNumber); - int height = GetFloorHeight(pointColl.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); - pointColl.Block->AddBridge(itemNumber); + pointColl.GetSector().RemoveBridge(itemNumber); + int height = GetFloorHeight(&pointColl.GetSector(), item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z); + pointColl.GetSector().AddBridge(itemNumber); - auto bounds = GameBoundingBox(item); + auto bounds = GameBoundingBox(&item); int minHeight = precise ? bounds.Y2 : 0; - return (minHeight + item->Pose.Position.y - height); + return (minHeight + item.Pose.Position.y - height); } int GetWaterSurface(int x, int y, int z, short roomNumber) @@ -1122,9 +1126,9 @@ int GetWaterSurface(int x, int y, int z, short roomNumber) if (TestEnvironment(ENV_FLAG_WATER, roomPtr)) { - while (sectorPtr->GetRoomNumberAbove(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_ROOM) != NO_ROOM) { - roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberAbove(Vector3i(x, y, z)).value_or(sectorPtr->RoomNumber)]; + roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sectorPtr->RoomNumber)]; if (!TestEnvironment(ENV_FLAG_WATER, roomPtr)) return (sectorPtr->GetSurfaceHeight(x, z, false)); @@ -1135,9 +1139,9 @@ int GetWaterSurface(int x, int y, int z, short roomNumber) } else { - while (sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) { - roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(sectorPtr->RoomNumber)]; + roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sectorPtr->RoomNumber)]; if (TestEnvironment(ENV_FLAG_WATER, roomPtr)) return (sectorPtr->GetSurfaceHeight(x, z, true)); @@ -1198,7 +1202,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) } sectorPtr = &roomPtr->floor[zFloor + (xFloor * roomPtr->zSize)]; - adjoiningRoomNumber = sectorPtr->WallPortalRoomNumber; + adjoiningRoomNumber = sectorPtr->SidePortalRoomNumber; if (adjoiningRoomNumber != NO_ROOM) { roomNumber = adjoiningRoomNumber; @@ -1210,9 +1214,9 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { - while (sectorPtr->GetRoomNumberAbove(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_ROOM) != NO_ROOM) { - roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberAbove(Vector3i(x, y, z)).value_or(sectorPtr->RoomNumber)]; + roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sectorPtr->RoomNumber)]; if (!TestEnvironment(ENV_FLAG_WATER, roomPtr) && !TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) @@ -1229,9 +1233,9 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) } else { - while (sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) { - roomPtr = &g_Level.Rooms[sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(sectorPtr->RoomNumber)]; + roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sectorPtr->RoomNumber)]; if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) @@ -1298,7 +1302,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) } sectorPtr = &roomPtr->floor[zBlock + (xBlock * roomPtr->zSize)]; - adjoiningRoomNumber = sectorPtr->WallPortalRoomNumber; + adjoiningRoomNumber = sectorPtr->SidePortalRoomNumber; if (adjoiningRoomNumber != NO_ROOM) { @@ -1314,9 +1318,9 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) { - while (sectorPtr->GetRoomNumberAbove(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_ROOM) != NO_ROOM) { - auto* room = &g_Level.Rooms[sectorPtr->GetRoomNumberAbove(Vector3i(x, y, z)).value_or(sectorPtr->RoomNumber)]; + auto* room = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sectorPtr->RoomNumber)]; if (!TestEnvironment(ENV_FLAG_WATER, room) && !TestEnvironment(ENV_FLAG_SWAMP, room)) @@ -1329,11 +1333,11 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) return GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), false); } - else if (sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + else if (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) { - while (sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(NO_ROOM) != NO_ROOM) + while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) { - auto* roomPtr2 = &g_Level.Rooms[sectorPtr->GetRoomNumberBelow(Vector3i(x, y, z)).value_or(sectorPtr->RoomNumber)]; + auto* roomPtr2 = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sectorPtr->RoomNumber)]; if (TestEnvironment(ENV_FLAG_WATER, roomPtr2) || TestEnvironment(ENV_FLAG_SWAMP, roomPtr2)) @@ -1357,12 +1361,12 @@ int GetWaterHeight(ItemInfo* item) bool TestEnvironment(RoomEnvFlags environmentType, int x, int y, int z, int roomNumber) { - return TestEnvironment(environmentType, GetCollision(x, y, z, roomNumber).RoomNumber); + return TestEnvironment(environmentType, GetPointCollision(Vector3i(x, y, z), roomNumber).GetRoomNumber()); } -bool TestEnvironment(RoomEnvFlags environmentType, Vector3i pos, int roomNumber) +bool TestEnvironment(RoomEnvFlags environmentType, const Vector3i& pos, int roomNumber) { - return TestEnvironment(environmentType, GetCollision(pos.x, pos.y, pos.z, roomNumber).RoomNumber); + return TestEnvironment(environmentType, GetPointCollision(pos, roomNumber).GetRoomNumber()); } bool TestEnvironment(RoomEnvFlags environmentType, const ItemInfo* item) diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 58936b2d8..2b36d8dca 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -43,13 +43,13 @@ enum class CornerType struct CollisionPosition { - int Floor; - int Ceiling; - int Bridge; - float SplitAngle; - bool FloorSlope; - bool CeilingSlope; - bool DiagonalStep; + int Floor = 0; + int Ceiling = 0; + int Bridge = 0; + float SplitAngle = 0.0f; + bool FloorSlope = false; + bool CeilingSlope = false; + bool DiagonalStep = false; bool HasDiagonalSplit() { return ((SplitAngle == (45.0f * RADIAN)) || (SplitAngle == (135.0f * RADIAN))); } bool HasFlippedDiagonalSplit() { return (HasDiagonalSplit() && (SplitAngle != (45.0f * RADIAN))); } @@ -138,10 +138,9 @@ struct CollisionInfo // NOTE: All overloads deprecated. Use GetPointCollision(). CollisionResult GetCollision(const ItemInfo* item); CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); -CollisionResult GetCollision(int x, int y, int z, short roomNumber); -void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false); void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom = false); +void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false); int GetQuadrant(short angle); short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance); @@ -165,8 +164,9 @@ void SnapItemToGrid(ItemInfo* item, CollisionInfo* coll); void AlignEntityToSurface(ItemInfo* item, const Vector2& ellipse, float alpha = 0.75f, short constraintAngle = ANGLE(70.0f)); +// TODO: Deprecated. bool TestEnvironment(RoomEnvFlags environmentType, int x, int y, int z, int roomNumber); -bool TestEnvironment(RoomEnvFlags environmentType, Vector3i pos, int roomNumber); +bool TestEnvironment(RoomEnvFlags environmentType, const Vector3i& pos, int roomNumber); bool TestEnvironment(RoomEnvFlags environmentType, const ItemInfo* item); bool TestEnvironment(RoomEnvFlags environmentType, int roomNumber); bool TestEnvironment(RoomEnvFlags environmentType, ROOM_INFO* room); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 820cd1406..14a718ded 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -2129,7 +2129,7 @@ void AdjustStopperFlag(ItemInfo* item, int direction) x = item->Pose.Position.x + BLOCK(1) * phd_sin(direction); z = item->Pose.Position.z + BLOCK(1) * phd_cos(direction); - room = &g_Level.Rooms[GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).RoomNumber]; + room = &g_Level.Rooms[GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetRoomNumber()]; floor = GetSector(room, x - room->x, z - room->z); floor->Stopper = !floor->Stopper; diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 7a9443d12..6f4aad9eb 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -314,12 +314,12 @@ void RefreshCamera(short type, short* data) short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z) { - auto bottomBlock = GetCollision(x, y, z, floor->RoomNumber).BottomBlock; + const auto& bottomSector = GetPointCollision(Vector3i(x, y, z), floor->RoomNumber).GetBottomSector(); - if (bottomBlock->TriggerIndex == -1) + if (bottomSector.TriggerIndex == -1) return nullptr; - return &g_Level.FloorData[bottomBlock->TriggerIndex]; + return &g_Level.FloorData[bottomSector.TriggerIndex]; } short* GetTriggerIndex(ItemInfo* item) diff --git a/TombEngine/Game/effects/drip.cpp b/TombEngine/Game/effects/drip.cpp index 01609b5f0..ad6ee12e2 100644 --- a/TombEngine/Game/effects/drip.cpp +++ b/TombEngine/Game/effects/drip.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/Ripple.h" #include "Game/effects/weather.h" @@ -12,6 +13,7 @@ #include "Specific/clock.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Environment; using namespace TEN::Effects::Ripple; using namespace TEN::Collision::Floordata; @@ -111,11 +113,11 @@ namespace TEN::Effects::Drip drip.Velocity += Weather.Wind(); int prevRoomNumber = drip.RoomNumber; - auto pointColl = GetCollision(drip.Position.x, drip.Position.y, drip.Position.z, drip.RoomNumber); + auto pointColl = GetPointCollision(drip.Position, drip.RoomNumber); // Update position. drip.Position += drip.Velocity; - drip.RoomNumber = pointColl.RoomNumber; + drip.RoomNumber = pointColl.GetRoomNumber(); // Update size and color. float alpha = 1.0f - (drip.Life / drip.LifeMax); @@ -131,7 +133,7 @@ namespace TEN::Effects::Drip float waterHeight = GetWaterHeight(drip.Position.x, drip.Position.y, drip.Position.z, drip.RoomNumber); SpawnRipple( Vector3(drip.Position.x, waterHeight - RIPPLE_HEIGHT_OFFSET, drip.Position.z), - pointColl.RoomNumber, + pointColl.GetRoomNumber(), Random::GenerateFloat(RIPPLE_SIZE_WATER_MIN, RIPPLE_SIZE_WATER_MAX), (int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity); } @@ -140,20 +142,20 @@ namespace TEN::Effects::Drip continue; } // Hit floor; spawn ripple. - else if (drip.Position.y >= pointColl.Position.Floor) + else if (drip.Position.y >= pointColl.GetFloorHeight()) { SpawnRipple( - Vector3(drip.Position.x, pointColl.Position.Floor - RIPPLE_HEIGHT_OFFSET, drip.Position.z), - pointColl.RoomNumber, + Vector3(drip.Position.x, pointColl.GetFloorHeight() - RIPPLE_HEIGHT_OFFSET, drip.Position.z), + pointColl.GetRoomNumber(), Random::GenerateFloat(RIPPLE_SIZE_GROUND_MIN, RIPPLE_SIZE_GROUND_MAX), (int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity | (int)RippleFlags::OnGround, - pointColl.FloorNormal); + pointColl.GetFloorNormal()); drip.Life = 0.0f; continue; } // Hit ceiling; deactivate. - else if (drip.Position.y <= pointColl.Position.Ceiling) + else if (drip.Position.y <= pointColl.GetCeilingHeight()) { drip.Life = 0.0f; continue; diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 9913a9486..1cd9b2eb7 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -4,6 +4,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/Blood.h" #include "Game/effects/Bubble.h" #include "Game/effects/Drip.h" @@ -25,6 +26,7 @@ #include "Specific/clock.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Blood; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Drip; @@ -1073,11 +1075,15 @@ void UpdateSplashes() short DoBloodSplat(int x, int y, int z, short speed, short direction, short roomNumber) { - short probedRoomNumber = GetCollision(x, y, z, roomNumber).RoomNumber; + short probedRoomNumber = GetPointCollision(Vector3i(x, y, z), roomNumber).GetRoomNumber(); if (TestEnvironment(ENV_FLAG_WATER, probedRoomNumber)) + { SpawnUnderwaterBlood(Vector3(x, y, z), probedRoomNumber, speed); + } else + { TriggerBlood(x, y, z, direction >> 4, speed); + } return 0; } diff --git a/TombEngine/Game/effects/footprint.cpp b/TombEngine/Game/effects/footprint.cpp index cb0bd1717..d990792d9 100644 --- a/TombEngine/Game/effects/footprint.cpp +++ b/TombEngine/Game/effects/footprint.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -16,6 +17,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Effects::Footprint @@ -100,7 +102,7 @@ namespace TEN::Effects::Footprint constexpr auto FOOT_OFFSET = Vector3i(0, HEIGHT_OFFSET, 0); auto footPos = GetJointPosition(item, jointIndex, FOOT_OFFSET); - int floorHeight = GetCollision(footPos.x, footPos.y - CLICK(1), footPos.z, item.RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(footPos, item.RoomNumber, -Vector3::UnitY, CLICK(1)).GetFloorHeight(); bool canSpawn = (abs(footPos.y - floorHeight) < ABS_FLOOR_BOUND); auto pos = Vector3(footPos.x, floorHeight - SURFACE_OFFSET, footPos.z); @@ -112,16 +114,16 @@ namespace TEN::Effects::Footprint constexpr auto ABS_FLOOR_BOUND = CLICK(0.5f); // Get point collision at every vertex point. - auto pointColl0 = GetCollision(vertexPoints[0].x, pos.y - CLICK(1), vertexPoints[0].z, item.RoomNumber); - auto pointColl1 = GetCollision(vertexPoints[1].x, pos.y - CLICK(1), vertexPoints[1].z, item.RoomNumber); - auto pointColl2 = GetCollision(vertexPoints[2].x, pos.y - CLICK(1), vertexPoints[2].z, item.RoomNumber); - auto pointColl3 = GetCollision(vertexPoints[3].x, pos.y - CLICK(1), vertexPoints[3].z, item.RoomNumber); + auto pointColl0 = GetPointCollision(Vector3i(vertexPoints[0].x, pos.y - CLICK(1), vertexPoints[0].z), item.RoomNumber); + auto pointColl1 = GetPointCollision(Vector3i(vertexPoints[1].x, pos.y - CLICK(1), vertexPoints[1].z), item.RoomNumber); + auto pointColl2 = GetPointCollision(Vector3i(vertexPoints[2].x, pos.y - CLICK(1), vertexPoints[2].z), item.RoomNumber); + auto pointColl3 = GetPointCollision(Vector3i(vertexPoints[3].x, pos.y - CLICK(1), vertexPoints[3].z), item.RoomNumber); // Don't spawn footprint if floor heights at vertex points are outside upper/lower floor height bound. - if ((abs(pointColl0.Position.Floor - pointColl1.Position.Floor) > ABS_FLOOR_BOUND) || - (abs(pointColl1.Position.Floor - pointColl2.Position.Floor) > ABS_FLOOR_BOUND) || - (abs(pointColl2.Position.Floor - pointColl3.Position.Floor) > ABS_FLOOR_BOUND) || - (abs(pointColl3.Position.Floor - pointColl0.Position.Floor) > ABS_FLOOR_BOUND)) + if ((abs(pointColl0.GetFloorHeight() - pointColl1.GetFloorHeight()) > ABS_FLOOR_BOUND) || + (abs(pointColl1.GetFloorHeight() - pointColl2.GetFloorHeight()) > ABS_FLOOR_BOUND) || + (abs(pointColl2.GetFloorHeight() - pointColl3.GetFloorHeight()) > ABS_FLOOR_BOUND) || + (abs(pointColl3.GetFloorHeight() - pointColl0.GetFloorHeight()) > ABS_FLOOR_BOUND)) { return false; } @@ -163,15 +165,15 @@ namespace TEN::Effects::Footprint // Slightly randomize 2D position. posData.Position += Vector3(Random::GenerateFloat(-5.0f, 5.0f), 0.0f, Random::GenerateFloat(-5.0f, 5.0f)); - auto pointColl = GetCollision(posData.Position.x, posData.Position.y - CLICK(1), posData.Position.z, item.RoomNumber); + auto pointColl = GetPointCollision(posData.Position, item.RoomNumber, -Vector3::UnitY, CLICK(1)); // Don't process material if foot hit bridge object. // TODO: Handle bridges once bridge collision is less stupid. - if (pointColl.Position.Bridge >= 0) + if (pointColl.GetFloorBridgeItemNumber() >= 0) return; // Get and emit footstep sound for floor material. - auto sfx = GetFootprintSfx(pointColl.BottomBlock->GetSurfaceMaterial(pointColl.Coordinates.x, pointColl.Coordinates.z, true)); + auto sfx = GetFootprintSfx(pointColl.GetBottomSector().GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true)); if (sfx != SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS) // HACK: Must be here until reference WAD2 is revised. { auto pose = item.Pose; @@ -179,10 +181,10 @@ namespace TEN::Effects::Footprint } // Check floor material. - if (!TestMaterial(pointColl.BottomBlock->GetSurfaceMaterial(pointColl.Coordinates.x, pointColl.Coordinates.z, true), FootprintMaterials)) + if (!TestMaterial(pointColl.GetBottomSector().GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true), FootprintMaterials)) return; - auto vertexPoints = GetFootprintVertexPoints(item, posData.Position, pointColl.FloorNormal); + auto vertexPoints = GetFootprintVertexPoints(item, posData.Position, pointColl.GetFloorNormal()); // Test floor continuity. if (!TestFootprintFloor(item, posData.Position, vertexPoints)) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 4a27ba83a..cb9a0514f 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/weather.h" @@ -14,6 +15,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Environment; using TEN::Renderer::g_Renderer; @@ -253,8 +255,8 @@ namespace TEN::Effects::Hair { constexpr auto VELOCITY_COEFF = 0.75f; - auto pointColl = GetCollision(segment.Position.x, segment.Position.y, segment.Position.z, roomNumber); - int floorHeight = pointColl.Position.Floor; + auto pointColl = GetPointCollision(segment.Position, roomNumber); + int floorHeight = pointColl.GetFloorHeight(); Segments[0].Velocity = segment.Position; segment.Position += segment.Velocity * VELOCITY_COEFF; @@ -263,7 +265,7 @@ namespace TEN::Effects::Hair if (isOnLand) { // Let wind affect position. - if (TestEnvironment(ENV_FLAG_WIND, pointColl.RoomNumber)) + if (TestEnvironment(ENV_FLAG_WIND, pointColl.GetRoomNumber())) segment.Position += Weather.Wind() * 2; // Apply gravity. diff --git a/TombEngine/Game/effects/item_fx.cpp b/TombEngine/Game/effects/item_fx.cpp index b3a203a0c..09a127024 100644 --- a/TombEngine/Game/effects/item_fx.cpp +++ b/TombEngine/Game/effects/item_fx.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/smoke.h" @@ -13,6 +14,7 @@ #include "Specific/clock.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Smoke; namespace TEN::Effects::Items @@ -70,7 +72,7 @@ namespace TEN::Effects::Items if (item->HitPoints < 0) return; - auto height = GetCollision(item->Pose.Position.x, 32000, item->Pose.Position.z, item->RoomNumber).Position.Floor; + auto height = GetPointCollision(Vector3i(item->Pose.Position.x, 32000, item->Pose.Position.z), item->RoomNumber).GetFloorHeight(); if (item->Floor == height) { item->HitPoints = -1; diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index 443968e6e..3536fa663 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -3,6 +3,7 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/Ripple.h" #include "Game/effects/tomb4fx.h" @@ -13,6 +14,7 @@ #include "Specific/level.h" #include "Scripting/Include/ScriptInterfaceLevel.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Ripple; using namespace TEN::Math::Random; @@ -278,19 +280,19 @@ namespace TEN::Effects::Environment if (p.Type == WeatherType::None) continue; - CollisionResult coll; + auto pointColl = GetPointCollision(p.Position, p.Room); bool collisionCalculated = false; if (p.CollisionCheckDelay <= 0) { - coll = GetCollision(p.Position.x, p.Position.y, p.Position.z, p.Room); + pointColl = GetPointCollision(p.Position, p.Room); // Determine collision checking frequency based on nearest floor/ceiling surface position. // If floor and ceiling is too far, don't do precise collision checks, instead doing it // every 5th frame. If particle approaches floor or ceiling, make checks more frequent. // This allows to avoid unnecessary thousands of calls to GetCollisionResult for every particle. - auto coeff = std::min(std::max(0.0f, (coll.Position.Floor - p.Position.y)), std::max(0.0f, (p.Position.y - coll.Position.Ceiling))); + auto coeff = std::min(std::max(0.0f, (pointColl.GetFloorHeight() - p.Position.y)), std::max(0.0f, (p.Position.y - pointColl.GetCeilingHeight()))); p.CollisionCheckDelay = std::min(floor(coeff / std::max(std::numeric_limits::denorm_min(), p.Velocity.y)), WEATHER_PARTICLES_MAX_COLL_CHECK_DELAY); collisionCalculated = true; } @@ -305,17 +307,19 @@ namespace TEN::Effects::Environment { if (!collisionCalculated) { - coll = GetCollision(p.Position.x, p.Position.y, p.Position.z, p.Room); + pointColl = GetPointCollision(p.Position, p.Room); collisionCalculated = true; } - if (coll.RoomNumber == p.Room) + if (pointColl.GetRoomNumber() == p.Room) { p.Enabled = false; // Not landed on door, so out of room bounds - delete continue; } else - p.Room = coll.RoomNumber; + { + p.Room = pointColl.GetRoomNumber(); + } } // If collision was updated, process with position checks. @@ -325,8 +329,8 @@ namespace TEN::Effects::Environment // If particle is inside water or swamp, count it as "inSubstance". // If particle got below floor or above ceiling, count it as "landed". - bool inSubstance = g_Level.Rooms[coll.RoomNumber].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP); - bool landed = (coll.Position.Floor <= p.Position.y) || (coll.Position.Ceiling >= p.Position.y); + bool inSubstance = g_Level.Rooms[pointColl.GetRoomNumber()].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP); + bool landed = (pointColl.GetFloorHeight() <= p.Position.y) || (pointColl.GetCeilingHeight() >= p.Position.y); if (inSubstance || landed) { @@ -478,9 +482,9 @@ namespace TEN::Effects::Environment if (g_Level.Rooms[outsideRoom].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP)) continue; - auto coll = GetCollision(xPos, yPos, zPos, outsideRoom); + auto pointColl = GetPointCollision(Vector3i(xPos, yPos, zPos), outsideRoom); - if (!(coll.Position.Ceiling < yPos || coll.Block->GetNextRoomNumber(Vector3i(xPos, yPos, zPos), false).has_value())) + if (!(pointColl.GetCeilingHeight() < yPos || pointColl.GetSector().GetNextRoomNumber(Vector3i(xPos, yPos, zPos), false).has_value())) continue; auto part = WeatherParticle(); diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 69403000a..c4d6973d2 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -3,6 +3,7 @@ #include "Game/collision/floordata.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/control/volume.h" #include "Game/effects/effects.h" @@ -26,6 +27,7 @@ #include "Specific/trutils.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Collision::Room; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Items; @@ -803,10 +805,9 @@ bool UpdateItemRoom(short itemNumber) { auto* item = &g_Level.Items[itemNumber]; - auto roomNumber = GetCollision(item->Pose.Position.x, - item->Pose.Position.y - CLICK(2), - item->Pose.Position.z, - item->RoomNumber).RoomNumber; + auto roomNumber = GetPointCollision( + Vector3i(item->Pose.Position.x, item->Pose.Position.y - CLICK(2), item->Pose.Position.z), + item->RoomNumber).GetRoomNumber(); if (roomNumber != item->RoomNumber) { diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index b1449629b..d8891afa0 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -60,12 +60,12 @@ void ControlMissile(short fxNumber) fx.pos.Translate(fx.pos.Orientation, fx.speed); - auto pointColl = GetCollision(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, fx.roomNumber); + auto pointColl = GetPointCollision(fx.pos.Position, fx.roomNumber); auto hasHitPlayer = ItemNearLara(fx.pos.Position, hitRadius); // Check whether something was hit. - if (fx.pos.Position.y >= pointColl.Position.Floor || - fx.pos.Position.y <= pointColl.Position.Ceiling || + if (fx.pos.Position.y >= pointColl.GetFloorHeight() || + fx.pos.Position.y <= pointColl.GetCeilingHeight() || hasHitPlayer) { if (fx.objectNumber == ID_KNIFETHROWER_KNIFE || @@ -113,8 +113,8 @@ void ControlMissile(short fxNumber) KillEffect(fxNumber); } - if (pointColl.RoomNumber != fx.roomNumber) - EffectNewRoom(fxNumber, pointColl.RoomNumber); + if (pointColl.GetRoomNumber() != fx.roomNumber) + EffectNewRoom(fxNumber, pointColl.GetRoomNumber()); if (fx.objectNumber == ID_KNIFETHROWER_KNIFE) fx.pos.Orientation.z += ANGLE(30.0f); // Update knife rotation over time. diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index 2207a8c7e..d48d8a746 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -5,6 +5,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/debris.h" #include "Game/Gui.h" #include "Game/Hud/Hud.h" @@ -30,6 +31,7 @@ #include "Specific/level.h" #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Generic; using namespace TEN::Hud; using namespace TEN::Input; @@ -849,7 +851,7 @@ void DropPickups(ItemInfo* item) // Also collect objects which are around. bool collidedWithObjects = GetCollidedObjects(item, extents.Length(), true, CollidedItems, CollidedMeshes, true); - short startAngle = ANGLE(Random::GenerateInt(0, 3) * 90); // Randomize start corner. + short startAngle = ANGLE(Random::GenerateInt(0, 3) * 90.0f); // Randomize start corner. // Iterate through 4 corners and find best-fitting position, which is not inside a wall, not on a slope // and also does not significantly differ in height to an object centerpoint height. @@ -858,31 +860,31 @@ void DropPickups(ItemInfo* item) for (int corner = 0; corner < 4; corner++) { auto angle = item->Pose.Orientation; - angle.y += startAngle + corner * ANGLE(90); + angle.y += startAngle + corner * ANGLE(90.0f); // At first, do an inside-wall test at an extended extent point to make sure player can correctly align. auto candidatePos = Geometry::TranslatePoint(origin, angle, extents * 1.2f); candidatePos.y = yPos; - auto collPoint = GetCollision(candidatePos.x, candidatePos.y, candidatePos.z, item->RoomNumber); + auto collPoint = GetPointCollision(candidatePos, item->RoomNumber); // If position is inside a wall or on a slope, don't use it. - if (collPoint.Position.Floor == NO_HEIGHT || collPoint.Position.FloorSlope) + if (collPoint.GetFloorHeight() == NO_HEIGHT || collPoint.IsIllegalFloor()) continue; // Remember floor position for a tested point. - int candidateYPos = collPoint.Position.Floor; + int candidateYPos = collPoint.GetFloorHeight(); // Now repeat the same test for original extent point to make sure it's also valid. candidatePos = Geometry::TranslatePoint(origin, angle, extents); candidatePos.y = yPos; - collPoint = GetCollision(candidatePos.x, candidatePos.y, candidatePos.z, item->RoomNumber); + collPoint = GetPointCollision(candidatePos, item->RoomNumber); // If position is inside a wall or on a slope, don't use it. - if (collPoint.Position.Floor == NO_HEIGHT || collPoint.Position.FloorSlope) + if (collPoint.GetFloorHeight() == NO_HEIGHT || collPoint.IsIllegalFloor()) continue; // If position is not in the same room, don't use it. - if (collPoint.RoomNumber != item->RoomNumber) + if (collPoint.GetRoomNumber() != item->RoomNumber) continue; // Setup a dummy sphere with 1-click diameter for item and static mesh collision tests. @@ -923,16 +925,16 @@ void DropPickups(ItemInfo* item) // Finally, do height difference tests. If difference is more than one and a half click, // most likely it's hanging in the air or submerged, so bypass the corner. - if (abs(collPoint.Position.Floor - yPos) > CLICK(1.5f)) + if (abs(collPoint.GetFloorHeight() - yPos) > CLICK(1.5f)) continue; // If height difference between extent points is more than one click, it means it landed // on a step, so let's search for other position. - if (abs(collPoint.Position.Floor - candidateYPos) >= CLICK(1.0f)) + if (abs(collPoint.GetFloorHeight() - candidateYPos) >= CLICK(1.0f)) continue; origin = candidatePos; - origin.y = collPoint.Position.Floor; + origin.y = collPoint.GetFloorHeight(); break; } diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index 4f374bb1d..85da187fc 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -2,6 +2,7 @@ #include "Game/room.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/control/lot.h" #include "Game/control/volume.h" @@ -13,6 +14,7 @@ using namespace TEN::Math; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Renderer; using namespace TEN::Utils; @@ -154,18 +156,18 @@ int IsRoomOutside(int x, int y, int z) (y > room.maxceiling && y < room.minfloor) && (z > (room.z + BLOCK(1)) && z < (room.z + (room.zSize - 1) * BLOCK(1)))) { - auto pointColl = GetCollision(x, y, z, roomNumber); + auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); - if (pointColl.Position.Floor == NO_HEIGHT || y > pointColl.Position.Floor) + if (pointColl.GetFloorHeight() == NO_HEIGHT || y > pointColl.GetFloorHeight()) return NO_ROOM; - if (y < pointColl.Position.Ceiling) + if (y < pointColl.GetCeilingHeight()) return NO_ROOM; if (TestEnvironmentFlags(ENV_FLAG_WATER, room.flags) || TestEnvironmentFlags(ENV_FLAG_WIND, room.flags)) { - return pointColl.RoomNumber; + return pointColl.GetRoomNumber(); } return NO_ROOM; diff --git a/TombEngine/Objects/Effects/enemy_missile.cpp b/TombEngine/Objects/Effects/enemy_missile.cpp index 0d4c47484..f11fdeddf 100644 --- a/TombEngine/Objects/Effects/enemy_missile.cpp +++ b/TombEngine/Objects/Effects/enemy_missile.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -17,6 +18,7 @@ #include "Renderer/RendererEnums.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Entities::Creatures::TR3; using namespace TEN::Entities::TR4; @@ -221,9 +223,9 @@ namespace TEN::Entities::Effects fx.pos.Position.y += -((fx.speed * phd_sin(fx.pos.Orientation.x))) + fx.fallspeed; fx.pos.Position.z += speed * phd_cos(fx.pos.Orientation.y); - auto pointColl = GetCollision(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, fx.roomNumber); + auto pointColl = GetPointCollision(fx.pos.Position, fx.roomNumber); - if (fx.pos.Position.y >= pointColl.Position.Floor || fx.pos.Position.y <= pointColl.Position.Ceiling) + if (fx.pos.Position.y >= pointColl.GetFloorHeight() || fx.pos.Position.y <= pointColl.GetCeilingHeight()) { fx.pos.Position = prevPos; @@ -361,8 +363,8 @@ namespace TEN::Entities::Effects } else { - if (pointColl.RoomNumber != fx.roomNumber) - EffectNewRoom(fxNumber, pointColl.RoomNumber); + if (pointColl.GetRoomNumber() != fx.roomNumber) + EffectNewRoom(fxNumber, pointColl.GetRoomNumber()); auto deltaPos = prevPos - fx.pos.Position; diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index 7068c36d7..973a41402 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -17,6 +18,7 @@ #include "Specific/clock.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Effects::Ripple; @@ -220,10 +222,9 @@ void ElectricityWiresControl(short itemNumber) for (int j = 0; j < collObj->nmeshes; j++) { auto collPos = GetJointPosition(collItem, j); + auto pointCollJointRoom = GetPointCollision(collPos, collItem->RoomNumber).GetRoomNumber(); - auto collJointRoom = GetCollision(collPos.x, collPos.y, collPos.z, collItem->RoomNumber).RoomNumber; - - if (!isWaterNearby && isTouchingWater && roomNumber == collJointRoom) + if (!isWaterNearby && isTouchingWater && roomNumber == pointCollJointRoom) isWaterNearby = true; } diff --git a/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp b/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp index 26cffbd02..5eb580d48 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/control/lot.h" #include "Game/items.h" @@ -11,6 +12,8 @@ #include "Game/misc.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::Creatures::TR1 { ItemInfo* FindDoppelgangerReference(const ItemInfo& item, int objectNumber) @@ -60,7 +63,7 @@ namespace TEN::Entities::Creatures::TR1 (referencePtr->Pose.Position.x * 2) - LaraItem->Pose.Position.x, LaraItem->Pose.Position.y, (referencePtr->Pose.Position.z * 2) - LaraItem->Pose.Position.z); - item.Floor = GetCollision(pos.x, pos.y, pos.z, item.RoomNumber).Position.Floor; + item.Floor = GetPointCollision(pos, item.RoomNumber).GetFloorHeight(); // Animate doppelganger, mirroring player's position. item.Animation.AnimNumber = LaraItem->Animation.AnimNumber; diff --git a/TombEngine/Objects/TR2/Entity/Dragon.cpp b/TombEngine/Objects/TR2/Entity/Dragon.cpp index da70668e5..9e7c233e2 100644 --- a/TombEngine/Objects/TR2/Entity/Dragon.cpp +++ b/TombEngine/Objects/TR2/Entity/Dragon.cpp @@ -3,6 +3,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -16,6 +17,7 @@ #include "Specific/clock.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; using namespace TEN::Math; @@ -333,15 +335,15 @@ namespace TEN::Entities::Creatures::TR2 { if (GetFrameNumber(item) == GetFrameCount(item.Animation.AnimNumber)) { - auto pointColl = GetCollision(pos, item.RoomNumber); + auto pointColl = GetPointCollision(pos, item.RoomNumber); - if (pointColl.Position.Floor == NO_HEIGHT) + if (pointColl.GetFloorHeight() == NO_HEIGHT) { pos.y -= CLICK(0.5f); } else { - pos.y = pointColl.Position.Floor - CLICK(0.5f); + pos.y = pointColl.GetFloorHeight() - CLICK(0.5f); } auto pose = Pose(pos, EulerAngles::Identity); diff --git a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp index 9c16dfea7..adb472b24 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp +++ b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -11,6 +12,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + void InitializeSpinningBlade(short itemNumber) { auto* item = &g_Level.Items[itemNumber]; @@ -30,7 +33,7 @@ void SpinningBladeControl(short itemNumber) int x = item->Pose.Position.x + BLOCK(3) * phd_sin(item->Pose.Orientation.y) / 2; int z = item->Pose.Position.z + BLOCK(3) * phd_cos(item->Pose.Orientation.y) / 2; - int floorHeight = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetFloorHeight(); if (floorHeight == NO_HEIGHT) item->Animation.TargetState = 1; } diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index b8e5dea9f..795170420 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -21,6 +22,7 @@ #include "Math/Math.h" #include "Sound/sound.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; using namespace TEN::Math; @@ -773,8 +775,8 @@ namespace TEN::Entities::Vehicles x = 0; z = 0; - auto probe = GetCollision(old->x, pos->y, pos->z, skidooItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + auto probe = GetPointCollision(Vector3i(old->x, pos->y, pos->z), skidooItem->RoomNumber); + if (probe.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->z > old->z) z = -shiftZ - 1; @@ -782,8 +784,8 @@ namespace TEN::Entities::Vehicles z = BLOCK(1) - shiftZ; } - probe = GetCollision(pos->x, pos->y, old->z, skidooItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + probe = GetPointCollision(Vector3i(pos->x, pos->y, old->z), skidooItem->RoomNumber); + if (probe.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->x > old->x) x = -shiftX - 1; diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index 30e424ef3..5d90ae406 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -17,6 +18,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; namespace TEN::Entities::Vehicles @@ -237,19 +239,19 @@ namespace TEN::Entities::Vehicles int x = speedboatItem->Pose.Position.x + SPEEDBOAT_DISMOUNT_DISTANCE * phd_sin(angle); int y = speedboatItem->Pose.Position.y; int z = speedboatItem->Pose.Position.z + SPEEDBOAT_DISMOUNT_DISTANCE * phd_cos(angle); - auto probe = GetCollision(x, y, z, speedboatItem->RoomNumber); + auto probe = GetPointCollision(Vector3i(x, y, z), speedboatItem->RoomNumber); - if ((probe.Position.Floor - speedboatItem->Pose.Position.y) < -CLICK(2)) + if ((probe.GetFloorHeight() - speedboatItem->Pose.Position.y) < -CLICK(2)) return false; - if (probe.Position.FloorSlope || - probe.Position.Floor == NO_HEIGHT) + if (probe.IsIllegalFloor() || + probe.GetFloorHeight() == NO_HEIGHT) { return false; } - if ((probe.Position.Floor - probe.Position.Ceiling) < LARA_HEIGHT || - (probe.Position.Ceiling - speedboatItem->Pose.Position.y) > -LARA_HEIGHT) + if ((probe.GetFloorHeight() - probe.GetCeilingHeight()) < LARA_HEIGHT || + (probe.GetCeilingHeight() - speedboatItem->Pose.Position.y) > -LARA_HEIGHT) { return false; } @@ -281,15 +283,15 @@ namespace TEN::Entities::Vehicles int x = laraItem->Pose.Position.x + 360 * phd_sin(laraItem->Pose.Orientation.y); int y = laraItem->Pose.Position.y - 90; int z = laraItem->Pose.Position.z + 360 * phd_cos(laraItem->Pose.Orientation.y); - auto probe = GetCollision(x, y, z, laraItem->RoomNumber); + auto probe = GetPointCollision(Vector3i(x, y, z), laraItem->RoomNumber); - if (probe.Position.Floor >= (y - CLICK(1))) + if (probe.GetFloorHeight() >= (y - CLICK(1))) { laraItem->Pose.Position.x = x; laraItem->Pose.Position.z = z; - if (probe.RoomNumber != laraItem->RoomNumber) - ItemNewRoom(laraItem->Index, probe.RoomNumber); + if (probe.GetRoomNumber() != laraItem->RoomNumber) + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose.Position.y = y; @@ -373,8 +375,8 @@ namespace TEN::Entities::Vehicles x = 0; z = 0; - auto probe = GetCollision(old->x, pos->y, pos->z, speedboatItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + auto probe = GetPointCollision(Vector3i(old->x, pos->y, pos->z), speedboatItem->RoomNumber); + if (probe.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->z > old->z) z = -shiftZ - 1; @@ -382,8 +384,8 @@ namespace TEN::Entities::Vehicles z = BLOCK(1) - shiftZ; } - probe = GetCollision(pos->x, pos->y, old->z, speedboatItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + probe = GetPointCollision(Vector3i(pos->x, pos->y, old->z), speedboatItem->RoomNumber); + if (probe.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->x > old->x) x = -shiftX - 1; @@ -815,7 +817,7 @@ namespace TEN::Entities::Vehicles int heightFrontLeft = GetVehicleWaterHeight(speedboatItem, SPEEDBOAT_FRONT, -SPEEDBOAT_SIDE, true, &frontLeft); int heightFrontRight = GetVehicleWaterHeight(speedboatItem, SPEEDBOAT_FRONT, SPEEDBOAT_SIDE, true, &frontRight); - auto probe = GetCollision(speedboatItem); + auto probe = GetPointCollision(*speedboatItem); if (lara->Context.Vehicle == itemNumber) { @@ -823,7 +825,7 @@ namespace TEN::Entities::Vehicles TestTriggers(speedboatItem, false); } - auto water = GetWaterHeight(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y, speedboatItem->Pose.Position.z, probe.RoomNumber); + auto water = GetWaterHeight(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y, speedboatItem->Pose.Position.z, probe.GetRoomNumber()); speedboat->Water = water; bool noTurn = true; @@ -864,9 +866,9 @@ namespace TEN::Entities::Vehicles speedboat->TurnRate = 0; } - speedboatItem->Floor = probe.Position.Floor - 5; + speedboatItem->Floor = probe.GetFloorHeight() - 5; if (speedboat->Water == NO_HEIGHT) - speedboat->Water = probe.Position.Floor; + speedboat->Water = probe.GetFloorHeight(); else speedboat->Water -= 5; @@ -878,14 +880,18 @@ namespace TEN::Entities::Vehicles if (ofs - speedboatItem->Animation.Velocity.y > 32 && speedboatItem->Animation.Velocity.y == 0 && water != NO_HEIGHT) SpeedboatSplash(speedboatItem, ofs - speedboatItem->Animation.Velocity.y, water); - probe.Position.Floor = (frontLeft.y + frontRight.y); - if (probe.Position.Floor < 0) - probe.Position.Floor = -(abs(probe.Position.Floor) / 2); + int floorHeight = (frontLeft.y + frontRight.y); + if (floorHeight < 0) + { + floorHeight = -(abs(floorHeight) / 2); + } else - probe.Position.Floor /= 2; + { + floorHeight /= 2; + } - short xRot = phd_atan(SPEEDBOAT_FRONT, speedboatItem->Pose.Position.y - probe.Position.Floor); - short zRot = phd_atan(SPEEDBOAT_SIDE, probe.Position.Floor - frontLeft.y); + short xRot = phd_atan(SPEEDBOAT_FRONT, speedboatItem->Pose.Position.y - floorHeight); + short zRot = phd_atan(SPEEDBOAT_SIDE, floorHeight - frontLeft.y); speedboatItem->Pose.Orientation.x += ((xRot - speedboatItem->Pose.Orientation.x) / 2); speedboatItem->Pose.Orientation.z += ((zRot - speedboatItem->Pose.Orientation.z) / 2); @@ -899,10 +905,10 @@ namespace TEN::Entities::Vehicles { SpeedboatAnimation(speedboatItem, laraItem, collide); - if (probe.RoomNumber != speedboatItem->RoomNumber) + if (probe.GetRoomNumber() != speedboatItem->RoomNumber) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose = speedboatItem->Pose; @@ -930,8 +936,8 @@ namespace TEN::Entities::Vehicles } else { - if (probe.RoomNumber != speedboatItem->RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + if (probe.GetRoomNumber() != speedboatItem->RoomNumber) + ItemNewRoom(itemNumber, probe.GetRoomNumber()); speedboatItem->Pose.Orientation.z += speedboat->LeanAngle; } @@ -941,7 +947,7 @@ namespace TEN::Entities::Vehicles if (speedboatItem->Animation.Velocity.z && (water - 5) == speedboatItem->Pose.Position.y) { - auto roomNumber = probe.Block->GetNextRoomNumber(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.z, true); + auto roomNumber = probe.GetSector().GetNextRoomNumber(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.z, true); if (roomNumber.has_value() && (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, *roomNumber) || TestEnvironment(RoomEnvFlags::ENV_FLAG_SWAMP, *roomNumber))) { diff --git a/TombEngine/Objects/TR3/Entity/Shiva.cpp b/TombEngine/Objects/TR3/Entity/Shiva.cpp index c7e5d6641..1b07d640a 100644 --- a/TombEngine/Objects/TR3/Entity/Shiva.cpp +++ b/TombEngine/Objects/TR3/Entity/Shiva.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/effects/effects.h" #include "Game/itemdata/creature_info.h" @@ -17,6 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 @@ -339,7 +341,7 @@ namespace TEN::Entities::Creatures::TR3 { int x = item->Pose.Position.x + BLOCK(1) * phd_sin(item->Pose.Orientation.y + ANGLE(180.0f)); int z = item->Pose.Position.z + BLOCK(1) * phd_cos(item->Pose.Orientation.y + ANGLE(180.0f)); - auto box = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).BottomBlock->Box; + auto box = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetBottomSector().Box; if (box != NO_BOX && !(g_Level.Boxes[box].flags & BLOCKABLE) && !creature.Flags) item->Animation.TargetState = SHIVA_STATE_WALK_BACK; diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp index a4eaaba5a..12bdf11a7 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/collision/sphere.h" @@ -17,6 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 @@ -163,7 +165,7 @@ namespace TEN::Entities::Creatures::TR3 int y = item->Pose.Position.y; int z = item->Pose.Position.z + BLOCK(1) * phd_cos(item->Pose.Orientation.y + laraAI.angle); - int height = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); bool cover = (item->Pose.Position.y > (height + CLICK(3)) && item->Pose.Position.y < (height + CLICK(4.5f)) && laraAI.distance > pow(BLOCK(1), 2)); auto* enemy = creature->Enemy; diff --git a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp index 4359ac2d8..efc5feef8 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -18,6 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Effects::Boss; @@ -412,10 +414,10 @@ namespace TEN::Entities::Creatures::TR3 break; } - auto probe = GetCollision(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, fx.roomNumber); + auto pointColl = GetPointCollision(fx.pos.Position, fx.roomNumber); - if (fx.pos.Position.y >= probe.Position.Floor || - fx.pos.Position.y < probe.Position.Ceiling) + if (fx.pos.Position.y >= pointColl.GetFloorHeight() || + fx.pos.Position.y < pointColl.GetCeilingHeight()) { Vector3i pos; int debrisCount = type == TonyFlameType::InFront ? 7 : 3; @@ -427,13 +429,13 @@ namespace TEN::Entities::Creatures::TR3 for (int x = 0; x < 2; x++) TriggerExplosionSparks(prevPos.x, prevPos.y, prevPos.z, 3, -1, 0, fx.roomNumber); - probe = GetCollision(LaraItem); // TODO: Deal with LaraItem global. - pos.y = probe.Position.Ceiling + CLICK(1); + pointColl = GetPointCollision(*LaraItem); // TODO: Deal with LaraItem global. + pos.y = pointColl.GetCeilingHeight() + CLICK(1); pos.x = LaraItem->Pose.Position.x + (GetRandomControl() & 1023) - CLICK(2); pos.z = LaraItem->Pose.Position.z + (GetRandomControl() & 1023) - CLICK(2); - TriggerExplosionSparks(pos.x, pos.y, pos.z, 3, -2, 0, probe.RoomNumber); - TriggerFireBall(nullptr, TonyFlameType::ShowerFromCeiling, &pos, probe.RoomNumber, 0, 0); // Fallthrough is intended. + TriggerExplosionSparks(pos.x, pos.y, pos.z, 3, -2, 0, pointColl.GetRoomNumber()); + TriggerFireBall(nullptr, TonyFlameType::ShowerFromCeiling, &pos, pointColl.GetRoomNumber(), 0, 0); // Fallthrough is intended. case TonyFlameType::InFront: case TonyFlameType::ShowerFromCeiling: @@ -450,7 +452,7 @@ namespace TEN::Entities::Creatures::TR3 return; } - if (TestEnvironment(ENV_FLAG_WATER, probe.RoomNumber)) + if (TestEnvironment(ENV_FLAG_WATER, pointColl.GetRoomNumber())) { KillEffect(fxNumber); return; @@ -468,7 +470,7 @@ namespace TEN::Entities::Creatures::TR3 } } - if (probe.RoomNumber != fx.roomNumber) + if (pointColl.GetRoomNumber() != fx.roomNumber) EffectNewRoom(fxNumber, LaraItem->RoomNumber); if (LightIntensityTable[fx.flag1]) diff --git a/TombEngine/Objects/TR3/Trap/train.cpp b/TombEngine/Objects/TR3/Trap/train.cpp index 84c2b521a..54617dd04 100644 --- a/TombEngine/Objects/TR3/Trap/train.cpp +++ b/TombEngine/Objects/TR3/Trap/train.cpp @@ -6,6 +6,7 @@ #include "Game/control/control.h" #include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/floordata.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" @@ -16,6 +17,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + constexpr auto TRAIN_VEL = 260; long TrainTestHeight(ItemInfo* item, long x, long z, short* roomNumber) @@ -28,12 +31,11 @@ long TrainTestHeight(ItemInfo* item, long x, long z, short* roomNumber) auto pos = Vector3i( round(item->Pose.Position.x + ((z * sinY) + (x * cosY))), round(item->Pose.Position.y - ((z * sinX) + (x * sinZ))), - round(item->Pose.Position.z + ((z * cosY) - (x * sinY))) - ); - auto probe = GetCollision(pos.x, pos.y, pos.z, item->RoomNumber); + round(item->Pose.Position.z + ((z * cosY) - (x * sinY)))); + auto pointColl = GetPointCollision(pos, item->RoomNumber); - *roomNumber = probe.RoomNumber; - return probe.Position.Floor; + *roomNumber = pointColl.GetRoomNumber(); + return pointColl.GetFloorHeight(); } void TrainControl(short itemNumber) @@ -84,7 +86,7 @@ void TrainControl(short itemNumber) ForcedFixedCamera.x = item->Pose.Position.x + BLOCK(8) * sinY; ForcedFixedCamera.z = item->Pose.Position.z + BLOCK(8) * cosY; - ForcedFixedCamera.y = GetCollision(ForcedFixedCamera.x, item->Pose.Position.y - CLICK(2), ForcedFixedCamera.z, item->RoomNumber).Position.Floor; + ForcedFixedCamera.y = GetPointCollision(Vector3i(ForcedFixedCamera.x, item->Pose.Position.y - CLICK(2), ForcedFixedCamera.z), item->RoomNumber).GetFloorHeight(); ForcedFixedCamera.RoomNumber = roomNumber; UseForcedFixedCamera = 1; diff --git a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp index e758af3a6..b27904790 100644 --- a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp +++ b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp @@ -4,8 +4,9 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/control/box.h" -#include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" +#include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Game/items.h" @@ -20,6 +21,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; namespace TEN::Entities::Vehicles @@ -126,8 +128,8 @@ namespace TEN::Entities::Vehicles auto* projectileItem = &g_Level.Items[itemNumber]; projectileItem->ObjectNumber = ID_ROCKET; auto pos = GetJointPosition(bigGunItem, BigGunBite); - auto probe = GetCollision(pos.x, pos.y, pos.z, bigGunItem->RoomNumber); - projectileItem->RoomNumber = probe.RoomNumber; + auto pointColl = GetPointCollision(pos, bigGunItem->RoomNumber); + projectileItem->RoomNumber = pointColl.GetRoomNumber(); projectileItem->Pose.Position = pos; projectileItem->Pose.Orientation = EulerAngles( -((bigGun->XOrientFrame - 32) * ANGLE(1.0f)), diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index ecaf80943..38b3b1423 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -5,6 +5,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -18,6 +19,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; namespace TEN::Entities::Vehicles @@ -212,7 +214,7 @@ namespace TEN::Entities::Vehicles int x = kayakItem->Pose.Position.x + (zOffset * sinY) + (xOffset * cosY); int z = kayakItem->Pose.Position.z + (zOffset * cosY) - (xOffset * sinY); - int probedRoomNumber = GetCollision(x, kayakItem->Pose.Position.y, z, kayakItem->RoomNumber).RoomNumber; + int probedRoomNumber = GetPointCollision(Vector3i(x, kayakItem->Pose.Position.y, z), kayakItem->RoomNumber).GetRoomNumber(); int waterHeight = GetWaterHeight(x, kayakItem->Pose.Position.y, z, probedRoomNumber); //if (waterHeight != NO_HEIGHT) @@ -405,8 +407,8 @@ namespace TEN::Entities::Vehicles x = 0; z = 0; - auto probe = GetCollision(old->x, pos->y, pos->z, kayakItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + auto probe = GetPointCollision(Vector3i(old->x, pos->y, pos->z), kayakItem->RoomNumber); + if (probe.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->z > old->z) z = -zShift - 1; @@ -414,8 +416,8 @@ namespace TEN::Entities::Vehicles z = BLOCK(1) - zShift; } - probe = GetCollision(pos->x, pos->y, old->z, kayakItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + probe = GetPointCollision(Vector3i(pos->x, pos->y, old->z), kayakItem->RoomNumber); + if (probe.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->x > old->x) x = -xShift - 1; diff --git a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp index 8e199aacb..648d6484e 100644 --- a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp +++ b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp @@ -3,8 +3,9 @@ #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" +#include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" #include "Game/effects/tomb4fx.h" @@ -22,6 +23,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; using namespace TEN::Math; @@ -236,19 +238,19 @@ namespace TEN::Entities::Vehicles int y = quadBikeItem->Pose.Position.y; int z = quadBikeItem->Pose.Position.z + CLICK(2) * phd_cos(angle); - auto collResult = GetCollision(x, y, z, quadBikeItem->RoomNumber); + auto pointColl = GetPointCollision(Vector3i(x, y, z), quadBikeItem->RoomNumber); - if (collResult.Position.FloorSlope || - collResult.Position.Floor == NO_HEIGHT) + if (pointColl.IsIllegalFloor() || + pointColl.GetFloorHeight() == NO_HEIGHT) { return false; } - if (abs(collResult.Position.Floor - quadBikeItem->Pose.Position.y) > CLICK(2)) + if (abs(pointColl.GetFloorHeight() - quadBikeItem->Pose.Position.y) > CLICK(2)) return false; - if ((collResult.Position.Ceiling - quadBikeItem->Pose.Position.y) > -LARA_HEIGHT || - (collResult.Position.Floor - collResult.Position.Ceiling) < LARA_HEIGHT) + if ((pointColl.GetCeilingHeight() - quadBikeItem->Pose.Position.y) > -LARA_HEIGHT || + (pointColl.GetFloorHeight() - pointColl.GetCeilingHeight()) < LARA_HEIGHT) { return false; } @@ -343,7 +345,6 @@ namespace TEN::Entities::Vehicles static int DoQuadShift(ItemInfo* quadBikeItem, Vector3i* pos, Vector3i* old) { - CollisionResult probe; int x = pos->x / BLOCK(1); int z = pos->z / BLOCK(1); int oldX = old->x / BLOCK(1); @@ -387,8 +388,8 @@ namespace TEN::Entities::Vehicles x = 0; z = 0; - probe = GetCollision(old->x, pos->y, pos->z, quadBikeItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + auto pointColl = GetPointCollision(Vector3i(old->x, pos->y, pos->z), quadBikeItem->RoomNumber); + if (pointColl.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->z > old->z) z = -shiftZ - 1; @@ -396,8 +397,8 @@ namespace TEN::Entities::Vehicles z = BLOCK(1) - shiftZ; } - probe = GetCollision(pos->x, pos->y, old->z, quadBikeItem->RoomNumber); - if (probe.Position.Floor < (old->y - CLICK(1))) + pointColl = GetPointCollision(Vector3i(pos->x, pos->y, old->z), quadBikeItem->RoomNumber); + if (pointColl.GetFloorHeight() < (old->y - CLICK(1))) { if (pos->x > old->x) x = -shiftX - 1; diff --git a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp index 51e7f878c..c73754806 100644 --- a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp +++ b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/Bubble.h" #include "Game/effects/effects.h" @@ -19,6 +20,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Bubble; using namespace TEN::Input; @@ -262,7 +264,7 @@ namespace TEN::Entities::Vehicles x = 0; z = 0; - int height = GetCollision(old->x, pos->y, pos->z, rBoatItem->RoomNumber).Position.Floor; + int height = GetPointCollision(Vector3i(old->x, pos->y, pos->z), rBoatItem->RoomNumber).GetFloorHeight(); if (height < (old->y - CLICK(1))) { if (pos->z > old->z) @@ -271,7 +273,7 @@ namespace TEN::Entities::Vehicles z = BLOCK(1) - zShift; } - height = GetCollision(pos->x, pos->y, old->z, rBoatItem->RoomNumber).Position.Floor; + height = GetPointCollision(Vector3i(pos->x, pos->y, old->z), rBoatItem->RoomNumber).GetFloorHeight(); if (height < (old->y - CLICK(1))) { if (pos->x > old->x) @@ -604,16 +606,16 @@ namespace TEN::Entities::Vehicles int y = sBoatItem->Pose.Position.y; int z = sBoatItem->Pose.Position.z + BLOCK(1) * phd_cos(angle); - auto collResult = GetCollision(x, y, z, sBoatItem->RoomNumber); + auto pointColl = GetPointCollision(Vector3i(x, y, z), sBoatItem->RoomNumber); - if ((collResult.Position.Floor - sBoatItem->Pose.Position.y) < -512) + if ((pointColl.GetFloorHeight() - sBoatItem->Pose.Position.y) < -512) return false; - if (collResult.Position.FloorSlope || collResult.Position.Floor == NO_HEIGHT) + if (pointColl.IsIllegalFloor() || pointColl.GetFloorHeight() == NO_HEIGHT) return false; - if ((collResult.Position.Ceiling - sBoatItem->Pose.Position.y) > -LARA_HEIGHT || - (collResult.Position.Floor - collResult.Position.Ceiling) < LARA_HEIGHT) + if ((pointColl.GetCeilingHeight() - sBoatItem->Pose.Position.y) > -LARA_HEIGHT || + (pointColl.GetFloorHeight() - pointColl.GetCeilingHeight()) < LARA_HEIGHT) { return false; } @@ -786,14 +788,14 @@ namespace TEN::Entities::Vehicles int y = laraItem->Pose.Position.y - 90; int z = laraItem->Pose.Position.z + 360 * phd_cos(laraItem->Pose.Orientation.y); - auto probe = GetCollision(x, y, z, laraItem->RoomNumber); - if (probe.Position.Floor >= (y - CLICK(1))) + auto probe = GetPointCollision(Vector3i(x, y, z), laraItem->RoomNumber); + if (probe.GetFloorHeight() >= (y - CLICK(1))) { laraItem->Pose.Position.x = x; laraItem->Pose.Position.z = z; - if (probe.RoomNumber != laraItem->RoomNumber) - ItemNewRoom(laraItem->Index, probe.RoomNumber); + if (probe.GetRoomNumber() != laraItem->RoomNumber) + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose.Position.y = y; @@ -824,8 +826,8 @@ namespace TEN::Entities::Vehicles TestTriggers(rBoatItem, true); } - auto probe = GetCollision(rBoatItem); - int water = GetWaterHeight(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y, rBoatItem->Pose.Position.z, probe.RoomNumber); + auto probe = GetPointCollision(*rBoatItem); + int water = GetWaterHeight(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y, rBoatItem->Pose.Position.z, probe.GetRoomNumber()); rBoat->Water = water; if (lara->Context.Vehicle == itemNumber && laraItem->HitPoints > 0) @@ -861,7 +863,7 @@ namespace TEN::Entities::Vehicles rBoat->TurnRate = 0; } - height = probe.Position.Floor; + height = probe.GetFloorHeight(); rBoatItem->Floor = height - 5; if (rBoat->Water == NO_HEIGHT) @@ -895,10 +897,10 @@ namespace TEN::Entities::Vehicles { RubberBoatAnimation(rBoatItem, laraItem, collide); - if (probe.RoomNumber != rBoatItem->RoomNumber) + if (probe.GetRoomNumber() != rBoatItem->RoomNumber) { - ItemNewRoom(itemNumber, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(itemNumber, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } rBoatItem->Pose.Orientation.z += rBoat->LeanAngle; @@ -914,8 +916,8 @@ namespace TEN::Entities::Vehicles } else { - if (probe.RoomNumber != rBoatItem->RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + if (probe.GetRoomNumber() != rBoatItem->RoomNumber) + ItemNewRoom(itemNumber, probe.GetRoomNumber()); rBoatItem->Pose.Orientation.z += rBoat->LeanAngle; } @@ -933,7 +935,7 @@ namespace TEN::Entities::Vehicles DoRubberBoatDismount(rBoatItem, laraItem); - short probedRoomNumber = GetCollision(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y + 128, rBoatItem->Pose.Position.z, rBoatItem->RoomNumber).RoomNumber; + short probedRoomNumber = GetPointCollision(Vector3i(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y + 128, rBoatItem->Pose.Position.z), rBoatItem->RoomNumber).GetRoomNumber(); height = GetWaterHeight(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y + 128, rBoatItem->Pose.Position.z, probedRoomNumber); if (height > rBoatItem->Pose.Position.y + 32 || height == NO_HEIGHT) height = 0; @@ -941,7 +943,7 @@ namespace TEN::Entities::Vehicles height = 1; auto prop = GetJointPosition(rBoatItem, 2, Vector3i(0, 0, -80)); - probedRoomNumber = GetCollision(prop.x, prop.y, prop.z, rBoatItem->RoomNumber).RoomNumber; + probedRoomNumber = GetPointCollision(prop, rBoatItem->RoomNumber).GetRoomNumber(); if (rBoatItem->Animation.Velocity.z && height < prop.y && @@ -968,7 +970,7 @@ namespace TEN::Entities::Vehicles } else { - height = GetCollision(prop.x, prop.y, prop.z, rBoatItem->RoomNumber).Position.Floor; + height = GetPointCollision(prop, rBoatItem->RoomNumber).GetFloorHeight(); if (prop.y > height && !TestEnvironment(ENV_FLAG_WATER, probedRoomNumber)) { diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index fdea14fe2..b05b4f156 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -6,6 +6,7 @@ #include "Game/collision/sphere.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/Bubble.h" @@ -26,6 +27,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Streamer; using namespace TEN::Input; @@ -311,7 +313,7 @@ namespace TEN::Entities::Vehicles if (Random::TestProbability(1 / 2.0f)) { auto bubblePos = Random::GeneratePointInSphere(sphere); - int probedRoomNumber = GetCollision(bubblePos.x, bubblePos.y, bubblePos.z, UPVItem->RoomNumber).RoomNumber; + int probedRoomNumber = GetPointCollision(bubblePos, UPVItem->RoomNumber).GetRoomNumber(); for (int i = 0; i < 3; i++) SpawnBubble(bubblePos, probedRoomNumber, (int)BubbleFlags::HighAmplitude); @@ -358,12 +360,12 @@ namespace TEN::Entities::Vehicles int z = UPVItem->Pose.Position.z + velocity * phd_cos(moveAngle); int y = UPVItem->Pose.Position.y - UPV_DISMOUNT_DISTANCE * phd_sin(-UPVItem->Pose.Orientation.x); - auto probe = GetCollision(x, y, z, UPVItem->RoomNumber); - if ((probe.Position.Floor - probe.Position.Ceiling) < CLICK(1) || - probe.Position.Floor < y || - probe.Position.Ceiling > y || - probe.Position.Floor == NO_HEIGHT || - probe.Position.Ceiling == NO_HEIGHT) + auto probe = GetPointCollision(Vector3i(x, y, z), UPVItem->RoomNumber); + if ((probe.GetFloorHeight() - probe.GetCeilingHeight()) < CLICK(1) || + probe.GetFloorHeight() < y || + probe.GetCeilingHeight() > y || + probe.GetFloorHeight() == NO_HEIGHT || + probe.GetCeilingHeight() == NO_HEIGHT) { return false; } @@ -849,7 +851,7 @@ namespace TEN::Entities::Vehicles auto* UPV = GetUPVInfo(UPVItem); auto oldPos = UPVItem->Pose; - auto probe = GetCollision(UPVItem); + auto probe = GetPointCollision(*UPVItem); if (!(UPV->Flags & UPV_FLAG_DEAD)) { @@ -869,7 +871,7 @@ namespace TEN::Entities::Vehicles TranslateItem(UPVItem, UPVItem->Pose.Orientation, UPVItem->Animation.Velocity.z); } - int newHeight = GetCollision(UPVItem).Position.Floor; + int newHeight = GetPointCollision(*UPVItem).GetFloorHeight(); int waterHeight = GetWaterHeight(UPVItem); if ((newHeight - waterHeight) < UPV_HEIGHT || (newHeight < UPVItem->Pose.Position.y - UPV_HEIGHT / 2) || @@ -879,7 +881,7 @@ namespace TEN::Entities::Vehicles UPVItem->Animation.Velocity.z = 0; } - UPVItem->Floor = probe.Position.Floor; + UPVItem->Floor = probe.GetFloorHeight(); if (UPV->Flags & UPV_FLAG_CONTROL && !(UPV->Flags & UPV_FLAG_DEAD)) { @@ -898,7 +900,7 @@ namespace TEN::Entities::Vehicles UPV->Flags |= UPV_FLAG_SURFACE; } else if ((waterHeight - UPVItem->Pose.Position.y) >= -UPV_WATER_SURFACE_DISTANCE && waterHeight != NO_HEIGHT && - (laraItem->Pose.Position.y - probe.Position.Ceiling) >= CLICK(1)) + (laraItem->Pose.Position.y - probe.GetCeilingHeight()) >= CLICK(1)) { UPVItem->Pose.Position.y = waterHeight + UPV_WATER_SURFACE_DISTANCE; @@ -963,10 +965,10 @@ namespace TEN::Entities::Vehicles } } - if (probe.RoomNumber != UPVItem->RoomNumber) + if (probe.GetRoomNumber() != UPVItem->RoomNumber) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose = UPVItem->Pose; @@ -991,8 +993,8 @@ namespace TEN::Entities::Vehicles { AnimateItem(laraItem); - if (probe.RoomNumber != UPVItem->RoomNumber) - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); + if (probe.GetRoomNumber() != UPVItem->RoomNumber) + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); BackgroundCollision(UPVItem, laraItem); diff --git a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp index ea22508c9..b201ba54a 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp @@ -2,6 +2,7 @@ #include "Objects/TR4/Entity/tr4_baboon.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/control/control.h" @@ -15,6 +16,7 @@ #include "Game/Setup.h" #include "Math/Math.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Environment; using namespace TEN::Math; @@ -512,9 +514,9 @@ namespace TEN::Entities::TR4 pos.y = item->Pose.Position.y; - auto probe = GetCollision(pos.x, pos.y, pos.z, item->RoomNumber); - item->Floor = probe.Position.Floor; - TestTriggers(pos.x, pos.y, pos.z, probe.RoomNumber, true); + auto probe = GetPointCollision(pos, item->RoomNumber); + item->Floor = probe.GetFloorHeight(); + TestTriggers(pos.x, pos.y, pos.z, probe.GetRoomNumber(), true); item->TriggerFlags = 1; } diff --git a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp index 2feee2dcb..f1f808d8b 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/lot.h" @@ -18,6 +19,7 @@ #include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; /* @@ -359,15 +361,15 @@ namespace TEN::Entities::TR4 x += dx; z += dz; - int height1 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height2 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height3 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height3 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); int height = 0; bool canJump1Sector = true; @@ -421,11 +423,11 @@ namespace TEN::Entities::TR4 item->ItemFlags[1] = item->RoomNumber; - CollisionResult probe; + auto probe = GetPointCollision(*item); if (item->HitPoints <= 0) { - item->Floor = GetCollision(item).Position.Floor; + item->Floor = GetPointCollision(*item).GetFloorHeight(); currentCreature->LOT.IsMonkeying = false; switch (item->Animation.ActiveState) @@ -575,7 +577,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height4 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height4 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); dx = 942 * phd_sin(item->Pose.Orientation.y + ANGLE(78.75f)); dz = 942 * phd_cos(item->Pose.Orientation.y + ANGLE(78.75f)); @@ -583,7 +585,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height5 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height5 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); if (abs(height5 - item->Pose.Position.y) > CLICK(1)) jump = false; @@ -600,7 +602,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height6 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height6 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); dx = 942 * phd_sin(item->Pose.Orientation.y - ANGLE(78.75f)); dz = 942 * phd_cos(item->Pose.Orientation.y - ANGLE(78.75f)); @@ -608,7 +610,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height7 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height7 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); if (abs(height7 - item->Pose.Position.y) > CLICK(1) || (height6 + CLICK(2)) >= item->Pose.Position.y) @@ -715,8 +717,8 @@ namespace TEN::Entities::TR4 if (currentCreature->MonkeySwingAhead) { - probe = GetCollision(item); - if (probe.Position.Ceiling == probe.Position.Floor - CLICK(6)) + probe = GetPointCollision(*item); + if (probe.GetCeilingHeight() == probe.GetFloorHeight() - CLICK(6)) { if (item->TestMeshSwapFlags(MESHSWAPFLAGS_BADDY_EMPTY)) { @@ -950,7 +952,7 @@ namespace TEN::Entities::TR4 joint1 = 0; joint2 = 0; - probe = GetCollision(item); + probe = GetPointCollision(*item); if (laraAI.ahead && laraAI.distance < pow(682, 2) && (LaraItem->Animation.ActiveState == LS_MONKEY_IDLE || @@ -965,7 +967,7 @@ namespace TEN::Entities::TR4 } else if (item->BoxNumber != currentCreature->LOT.TargetBox && currentCreature->MonkeySwingAhead || - probe.Position.Ceiling != (probe.Position.Floor - CLICK(6))) + probe.GetCeilingHeight() != (probe.GetFloorHeight() - CLICK(6))) { item->Animation.TargetState = BADDY_STATE_MONKEY_FORWARD; } @@ -989,9 +991,9 @@ namespace TEN::Entities::TR4 if (item->BoxNumber == currentCreature->LOT.TargetBox || !currentCreature->MonkeySwingAhead) { - probe = GetCollision(item); + probe = GetPointCollision(*item); - if (probe.Position.Ceiling == probe.Position.Floor - CLICK(6)) + if (probe.GetCeilingHeight() == probe.GetFloorHeight() - CLICK(6)) item->Animation.TargetState = BADDY_STATE_MONKEY_IDLE; } diff --git a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp index b37d4f247..ead8f8949 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/control/trigger.h" @@ -17,6 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::TR4 @@ -98,7 +100,7 @@ namespace TEN::Entities::TR4 int dx = 682 * phd_sin(item->Pose.Orientation.y); int dz = 682 * phd_cos(item->Pose.Orientation.y); - int height1 = GetCollision(x - dz, y, z - dx, item->RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x - dz, y, z - dx), item->RoomNumber).GetFloorHeight(); if (abs(item->Pose.Position.y - height1) > CLICK(3)) { item->Pose.Position.x += dz / 64; @@ -107,7 +109,7 @@ namespace TEN::Entities::TR4 height1 = y; } - int height2 = GetCollision(x + dz, y, z - dx, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x + dz, y, z - dx), item->RoomNumber).GetFloorHeight(); if (abs(item->Pose.Position.y - height2) > CLICK(3)) { item->Pose.Orientation.y -= ANGLE(2.0f); @@ -118,11 +120,11 @@ namespace TEN::Entities::TR4 short zRot = phd_atan(1364, height2 - height1); - int height3 = GetCollision(x + dx, y, z + dz, item->RoomNumber).Position.Floor; + int height3 = GetPointCollision(Vector3i(x + dx, y, z + dz), item->RoomNumber).GetFloorHeight(); if (abs(y - height3) > CLICK(3)) height3 = y; - int height4 = GetCollision(x - dx, y, z - dz, item->RoomNumber).Position.Floor; + int height4 = GetPointCollision(Vector3i(x - dx, y, z - dz), item->RoomNumber).GetFloorHeight(); if (abs(y - height4) > CLICK(3)) height4 = y; @@ -358,13 +360,15 @@ namespace TEN::Entities::TR4 creature->MaxTurn = 0; AnimateItem(item); - auto probe = GetCollision(item); - item->Floor = probe.Position.Floor; - if (item->RoomNumber != probe.RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + auto probe = GetPointCollision(*item); + item->Floor = probe.GetFloorHeight(); + if (item->RoomNumber != probe.GetRoomNumber()) + ItemNewRoom(itemNumber, probe.GetRoomNumber()); if (item->Pose.Position.y < item->Floor) + { item->Animation.IsAirborne = true; + } else { item->Pose.Position.y = item->Floor; diff --git a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp index 59ed96052..2b48d98b3 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/box.h" #include "Game/control/control.h" @@ -16,6 +17,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::TR4 @@ -251,14 +253,14 @@ namespace TEN::Entities::TR4 int y = horseItem->Pose.Position.y; int z = horseItem->Pose.Position.z + 341 * phd_cos(horseItem->Pose.Orientation.y); - auto probe = GetCollision(x, y, z, item->RoomNumber); - int height1 = probe.Position.Floor; + auto probe = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); + int height1 = probe.GetFloorHeight(); x = horseItem->Pose.Position.x - 341 * phd_sin(horseItem->Pose.Orientation.y); y = horseItem->Pose.Position.y; z = horseItem->Pose.Position.z - 341 * phd_cos(horseItem->Pose.Orientation.y); - int height2 = GetCollision(x, y, z, probe.RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, y, z), probe.GetRoomNumber()).GetFloorHeight(); xRot = phd_atan(682, height2 - height1); } diff --git a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp index 9c4d8a199..65633f6a2 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/volume.h" @@ -23,6 +24,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Control::Volumes; using namespace TEN::Input; using namespace TEN::Math; @@ -655,7 +657,7 @@ namespace TEN::Entities::TR4 auto pos = GetJointPosition(&item, SasGunBite); grenadeItem->Pose.Position = pos; - auto floorHeight = GetCollision(pos.x, pos.y, pos.z, grenadeItem->RoomNumber).Position.Floor; + auto floorHeight = GetPointCollision(pos, grenadeItem->RoomNumber).GetFloorHeight(); if (floorHeight < pos.y) { grenadeItem->Pose.Position = Vector3i(item.Pose.Position.x, pos.y, item.Pose.Position.z); diff --git a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp index b57bdf826..ef0742ccc 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp @@ -5,6 +5,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/spark.h" @@ -20,6 +21,7 @@ #include "Specific/clock.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; using namespace TEN::Math; @@ -129,19 +131,19 @@ namespace TEN::Entities::TR4 int dx = 870 * phd_sin(item->Pose.Orientation.y); int dz = 870 * phd_cos(item->Pose.Orientation.y); - int ceiling = GetCollision(x, y, z, item->RoomNumber).Position.Ceiling; + int ceiling = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetCeilingHeight(); x += dx; z += dz; - int height1 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height2 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height3 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height3 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); bool canJump = false; if ((y < (height1 - CLICK(1.5f)) || y < (height2 - CLICK(1.5f))) && @@ -152,7 +154,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x - dx; z = item->Pose.Position.z - dz; - int height4 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height4 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); AI_INFO AI; short angle = 0; diff --git a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp index e39adb3d5..6f346fabb 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/floordata.h" #include "Game/control/box.h" #include "Game/control/lot.h" @@ -20,6 +21,7 @@ #include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::TR4 @@ -148,7 +150,7 @@ namespace TEN::Entities::TR4 auto* fx = &EffectList[fxNumber]; fx->pos.Position.x = (byte)GetRandomControl() + item->Pose.Position.x - 128; - fx->pos.Position.y = GetCollision(item).Position.Floor; + fx->pos.Position.y = GetPointCollision(*item).GetFloorHeight(); fx->pos.Position.z = (byte)GetRandomControl() + item->Pose.Position.z - 128; fx->roomNumber = item->RoomNumber; fx->pos.Orientation.y = 2 * GetRandomControl(); @@ -223,15 +225,15 @@ namespace TEN::Entities::TR4 x += dx; z += dz; - int height1 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height2 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height3 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height3 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); int height = 0; bool canJump1Block = true; @@ -338,7 +340,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height4 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height4 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); dx = 870 * phd_sin(item->Pose.Orientation.y + ANGLE(78.75f)); dz = 870 * phd_cos(item->Pose.Orientation.y + ANGLE(78.75f)); @@ -346,7 +348,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height5 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height5 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); if (abs(height5 - item->Pose.Position.y) > CLICK(1)) jumpRight = false; @@ -364,7 +366,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height6 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height6 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); dx = 870 * phd_sin(item->Pose.Orientation.y - ANGLE(78.75f)); dz = 870 * phd_cos(item->Pose.Orientation.y - ANGLE(78.75f)); @@ -372,7 +374,7 @@ namespace TEN::Entities::TR4 x = item->Pose.Position.x + dx; y = item->Pose.Position.y; z = item->Pose.Position.z + dz; - int height7 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height7 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); if (abs(height7 - item->Pose.Position.y) > CLICK(1) || height6 + CLICK(2) >= item->Pose.Position.y) jumpLeft = false; @@ -557,7 +559,7 @@ namespace TEN::Entities::TR4 creature->LOT.IsJumping = true; - if (GetCollision(item).Position.Floor > item->Pose.Position.y + BLOCK(1)) + if (GetPointCollision(*item).GetFloorHeight() > item->Pose.Position.y + BLOCK(1)) { item->Animation.AnimNumber = Objects[ID_SKELETON].animIndex + 44; item->Animation.FrameNumber = GetAnimData(item).frameBase; @@ -641,8 +643,8 @@ namespace TEN::Entities::TR4 auto pos = GetJointPosition(item, 16); - auto floor = GetCollision(x, y, z, item->RoomNumber).Block; - if (floor->Stopper) + auto& sector = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetSector(); + if (sector.Stopper) { for (int i = 0; i < room->mesh.size(); i++) { @@ -654,7 +656,7 @@ namespace TEN::Entities::TR4 { ShatterObject(0, staticMesh, -128, LaraItem->RoomNumber, 0); SoundEffect(SFX_TR4_SMASH_ROCK, &item->Pose); - floor->Stopper = false; + sector.Stopper = false; TestTriggers(item, true); break; } @@ -702,7 +704,7 @@ namespace TEN::Entities::TR4 case SKELETON_STATE_JUMP_FORWARD_1_BLOCK: if (item->Animation.AnimNumber == Objects[item->ObjectNumber].animIndex + 43) { - if (GetCollision(item).Position.Floor > (item->Pose.Position.y + CLICK(5))) + if (GetPointCollision(*item).GetFloorHeight() > (item->Pose.Position.y + CLICK(5))) { item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex + 44; item->Animation.FrameNumber = GetAnimData(item).frameBase; @@ -717,7 +719,7 @@ namespace TEN::Entities::TR4 case SKELETON_STATE_JUMP_CONTINUE: case SKELETON_STATE_JUMP_START: - if (GetCollision(item).Position.Floor <= item->Pose.Position.y) + if (GetPointCollision(*item).GetFloorHeight() <= item->Pose.Position.y) { if (item->Active) { @@ -750,7 +752,7 @@ namespace TEN::Entities::TR4 creature->LOT.IsJumping = false; - if (GetCollision(item).Position.Floor <= (item->Pose.Position.y + BLOCK(1))) + if (GetPointCollision(*item).GetFloorHeight() <= (item->Pose.Position.y + BLOCK(1))) { if (Random::TestProbability(1 / 32.0f)) item->Animation.TargetState = 14; diff --git a/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp b/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp index b50c351fa..5fd89bdb2 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp @@ -2,6 +2,7 @@ #include "Objects/TR4/Entity/tr4_sphinx.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -13,6 +14,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::TR4 { constexpr auto SPHINX_ATTACK_DAMAGE = 200; @@ -78,11 +81,11 @@ namespace TEN::Entities::TR4 int y = item->Pose.Position.y; int z = item->Pose.Position.z + 614 * phd_cos(item->Pose.Orientation.y); - auto probe = GetCollision(x, y, z, item->RoomNumber); + auto pointColl = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); - int height1 = probe.Position.Floor; + int height1 = pointColl.GetFloorHeight(); - if (item->Animation.ActiveState == SPHINX_STATE_RUN_FORWARD && probe.Block->Stopper) + if (item->Animation.ActiveState == SPHINX_STATE_RUN_FORWARD && pointColl.GetSector().Stopper) { auto* room = &g_Level.Rooms[item->RoomNumber]; @@ -97,8 +100,6 @@ namespace TEN::Entities::TR4 ShatterObject(nullptr, mesh, -64, item->RoomNumber, 0); SoundEffect(SFX_TR4_SMASH_ROCK, &item->Pose); - probe.Block = false; - TestTriggers(x, y, z, item->RoomNumber, true); } } @@ -108,7 +109,7 @@ namespace TEN::Entities::TR4 y = item->Pose.Position.y; z = item->Pose.Position.z - 614 * phd_cos(item->Pose.Orientation.y); - int height2 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); phd_atan(1228, height2 - height1); diff --git a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp index 0a0731328..96b7d8ed6 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -16,6 +17,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::TR4 @@ -170,20 +172,20 @@ namespace TEN::Entities::TR4 x += dx; z += dz; - int height1 = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height2 = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height3 = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).Position.Floor; + int height3 = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - auto probe = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber); - int height4 = probe.Position.Floor; + auto probe = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber); + int height4 = probe.GetFloorHeight(); bool canJump1block = true; if (item->BoxNumber == LaraItem->BoxNumber || @@ -419,13 +421,17 @@ namespace TEN::Entities::TR4 if (creature->MonkeySwingAhead) { - probe = GetCollision(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, probe.RoomNumber); - if (probe.Position.Ceiling == (probe.Position.Floor - 1536)) + probe = GetPointCollision(item->Pose.Position, probe.GetRoomNumber()); + if (probe.GetCeilingHeight() == (probe.GetFloorHeight() - 1536)) { if (item->TestMeshSwapFlags(VonCroyKnifeSwapJoints)) + { item->Animation.TargetState = VON_CROY_STATE_TOGGLE_KNIFE; + } else + { item->Animation.TargetState = VON_CROY_STATE_START_MONKEY; + } break; } @@ -598,8 +604,8 @@ namespace TEN::Entities::TR4 item->Animation.TargetState = VON_CROY_STATE_MONKEY; else { - probe = GetCollision(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, probe.RoomNumber); - if (probe.Position.Ceiling == probe.Position.Floor - 1536) + probe = GetPointCollision(item->Pose.Position, probe.GetRoomNumber()); + if (probe.GetCeilingHeight() == probe.GetFloorHeight() - 1536) item->Animation.TargetState = VON_CROY_STATE_IDLE; } @@ -612,8 +618,8 @@ namespace TEN::Entities::TR4 if (item->BoxNumber == creature->LOT.TargetBox || !creature->MonkeySwingAhead) { - probe = GetCollision(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, probe.RoomNumber); - if (probe.Position.Ceiling == (probe.Position.Floor - BLOCK(1.5f))) + probe = GetPointCollision(item->Pose.Position, probe.GetRoomNumber()); + if (probe.GetCeilingHeight() == (probe.GetFloorHeight() - BLOCK(1.5f))) item->Animation.TargetState = VON_CROY_STATE_START_MONKEY; } diff --git a/TombEngine/Objects/TR4/Object/tr4_senet.cpp b/TombEngine/Objects/TR4/Object/tr4_senet.cpp index 46e633d71..f923e964c 100644 --- a/TombEngine/Objects/TR4/Object/tr4_senet.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_senet.cpp @@ -12,7 +12,9 @@ #include "Specific/level.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; int SenetPiecesNumber[6]; @@ -123,7 +125,7 @@ void GameSticksControl(short itemNumber) else item2->Pose.Position.z -= 128; - probedRoomNumber = GetCollision(item2->Pose.Position.x, item2->Pose.Position.y - 32, item2->Pose.Position.z, item2->RoomNumber).RoomNumber; + probedRoomNumber = GetPointCollision(Vector3i(item2->Pose.Position.x, item2->Pose.Position.y - 32, item2->Pose.Position.z), item2->RoomNumber).GetRoomNumber(); if (item2->RoomNumber != probedRoomNumber) ItemNewRoom(SenetPiecesNumber[ActivePiece], probedRoomNumber); @@ -179,7 +181,7 @@ void GameSticksControl(short itemNumber) item2->Pose.Position.x = SenetTargetX - BLOCK(4 * number) + BLOCK(7); item2->Pose.Position.z = SenetTargetZ + BLOCK(i % 3); - probedRoomNumber = GetCollision(item2->Pose.Position.x, item2->Pose.Position.y - 32, item2->Pose.Position.z, item2->RoomNumber).RoomNumber; + probedRoomNumber = GetPointCollision(Vector3i(item2->Pose.Position.x, item2->Pose.Position.y - 32, item2->Pose.Position.z), item2->RoomNumber).GetRoomNumber(); if (item2->RoomNumber != probedRoomNumber) ItemNewRoom(SenetPiecesNumber[i], probedRoomNumber); diff --git a/TombEngine/Objects/TR4/Vehicles/jeep.cpp b/TombEngine/Objects/TR4/Vehicles/jeep.cpp index 8697f27bc..1a70f3fbe 100644 --- a/TombEngine/Objects/TR4/Vehicles/jeep.cpp +++ b/TombEngine/Objects/TR4/Vehicles/jeep.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" #include "Game/effects/tomb4fx.h" @@ -22,6 +23,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; namespace TEN::Entities::Vehicles @@ -372,16 +374,16 @@ namespace TEN::Entities::Vehicles int y = jeepItem->Pose.Position.y; int z = jeepItem->Pose.Position.z - JEEP_DISMOUNT_DISTANCE * phd_cos(angle); - auto probe = GetCollision(x, y, z, jeepItem->RoomNumber); + auto probe = GetPointCollision(Vector3i(x, y, z), jeepItem->RoomNumber); - if (probe.Position.FloorSlope || probe.Position.Floor == NO_HEIGHT) + if (probe.IsIllegalFloor() || probe.GetFloorHeight() == NO_HEIGHT) return false; - if (abs(probe.Position.Floor - jeepItem->Pose.Position.y) > BLOCK(1 / 2.0f)) + if (abs(probe.GetFloorHeight() - jeepItem->Pose.Position.y) > BLOCK(1 / 2.0f)) return false; - if ((probe.Position.Ceiling - jeepItem->Pose.Position.y) > -LARA_HEIGHT || - (probe.Position.Floor - probe.Position.Ceiling) < LARA_HEIGHT) + if ((probe.GetCeilingHeight() - jeepItem->Pose.Position.y) > -LARA_HEIGHT || + (probe.GetFloorHeight() - probe.GetCeilingHeight()) < LARA_HEIGHT) { return false; } diff --git a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp index 60d276cab..25012ecac 100644 --- a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp +++ b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp @@ -5,6 +5,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -23,6 +24,7 @@ #include "Specific/level.h" using std::vector; +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; using namespace TEN::Math::Random; @@ -259,7 +261,7 @@ namespace TEN::Entities::Vehicles x = 0; z = 0; - int floorHeight = GetCollision(old->x, pos->y, pos->z, motorbikeItem->RoomNumber).Position.Floor; + int floorHeight = GetPointCollision(Vector3i(old->x, pos->y, pos->z), motorbikeItem->RoomNumber).GetFloorHeight(); if (floorHeight < (old->y - CLICK(1))) { if (pos->z > old->z) @@ -268,7 +270,7 @@ namespace TEN::Entities::Vehicles z = BLOCK(1) - shiftZ; } - floorHeight = GetCollision(pos->x, pos->y, old->z, motorbikeItem->RoomNumber).Position.Floor; + floorHeight = GetPointCollision(Vector3i(pos->x, pos->y, old->z), motorbikeItem->RoomNumber).GetFloorHeight(); if (floorHeight < (old->y - CLICK(1))) { if (pos->x > old->x) diff --git a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp index e489eca4e..1d4a94fd2 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" @@ -20,6 +21,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; @@ -144,17 +146,17 @@ namespace TEN::Entities::Creatures::TR5 x += dx; z += dz; - int height1 = GetCollision(x, item.Pose.Position.y, z, item.RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x, item.Pose.Position.y, z), item.RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height2 = GetCollision(x, item.Pose.Position.y, z, item.RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, item.Pose.Position.y, z), item.RoomNumber).GetFloorHeight(); x += dx; z += dz; - auto pointColl = GetCollision(x, item.Pose.Position.y, z, item.RoomNumber); - int roomNumber = pointColl.RoomNumber; - int height3 = pointColl.Position.Floor; + auto pointColl = GetPointCollision(Vector3i(x, item.Pose.Position.y, z), item.RoomNumber); + int roomNumber = pointColl.GetRoomNumber(); + int height3 = pointColl.GetFloorHeight(); bool canJump1block = true; if (item.BoxNumber == LaraItem->BoxNumber || @@ -220,7 +222,7 @@ namespace TEN::Entities::Creatures::TR5 if (randomIndex == 5 || randomIndex == 7 || randomIndex == 10) { auto pos2 = Vector3::Zero; - auto pointColl2 = GetCollision(pos2.x, pos2.y, pos2.z, item.RoomNumber); + auto pointColl2 = GetPointCollision(pos2, item.RoomNumber); switch (randomIndex) { @@ -230,9 +232,9 @@ namespace TEN::Entities::Creatures::TR5 case 7: pos2 = GetJointPosition(&item, 6, Vector3i(0, 0, 50)).ToVector3(); - pointColl2 = GetCollision(pos2.x, pos2.y, pos2.z, item.RoomNumber); + pointColl2 = GetPointCollision(pos2, item.RoomNumber); - if (TestEnvironment(ENV_FLAG_WATER, pointColl2.RoomNumber) && item.HitPoints > 0) + if (TestEnvironment(ENV_FLAG_WATER, pointColl2.GetRoomNumber()) && item.HitPoints > 0) { DropPickups(&item); DoDamage(&item, INT_MAX); @@ -379,11 +381,11 @@ namespace TEN::Entities::Creatures::TR5 } else { - pointColl = GetCollision(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, roomNumber); - roomNumber = pointColl.RoomNumber; - height = pointColl.Position.Floor; + pointColl = GetPointCollision(item.Pose.Position, roomNumber); + roomNumber = pointColl.GetRoomNumber(); + height = pointColl.GetFloorHeight(); - if (pointColl.Position.Ceiling == (height - BLOCK(1.5f))) + if (pointColl.GetCeilingHeight() == (height - BLOCK(1.5f))) item.Animation.TargetState = CYBORG_STATE_START_END_MONKEY; else item.Animation.TargetState = CYBORG_STATE_WALK; @@ -481,11 +483,11 @@ namespace TEN::Entities::Creatures::TR5 if (item.BoxNumber == creature.LOT.TargetBox || !creature.MonkeySwingAhead) { - pointColl = GetCollision(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, roomNumber); - roomNumber = pointColl.RoomNumber; - height = pointColl.Position.Floor; + pointColl = GetPointCollision(item.Pose.Position, roomNumber); + roomNumber = pointColl.GetRoomNumber(); + height = pointColl.GetFloorHeight(); - if (pointColl.Position.Ceiling == height - BLOCK(1.5f), 2) + if (pointColl.GetCeilingHeight() == height - BLOCK(1.5f), 2) item.Animation.TargetState = CYBORG_STATE_IDLE; } else @@ -503,11 +505,11 @@ namespace TEN::Entities::Creatures::TR5 if (item.BoxNumber == creature.LOT.TargetBox || !creature.MonkeySwingAhead) { - pointColl = GetCollision(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, roomNumber); - roomNumber = pointColl.RoomNumber; - height = pointColl.Position.Floor; + pointColl = GetPointCollision(item.Pose.Position, roomNumber); + roomNumber = pointColl.GetRoomNumber(); + height = pointColl.GetFloorHeight(); - if (pointColl.Position.Ceiling == height - BLOCK(1.5f), 2) + if (pointColl.GetCeilingHeight() == height - BLOCK(1.5f), 2) item.Animation.TargetState = CYBORG_STATE_START_END_MONKEY; } @@ -583,9 +585,9 @@ namespace TEN::Entities::Creatures::TR5 else if (item.Animation.ActiveState == CYBORG_STATE_DEATH && LaraItem->Effect.Type == EffectType::None) { auto pos = GetJointPosition(LaraItem, LM_RFOOT); - auto footProbeRight = GetCollision(pos.x, pos.y, pos.z, LaraItem->RoomNumber); + auto footProbeRight = GetPointCollision(pos, LaraItem->RoomNumber); pos = GetJointPosition(LaraItem, LM_LFOOT); - auto footProbeLeft = GetCollision(pos.x, pos.y, pos.z, LaraItem->RoomNumber); + auto footProbeLeft = GetPointCollision(pos, LaraItem->RoomNumber); short roomNumberLeft = LaraItem->RoomNumber; GetFloor(pos.x, pos.y, pos.z, &roomNumberLeft); @@ -599,8 +601,8 @@ namespace TEN::Entities::Creatures::TR5 short flipNumber = g_Level.Rooms[item.RoomNumber].flipNumber; - if (TestEnvironment(ENV_FLAG_WATER, footProbeLeft.RoomNumber) || - TestEnvironment(ENV_FLAG_WATER, footProbeRight.RoomNumber)) + if (TestEnvironment(ENV_FLAG_WATER, footProbeLeft.GetRoomNumber()) || + TestEnvironment(ENV_FLAG_WATER, footProbeRight.GetRoomNumber())) { if (roomLeft->flipNumber == flipNumber || roomRight->flipNumber == flipNumber) { diff --git a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp index e02a89ca0..ce1cc5591 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp @@ -1149,15 +1149,15 @@ namespace TEN::Entities::Creatures::TR5 x += dx; z += dz; - int height1 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height1 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height2 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height2 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); x += dx; z += dz; - int height3 = GetCollision(x, y, z, item->RoomNumber).Position.Floor; + int height3 = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetFloorHeight(); int height = 0; bool canJump1Sector = true; diff --git a/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp b/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp index 4ad272ffc..33baf715d 100644 --- a/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp @@ -1,5 +1,6 @@ #include "framework.h" #include "tr5_bodypart.h" + #include "Game/effects/effects.h" #include "Math/Math.h" #include "Sound/sound.h" @@ -7,10 +8,12 @@ #include "Game/Lara/lara.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/items.h" #include "Game/effects/tomb4fx.h" #include "Math/Random.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math::Random; constexpr int BODY_PART_LIFE = 64; @@ -76,18 +79,18 @@ void ControlBodyPart(short fxNumber) TriggerFireFlame(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, FlameType::Medium); } - auto pointColl = GetCollision(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, fx->roomNumber); + auto pointColl = GetPointCollision(fx->pos.Position, fx->roomNumber); if (!fx->counter) { - if (fx->pos.Position.y < pointColl.Position.Ceiling) + if (fx->pos.Position.y < pointColl.GetCeilingHeight()) { - fx->pos.Position.y = pointColl.Position.Ceiling; + fx->pos.Position.y = pointColl.GetCeilingHeight(); fx->fallspeed = -fx->fallspeed; fx->speed -= (fx->speed / 8); } - if (fx->pos.Position.y >= pointColl.Position.Floor) + if (fx->pos.Position.y >= pointColl.GetFloorHeight()) { if (fx->flag2 & BODY_NO_BOUNCE) { @@ -119,7 +122,7 @@ void ControlBodyPart(short fxNumber) return; } - if (y <= pointColl.Position.Floor) + if (y <= pointColl.GetFloorHeight()) { // Remove if touched floor (no bounce mode). if (fx->flag2 & BODY_PART_EXPLODE) @@ -201,19 +204,19 @@ void ControlBodyPart(short fxNumber) } } - if (pointColl.RoomNumber != fx->roomNumber) + if (pointColl.GetRoomNumber() != fx->roomNumber) { - if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointColl.RoomNumber) && + if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointColl.GetRoomNumber()) && !TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, fx->roomNumber)) { - int waterHeight = GetWaterHeight(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, pointColl.RoomNumber); + int waterHeight = GetWaterHeight(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, pointColl.GetRoomNumber()); SplashSetup.y = waterHeight - 1; SplashSetup.x = fx->pos.Position.x; SplashSetup.z = fx->pos.Position.z; SplashSetup.splashPower = fx->fallspeed; SplashSetup.innerRadius = 48; - SetupSplash(&SplashSetup, pointColl.RoomNumber); + SetupSplash(&SplashSetup, pointColl.GetRoomNumber()); // Remove if touched water. if (fx->flag2 & BODY_PART_EXPLODE) @@ -223,6 +226,6 @@ void ControlBodyPart(short fxNumber) } } - EffectNewRoom(fxNumber, pointColl.RoomNumber); + EffectNewRoom(fxNumber, pointColl.GetRoomNumber()); } } \ No newline at end of file diff --git a/TombEngine/Objects/TR5/Object/tr5_missile.cpp b/TombEngine/Objects/TR5/Object/tr5_missile.cpp index 93bdbe42b..4ee9a44af 100644 --- a/TombEngine/Objects/TR5/Object/tr5_missile.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_missile.cpp @@ -2,6 +2,7 @@ #include "tr5_missile.h" #include "Game/items.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/effects.h" @@ -15,6 +16,7 @@ #include "Game/effects/item_fx.h" #include "Math/Math.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Math; @@ -106,9 +108,9 @@ void MissileControl(short itemNumber) fx->pos.Position.y += fx->speed * phd_sin(-fx->pos.Orientation.x); fx->pos.Position.z += c * phd_cos(fx->pos.Orientation.y); - auto probe = GetCollision(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, fx->roomNumber); + auto probe = GetPointCollision(fx->pos.Position, fx->roomNumber); - if (fx->pos.Position.y >= probe.Position.Floor || fx->pos.Position.y <= probe.Position.Ceiling) + if (fx->pos.Position.y >= probe.GetFloorHeight() || fx->pos.Position.y <= probe.GetCeilingHeight()) { fx->pos.Position.x = x; fx->pos.Position.y = y; @@ -182,8 +184,8 @@ void MissileControl(short itemNumber) } else { - if (probe.RoomNumber != fx->roomNumber) - EffectNewRoom(itemNumber, probe.RoomNumber); + if (probe.GetRoomNumber() != fx->roomNumber) + EffectNewRoom(itemNumber, probe.GetRoomNumber()); if (GlobalCounter & 1) { diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index 7f04f59c3..67c9b2bbd 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -15,6 +16,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + constexpr auto ROLLING_BALL_MAX_VELOCITY = BLOCK(3); void RollingBallCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) @@ -66,7 +69,7 @@ void RollingBallControl(short itemNumber) item->Pose.Position.z += item->ItemFlags[1] / hDivider; item->Animation.Velocity.z = Vector3i::Distance(item->Pose.Position, oldPos.Position); - int dh = GetCollision(item).Position.Floor - bigRadius; + int dh = GetPointCollision(*item).GetFloorHeight() - bigRadius; if (item->Pose.Position.y > dh) { @@ -106,20 +109,20 @@ void RollingBallControl(short itemNumber) int leftX = item->Pose.Position.x - smallRadius; int leftZ = item->Pose.Position.z; - auto frontFloor = GetCollision(frontX, item->Pose.Position.y, frontZ, item->RoomNumber); - auto backFloor = GetCollision(backX, item->Pose.Position.y, backZ, item->RoomNumber); - auto rightFloor = GetCollision(rightX, item->Pose.Position.y, rightZ, item->RoomNumber); - auto leftFloor = GetCollision(leftX, item->Pose.Position.y, leftZ, item->RoomNumber); + auto frontFloor = GetPointCollision(Vector3i(frontX, item->Pose.Position.y, frontZ), item->RoomNumber); + auto backFloor = GetPointCollision(Vector3i(backX, item->Pose.Position.y, backZ), item->RoomNumber); + auto rightFloor = GetPointCollision(Vector3i(rightX, item->Pose.Position.y, rightZ), item->RoomNumber); + auto leftFloor = GetPointCollision(Vector3i(leftX, item->Pose.Position.y, leftZ), item->RoomNumber); - int frontHeight = frontFloor.Position.Floor - bigRadius; - int backHeight = backFloor.Position.Floor - bigRadius; - int rightHeight = rightFloor.Position.Floor - bigRadius; - int leftHeight = leftFloor.Position.Floor - bigRadius; + int frontHeight = frontFloor.GetFloorHeight() - bigRadius; + int backHeight = backFloor.GetFloorHeight() - bigRadius; + int rightHeight = rightFloor.GetFloorHeight() - bigRadius; + int leftHeight = leftFloor.GetFloorHeight() - bigRadius; - int frontCeiling = frontFloor.Position.Ceiling + bigRadius; - int backCeiling = backFloor.Position.Ceiling + bigRadius; - int rightCeiling = rightFloor.Position.Ceiling + bigRadius; - int leftCeiling = leftFloor.Position.Ceiling + bigRadius; + int frontCeiling = frontFloor.GetCeilingHeight() + bigRadius; + int backCeiling = backFloor.GetCeilingHeight() + bigRadius; + int rightCeiling = rightFloor.GetCeilingHeight() + bigRadius; + int leftCeiling = leftFloor.GetCeilingHeight() + bigRadius; frontX = item->Pose.Position.x; frontZ = item->Pose.Position.z + bigRadius; @@ -130,20 +133,20 @@ void RollingBallControl(short itemNumber) leftX = item->Pose.Position.x - bigRadius; leftZ = item->Pose.Position.z; - auto fronFarFloor = GetCollision(frontX, item->Pose.Position.y, frontZ, item->RoomNumber); - auto backFarFloor = GetCollision(backX, item->Pose.Position.y, backZ, item->RoomNumber); - auto rightFarFloor = GetCollision(rightX, item->Pose.Position.y, rightZ, item->RoomNumber); - auto leftFarFloor = GetCollision(leftX, item->Pose.Position.y, leftZ, item->RoomNumber); + auto fronFarFloor = GetPointCollision(Vector3i(frontX, item->Pose.Position.y, frontZ), item->RoomNumber); + auto backFarFloor = GetPointCollision(Vector3i(backX, item->Pose.Position.y, backZ), item->RoomNumber); + auto rightFarFloor = GetPointCollision(Vector3i(rightX, item->Pose.Position.y, rightZ), item->RoomNumber); + auto leftFarFloor = GetPointCollision(Vector3i(leftX, item->Pose.Position.y, leftZ), item->RoomNumber); - int frontFarHeight = fronFarFloor.Position.Floor - bigRadius; - int backFarHeight = backFarFloor.Position.Floor - bigRadius; - int rightFarHeight = rightFarFloor.Position.Floor - bigRadius; - int leftFarHeight = leftFarFloor.Position.Floor - bigRadius; + int frontFarHeight = fronFarFloor.GetFloorHeight() - bigRadius; + int backFarHeight = backFarFloor.GetFloorHeight() - bigRadius; + int rightFarHeight = rightFarFloor.GetFloorHeight() - bigRadius; + int leftFarHeight = leftFarFloor.GetFloorHeight() - bigRadius; - int frontFarCeiling = fronFarFloor.Position.Ceiling + bigRadius; - int backFarCeiling = backFarFloor.Position.Ceiling + bigRadius; - int rightFarCeiling = rightFarFloor.Position.Ceiling + bigRadius; - int leftFarCeiling = leftFarFloor.Position.Ceiling + bigRadius; + int frontFarCeiling = fronFarFloor.GetCeilingHeight() + bigRadius; + int backFarCeiling = backFarFloor.GetCeilingHeight() + bigRadius; + int rightFarCeiling = rightFarFloor.GetCeilingHeight() + bigRadius; + int leftFarCeiling = leftFarFloor.GetCeilingHeight() + bigRadius; if (item->Pose.Position.y - dh > -CLICK(1) || item->Pose.Position.y - frontFarHeight >= CLICK(2) || @@ -406,12 +409,12 @@ void ClassicRollingBallControl(short itemNum) AnimateItem(item); - auto coll = GetCollision(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); + auto pointColl = GetPointCollision(*item); - item->Floor = coll.Position.Floor; + item->Floor = pointColl.GetFloorHeight(); - if (item->RoomNumber != coll.RoomNumber) - ItemNewRoom(itemNum, coll.RoomNumber); + if (item->RoomNumber != pointColl.GetRoomNumber()) + ItemNewRoom(itemNum, pointColl.GetRoomNumber()); if (item->Pose.Position.y >= item->Floor - CLICK(1)) { @@ -443,8 +446,8 @@ void ClassicRollingBallControl(short itemNum) int x = item->Pose.Position.x + dist * phd_sin(item->Pose.Orientation.y); int z = item->Pose.Position.z + dist * phd_cos(item->Pose.Orientation.y); - int y1 = GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).Position.Floor; - int y2 = GetCollision(x, item->Pose.Position.y - ydist, z, item->RoomNumber).Position.Ceiling; + int y1 = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetFloorHeight(); + int y2 = GetPointCollision(Vector3i(x, item->Pose.Position.y - ydist, z), item->RoomNumber).GetCeilingHeight(); if (y1 < item->Pose.Position.y || y2 > (item->Pose.Position.y - ydist)) { diff --git a/TombEngine/Objects/Utils/VehicleHelpers.cpp b/TombEngine/Objects/Utils/VehicleHelpers.cpp index d007215fc..d1c2a8081 100644 --- a/TombEngine/Objects/Utils/VehicleHelpers.cpp +++ b/TombEngine/Objects/Utils/VehicleHelpers.cpp @@ -2,6 +2,7 @@ #include "Objects/Utils/VehicleHelpers.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/simple_particle.h" #include "Game/effects/Streamer.h" @@ -15,6 +16,7 @@ #include "Sound/sound.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Streamer; using namespace TEN::Hud; using namespace TEN::Input; @@ -154,15 +156,15 @@ namespace TEN::Entities::Vehicles pos->z = vehicleItem->Pose.Position.z + (forward * cosY) - (right * sinY); // Get collision a bit higher to be able to detect bridges. - auto probe = GetCollision(pos->x, pos->y - CLICK(2), pos->z, vehicleItem->RoomNumber); + auto probe = GetPointCollision(Vector3i(pos->x, pos->y - CLICK(2), pos->z), vehicleItem->RoomNumber); - if (pos->y < probe.Position.Ceiling || probe.Position.Ceiling == NO_HEIGHT) + if (pos->y < probe.GetCeilingHeight() || probe.GetCeilingHeight() == NO_HEIGHT) return NO_HEIGHT; - if (pos->y > probe.Position.Floor && clamp) - pos->y = probe.Position.Floor; + if (pos->y > probe.GetFloorHeight() && clamp) + pos->y = probe.GetFloorHeight(); - return probe.Position.Floor; + return probe.GetFloorHeight(); } int GetVehicleWaterHeight(ItemInfo* vehicleItem, int forward, int right, bool clamp, Vector3i* pos) @@ -175,12 +177,12 @@ namespace TEN::Entities::Vehicles point = Vector3::Transform(point, world); *pos = Vector3i(point); - auto pointColl = GetCollision(pos->x, pos->y, pos->z, vehicleItem->RoomNumber); - int height = GetWaterHeight(pos->x, pos->y, pos->z, pointColl.RoomNumber); + auto pointColl = GetPointCollision(*pos, vehicleItem->RoomNumber); + int height = GetWaterHeight(pos->x, pos->y, pos->z, pointColl.GetRoomNumber()); if (height == NO_HEIGHT) { - height = pointColl.Position.Floor; + height = pointColl.GetFloorHeight(); if (height == NO_HEIGHT) return height; } From 4ee1dda75f41f4c4177ab2840dc4896877b40cf1 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 23 Feb 2024 20:41:22 +1100 Subject: [PATCH 058/410] Remove last remnants of GetCollision() and related structs; remove old collision functions --- TombEngine/Game/Lara/PlayerContext.cpp | 146 ++++++++-------- TombEngine/Game/Lara/PlayerContextData.h | 6 +- TombEngine/Game/Lara/lara.cpp | 2 +- TombEngine/Game/Lara/lara_collide.cpp | 6 +- TombEngine/Game/Lara/lara_helpers.cpp | 16 +- TombEngine/Game/Lara/lara_one_gun.cpp | 20 +-- TombEngine/Game/Lara/lara_one_gun.h | 1 + TombEngine/Game/Lara/lara_overhang.cpp | 8 +- TombEngine/Game/Lara/lara_tests.cpp | 162 ++++++++---------- TombEngine/Game/Lara/lara_tests.h | 2 - TombEngine/Game/collision/PointCollision.cpp | 5 +- TombEngine/Game/collision/collide_room.cpp | 50 +----- TombEngine/Game/collision/collide_room.h | 105 +++++------- TombEngine/Game/control/box.cpp | 36 ++-- TombEngine/Game/control/trigger.cpp | 8 +- TombEngine/Game/control/volume.cpp | 4 +- TombEngine/Game/control/volume.h | 4 +- TombEngine/Game/effects/bubble.cpp | 2 +- TombEngine/Game/effects/effects.cpp | 14 +- TombEngine/Game/pickup/pickup.cpp | 14 +- TombEngine/Objects/Effects/flame_emitters.cpp | 16 +- .../Object/Pushable/PushableCollision.cpp | 2 +- .../Object/Pushable/PushableObject.cpp | 2 +- .../Generic/Object/Pushable/PushableStack.cpp | 8 +- .../Objects/TR1/Entity/tr1_doppelganger.cpp | 6 +- TombEngine/Objects/TR1/Trap/DamoclesSword.cpp | 8 +- .../Objects/TR2/Trap/tr2_spinningblade.cpp | 10 +- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 34 ++-- TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 6 +- .../Objects/TR3/Entity/tr3_scuba_diver.cpp | 11 +- TombEngine/Objects/TR3/Object/corpse.cpp | 8 +- .../Objects/TR3/Trap/ElectricCleaner.cpp | 2 +- TombEngine/Objects/TR3/Trap/train.cpp | 2 +- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 24 +-- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 27 +-- TombEngine/Objects/TR3/Vehicles/quad_bike.cpp | 28 +-- TombEngine/Objects/TR4/Entity/Wraith.cpp | 18 +- .../TR4/Object/tr4_clockwork_beetle.cpp | 5 +- TombEngine/Objects/TR4/Object/tr4_mapper.cpp | 5 +- TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp | 13 +- TombEngine/Objects/TR4/Trap/SpikyWall.cpp | 26 +-- .../Objects/TR4/Trap/tr4_joby_spikes.cpp | 9 +- .../Objects/TR4/Trap/tr4_slicerdicer.cpp | 5 +- .../Objects/TR4/Trap/tr4_teethspike.cpp | 5 +- TombEngine/Objects/TR4/Vehicles/motorbike.cpp | 28 +-- .../Objects/TR5/Entity/tr5_submarine.cpp | 15 +- .../Objects/TR5/Object/tr5_rollingball.cpp | 2 +- .../TR5/Object/tr5_twoblockplatform.cpp | 11 +- TombEngine/Objects/TR5/Trap/LaserBarrier.cpp | 6 +- TombEngine/Objects/TR5/Trap/ZipLine.cpp | 10 +- .../Objects/TR5/Trap/tr5_fallingceiling.cpp | 11 +- 51 files changed, 484 insertions(+), 490 deletions(-) diff --git a/TombEngine/Game/Lara/PlayerContext.cpp b/TombEngine/Game/Lara/PlayerContext.cpp index 633ee93e8..2ba92b6cc 100644 --- a/TombEngine/Game/Lara/PlayerContext.cpp +++ b/TombEngine/Game/Lara/PlayerContext.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/floordata.h" #include "Game/control/los.h" #include "Game/items.h" @@ -14,6 +15,7 @@ #include "Specific/Input/Input.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; namespace TEN::Entities::Player @@ -35,8 +37,8 @@ namespace TEN::Entities::Player const auto& player = GetLaraInfo(item); // Get point collision. - auto pointColl = GetCollision(&item, 0, 0, -coll.Setup.Height / 2); // NOTE: Height offset required for correct bridge collision. - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; + auto pointColl = GetPointCollision(item, 0, 0, -coll.Setup.Height / 2); // NOTE: Height offset required for correct bridge collision. + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; // 1) Test if player is already aligned with floor. if (relFloorHeight == 0) @@ -61,8 +63,8 @@ namespace TEN::Entities::Player constexpr auto UPPER_FLOOR_BOUND_DOWN = CLICK(0.75f); // Get point collision. - auto pointColl = GetCollision(&item, 0, 0, -coll.Setup.Height / 2); // NOTE: Height offset required for correct bridge collision. - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; + auto pointColl = GetPointCollision(item, 0, 0, -coll.Setup.Height / 2); // NOTE: Height offset required for correct bridge collision. + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; // Determine appropriate floor bounds. int lowerFloorBound = isGoingUp ? LOWER_FLOOR_BOUND_UP : LOWER_FLOOR_BOUND_DOWN; @@ -167,30 +169,30 @@ namespace TEN::Entities::Player int playerHeight = isCrawling ? LARA_HEIGHT_CRAWL : coll.Setup.Height; // Get point collision. - auto pointColl = GetCollision(&item, setup.HeadingAngle, OFFSET_RADIUS(playerRadius), -playerHeight); + auto pointColl = GetPointCollision(item, setup.HeadingAngle, OFFSET_RADIUS(playerRadius), -playerHeight); int vPos = item.Pose.Position.y; int vPosTop = vPos - playerHeight; // Calculate slope aspect delta angle. - short aspectAngle = Geometry::GetSurfaceAspectAngle(pointColl.FloorNormal); + short aspectAngle = Geometry::GetSurfaceAspectAngle(pointColl.GetFloorNormal()); short aspectAngleDelta = Geometry::GetShortestAngle(setup.HeadingAngle, aspectAngle); - // 1) Check for slippery slope below floor (if applicable). - if (setup.TestSlipperySlopeBelow && - (pointColl.Position.FloorSlope && abs(aspectAngleDelta) <= SLOPE_ASPECT_ANGLE_DELTA_MAX)) + // 1) Check for illegal slope below floor (if applicable). + if (setup.TestIllegalFloorBelow && + (pointColl.IsIllegalFloor() && abs(aspectAngleDelta) <= SLOPE_ASPECT_ANGLE_DELTA_MAX)) { return false; } - // 1) Check for slippery slope above floor (if applicable). - if (setup.TestSlipperySlopeAbove && - (pointColl.Position.FloorSlope && abs(aspectAngleDelta) >= SLOPE_ASPECT_ANGLE_DELTA_MAX)) + // 1) Check for illegal slope above floor (if applicable). + if (setup.TestIllegalFloorAbove && + (pointColl.IsIllegalFloor() && abs(aspectAngleDelta) >= SLOPE_ASPECT_ANGLE_DELTA_MAX)) { return false; } // 3) Check for death floor (if applicable). - if (setup.TestDeathFloor && pointColl.Block->Flags.Death) + if (setup.TestDeathFloor && pointColl.GetSector().Flags.Death) return false; // LOS setup at upper floor bound. @@ -200,9 +202,9 @@ namespace TEN::Entities::Player item.Pose.Position.z, item.RoomNumber); auto target0 = GameVector( - pointColl.Coordinates.x, + pointColl.GetPosition().x, (vPos + setup.UpperFloorBound) - 1, - pointColl.Coordinates.z, + pointColl.GetPosition().z, item.RoomNumber); // LOS setup at lowest ceiling bound (player height). @@ -212,9 +214,9 @@ namespace TEN::Entities::Player item.Pose.Position.z, item.RoomNumber); auto target1 = GameVector( - pointColl.Coordinates.x, + pointColl.GetPosition().x, vPosTop + 1, - pointColl.Coordinates.z, + pointColl.GetPosition().z, item.RoomNumber); // Calculate LOS direction. @@ -232,9 +234,9 @@ namespace TEN::Entities::Player if (!LOS(&origin0, &target0) || !LOS(&origin1, &target1)) return false; - int relFloorHeight = pointColl.Position.Floor - vPos; - int relCeilHeight = pointColl.Position.Ceiling - vPos; - int floorToCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + int relFloorHeight = pointColl.GetFloorHeight() - vPos; + int relCeilHeight = pointColl.GetCeilingHeight() - vPos; + int floorToCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); // 6) Assess point collision. if (relFloorHeight <= setup.LowerFloorBound && // Floor height is above lower floor bound. @@ -400,12 +402,12 @@ namespace TEN::Entities::Player return false; // Get point collision. - auto pointColl = GetCollision(&item, 0, 0, -coll.Setup.Height / 2); // NOTE: Offset required for correct bridge collision. - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; + auto pointColl = GetPointCollision(item, 0, 0, -coll.Setup.Height / 2); // NOTE: Offset required for correct bridge collision. + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; // 2) Assess point collision. if (abs(relFloorHeight) <= ABS_FLOOR_BOUND && // Floor height is within upper/lower floor bounds. - pointColl.Position.FloorSlope) // Floor is a slippery slope. + pointColl.IsIllegalFloor()) // Floor is a slippery slope. { return true; } @@ -432,8 +434,8 @@ namespace TEN::Entities::Player float radius = TestState(item.Animation.ActiveState, CROUCH_STATES) ? LARA_RADIUS_CRAWL : LARA_RADIUS; // Get center point collision. - auto pointCollCenter = GetCollision(&item, 0, 0.0f, -LARA_HEIGHT / 2); - int floorToCeilHeightCenter = abs(pointCollCenter.Position.Ceiling - pointCollCenter.Position.Floor); + auto pointCollCenter = GetPointCollision(item, 0, 0.0f, -LARA_HEIGHT / 2); + int floorToCeilHeightCenter = abs(pointCollCenter.GetCeilingHeight() - pointCollCenter.GetFloorHeight()); // Assess center point collision. if (floorToCeilHeightCenter < LARA_HEIGHT || // Floor-to-ceiling height isn't too wide. @@ -445,9 +447,9 @@ namespace TEN::Entities::Player // TODO: Check whether < or <= and > or >=. // Get front point collision. - auto pointCollFront = GetCollision(&item, item.Pose.Orientation.y, radius, -coll.Setup.Height); - int floorToCeilHeightFront = abs(pointCollFront.Position.Ceiling - pointCollFront.Position.Floor); - int relFloorHeightFront = abs(pointCollFront.Position.Floor - pointCollCenter.Position.Floor); + auto pointCollFront = GetPointCollision(item, item.Pose.Orientation.y, radius, -coll.Setup.Height); + int floorToCeilHeightFront = abs(pointCollFront.GetCeilingHeight() - pointCollFront.GetFloorHeight()); + int relFloorHeightFront = abs(pointCollFront.GetFloorHeight() - pointCollCenter.GetFloorHeight()); // Assess front point collision. if (relFloorHeightFront <= CRAWL_STEPUP_HEIGHT && // Floor is within upper/lower floor bounds. @@ -458,9 +460,9 @@ namespace TEN::Entities::Player } // Get back point collision. - auto pointCollBack = GetCollision(&item, item.Pose.Orientation.y, -radius, -coll.Setup.Height); - int floorToCeilHeightBack = abs(pointCollBack.Position.Ceiling - pointCollBack.Position.Floor); - int relFloorHeightBack = abs(pointCollBack.Position.Floor - pointCollCenter.Position.Floor); + auto pointCollBack = GetPointCollision(item, item.Pose.Orientation.y, -radius, -coll.Setup.Height); + int floorToCeilHeightBack = abs(pointCollBack.GetCeilingHeight() - pointCollBack.GetFloorHeight()); + int relFloorHeightBack = abs(pointCollBack.GetFloorHeight() - pointCollCenter.GetFloorHeight()); // Assess back point collision. if (relFloorHeightBack <= CRAWL_STEPUP_HEIGHT && // Floor is within upper/lower floor bounds. @@ -526,22 +528,22 @@ namespace TEN::Entities::Player // TODO: Extend point collision struct to also find water depths. float dist = 0.0f; - auto pointColl0 = GetCollision(&item); + auto pointColl0 = GetPointCollision(item); // 3) Test continuity of path. while (dist < PROBE_DIST_MAX) { // Get point collision. dist += STEP_DIST; - auto pointColl1 = GetCollision(&item, item.Pose.Orientation.y, dist, -LARA_HEIGHT_CRAWL); + auto pointColl1 = GetPointCollision(item, item.Pose.Orientation.y, dist, -LARA_HEIGHT_CRAWL); - int floorHeightDelta = abs(pointColl0.Position.Floor - pointColl1.Position.Floor); - int floorToCeilHeight = abs(pointColl1.Position.Ceiling - pointColl1.Position.Floor); + int floorHeightDelta = abs(pointColl0.GetFloorHeight() - pointColl1.GetFloorHeight()); + int floorToCeilHeight = abs(pointColl1.GetCeilingHeight() - pointColl1.GetFloorHeight()); // Assess point collision. if (floorHeightDelta > FLOOR_BOUND || // Avoid floor height delta beyond crawl stepup threshold. floorToCeilHeight <= FLOOR_TO_CEIL_HEIGHT_MAX || // Avoid narrow spaces. - pointColl1.Position.FloorSlope) // Avoid slippery floor slopes. + pointColl1.IsIllegalFloor()) // Avoid slippery floor slopes. { return false; } @@ -580,8 +582,8 @@ namespace TEN::Entities::Player constexpr auto UPPER_CEIL_BOUND = -MONKEY_STEPUP_HEIGHT; // Get point collision. - auto pointColl = GetCollision(&item); - int relCeilHeight = pointColl.Position.Ceiling - (item.Pose.Position.y - LARA_HEIGHT_MONKEY); + auto pointColl = GetPointCollision(item); + int relCeilHeight = pointColl.GetCeilingHeight() - (item.Pose.Position.y - LARA_HEIGHT_MONKEY); // Assess point collision. if (relCeilHeight <= LOWER_CEIL_BOUND && // Ceiling height is above lower ceiling bound. @@ -604,14 +606,14 @@ namespace TEN::Entities::Player return true; // Get point collision. - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); // 2) Test for slippery ceiling slope and check if overhang climb is disabled. - if (pointColl.Position.CeilingSlope && !g_GameFlow->HasOverhangClimb()) + if (pointColl.IsIllegalCeiling() && !g_GameFlow->HasOverhangClimb()) return true; // 3) Assess point collision. - int relCeilHeight = pointColl.Position.Ceiling - (item.Pose.Position.y - LARA_HEIGHT_MONKEY); + int relCeilHeight = pointColl.GetCeilingHeight() - (item.Pose.Position.y - LARA_HEIGHT_MONKEY); if (abs(relCeilHeight) > ABS_CEIL_BOUND) // Ceiling height is within lower/upper ceiling bound. return true; @@ -630,9 +632,9 @@ namespace TEN::Entities::Player return false; // Get point collision. - auto pointColl = GetCollision(&item); - int relCeilHeight = pointColl.Position.Ceiling - (item.Pose.Position.y - LARA_HEIGHT_MONKEY); - int floorToCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + auto pointColl = GetPointCollision(item); + int relCeilHeight = pointColl.GetCeilingHeight() - (item.Pose.Position.y - LARA_HEIGHT_MONKEY); + int floorToCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); // 2) Assess collision with ceiling. if (relCeilHeight < 0 && @@ -658,14 +660,14 @@ namespace TEN::Entities::Player constexpr auto PLAYER_HEIGHT = LARA_HEIGHT_MONKEY; // Get point collision. - auto pointColl = GetCollision(&item, setup.HeadingAngle, OFFSET_RADIUS(coll.Setup.Radius)); + auto pointColl = GetPointCollision(item, setup.HeadingAngle, OFFSET_RADIUS(coll.Setup.Radius)); // 1) Test if ceiling is monkey swing. - if (!pointColl.BottomBlock->Flags.Monkeyswing) + if (!pointColl.GetBottomSector().Flags.Monkeyswing) return false; - // 2) Test for ceiling slippery slope. - if (pointColl.Position.CeilingSlope) + // 2) Test for illegal ceiling. + if (pointColl.IsIllegalCeiling()) return false; int vPos = item.Pose.Position.y; @@ -678,9 +680,9 @@ namespace TEN::Entities::Player item.Pose.Position.z, item.RoomNumber); auto target0 = GameVector( - pointColl.Coordinates.x, + pointColl.GetPosition().x, vPos - 1, - pointColl.Coordinates.z, + pointColl.GetPosition().z, item.RoomNumber); // Raycast setup at lower ceiling bound. @@ -690,9 +692,9 @@ namespace TEN::Entities::Player item.Pose.Position.z, item.RoomNumber); auto target1 = GameVector( - pointColl.Coordinates.x, + pointColl.GetPosition().x, (vPosTop + setup.LowerCeilingBound) + 1, - pointColl.Coordinates.z, + pointColl.GetPosition().z, item.RoomNumber); // Prepare data for static object LOS. @@ -712,9 +714,9 @@ namespace TEN::Entities::Player // TODO: Assess static object geometry ray collision. - int relFloorHeight = pointColl.Position.Floor - vPos; - int relCeilHeight = pointColl.Position.Ceiling - vPosTop; - int floorToCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); + int relFloorHeight = pointColl.GetFloorHeight() - vPos; + int relCeilHeight = pointColl.GetCeilingHeight() - vPosTop; + int floorToCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); // 4) Assess point collision. if (relFloorHeight > 0 && // Floor is within highest floor bound (player base). @@ -782,8 +784,8 @@ namespace TEN::Entities::Player return false; // Get point collision. - auto pointColl = GetCollision(&item, 0, 0, -coll.Setup.Height / 2); - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; + auto pointColl = GetPointCollision(item, 0, 0, -coll.Setup.Height / 2); + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; // 2) Assess point collision. if (relFloorHeight > UPPER_FLOOR_BOUND) // Floor height is below upper floor bound. @@ -805,11 +807,11 @@ namespace TEN::Entities::Player return true; // Get point collision. - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); int vPos = item.Pose.Position.y; // 3) Assess point collision. - if ((pointColl.Position.Floor - vPos) <= projVerticalVel) // Floor height is above projected vertical position. + if ((pointColl.GetFloorHeight() - vPos) <= projVerticalVel) // Floor height is above projected vertical position. return true; return false; @@ -848,9 +850,9 @@ namespace TEN::Entities::Player return false;*/ // Get point collision. - auto pointColl = GetCollision(&item, setup.HeadingAngle, setup.Distance, -coll.Setup.Height); - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; - int relCeilHeight = pointColl.Position.Ceiling - item.Pose.Position.y; + auto pointColl = GetPointCollision(item, setup.HeadingAngle, setup.Distance, -coll.Setup.Height); + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; + int relCeilHeight = pointColl.GetCeilingHeight() - item.Pose.Position.y; // 4) Assess point collision. if (relFloorHeight >= -STEPUP_HEIGHT && // Floor is within highest floor bound. @@ -923,11 +925,11 @@ namespace TEN::Entities::Player return IsRunJumpQueueableState(item.Animation.TargetState); // Get point collision. - auto pointColl = GetCollision(&item, item.Pose.Orientation.y, BLOCK(1), -coll.Setup.Height); + auto pointColl = GetPointCollision(item, item.Pose.Orientation.y, BLOCK(1), -coll.Setup.Height); int lowerCeilingBound = (LOWER_CEIL_BOUND_BASE - coll.Setup.Height); - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; - int relCeilHeight = pointColl.Position.Ceiling - item.Pose.Position.y; + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; + int relCeilHeight = pointColl.GetCeilingHeight() - item.Pose.Position.y; // 2) Assess point collision for possible running jump ahead. if (relCeilHeight < lowerCeilingBound || // Ceiling height is above lower ceiling bound. @@ -993,7 +995,7 @@ namespace TEN::Entities::Player // TODO: Broken on diagonal slides? - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); //short aspectAngle = GetLaraSlideHeadingAngle(item, coll); //short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetSurfaceNormal(pointColl.FloorTilt, true)); @@ -1002,8 +1004,8 @@ namespace TEN::Entities::Player bool CanCrawlspaceDive(const ItemInfo& item, const CollisionInfo& coll) { - auto pointColl = GetCollision(&item, coll.Setup.ForwardAngle, coll.Setup.Radius, -coll.Setup.Height); - return (abs(pointColl.Position.Ceiling - pointColl.Position.Floor) < LARA_HEIGHT || IsInLowSpace(item, coll)); + auto pointColl = GetPointCollision(item, coll.Setup.ForwardAngle, coll.Setup.Radius, -coll.Setup.Height); + return (abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()) < LARA_HEIGHT || IsInLowSpace(item, coll)); } bool CanPerformLedgeJump(const ItemInfo& item, const CollisionInfo& coll) @@ -1031,8 +1033,8 @@ namespace TEN::Entities::Player // TODO: Assess static object geometry ray collision. // Get point collision. - auto pointColl = GetCollision(&item); - int relCeilHeight = pointColl.Position.Ceiling - (item.Pose.Position.y - LARA_HEIGHT_STRETCH); + auto pointColl = GetPointCollision(item); + int relCeilHeight = pointColl.GetCeilingHeight() - (item.Pose.Position.y - LARA_HEIGHT_STRETCH); // 3) Assess point collision. if (relCeilHeight >= -coll.Setup.Height) // Ceiling height is below upper ceiling bound. @@ -1045,10 +1047,10 @@ namespace TEN::Entities::Player { const auto& player = GetLaraInfo(item); - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); if (player.Control.Tightrope.CanDismount && // Dismount is allowed. - pointColl.Position.Floor == item.Pose.Position.y) // Floor is level with player. + pointColl.GetFloorHeight() == item.Pose.Position.y) // Floor is level with player. { return true; } diff --git a/TombEngine/Game/Lara/PlayerContextData.h b/TombEngine/Game/Lara/PlayerContextData.h index c53dcbd8b..8e3b315e2 100644 --- a/TombEngine/Game/Lara/PlayerContextData.h +++ b/TombEngine/Game/Lara/PlayerContextData.h @@ -8,9 +8,9 @@ namespace TEN::Entities::Player int LowerFloorBound = 0; int UpperFloorBound = 0; - bool TestSlipperySlopeBelow = true; - bool TestSlipperySlopeAbove = true; - bool TestDeathFloor = true; + bool TestIllegalFloorBelow = true; + bool TestIllegalFloorAbove = true; + bool TestDeathFloor = true; }; struct MonkeySwingMovementSetupData diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 128ce7143..9268b5f46 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -404,7 +404,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) if (DebugMode) { - DrawNearbyPathfinding(GetCollision(item).BottomBlock->Box); + DrawNearbyPathfinding(GetPointCollision(*item).GetBottomSector().Box); DrawNearbySectorFlags(*item); } } diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index 26d6cfa2e..358dc2c1d 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -19,6 +20,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Scripting/Include/ScriptInterfaceLevel.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Player; using namespace TEN::Input; @@ -486,10 +488,10 @@ void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll) item->Pose.Orientation.y -= ANGLE(5.0f); } - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(*item); int waterHeight = GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); - if ((pointColl.Position.Floor - item->Pose.Position.y) < SWIM_WATER_DEPTH) + if ((pointColl.GetFloorHeight() - item->Pose.Position.y) < SWIM_WATER_DEPTH) TestPlayerWaterStepOut(item, coll); } diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 9f1712f07..51c6dbe79 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -162,9 +162,9 @@ void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWa const auto& vehicleItem = g_Level.Items[player.Context.Vehicle]; if (vehicleItem.ObjectNumber == ID_UPV) { - auto pointColl = GetCollision(&item, 0, 0, CLICK(1)); + auto pointColl = GetPointCollision(item, 0, 0, CLICK(1)); - water.IsCold = (water.IsCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber)); + water.IsCold = (water.IsCold || TestEnvironment(ENV_FLAG_COLD, pointColl.GetRoomNumber())); if (water.IsCold) { player.Status.Exposure--; @@ -1324,20 +1324,20 @@ static short GetLegacySlideHeadingAngle(const Vector3& floorNormal) short GetPlayerSlideHeadingAngle(ItemInfo* item, CollisionInfo* coll) { short headingAngle = coll->Setup.ForwardAngle; - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(*item); // Ground is flat. - if (pointColl.FloorTilt == Vector2::Zero) + if (pointColl.GetFloorNormal() == -Vector3::UnitY) return coll->Setup.ForwardAngle; // Return slide heading angle. if (g_GameFlow->HasSlideExtended()) { - return Geometry::GetSurfaceAspectAngle(pointColl.FloorNormal); + return Geometry::GetSurfaceAspectAngle(pointColl.GetFloorNormal()); } else { - return GetLegacySlideHeadingAngle(pointColl.FloorNormal); + return GetLegacySlideHeadingAngle(pointColl.GetFloorNormal()); } } @@ -1526,7 +1526,7 @@ void ModulateLaraSlideVelocity(ItemInfo* item, CollisionInfo* coll) if (g_GameFlow->HasSlideExtended()) { - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); short minSlideAngle = ANGLE(33.75f); //short steepness = Geometry::GetSurfaceSlopeAngle(probe.FloorTilt); //short direction = Geometry::GetSurfaceAspectAngle(probe.FloorTilt); @@ -1547,7 +1547,7 @@ void ModulateLaraSlideVelocity(ItemInfo* item, CollisionInfo* coll) void AlignLaraToSurface(ItemInfo* item, float alpha) { // Determine relative orientation adhering to floor normal. - auto floorNormal = GetCollision(item).FloorNormal; + auto floorNormal = GetPointCollision(*item).GetFloorNormal(); auto orient = Geometry::GetRelOrientToNormal(item->Pose.Orientation.y, floorNormal); // Apply extra rotation according to alpha. diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index b9917a70f..aa16a6d1a 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -1422,20 +1422,20 @@ bool EmitFromProjectile(ItemInfo& projectile, ProjectileType type) return true; } -bool TestProjectileNewRoom(ItemInfo& item, const CollisionResult& coll) +bool TestProjectileNewRoom(ItemInfo& item, PointCollisionData& pointColl) { // Check if projectile changed room. - if (item.RoomNumber == coll.RoomNumber) + if (item.RoomNumber == pointColl.GetRoomNumber()) return false; // If currently in water and previously on land, spawn ripple. - if (TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) != TestEnvironment(ENV_FLAG_WATER, coll.RoomNumber)) + if (TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) != TestEnvironment(ENV_FLAG_WATER, pointColl.GetRoomNumber())) { const auto& player = GetLaraInfo(item); - int floorDiff = abs(coll.Position.Floor - item.Pose.Position.y); - int ceilingDiff = abs(coll.Position.Ceiling - item.Pose.Position.y); - int yPoint = (floorDiff > ceilingDiff) ? coll.Position.Ceiling : coll.Position.Floor; + int floorDiff = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); + int ceilingDiff = abs(pointColl.GetCeilingHeight() - item.Pose.Position.y); + int yPoint = (floorDiff > ceilingDiff) ? pointColl.GetCeilingHeight() : pointColl.GetFloorHeight(); if (player.Control.Weapon.GunType != LaraWeaponType::GrenadeLauncher && player.Control.Weapon.GunType != LaraWeaponType::RocketLauncher) { @@ -1451,7 +1451,7 @@ bool TestProjectileNewRoom(ItemInfo& item, const CollisionResult& coll) } } - ItemNewRoom(item.Index, coll.RoomNumber); + ItemNewRoom(item.Index, pointColl.GetRoomNumber()); return true; } @@ -1479,7 +1479,7 @@ void ExplodeProjectile(ItemInfo& item, const Vector3i& prevPos) void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& prevPos, ProjectileType type, int damage) { - auto pointColl = GetCollision(&projectile); + auto pointColl = GetPointCollision(projectile); bool hasHit = false; bool hasHitNotByEmitter = false; @@ -1489,8 +1489,8 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p // For non-grenade projectiles, check for room collision. if (type < ProjectileType::Grenade) { - if (pointColl.Position.Floor < projectile.Pose.Position.y || - pointColl.Position.Ceiling > projectile.Pose.Position.y) + if (pointColl.GetFloorHeight() < projectile.Pose.Position.y || + pointColl.GetCeilingHeight() > projectile.Pose.Position.y) { hasHit = hasHitNotByEmitter = true; } diff --git a/TombEngine/Game/Lara/lara_one_gun.h b/TombEngine/Game/Lara/lara_one_gun.h index 382d76567..b583b7eba 100644 --- a/TombEngine/Game/Lara/lara_one_gun.h +++ b/TombEngine/Game/Lara/lara_one_gun.h @@ -39,6 +39,7 @@ void HarpoonBoltControl(short itemNumber); void FireGrenade(ItemInfo& laraItem); void GrenadeControl(short itemNumber); void FireRocket(ItemInfo& laraItem); +void FireRocket(ItemInfo& laraItem); void RocketControl(short itemNumber); void FireCrossbow(ItemInfo& laraItem, const std::optional& pose = std::nullopt); void FireCrossBowFromLaserSight(ItemInfo& laraItem, GameVector* origin, GameVector* target); diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index a558b4035..a9b81c427 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -371,7 +371,7 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) if (GetClimbFlags(&probeUp.GetBottomSector()) & slopeData.ClimbOrient && InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, CLICK(3), CLICK(4))) { - //if (GetCollision(probeUp.Block, up.x, up.y, up.z).GetCeilingHeight() - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there. + //if (GetPointCollision(probeUp.Block, up.x, up.y, up.z).GetCeilingHeight() - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there. //{ // AlignToEdge(item, FORWARD_ALIGNMENT); // SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONVEX_START); @@ -416,7 +416,7 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll) } else if (IsHeld(In::Back)) { - //if ((GetClimbFlags(GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).BottomBlock) & slopeData.ClimbOrient) && + //if ((GetClimbFlags(GetPointCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).BottomBlock) & slopeData.ClimbOrient) && // InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, 0, CLICK(1))) //{ // AlignToEdge(item, BACKWARD_ALIGNMENT); @@ -1076,7 +1076,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { lara->Context.NextCornerPos.Orientation.z = AlignToGrab(item); - /*int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).GetCeilingHeight(); + /*int ceiling = GetPointCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).GetCeilingHeight(); item->Pose.Position.y = ceiling + HEIGHT_ADJUST;*/ SetAnimation(item, LA_OVERHANG_HANG_SWING); @@ -1094,7 +1094,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { /*if (probeDown.BottomBlock->Flags.Monkeyswing) { - int ceiling = GetCollision(probeDown.Block, down.x, now.y, down.z).GetCeilingHeight(); + int ceiling = GetPointCollision(probeDown.Block, down.x, now.y, down.z).GetCeilingHeight(); int yDiff = ceiling - probeNow.GetCeilingHeight(); int height; diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index ce6a61776..40e83998b 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -452,7 +452,7 @@ bool TestLaraClimbIdle(ItemInfo* item, CollisionInfo* coll) bool TestLaraNearClimbableWall(ItemInfo* item, FloorInfo* floor) { if (floor == nullptr) - floor = GetCollision(item).BottomBlock; + floor = &GetPointCollision(*item).GetBottomSector(); return ((256 << (GetQuadrant(item->Pose.Orientation.y))) & GetClimbFlags(floor)); } @@ -525,7 +525,7 @@ bool TestLaraValidHangPosition(ItemInfo* item, CollisionInfo* coll) // Get incoming ledge height and own Lara's upper bound. // First one will be negative while first one is positive. // Difference between two indicates difference in height between ledges. - auto frontFloor = GetCollision(item, lara->Control.MoveAngle, coll->Setup.Radius + CLICK(0.5f), -LARA_HEIGHT).Position.Floor; + auto frontFloor = GetPointCollision(*item, lara->Control.MoveAngle, coll->Setup.Radius + CLICK(0.5f), -LARA_HEIGHT).GetFloorHeight(); auto laraUpperBound = item->Pose.Position.y - coll->Setup.Height; // If difference is above 1/2 click, return false (ledge is out of reach). @@ -584,7 +584,7 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng item->Pose = cornerResult.RealPositionResult; lara->Context.NextCornerPos.Position = Vector3i( item->Pose.Position.x, - GetCollision(item, item->Pose.Orientation.y, coll->Setup.Radius + 16, -(coll->Setup.Height + CLICK(0.5f))).Position.Floor + abs(bounds.Y1), + GetPointCollision(*item, item->Pose.Orientation.y, coll->Setup.Radius + 16, -(coll->Setup.Height + CLICK(0.5f))).GetFloorHeight() + abs(bounds.Y1), item->Pose.Position.z ); lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y; @@ -642,7 +642,7 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng // Store next position item->Pose = cornerResult.RealPositionResult; lara->Context.NextCornerPos.Position.x = item->Pose.Position.x; - lara->Context.NextCornerPos.Position.y = GetCollision(item, item->Pose.Orientation.y, coll->Setup.Radius * 1.25f, -(abs(bounds.Y1) + LARA_HEADROOM)).Position.Floor + abs(bounds.Y1); + lara->Context.NextCornerPos.Position.y = GetPointCollision(*item, item->Pose.Orientation.y, coll->Setup.Radius * 1.25f, -(abs(bounds.Y1) + LARA_HEADROOM)).GetFloorHeight() + abs(bounds.Y1); lara->Context.NextCornerPos.Position.z = item->Pose.Position.z; lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y; lara->Control.MoveAngle = item->Pose.Orientation.y; @@ -747,11 +747,11 @@ bool TestHangSwingIn(ItemInfo* item, CollisionInfo* coll) auto* lara = GetLaraInfo(item); int y = item->Pose.Position.y; - auto probe = GetCollision(item, item->Pose.Orientation.y, OFFSET_RADIUS(coll->Setup.Radius)); + auto probe = GetPointCollision(*item, item->Pose.Orientation.y, OFFSET_RADIUS(coll->Setup.Radius)); - if ((probe.Position.Floor - y) > 0 && - (probe.Position.Ceiling - y) < -CLICK(1.6f) && - probe.Position.Floor != NO_HEIGHT) + if ((probe.GetFloorHeight() - y) > 0 && + (probe.GetCeilingHeight() - y) < -CLICK(1.6f) && + probe.GetFloorHeight() != NO_HEIGHT) { return true; } @@ -854,32 +854,22 @@ bool LaraPositionOnLOS(ItemInfo* item, short angle, int distance) int LaraFloorFront(ItemInfo* item, short angle, int distance) { - return LaraCollisionFront(item, angle, distance).Position.Floor; + auto pointColl = GetPointCollision(*item, angle, distance, -LARA_HEIGHT); + + if (pointColl.GetFloorHeight() == NO_HEIGHT) + return pointColl.GetFloorHeight(); + + return (pointColl.GetFloorHeight() - item->Pose.Position.y); } int LaraCeilingFront(ItemInfo* item, short angle, int distance, int height) { - return LaraCeilingCollisionFront(item, angle, distance, height).Position.Ceiling; -} + auto pointColl = GetPointCollision(*item, angle, distance, -height); -CollisionResult LaraCollisionFront(ItemInfo* item, short angle, int distance) -{ - auto probe = GetCollision(item, angle, distance, -LARA_HEIGHT); + if (pointColl.GetCeilingHeight() == NO_HEIGHT) + return pointColl.GetCeilingHeight(); - if (probe.Position.Floor != NO_HEIGHT) - probe.Position.Floor -= item->Pose.Position.y; - - return probe; -} - -CollisionResult LaraCeilingCollisionFront(ItemInfo* item, short angle, int distance, int height) -{ - auto probe = GetCollision(item, angle, distance, -height); - - if (probe.Position.Ceiling != NO_HEIGHT) - probe.Position.Ceiling += height - item->Pose.Position.y; - - return probe; + return ((pointColl.GetCeilingHeight() + height) - item->Pose.Position.y); } bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll) @@ -887,17 +877,17 @@ bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll) auto& player = GetLaraInfo(*item); // Get point collision. - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(*item); int vPos = item->Pose.Position.y; if (coll->CollisionType == CT_FRONT || - pointColl.Position.FloorSlope || - (pointColl.Position.Floor - vPos) <= 0) + pointColl.IsIllegalFloor() || + (pointColl.GetFloorHeight() - vPos) <= 0) { return false; } - if ((pointColl.Position.Floor - vPos) >= -CLICK(0.5f)) + if ((pointColl.GetFloorHeight() - vPos) >= -CLICK(0.5f)) { SetAnimation(item, LA_STAND_IDLE); } @@ -907,7 +897,7 @@ bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll) item->Animation.TargetState = LS_IDLE; } - item->Pose.Position.y = pointColl.Position.Floor; + item->Pose.Position.y = pointColl.GetFloorHeight(); UpdateLaraRoom(item, -(STEPUP_HEIGHT - 3)); ResetPlayerLean(item); @@ -963,8 +953,8 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) if (coll->HitStatic) return false; - auto probe = GetCollision(item, coll->Setup.ForwardAngle, CLICK(2), -CLICK(1)); - int headroom = probe.Position.Floor - probe.Position.Ceiling; + auto probe = GetPointCollision(*item, coll->Setup.ForwardAngle, CLICK(2), -CLICK(1)); + int headroom = probe.GetFloorHeight() - probe.GetCeilingHeight(); if (frontFloor <= -CLICK(1)) { @@ -1097,8 +1087,8 @@ void TestLaraWaterDepth(ItemInfo* item, CollisionInfo* coll) { auto& player = GetLaraInfo(*item); - auto pointColl = GetCollision(item); - int waterDepth = GetWaterDepth(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, pointColl.RoomNumber); + auto pointColl = GetPointCollision(*item); + int waterDepth = GetWaterDepth(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, pointColl.GetRoomNumber()); if (waterDepth == NO_HEIGHT) { @@ -1111,7 +1101,7 @@ void TestLaraWaterDepth(ItemInfo* item, CollisionInfo* coll) SetAnimation(item, LA_UNDERWATER_TO_STAND); ResetPlayerLean(item); item->Animation.TargetState = LS_IDLE; - item->Pose.Position.y = pointColl.Position.Floor; + item->Pose.Position.y = pointColl.GetFloorHeight(); item->Animation.IsAirborne = false; item->Animation.Velocity.y = 0.0f; item->Animation.Velocity.z = 0.0f; @@ -1204,12 +1194,12 @@ std::optional TestLaraVaultTolerance(ItemInfo* item, CollisionI auto* lara = GetLaraInfo(item); int distance = OFFSET_RADIUS(coll->Setup.Radius); - auto probeFront = GetCollision(item, coll->NearestLedgeAngle, distance, -coll->Setup.Height); - auto probeMiddle = GetCollision(item); + auto probeFront = GetPointCollision(*item, coll->NearestLedgeAngle, distance, -coll->Setup.Height); + auto probeMiddle = GetPointCollision(*item); bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, item); bool swampTooDeep = testSetup.CheckSwampDepth ? (isSwamp && lara->Context.WaterSurfaceDist < -CLICK(3)) : isSwamp; - int y = isSwamp ? item->Pose.Position.y : probeMiddle.Position.Floor; // HACK: Avoid cheese when in the midst of performing a step. Can be done better. @Sezz 2022.04.08 + int y = isSwamp ? item->Pose.Position.y : probeMiddle.GetFloorHeight(); // HACK: Avoid cheese when in the midst of performing a step. Can be done better. @Sezz 2022.04.08 // Check swamp depth (if applicable). if (swampTooDeep) @@ -1222,27 +1212,27 @@ std::optional TestLaraVaultTolerance(ItemInfo* item, CollisionI // Raise y position of point/room probe by increments of CLICK(0.5f) to find potential vault ledge. int yOffset = testSetup.LowerFloorBound; - while (((probeFront.Position.Ceiling - y) > -coll->Setup.Height || // Ceiling is below Lara's height... - abs(probeFront.Position.Ceiling - probeFront.Position.Floor) <= testSetup.ClampMin || // OR clamp is too small - abs(probeFront.Position.Ceiling - probeFront.Position.Floor) > testSetup.ClampMax) && // OR clamp is too large (future-proofing; not possible right now). + while (((probeFront.GetCeilingHeight() - y) > -coll->Setup.Height || // Ceiling is below Lara's height... + abs(probeFront.GetCeilingHeight() - probeFront.GetFloorHeight()) <= testSetup.ClampMin || // OR clamp is too small + abs(probeFront.GetCeilingHeight() - probeFront.GetFloorHeight()) > testSetup.ClampMax) && // OR clamp is too large (future-proofing; not possible right now). yOffset > (testSetup.UpperFloorBound - coll->Setup.Height)) // Offset is not too high. { - probeFront = GetCollision(item, coll->NearestLedgeAngle, distance, yOffset); + probeFront = GetPointCollision(*item, coll->NearestLedgeAngle, distance, yOffset); yOffset -= std::max(CLICK(0.5f), testSetup.ClampMin); } // Discard walls. - if (probeFront.Position.Floor == NO_HEIGHT) + if (probeFront.GetFloorHeight() == NO_HEIGHT) return std::nullopt; // Assess point/room collision. - if ((probeFront.Position.Floor - y) < testSetup.LowerFloorBound && // Within lower floor bound. - (probeFront.Position.Floor - y) >= testSetup.UpperFloorBound && // Within upper floor bound. - abs(probeFront.Position.Ceiling - probeFront.Position.Floor) > testSetup.ClampMin && // Within clamp min. - abs(probeFront.Position.Ceiling - probeFront.Position.Floor) <= testSetup.ClampMax && // Within clamp max. - abs(probeMiddle.Position.Ceiling - probeFront.Position.Floor) >= testSetup.GapMin) // Gap is optically permissive. + if ((probeFront.GetFloorHeight() - y) < testSetup.LowerFloorBound && // Within lower floor bound. + (probeFront.GetFloorHeight() - y) >= testSetup.UpperFloorBound && // Within upper floor bound. + abs(probeFront.GetCeilingHeight() - probeFront.GetFloorHeight()) > testSetup.ClampMin && // Within clamp min. + abs(probeFront.GetCeilingHeight() - probeFront.GetFloorHeight()) <= testSetup.ClampMax && // Within clamp max. + abs(probeMiddle.GetCeilingHeight() - probeFront.GetFloorHeight()) >= testSetup.GapMin) // Gap is optically permissive. { - return VaultTestResult{ probeFront.Position.Floor }; + return VaultTestResult{ probeFront.GetFloorHeight() }; } return std::nullopt; @@ -1392,20 +1382,20 @@ std::optional TestLaraLadderAutoJump(ItemInfo* item, CollisionI int y = item->Pose.Position.y; int distance = OFFSET_RADIUS(coll->Setup.Radius); - auto probeFront = GetCollision(item, coll->NearestLedgeAngle, distance, -coll->Setup.Height); - auto probeMiddle = GetCollision(item); + auto probeFront = GetPointCollision(*item, coll->NearestLedgeAngle, distance, -coll->Setup.Height); + auto probeMiddle = GetPointCollision(*item); // Check ledge angle. if (!TestValidLedgeAngle(item, coll)) return std::nullopt; if (lara->Control.CanClimbLadder && // Ladder sector flag set. - (probeMiddle.Position.Ceiling - y) <= -CLICK(6.5f) && // Within lowest middle ceiling bound. (Synced with TestLaraLadderMount()) - ((probeFront.Position.Floor - y) <= -CLICK(6.5f) || // Floor height is appropriate, OR - (probeFront.Position.Ceiling - y) > -CLICK(6.5f)) && // Ceiling height is appropriate. (Synced with TestLaraLadderMount()) + (probeMiddle.GetCeilingHeight() - y) <= -CLICK(6.5f) && // Within lowest middle ceiling bound. (Synced with TestLaraLadderMount()) + ((probeFront.GetFloorHeight() - y) <= -CLICK(6.5f) || // Floor height is appropriate, OR + (probeFront.GetCeilingHeight() - y) > -CLICK(6.5f)) && // Ceiling height is appropriate. (Synced with TestLaraLadderMount()) coll->NearestLedgeDistance <= coll->Setup.Radius) // Appropriate distance from wall. { - return VaultTestResult{ probeMiddle.Position.Ceiling, false, true, true }; + return VaultTestResult{ probeMiddle.GetCeilingHeight(), false, true, true }; } return std::nullopt; @@ -1417,18 +1407,18 @@ std::optional TestLaraLadderMount(ItemInfo* item, CollisionInfo int y = item->Pose.Position.y; int distance = OFFSET_RADIUS(coll->Setup.Radius); - auto probeFront = GetCollision(item, coll->NearestLedgeAngle, distance, -coll->Setup.Height); - auto probeMiddle = GetCollision(item); + auto probeFront = GetPointCollision(*item, coll->NearestLedgeAngle, distance, -coll->Setup.Height); + auto probeMiddle = GetPointCollision(*item); // Check ledge angle. if (!TestValidLedgeAngle(item, coll)) return std::nullopt; if (lara->Control.CanClimbLadder && // Ladder sector flag set. - (probeMiddle.Position.Ceiling - y) <= -CLICK(4.5f) && // Within lower middle ceiling bound. - (probeMiddle.Position.Ceiling - y) > -CLICK(6.5f) && // Within upper middle ceiling bound. - (probeMiddle.Position.Floor - y) > -CLICK(6.5f) && // Within upper middle floor bound. (Synced with TestLaraAutoJump()) - (probeFront.Position.Ceiling - y) <= -CLICK(4.5f) && // Within lowest front ceiling bound. + (probeMiddle.GetCeilingHeight() - y) <= -CLICK(4.5f) && // Within lower middle ceiling bound. + (probeMiddle.GetCeilingHeight() - y) > -CLICK(6.5f) && // Within upper middle ceiling bound. + (probeMiddle.GetFloorHeight() - y) > -CLICK(6.5f) && // Within upper middle floor bound. (Synced with TestLaraAutoJump()) + (probeFront.GetCeilingHeight() - y) <= -CLICK(4.5f) && // Within lowest front ceiling bound. coll->NearestLedgeDistance <= coll->Setup.Radius) // Appropriate distance from wall. { return VaultTestResult{ NO_HEIGHT, true, true, false }; @@ -1442,13 +1432,13 @@ std::optional TestLaraMonkeyAutoJump(ItemInfo* item, CollisionI auto* lara = GetLaraInfo(item); int y = item->Pose.Position.y; - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); if (lara->Control.CanMonkeySwing && // Monkey swing sector flag set. - (probe.Position.Ceiling - y) < -LARA_HEIGHT_MONKEY && // Within lower ceiling bound. - (probe.Position.Ceiling - y) >= -CLICK(7)) // Within upper ceiling bound. + (probe.GetCeilingHeight() - y) < -LARA_HEIGHT_MONKEY && // Within lower ceiling bound. + (probe.GetCeilingHeight() - y) >= -CLICK(7)) // Within upper ceiling bound. { - return VaultTestResult{ probe.Position.Ceiling, false, false, true }; + return VaultTestResult{ probe.GetCeilingHeight(), false, false, true }; } return std::nullopt; @@ -1608,15 +1598,15 @@ bool TestAndDoLaraLadderClimb(ItemInfo* item, CollisionInfo* coll) CrawlVaultTestResult TestLaraCrawlVaultTolerance(ItemInfo* item, CollisionInfo* coll, CrawlVaultTestSetup testSetup) { int y = item->Pose.Position.y; - auto probeA = GetCollision(item, item->Pose.Orientation.y, testSetup.CrossDist, -LARA_HEIGHT_CRAWL); // Crossing. - auto probeB = GetCollision(item, item->Pose.Orientation.y, testSetup.DestDist, -LARA_HEIGHT_CRAWL); // Approximate destination. - auto probeMiddle = GetCollision(item); + auto probeA = GetPointCollision(*item, item->Pose.Orientation.y, testSetup.CrossDist, -LARA_HEIGHT_CRAWL); // Crossing. + auto probeB = GetPointCollision(*item, item->Pose.Orientation.y, testSetup.DestDist, -LARA_HEIGHT_CRAWL); // Approximate destination. + auto probeMiddle = GetPointCollision(*item); - bool isSlope = testSetup.CheckSlope ? probeB.Position.FloorSlope : false; - bool isDeath = testSetup.CheckDeath ? probeB.Block->Flags.Death : false; + bool isSlope = testSetup.CheckSlope ? probeB.IsIllegalFloor() : false; + bool isDeath = testSetup.CheckDeath ? probeB.GetSector().Flags.Death : false; // Discard walls. - if (probeA.Position.Floor == NO_HEIGHT || probeB.Position.Floor == NO_HEIGHT) + if (probeA.GetFloorHeight() == NO_HEIGHT || probeB.GetFloorHeight() == NO_HEIGHT) return CrawlVaultTestResult{ false }; // Check for slope or death sector (if applicable). @@ -1624,14 +1614,14 @@ CrawlVaultTestResult TestLaraCrawlVaultTolerance(ItemInfo* item, CollisionInfo* return CrawlVaultTestResult{ false }; // Assess point/room collision. - if ((probeA.Position.Floor - y) <= testSetup.LowerFloorBound && // Within lower floor bound. - (probeA.Position.Floor - y) >= testSetup.UpperFloorBound && // Within upper floor bound. - abs(probeA.Position.Ceiling - probeA.Position.Floor) > testSetup.ClampMin && // Crossing clamp limit. - abs(probeB.Position.Ceiling - probeB.Position.Floor) > testSetup.ClampMin && // Destination clamp limit. - abs(probeMiddle.Position.Ceiling - probeA.Position.Floor) >= testSetup.GapMin && // Gap is optically permissive (going up). - abs(probeA.Position.Ceiling - probeMiddle.Position.Floor) >= testSetup.GapMin && // Gap is optically permissive (going down). - abs(probeA.Position.Floor - probeB.Position.Floor) <= testSetup.FloorBound && // Crossing/destination floor height difference suggests continuous crawl surface. - (probeA.Position.Ceiling - y) < -testSetup.GapMin) // Ceiling height is permissive. + if ((probeA.GetFloorHeight() - y) <= testSetup.LowerFloorBound && // Within lower floor bound. + (probeA.GetFloorHeight() - y) >= testSetup.UpperFloorBound && // Within upper floor bound. + abs(probeA.GetCeilingHeight() - probeA.GetFloorHeight()) > testSetup.ClampMin && // Crossing clamp limit. + abs(probeB.GetCeilingHeight() - probeB.GetFloorHeight()) > testSetup.ClampMin && // Destination clamp limit. + abs(probeMiddle.GetCeilingHeight() - probeA.GetFloorHeight()) >= testSetup.GapMin && // Gap is optically permissive (going up). + abs(probeA.GetCeilingHeight() - probeMiddle.GetFloorHeight()) >= testSetup.GapMin && // Gap is optically permissive (going down). + abs(probeA.GetFloorHeight() - probeB.GetFloorHeight()) <= testSetup.FloorBound && // Crossing/destination floor height difference suggests continuous crawl surface. + (probeA.GetCeilingHeight() - y) < -testSetup.GapMin) // Ceiling height is permissive. { return CrawlVaultTestResult{ true }; } @@ -1765,14 +1755,14 @@ bool TestLaraCrawlToHang(ItemInfo* item, CollisionInfo* coll) { int y = item->Pose.Position.y; int distance = CLICK(1.2f); - auto probe = GetCollision(item, item->Pose.Orientation.y + ANGLE(180.0f), distance, -LARA_HEIGHT_CRAWL); + auto probe = GetPointCollision(*item, item->Pose.Orientation.y + ANGLE(180.0f), distance, -LARA_HEIGHT_CRAWL); bool objectCollided = TestLaraObjectCollision(item, item->Pose.Orientation.y + ANGLE(180.0f), CLICK(1.2f), -LARA_HEIGHT_CRAWL); if (!objectCollided && // No obstruction. - (probe.Position.Floor - y) >= LARA_HEIGHT_STRETCH && // Highest floor bound. - (probe.Position.Ceiling - y) <= -CLICK(0.75f) && // Gap is optically permissive. - probe.Position.Floor != NO_HEIGHT) + (probe.GetFloorHeight() - y) >= LARA_HEIGHT_STRETCH && // Highest floor bound. + (probe.GetCeilingHeight() - y) <= -CLICK(0.75f) && // Gap is optically permissive. + probe.GetFloorHeight() != NO_HEIGHT) { return true; } diff --git a/TombEngine/Game/Lara/lara_tests.h b/TombEngine/Game/Lara/lara_tests.h index 4ddebea69..1081a1d79 100644 --- a/TombEngine/Game/Lara/lara_tests.h +++ b/TombEngine/Game/Lara/lara_tests.h @@ -34,8 +34,6 @@ bool TestLaraFacingCorner(const ItemInfo* item, short headingAngle, float dist); bool LaraPositionOnLOS(ItemInfo* item, short angle, int distance); int LaraFloorFront(ItemInfo* item, short angle, int distance); int LaraCeilingFront(ItemInfo* item, short angle, int distance, int height); -CollisionResult LaraCollisionFront(ItemInfo* item, short angle, int distance); -CollisionResult LaraCeilingCollisionFront(ItemInfo* item, short angle, int distance, int height); bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll); bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll); diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 1112ed12e..42e34c183 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -14,6 +14,9 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Room; using namespace TEN::Math; +// TODO +// BUG: Grabbing diagonal ledges stopped working. Lara deflects. Minor error somewhere. + namespace TEN::Collision::PointCollision { PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) @@ -339,7 +342,7 @@ namespace TEN::Collision::PointCollision { // TEMP HACK // GetPointCollision() takes arguments for a *current* position and room number. - // However, since some calls to the old GetCollision() function had *projected* + // However, since some calls to the old GetPointCollision() function had *projected* // positions passed to it, the room number had be corrected to account for such cases. // These are primarily found in camera.cpp. short correctedRoomNumber = roomNumber; diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index f13c1881f..e1fe0f465 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -121,45 +121,9 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) return collided; } -static CollisionResult ConvertPointCollDataToCollResult(PointCollisionData& pointColl) +static CollisionPositionData GetCollisionPositionData(PointCollisionData& pointColl) { - auto collResult = CollisionResult{}; - collResult.Coordinates = pointColl.GetPosition(); - collResult.RoomNumber = pointColl.GetRoomNumber(); - collResult.Block = &pointColl.GetSector(); - collResult.BottomBlock = &pointColl.GetBottomSector(); - collResult.Position.Floor = pointColl.GetFloorHeight(); - collResult.Position.Ceiling = pointColl.GetCeilingHeight(); - collResult.Position.Bridge = pointColl.GetFloorBridgeItemNumber(); - collResult.Position.SplitAngle = pointColl.GetBottomSector().FloorSurface.SplitAngle; - collResult.Position.FloorSlope = collResult.Position.Bridge == NO_ITEM && pointColl.IsIllegalFloor(); - collResult.Position.CeilingSlope = pointColl.IsIllegalCeiling(); - collResult.Position.DiagonalStep = pointColl.IsDiagonalFloorStep(); - collResult.FloorNormal = pointColl.GetFloorNormal(); - collResult.CeilingNormal = pointColl.GetCeilingNormal(); - collResult.FloorTilt = GetSurfaceTilt(collResult.FloorNormal, true).ToVector2(); - collResult.CeilingTilt = GetSurfaceTilt(collResult.CeilingNormal, false).ToVector2(); - - return collResult; -} - -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const ItemInfo* item) -{ - auto pointColl = GetPointCollision(*item); - return ConvertPointCollDataToCollResult(pointColl); -} - -// NOTE: Deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down, float right) -{ - auto pointColl = GetPointCollision(*item, headingAngle, forward, down, right); - return ConvertPointCollDataToCollResult(pointColl); -} - -static CollisionPosition GetCollisionPositionData(PointCollisionData& pointColl) -{ - auto collPos = CollisionPosition{}; + auto collPos = CollisionPositionData{}; collPos.Floor = pointColl.GetFloorHeight(); collPos.Ceiling = pointColl.GetCeilingHeight(); collPos.Bridge = pointColl.GetFloorBridgeItemNumber(); @@ -171,7 +135,7 @@ static CollisionPosition GetCollisionPositionData(PointCollisionData& pointColl) return collPos; } -static void SetSectorAttribs(CollisionPosition& sectorAttribs, const CollisionSetup& collSetup, PointCollisionData& pointColl, +static void SetSectorAttribs(CollisionPositionData& sectorAttribs, const CollisionSetupData& collSetup, PointCollisionData& pointColl, const Vector3i& probePos, int realRoomNumber) { constexpr auto ASPECT_ANGLE_DELTA_MAX = ANGLE(90.0f); @@ -740,10 +704,10 @@ void AlignEntityToSurface(ItemInfo* item, const Vector2& ellipse, float alpha, s auto reducedEllipse = ellipse * 0.75f; // Probe heights at points around entity. - int frontHeight = GetCollision(item, item->Pose.Orientation.y, reducedEllipse.y).Position.Floor; - int backHeight = GetCollision(item, item->Pose.Orientation.y + ANGLE(180.0f), reducedEllipse.y).Position.Floor; - int leftHeight = GetCollision(item, item->Pose.Orientation.y - ANGLE(90.0f), reducedEllipse.x).Position.Floor; - int rightHeight = GetCollision(item, item->Pose.Orientation.y + ANGLE(90.0f), reducedEllipse.x).Position.Floor; + int frontHeight = GetPointCollision(*item, item->Pose.Orientation.y, reducedEllipse.y).GetFloorHeight(); + int backHeight = GetPointCollision(*item, item->Pose.Orientation.y + ANGLE(180.0f), reducedEllipse.y).GetFloorHeight(); + int leftHeight = GetPointCollision(*item, item->Pose.Orientation.y - ANGLE(90.0f), reducedEllipse.x).GetFloorHeight(); + int rightHeight = GetPointCollision(*item, item->Pose.Orientation.y + ANGLE(90.0f), reducedEllipse.x).GetFloorHeight(); // Calculate height deltas. int forwardHeightDelta = backHeight - frontHeight; diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 2b36d8dca..363545bc5 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -1,13 +1,14 @@ #pragma once - #include "Math/Math.h" #include "Objects/game_object_ids.h" -struct ItemInfo; -class FloorInfo; -struct ROOM_INFO; -struct MESH_INFO; enum RoomEnvFlags; +class FloorInfo; +struct ItemInfo; +struct MESH_INFO; +struct ROOM_INFO; + +using namespace TEN::Math; constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBound. constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound. @@ -41,7 +42,7 @@ enum class CornerType Outer }; -struct CollisionPosition +struct CollisionPositionData { int Floor = 0; int Ceiling = 0; @@ -55,43 +56,26 @@ struct CollisionPosition bool HasFlippedDiagonalSplit() { return (HasDiagonalSplit() && (SplitAngle != (45.0f * RADIAN))); } }; -// Deprecated. Use PointCollisionData. -struct CollisionResult +struct CollisionSetupData { - Vector3i Coordinates; - int RoomNumber; + CollisionProbeMode Mode = CollisionProbeMode::Quadrants; // Probe rotation mode + int Radius = 0; // Collision bounds horizontal size + int Height = 0; // Collision bounds vertical size + short ForwardAngle = 0; // Forward angle direction - FloorInfo* Block; - FloorInfo* BottomBlock; + int LowerFloorBound = 0; // Borderline floor step-up height + int UpperFloorBound = 0; // Borderline floor step-down height + int LowerCeilingBound = 0; // Borderline ceiling step-up height + int UpperCeilingBound = 0; // Borderline ceiling step-down height - CollisionPosition Position; - Vector2 FloorTilt; // x = x, y = z - Vector2 CeilingTilt; // x = x, y = z - - Vector3 FloorNormal; - Vector3 CeilingNormal; -}; - -struct CollisionSetup -{ - CollisionProbeMode Mode; // Probe rotation mode - int Radius; // Collision bounds horizontal size - int Height; // Collision bounds vertical size - short ForwardAngle; // Forward angle direction - - int LowerFloorBound; // Borderline floor step-up height - int UpperFloorBound; // Borderline floor step-down height - int LowerCeilingBound; // Borderline ceiling step-up height - int UpperCeilingBound; // Borderline ceiling step-down height - - bool BlockFloorSlopeUp; // Treat steep slopes as walls - bool BlockFloorSlopeDown; // Treat steep slopes as pits - bool BlockCeilingSlope; // Treat steep slopes on ceilings as walls - bool BlockDeathFloorDown; // Treat death sectors as pits - bool BlockMonkeySwingEdge; // Treat non-monkey sectors as walls + bool BlockFloorSlopeUp = false; // Treat steep slopes as walls + bool BlockFloorSlopeDown = false; // Treat steep slopes as pits + bool BlockCeilingSlope = false; // Treat steep slopes on ceilings as walls + bool BlockDeathFloorDown = false; // Treat death sectors as pits + bool BlockMonkeySwingEdge = false; // Treat non-monkey sectors as walls - bool EnableObjectPush; // Can be pushed by objects - bool EnableSpasm; // Convulse when pushed + bool EnableObjectPush = false; // Can be pushed by objects + bool EnableSpasm = false; // Convulse when pushed // Preserve previous parameters to restore later. Vector3i PrevPosition = Vector3i::Zero; @@ -103,29 +87,30 @@ struct CollisionSetup struct CollisionInfo { - CollisionSetup Setup; // In parameters + CollisionSetupData Setup = {}; // In parameters - CollisionPosition Middle; - CollisionPosition MiddleLeft; - CollisionPosition MiddleRight; - CollisionPosition Front; - CollisionPosition FrontLeft; - CollisionPosition FrontRight; + CollisionPositionData Middle = {}; + CollisionPositionData MiddleLeft = {}; + CollisionPositionData MiddleRight = {}; + CollisionPositionData Front = {}; + CollisionPositionData FrontLeft = {}; + CollisionPositionData FrontRight = {}; - Pose Shift = Pose::Zero; - CollisionType CollisionType; - Vector3 FloorNormal; - Vector3 CeilingNormal; - Vector2 FloorTilt; // x = x, y = z - Vector2 CeilingTilt; // x = x, y = z - short NearestLedgeAngle; - float NearestLedgeDistance; + CollisionType CollisionType = CT_NONE; + Pose Shift = Pose::Zero; - int LastBridgeItemNumber; - Pose LastBridgeItemPose; + Vector3 FloorNormal = Vector3::Zero; + Vector3 CeilingNormal = Vector3::Zero; + Vector2 FloorTilt = Vector2::Zero; // NOTE: Deprecated. + Vector2 CeilingTilt = Vector2::Zero; // NOTE: Deprecated. + short NearestLedgeAngle = 0; + float NearestLedgeDistance = 0.0f; - bool HitStatic; - bool HitTallObject; + int LastBridgeItemNumber = 0; + Pose LastBridgeItemPose = Pose::Zero; + + bool HitStatic = false; + bool HitTallObject = false; bool TriangleAtRight() { return ((MiddleRight.SplitAngle != 0.0f) && (MiddleRight.SplitAngle == Middle.SplitAngle)); } bool TriangleAtLeft() { return ((MiddleLeft.SplitAngle != 0.0f) && (MiddleLeft.SplitAngle == Middle.SplitAngle)); } @@ -135,10 +120,6 @@ struct CollisionInfo [[nodiscard]] bool TestItemRoomCollisionAABB(ItemInfo* item); -// NOTE: All overloads deprecated. Use GetPointCollision(). -CollisionResult GetCollision(const ItemInfo* item); -CollisionResult GetCollision(const ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); - void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom = false); void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false); int GetQuadrant(short angle); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 14a718ded..6db0d80c7 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -613,22 +613,28 @@ void CreatureUnderwater(ItemInfo* item, int depth) waterLevel = 0; } else + { waterHeight = GetWaterHeight(item); + } int y = waterHeight + waterLevel; if (item->Pose.Position.y < y) { - int height = GetCollision(item).Position.Floor; + int height = GetPointCollision(*item).GetFloorHeight(); item->Pose.Position.y = y; if (y > height) item->Pose.Position.y = height; if (item->Pose.Orientation.x > ANGLE(2.0f)) + { item->Pose.Orientation.x -= ANGLE(2.0f); + } else if (item->Pose.Orientation.x > 0) + { item->Pose.Orientation.x = 0; + } } } @@ -636,7 +642,7 @@ void CreatureFloat(short itemNumber) { auto* item = &g_Level.Items[itemNumber]; - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(*item); item->HitPoints = NOT_TARGETABLE; item->Pose.Orientation.x = 0; @@ -654,9 +660,9 @@ void CreatureFloat(short itemNumber) AnimateItem(item); - item->Floor = pointColl.Position.Floor; - if (pointColl.RoomNumber != item->RoomNumber) - ItemNewRoom(itemNumber, pointColl.RoomNumber); + item->Floor = pointColl.GetFloorHeight(); + if (pointColl.GetRoomNumber() != item->RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); if (item->Pose.Position.y <= waterLevel) { @@ -2193,18 +2199,18 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) } int vPos = item.Pose.Position.y; - auto pointCollA = GetCollision(&item, item.Pose.Orientation.y, stepDist); - auto pointCollB = GetCollision(&item, item.Pose.Orientation.y, stepDist * 2); - auto pointCollC = GetCollision(&item, item.Pose.Orientation.y, stepDist * 3); + auto pointCollA = GetPointCollision(item, item.Pose.Orientation.y, stepDist); + auto pointCollB = GetPointCollision(item, item.Pose.Orientation.y, stepDist * 2); + auto pointCollC = GetPointCollision(item, item.Pose.Orientation.y, stepDist * 3); switch (jumpDistType) { default: case JumpDistance::Block1: if (item.BoxNumber == creature.Enemy->BoxNumber || - vPos >= (pointCollA.Position.Floor - STEPUP_HEIGHT) || - vPos >= (pointCollB.Position.Floor + CLICK(1)) || - vPos <= (pointCollB.Position.Floor - CLICK(1))) + vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) || + vPos >= (pointCollB.GetFloorHeight() + CLICK(1)) || + vPos <= (pointCollB.GetFloorHeight() - CLICK(1))) { return false; } @@ -2213,10 +2219,10 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) case JumpDistance::Block2: if (item.BoxNumber == creature.Enemy->BoxNumber || - vPos >= (pointCollA.Position.Floor - STEPUP_HEIGHT) || - vPos >= (pointCollB.Position.Floor - STEPUP_HEIGHT) || - vPos >= (pointCollC.Position.Floor + CLICK(1)) || - vPos <= (pointCollC.Position.Floor - CLICK(1))) + vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) || + vPos >= (pointCollB.GetFloorHeight() - STEPUP_HEIGHT) || + vPos >= (pointCollC.GetFloorHeight() + CLICK(1)) || + vPos <= (pointCollC.GetFloorHeight() - CLICK(1))) { return false; } diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 6f4aad9eb..616ed1e46 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -843,8 +843,8 @@ void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFl void ProcessSectorFlags(ItemInfo* item) { - auto pointColl = GetCollision(item); - auto* sectorPtr = GetCollision(item).BottomBlock; + auto pointColl = GetPointCollision(*item); + auto* sectorPtr = &GetPointCollision(*item).GetBottomSector(); bool isPlayer = item->IsLara(); @@ -872,7 +872,7 @@ void ProcessSectorFlags(ItemInfo* item) GetLaraInfo(item)->Control.WaterStatus != WaterStatus::Dry) { // To allow both lava and rapids in same level, also check floor material flag. - if (sectorPtr->GetSurfaceMaterial(pointColl.Coordinates.x, pointColl.Coordinates.z, true) == MaterialType::Water && + if (sectorPtr->GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true) == MaterialType::Water && Objects[ID_KAYAK_LARA_ANIMS].loaded) { KayakLaraRapidsDrown(item); @@ -885,7 +885,7 @@ void ProcessSectorFlags(ItemInfo* item) } else if (Objects[item->ObjectNumber].intelligent && item->HitPoints != NOT_TARGETABLE) { - if (sectorPtr->GetSurfaceMaterial(pointColl.Coordinates.x, pointColl.Coordinates.z, true) == MaterialType::Water || + if (sectorPtr->GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true) == MaterialType::Water || TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, sectorPtr->RoomNumber)) { DoDamage(item, INT_MAX); // TODO: Implement correct rapids behaviour for other objects! diff --git a/TombEngine/Game/control/volume.cpp b/TombEngine/Game/control/volume.cpp index 310ef84b9..26c15b40b 100644 --- a/TombEngine/Game/control/volume.cpp +++ b/TombEngine/Game/control/volume.cpp @@ -49,7 +49,7 @@ namespace TEN::Control::Volumes } } - BoundingOrientedBox ConstructRoughBox(ItemInfo& item, const CollisionSetup& coll) + BoundingOrientedBox ConstructRoughBox(ItemInfo& item, const CollisionSetupData& coll) { auto pBounds = GameBoundingBox(&item).ToBoundingOrientedBox(item.Pose); auto pos = Vector3(item.Pose.Position.x, pBounds.Center.y, item.Pose.Position.z); @@ -244,7 +244,7 @@ namespace TEN::Control::Volumes TestVolumes(roomNumber, box, ActivatorFlags::Static, mesh); } - void TestVolumes(short itemNumber, const CollisionSetup* coll) + void TestVolumes(short itemNumber, const CollisionSetupData* coll) { auto& item = g_Level.Items[itemNumber]; auto box = (coll != nullptr) ? diff --git a/TombEngine/Game/control/volume.h b/TombEngine/Game/control/volume.h index 9d9fc6a84..2c050364e 100644 --- a/TombEngine/Game/control/volume.h +++ b/TombEngine/Game/control/volume.h @@ -4,7 +4,7 @@ #include "Game/Setup.h" #include "Renderer/Renderer.h" -struct CollisionSetup; +struct CollisionSetupData; namespace TEN::Control::Volumes { @@ -39,7 +39,7 @@ namespace TEN::Control::Volumes }; void TestVolumes(short roomNumber, const BoundingOrientedBox& box, ActivatorFlags activatorFlag, Activator activator); - void TestVolumes(short itemNumber, const CollisionSetup* coll = nullptr); + void TestVolumes(short itemNumber, const CollisionSetupData* coll = nullptr); void TestVolumes(short roomNumber, MESH_INFO* mesh); void TestVolumes(CAMERA_INFO* camera); diff --git a/TombEngine/Game/effects/bubble.cpp b/TombEngine/Game/effects/bubble.cpp index 58f10ccf4..7a51a81b3 100644 --- a/TombEngine/Game/effects/bubble.cpp +++ b/TombEngine/Game/effects/bubble.cpp @@ -147,7 +147,7 @@ namespace TEN::Effects::Bubble if (bubble.Life <= 0.0f) continue; - // Update room number. TODO: Should use GetCollision(), but calling it for each bubble is very inefficient. + // Update room number. TODO: Should use GetPointCollision(), but calling it for each bubble is very inefficient. auto roomVector = RoomVector(bubble.RoomNumber, int(bubble.Position.y - bubble.Gravity)); int roomNumber = GetRoomVector(roomVector, Vector3i(bubble.Position.x, bubble.Position.y - bubble.Gravity, bubble.Position.z)).RoomNumber; int prevRoomNumber = bubble.RoomNumber; diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 1cd9b2eb7..33a36982e 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -1261,15 +1261,15 @@ void SpawnPlayerWaterSurfaceEffects(const ItemInfo& item, int waterHeight, int w return; // Get point collision. - auto pointColl0 = GetCollision(&item, 0, 0, -(LARA_HEIGHT / 2)); - auto pointColl1 = GetCollision(&item, 0, 0, item.Animation.Velocity.y); + auto pointColl0 = GetPointCollision(item, 0, 0, -(LARA_HEIGHT / 2)); + auto pointColl1 = GetPointCollision(item, 0, 0, item.Animation.Velocity.y); // In swamp; return early. - if (TestEnvironment(ENV_FLAG_SWAMP, pointColl1.RoomNumber)) + if (TestEnvironment(ENV_FLAG_SWAMP, pointColl1.GetRoomNumber())) return; - bool isWater0 = TestEnvironment(ENV_FLAG_WATER, pointColl0.RoomNumber); - bool isWater1 = TestEnvironment(ENV_FLAG_WATER, pointColl1.RoomNumber); + bool isWater0 = TestEnvironment(ENV_FLAG_WATER, pointColl0.GetRoomNumber()); + bool isWater1 = TestEnvironment(ENV_FLAG_WATER, pointColl1.GetRoomNumber()); // Spawn splash. if (!isWater0 && isWater1 && @@ -1282,7 +1282,7 @@ void SpawnPlayerWaterSurfaceEffects(const ItemInfo& item, int waterHeight, int w SplashSetup.innerRadius = 16; SplashSetup.splashPower = item.Animation.Velocity.z; - SetupSplash(&SplashSetup, pointColl0.RoomNumber); + SetupSplash(&SplashSetup, pointColl0.GetRoomNumber()); SplashCount = 16; } // Spawn ripple. @@ -1307,7 +1307,7 @@ void SpawnPlayerWaterSurfaceEffects(const ItemInfo& item, int waterHeight, int w void Splash(ItemInfo* item) { - int probedRoomNumber = GetCollision(item).RoomNumber; + int probedRoomNumber = GetPointCollision(*item).GetRoomNumber(); if (!TestEnvironment(ENV_FLAG_WATER, probedRoomNumber)) return; diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index d48d8a746..9618c1a5b 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -844,7 +844,7 @@ void DropPickups(ItemInfo* item) auto bounds = GameBoundingBox(item); auto extents = bounds.GetExtents(); auto origin = Geometry::TranslatePoint(item->Pose.Position.ToVector3(), item->Pose.Orientation, bounds.GetCenter()); - auto yPos = GetCollision(item).Position.Floor; + auto yPos = GetPointCollision(*item).GetFloorHeight(); origin.y = yPos; // Initialize drop origin Y point as floor height at centerpoint, in case all corner tests fail. @@ -1088,19 +1088,19 @@ void InitializePickup(short itemNumber) if (triggerFlags == 0) { // Automatically align pickups to the floor surface. - auto pointColl = GetCollision(item); - int bridgeItemNumber = pointColl.Block->GetInsideBridgeItemNumber(item->Pose.Position, true, true); + auto pointColl = GetPointCollision(*item); + int bridgeItemNumber = pointColl.GetSector().GetInsideBridgeItemNumber(item->Pose.Position, true, true); if (bridgeItemNumber != NO_ITEM) { // If pickup is within bridge item, most likely it means it is // below pushable or raising block, so ignore its collision. - pointColl.Block->RemoveBridge(bridgeItemNumber); - pointColl = GetCollision(item); - pointColl.Block->AddBridge(bridgeItemNumber); + pointColl.GetSector().RemoveBridge(bridgeItemNumber); + pointColl = GetPointCollision(*item); + pointColl.GetSector().AddBridge(bridgeItemNumber); } - item->Pose.Position.y = pointColl.Position.Floor - bounds.Y2; + item->Pose.Position.y = pointColl.GetFloorHeight() - bounds.Y2; AlignEntityToSurface(item, Vector2(Objects[item->ObjectNumber].radius)); } } diff --git a/TombEngine/Objects/Effects/flame_emitters.cpp b/TombEngine/Objects/Effects/flame_emitters.cpp index 7fd725ce7..37ccc5465 100644 --- a/TombEngine/Objects/Effects/flame_emitters.cpp +++ b/TombEngine/Objects/Effects/flame_emitters.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" @@ -20,6 +21,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Environment; using namespace TEN::Effects::Items; @@ -266,21 +268,21 @@ namespace TEN::Entities::Effects item->Pose.Position.x += phd_sin(item->Pose.Orientation.y - ANGLE(180)) * (CLICK(1) / FPS); item->Pose.Position.z += phd_cos(item->Pose.Orientation.y - ANGLE(180)) * (CLICK(1) / FPS); - auto pointColl = GetCollision(item); + auto pointColl = GetPointCollision(*item); - if (TestEnvironment(ENV_FLAG_WATER, pointColl.RoomNumber) || - pointColl.Position.Floor - item->Pose.Position.y > CLICK(2) || - pointColl.Position.Floor == NO_HEIGHT) + if (TestEnvironment(ENV_FLAG_WATER, pointColl.GetRoomNumber()) || + pointColl.GetFloorHeight() - item->Pose.Position.y > CLICK(2) || + pointColl.GetFloorHeight() == NO_HEIGHT) { Weather.Flash(255, 128, 0, 0.03f); KillItem(itemNumber); return; } - if (item->RoomNumber != pointColl.RoomNumber) - ItemNewRoom(itemNumber, pointColl.RoomNumber); + if (item->RoomNumber != pointColl.GetRoomNumber()) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); - item->Pose.Position.y = pointColl.Position.Floor; + item->Pose.Position.y = pointColl.GetFloorHeight(); if (Wibble & 7) TriggerFireFlame(item->Pose.Position.x, item->Pose.Position.y - 32, item->Pose.Position.z, FlameType::Medium); diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index d2eac7afb..d9a06eb94 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -104,7 +104,7 @@ namespace TEN::Entities::Generic // Check for stopper flag. /*if (collisionResult.Block->Stopper) { - if (collisionResult.Position.Floor <= pushableItem.Pose.Position.y) + if (collisionResult.GetFloorHeight() <= pushableItem.Pose.Position.y) return false; }*/ diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp index e96226e1b..57d9658fe 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp @@ -104,7 +104,7 @@ namespace TEN::Entities::Generic // Update bridge. AddPushableStackBridge(pushableItem, false); - int probeRoomNumber = GetCollision(&pushableItem).RoomNumber; + int probeRoomNumber = GetPointCollision(pushableItem).GetRoomNumber(); AddPushableStackBridge(pushableItem, true); // Update room number. diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp index a8995ae3b..833efe10d 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp @@ -2,12 +2,14 @@ #include "Objects/Generic/Object/Pushable/PushableStack.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/Setup.h" #include "Objects/Generic/Object/Pushable/PushableBridge.h" #include "Objects/Generic/Object/Pushable/PushableObject.h" #include "Specific/level.h" using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; namespace TEN::Entities::Generic { @@ -44,8 +46,8 @@ namespace TEN::Entities::Generic int x = pushableItem.Pose.Position.x; int z = pushableItem.Pose.Position.z; - auto pointColl = GetCollision(&pushableItem); - int y = pointColl.Position.Floor; + auto pointColl = GetPointCollision(pushableItem); + int y = pointColl.GetFloorHeight(); stackGroups.emplace(Vector3i(x, y, z), std::vector()).first->second.push_back(itemNumber); } @@ -144,7 +146,7 @@ namespace TEN::Entities::Generic return pushabelStackFound; // Otherwise, check room below. - //auto collisionResult = GetCollision(pushableItem.Pose.Position.x, pushableItem.Pose.Position.y, pushableItem.Pose.Position.z, pushableItem.RoomNumber); + //auto collisionResult = GetPointCollision(pushableItem.Pose.Position.x, pushableItem.Pose.Position.y, pushableItem.Pose.Position.z, pushableItem.RoomNumber); //auto roomNumberBelow = collisionResult.Block->GetRoomNumberBelow(pushableItem.Pose.Position.x, pushableItem.Pose.Position.y, pushableItem.Pose.Position.z).value(); //pushabelStackFound = FindPushableStackInRoom(itemNumber, roomNumberBelow); diff --git a/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp b/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp index 5eb580d48..d91999010 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp @@ -56,7 +56,7 @@ namespace TEN::Entities::Creatures::TR1 { case 0: { - int laraFloorHeight = GetCollision(LaraItem).Position.Floor; + int laraFloorHeight = GetPointCollision(*LaraItem).GetFloorHeight(); // Get floor heights for comparison. auto pos = Vector3i( @@ -113,7 +113,7 @@ namespace TEN::Entities::Creatures::TR1 } TestTriggers(&item, true); - item.Floor = GetCollision(&item).Position.Floor; + item.Floor = GetPointCollision(item).GetFloorHeight(); if (item.Pose.Position.y >= item.Floor) { @@ -137,7 +137,7 @@ namespace TEN::Entities::Creatures::TR1 break; } - ItemNewRoom(itemNumber, GetCollision(&item).RoomNumber); + ItemNewRoom(itemNumber, GetPointCollision(item).GetRoomNumber()); AnimateItem(&item); } } diff --git a/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp b/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp index 25290c7c3..50b1cccec 100644 --- a/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp +++ b/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp @@ -4,12 +4,14 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/Lara/lara.h" #include "Game/Setup.h" #include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; namespace TEN::Entities::Traps::TR1 @@ -59,10 +61,10 @@ namespace TEN::Entities::Traps::TR1 TranslateItem(&item, headingAngle, item.ItemFlags[1], item.Animation.Velocity.y); int vPos = item.Pose.Position.y; - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); // Impale floor. - if ((pointColl.Position.Floor - vPos) <= DAMOCLES_SWORD_IMPALE_DEPTH) + if ((pointColl.GetFloorHeight() - vPos) <= DAMOCLES_SWORD_IMPALE_DEPTH) { SoundEffect(SFX_TR1_DAMOCLES_ROOM_SWORD, &item.Pose); float distance = Vector3::Distance(item.Pose.Position.ToVector3(), Camera.pos.ToVector3()); @@ -79,7 +81,7 @@ namespace TEN::Entities::Traps::TR1 } // Scan for player. - if (item.Pose.Position.y < GetCollision(&item).Position.Floor) + if (item.Pose.Position.y < GetPointCollision(item).GetFloorHeight()) { item.Pose.Orientation.y += item.ItemFlags[0]; diff --git a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp index adb472b24..50a2800e4 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp +++ b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp @@ -58,13 +58,13 @@ void SpinningBladeControl(short itemNumber) AnimateItem(item); - auto probe = GetCollision(item); + auto pointColl = GetPointCollision(*item); - item->Floor = probe.Position.Floor; - item->Pose.Position.y = probe.Position.Floor; + item->Floor = pointColl.GetFloorHeight(); + item->Pose.Position.y = pointColl.GetFloorHeight(); - if (probe.RoomNumber != item->RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + if (pointColl.GetRoomNumber() != item->RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); if (isSpinning && item->Animation.ActiveState == 1) item->Pose.Orientation.y += -ANGLE(180.0f); diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index 795170420..c72777c44 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -187,12 +187,12 @@ namespace TEN::Entities::Vehicles else angle = skidooItem->Pose.Orientation.y - ANGLE(90.0f); - auto probe = GetCollision(skidooItem, angle, -SKIDOO_DISMOUNT_DISTANCE); + auto probe = GetPointCollision(*skidooItem, angle, -SKIDOO_DISMOUNT_DISTANCE); - if ((probe.Position.FloorSlope || probe.Position.Floor == NO_HEIGHT) || - abs(probe.Position.Floor - skidooItem->Pose.Position.y) > CLICK(2) || - ((probe.Position.Ceiling - skidooItem->Pose.Position.y) > -LARA_HEIGHT || - (probe.Position.Floor - probe.Position.Ceiling) < LARA_HEIGHT)) + if ((probe.IsIllegalFloor() || probe.GetFloorHeight() == NO_HEIGHT) || + abs(probe.GetFloorHeight() - skidooItem->Pose.Position.y) > CLICK(2) || + ((probe.GetCeilingHeight() - skidooItem->Pose.Position.y) > -LARA_HEIGHT || + (probe.GetFloorHeight() - probe.GetCeilingHeight()) < LARA_HEIGHT)) { return false; } @@ -280,7 +280,7 @@ namespace TEN::Entities::Vehicles auto heightFrontLeft = GetVehicleHeight(skidooItem, SKIDOO_FRONT, -SKIDOO_SIDE, true, &frontLeft); auto heightFrontRight = GetVehicleHeight(skidooItem, SKIDOO_FRONT, SKIDOO_SIDE, true, &frontRight); - auto probe = GetCollision(skidooItem); + auto probe = GetPointCollision(*skidooItem); TestTriggers(skidooItem, true); TestTriggers(skidooItem, false); @@ -302,7 +302,7 @@ namespace TEN::Entities::Vehicles collide = 0; } - int height = probe.Position.Floor; + int height = probe.GetFloorHeight(); int pitch = 0; if (skidooItem->Flags & IFLAG_INVISIBLE) @@ -363,10 +363,10 @@ namespace TEN::Entities::Vehicles if (skidooItem->Flags & IFLAG_INVISIBLE) { - if (probe.RoomNumber != skidooItem->RoomNumber) + if (probe.GetRoomNumber() != skidooItem->RoomNumber) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } AnimateItem(laraItem); @@ -379,10 +379,10 @@ namespace TEN::Entities::Vehicles SkidooAnimation(skidooItem, laraItem, collide, dead); - if (probe.RoomNumber != skidooItem->RoomNumber) + if (probe.GetRoomNumber() != skidooItem->RoomNumber) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } if (laraItem->Animation.ActiveState != SKIDOO_STATE_FALLOFF) @@ -692,8 +692,8 @@ namespace TEN::Entities::Vehicles void DoSnowEffect(ItemInfo* skidooItem) { - auto pointColl = GetCollision(skidooItem); - auto material = pointColl.BottomBlock->GetSurfaceMaterial(pointColl.Coordinates.x, pointColl.Coordinates.z, true); + auto pointColl = GetPointCollision(*skidooItem); + auto material = pointColl.GetBottomSector().GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true); if (material != MaterialType::Ice && material != MaterialType::Snow) return; @@ -922,8 +922,8 @@ namespace TEN::Entities::Vehicles if (heightFrontRight < (frontRightOld.y - CLICK(1))) rotation += DoSkidooShift(skidooItem, &frontRight, &frontRightOld); - auto probe = GetCollision(skidooItem); - if (probe.Position.Floor < (skidooItem->Pose.Position.y - CLICK(1))) + auto probe = GetPointCollision(*skidooItem); + if (probe.GetFloorHeight() < (skidooItem->Pose.Position.y - CLICK(1))) DoSkidooShift(skidooItem, (Vector3i*)&skidooItem->Pose, &oldPos); skidoo->ExtraRotation = rotation; diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index 5d90ae406..162d6df91 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -549,11 +549,11 @@ namespace TEN::Entities::Vehicles SpeedboatDoShift(speedboatItem, &f, &frontOld); } - auto probe = GetCollision(speedboatItem); - auto height = GetWaterHeight(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z, probe.RoomNumber); + auto probe = GetPointCollision(*speedboatItem); + auto height = GetWaterHeight(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z, probe.GetRoomNumber()); if (height == NO_HEIGHT) - height = GetFloorHeight(probe.Block, speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z); + height = GetFloorHeight(&probe.GetSector(), speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z); if (height < (speedboatItem->Pose.Position.y - CLICK(0.5f))) SpeedboatDoShift(speedboatItem, (Vector3i*)&speedboatItem->Pose, &old); diff --git a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp index 0cd3f0306..802578b2d 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp @@ -2,6 +2,7 @@ #include "Objects/TR3/Entity/tr3_scuba_diver.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/los.h" @@ -13,6 +14,8 @@ #include "Game/Setup.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::Creatures::TR3 { constexpr auto SCUBA_DIVER_ATTACK_DAMAGE = 50; @@ -92,12 +95,12 @@ namespace TEN::Entities::Creatures::TR3 { TranslateItem(item, item->Pose.Orientation, item->Animation.Velocity.z); - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); - if (item->RoomNumber != probe.RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + if (item->RoomNumber != probe.GetRoomNumber()) + ItemNewRoom(itemNumber, probe.GetRoomNumber()); - item->Floor = GetCollision(item).Position.Floor; + item->Floor = GetPointCollision(*item).GetFloorHeight(); if (item->Pose.Position.y >= item->Floor) KillItem(itemNumber); } diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp index 1deb1da4c..987c695f7 100644 --- a/TombEngine/Objects/TR3/Object/corpse.cpp +++ b/TombEngine/Objects/TR3/Object/corpse.cpp @@ -7,6 +7,7 @@ #include "Game/control/control.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/floordata.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" @@ -18,6 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Ripple; using namespace TEN::Math::Random; @@ -69,7 +71,7 @@ namespace TEN::Entities::TR3 bool isWater = TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber); int VerticalVelCoeff = isWater ? 81.0f : 1.0f; - int roomNumber = GetCollision(&item).RoomNumber; + int roomNumber = GetPointCollision(item).GetRoomNumber(); if (item.RoomNumber != roomNumber) { if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, roomNumber) && @@ -89,10 +91,10 @@ namespace TEN::Entities::TR3 ItemNewRoom(itemNumber, roomNumber); } - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); item.Animation.IsAirborne = true; - if (pointColl.Position.Floor < item.Pose.Position.y) + if (pointColl.GetFloorHeight() < item.Pose.Position.y) { if (!isWater) { diff --git a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp index 3f88cdc9d..b823d479a 100644 --- a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp +++ b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp @@ -413,7 +413,7 @@ namespace TEN::Entities::Traps AnimateItem(&item); - int probedRoomNumber = GetCollision(&item).RoomNumber; + int probedRoomNumber = GetPointCollision(item).GetRoomNumber(); if (item.RoomNumber != probedRoomNumber) ItemNewRoom(itemNumber, probedRoomNumber); diff --git a/TombEngine/Objects/TR3/Trap/train.cpp b/TombEngine/Objects/TR3/Trap/train.cpp index 54617dd04..aab505f7a 100644 --- a/TombEngine/Objects/TR3/Trap/train.cpp +++ b/TombEngine/Objects/TR3/Trap/train.cpp @@ -67,7 +67,7 @@ void TrainControl(short itemNumber) item->Pose.Position.y -= 32;// ? - short probedRoomNumber = GetCollision(item).RoomNumber; + short probedRoomNumber = GetPointCollision(*item).GetRoomNumber(); if (probedRoomNumber != item->RoomNumber) ItemNewRoom(itemNumber, probedRoomNumber); diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index 38b3b1423..5b26186bf 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -535,22 +535,22 @@ namespace TEN::Entities::Vehicles kayakItem->Pose.Orientation.y += rot; - auto probe = GetCollision(kayakItem); - int probedRoomNum = probe.RoomNumber; + auto probe = GetPointCollision(*kayakItem); + int probedRoomNum = probe.GetRoomNumber(); height2 = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probedRoomNum); if (height2 == NO_HEIGHT) - height2 = probe.Position.Floor; + height2 = probe.GetFloorHeight(); if (height2 < (kayakItem->Pose.Position.y - KAYAK_COLLIDE)) KayakDoShift(kayakItem, (Vector3i*)&kayakItem->Pose, &oldPos[8]); - probe = GetCollision(kayakItem); - probedRoomNum = probe.RoomNumber; + probe = GetPointCollision(*kayakItem); + probedRoomNum = probe.GetRoomNumber(); height2 = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probedRoomNum); if (height2 == NO_HEIGHT) - height2 = probe.Position.Floor; + height2 = probe.GetFloorHeight(); if (height2 == NO_HEIGHT) { @@ -1081,13 +1081,13 @@ namespace TEN::Entities::Vehicles KayakToBackground(kayakItem, laraItem); TestTriggers(kayakItem, false); - auto probe = GetCollision(kayakItem); - int water = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probe.RoomNumber); + auto probe = GetPointCollision(*kayakItem); + int water = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probe.GetRoomNumber()); kayak->WaterHeight = water; if (kayak->WaterHeight == NO_HEIGHT) { - water = probe.Position.Floor; + water = probe.GetFloorHeight(); kayak->WaterHeight = water; kayak->TrueWater = false; } @@ -1108,10 +1108,10 @@ namespace TEN::Entities::Vehicles if (lara->Context.Vehicle != NO_ITEM) { - if (kayakItem->RoomNumber != probe.RoomNumber) + if (kayakItem->RoomNumber != probe.GetRoomNumber()) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose.Position = kayakItem->Pose.Position; diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index d65f36303..b3ac6e8de 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -5,6 +5,7 @@ #include "Game/camera.h" #include "Game/collision/sphere.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/spark.h" #include "Game/effects/tomb4fx.h" @@ -20,6 +21,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Spark; using namespace TEN::Input; using namespace TEN::Math; @@ -180,7 +182,7 @@ namespace TEN::Entities::Vehicles // This allows creation of minecarts which will get to a point and stop forever. auto mountType = GetVehicleMountType(minecartItem, laraItem, coll, MinecartMountTypes, MINECART_MOUNT_DISTANCE); if (mountType == VehicleMountType::None || - GetCollision(minecartItem, minecartItem->Pose.Orientation.y, BLOCK(1)).BottomBlock->Flags.MinecartStop()) + GetPointCollision(*minecartItem, minecartItem->Pose.Orientation.y, BLOCK(1)).GetBottomSector().Flags.MinecartStop()) { ObjectCollision(itemNumber, laraItem, coll); } @@ -240,12 +242,13 @@ namespace TEN::Entities::Vehicles static int GetMinecartCollision(ItemInfo* minecartItem, short angle, int distance) { - auto probe = GetCollision(minecartItem, angle, distance, -LARA_HEIGHT); + auto probe = GetPointCollision(*minecartItem, angle, distance, -LARA_HEIGHT); - if (probe.Position.Floor != NO_HEIGHT) - probe.Position.Floor -= minecartItem->Pose.Position.y; + if (probe.GetFloorHeight() == NO_HEIGHT) + return probe.GetFloorHeight(); + + return (probe.GetFloorHeight() - minecartItem->Pose.Position.y); - return probe.Position.Floor; } static bool TestMinecartDismount(ItemInfo* laraItem, int direction) @@ -259,16 +262,16 @@ namespace TEN::Entities::Vehicles else angle = minecartItem->Pose.Orientation.y - ANGLE(90.0f); - auto probe = GetCollision(minecartItem, angle, -MINECART_DISMOUNT_DISTANCE); + auto probe = GetPointCollision(*minecartItem, angle, -MINECART_DISMOUNT_DISTANCE); - if (probe.Position.FloorSlope || probe.Position.Floor == NO_HEIGHT) + if (probe.IsIllegalFloor() || probe.GetFloorHeight() == NO_HEIGHT) return false; - if (abs(probe.Position.Floor - minecartItem->Pose.Position.y) > CLICK(2)) + if (abs(probe.GetFloorHeight() - minecartItem->Pose.Position.y) > CLICK(2)) return false; - if ((probe.Position.Ceiling - minecartItem->Pose.Position.y) > -LARA_HEIGHT || - (probe.Position.Floor - probe.Position.Ceiling) < LARA_HEIGHT) + if ((probe.GetCeilingHeight() - minecartItem->Pose.Position.y) > -LARA_HEIGHT || + (probe.GetFloorHeight() - probe.GetCeilingHeight()) < LARA_HEIGHT) { return false; } @@ -351,7 +354,7 @@ namespace TEN::Entities::Vehicles auto* minecart = GetMinecartInfo(minecartItem); auto* lara = GetLaraInfo(laraItem); - auto flags = GetCollision(minecartItem).BottomBlock->Flags; + auto flags = GetPointCollision(*minecartItem).GetBottomSector().Flags; if (minecart->StopDelayTime) minecart->StopDelayTime--; @@ -968,7 +971,7 @@ namespace TEN::Entities::Vehicles if (lara->Context.Vehicle != NO_ITEM) laraItem->Pose = minecartItem->Pose; - short probedRoomNumber = GetCollision(minecartItem).RoomNumber; + short probedRoomNumber = GetPointCollision(*minecartItem).GetRoomNumber(); if (probedRoomNumber != minecartItem->RoomNumber) { ItemNewRoom(lara->Context.Vehicle, probedRoomNumber); diff --git a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp index 648d6484e..15b4ce4f4 100644 --- a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp +++ b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp @@ -537,9 +537,9 @@ namespace TEN::Entities::Vehicles else quadBikeItem->Pose.Orientation.y += quadBike->TurnRate + quadBike->ExtraRotation; - auto probe = GetCollision(quadBikeItem); + auto probe = GetPointCollision(*quadBikeItem); int speed = 0; - if (quadBikeItem->Pose.Position.y >= probe.Position.Floor) + if (quadBikeItem->Pose.Position.y >= probe.GetFloorHeight()) speed = quadBikeItem->Animation.Velocity.z * phd_cos(quadBikeItem->Pose.Orientation.x); else speed = quadBikeItem->Animation.Velocity.z; @@ -636,8 +636,8 @@ namespace TEN::Entities::Vehicles rot += rotAdd; } - probe = GetCollision(quadBikeItem); - if (probe.Position.Floor < quadBikeItem->Pose.Position.y - CLICK(1)) + probe = GetPointCollision(*quadBikeItem); + if (probe.GetFloorHeight() < quadBikeItem->Pose.Position.y - CLICK(1)) DoQuadShift(quadBikeItem, (Vector3i*)&quadBikeItem->Pose, &old); quadBike->ExtraRotation = rot; @@ -1095,7 +1095,7 @@ namespace TEN::Entities::Vehicles bool collide = QuadDynamics(quadBikeItem, laraItem); - auto probe = GetCollision(quadBikeItem); + auto probe = GetPointCollision(*quadBikeItem); Vector3i frontLeft, frontRight; auto floorHeightLeft = GetVehicleHeight(quadBikeItem, QBIKE_FRONT, -QBIKE_SIDE, false, &frontLeft); @@ -1130,7 +1130,7 @@ namespace TEN::Entities::Vehicles break; default: - drive = QuadUserControl(quadBikeItem, probe.Position.Floor, &pitch); + drive = QuadUserControl(quadBikeItem, probe.GetFloorHeight(), &pitch); HandleVehicleSpeedometer(quadBikeItem->Animation.Velocity.z, MAX_VELOCITY / (float)VEHICLE_VELOCITY_SCALE); break; } @@ -1154,7 +1154,7 @@ namespace TEN::Entities::Vehicles quadBike->Pitch = 0; } - quadBikeItem->Floor = probe.Position.Floor; + quadBikeItem->Floor = probe.GetFloorHeight(); short rotAdd = quadBike->Velocity / 4; quadBike->RearRot -= rotAdd; @@ -1163,22 +1163,22 @@ namespace TEN::Entities::Vehicles quadBike->LeftVerticalVelocity = DoQuadDynamics(floorHeightLeft, quadBike->LeftVerticalVelocity, (int*)&frontLeft.y); quadBike->RightVerticalVelocity = DoQuadDynamics(floorHeightRight, quadBike->RightVerticalVelocity, (int*)&frontRight.y); - quadBikeItem->Animation.Velocity.y = DoQuadDynamics(probe.Position.Floor, quadBikeItem->Animation.Velocity.y, (int*)&quadBikeItem->Pose.Position.y); + quadBikeItem->Animation.Velocity.y = DoQuadDynamics(probe.GetFloorHeight(), quadBikeItem->Animation.Velocity.y, (int*)&quadBikeItem->Pose.Position.y); quadBike->Velocity = DoVehicleWaterMovement(quadBikeItem, laraItem, quadBike->Velocity, QBIKE_RADIUS, &quadBike->TurnRate, QBIKE_WAKE_OFFSET); - probe.Position.Floor = (frontLeft.y + frontRight.y) / 2; - short xRot = phd_atan(QBIKE_FRONT, quadBikeItem->Pose.Position.y - probe.Position.Floor); - short zRot = phd_atan(QBIKE_SIDE, probe.Position.Floor - frontLeft.y); + int floorHeight = (frontLeft.y + frontRight.y) / 2; + short xRot = phd_atan(QBIKE_FRONT, quadBikeItem->Pose.Position.y - floorHeight); + short zRot = phd_atan(QBIKE_SIDE, floorHeight - frontLeft.y); quadBikeItem->Pose.Orientation.x += ((xRot - quadBikeItem->Pose.Orientation.x) / 2); quadBikeItem->Pose.Orientation.z += ((zRot - quadBikeItem->Pose.Orientation.z) / 2); if (!(quadBike->Flags & QBIKE_FLAG_DEAD)) { - if (probe.RoomNumber != quadBikeItem->RoomNumber) + if (probe.GetRoomNumber() != quadBikeItem->RoomNumber) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose = quadBikeItem->Pose; diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index ccca9f896..790f0ed8c 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -2,6 +2,7 @@ #include "Objects/TR4/Entity/Wraith.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/flipeffect.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" @@ -18,6 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Streamer; @@ -303,11 +305,11 @@ namespace TEN::Entities::TR4 item.Pose.Orientation.x += angleV; } - auto pointColl = GetCollision(&item); + auto pointColl = GetPointCollision(item); bool hasHitWall = false; - if (pointColl.Position.Floor < item.Pose.Position.y || - pointColl.Position.Ceiling > item.Pose.Position.y) + if (pointColl.GetFloorHeight() < item.Pose.Position.y || + pointColl.GetCeilingHeight() > item.Pose.Position.y) { hasHitWall = true; } @@ -317,8 +319,8 @@ namespace TEN::Entities::TR4 item.Pose.Position.y += item.Animation.Velocity.z * phd_sin(item.Pose.Orientation.x); item.Pose.Position.z += item.Animation.Velocity.z * phd_cos(item.Pose.Orientation.y); - if (pointColl.RoomNumber != item.RoomNumber) - ItemNewRoom(itemNumber, pointColl.RoomNumber); + if (pointColl.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); for (int linkItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkItemNumber != NO_ITEM; linkItemNumber = g_Level.Items[linkItemNumber].NextItem) { @@ -550,10 +552,10 @@ namespace TEN::Entities::TR4 } // Check if WRAITH is below floor or above ceiling and spawn wall effect - pointColl = GetCollision(&item); + pointColl = GetPointCollision(item); - if (pointColl.Position.Floor < item.Pose.Position.y || - pointColl.Position.Ceiling > item.Pose.Position.y) + if (pointColl.GetFloorHeight() < item.Pose.Position.y || + pointColl.GetCeilingHeight() > item.Pose.Position.y) { if (!hasHitWall) WraithWallEffect(prevPos, item.Pose.Orientation.y - ANGLE(180.0f), item.ObjectNumber); diff --git a/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp b/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp index 5e141e1a9..b48269f15 100644 --- a/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp @@ -6,8 +6,11 @@ #include "Game/animation.h" #include "Sound/sound.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/debris.h" +using namespace TEN::Collision::PointCollision; + void ClockworkBeetleControl(short itemNumber) { auto* beetle = &g_Level.Items[itemNumber]; @@ -323,7 +326,7 @@ void UseClockworkBeetle(short flag) item->Pose.Orientation.z = 0; if (Lara.Inventory.BeetleLife) - item->ItemFlags[0] = GetCollision(item).Block->Flags.MarkBeetle; + item->ItemFlags[0] = GetPointCollision(*item).GetSector().Flags.MarkBeetle; else item->ItemFlags[0] = 0; diff --git a/TombEngine/Objects/TR4/Object/tr4_mapper.cpp b/TombEngine/Objects/TR4/Object/tr4_mapper.cpp index 5238ef5ad..e12847de8 100644 --- a/TombEngine/Objects/TR4/Object/tr4_mapper.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_mapper.cpp @@ -2,6 +2,7 @@ #include "Objects/TR4/Object/tr4_mapper.h" #include "Specific/level.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Sound/sound.h" #include "Game/animation.h" @@ -11,6 +12,8 @@ #include "Game/items.h" #include "Renderer/RendererEnums.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::TR4 { void InitializeMapper(short itemNumber) @@ -35,7 +38,7 @@ namespace TEN::Entities::TR4 byte color = (GetRandomControl() & 0x1F) + 192; TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 3) + 16, color, color, 0); - int height = GetCollision(item).Position.Floor; + int height = GetPointCollision(*item).GetFloorHeight(); for (int i = 0; i < 2; i++) { diff --git a/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp b/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp index e685b46bb..52bebb8fa 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -12,6 +13,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::Traps { // NOTES: @@ -39,9 +42,9 @@ namespace TEN::Entities::Traps int lowerCeilBound = bounds.Y1; // Get point collision. - auto pointColl = GetCollision(&item); - int relFloorHeight = pointColl.Position.Floor - item.Pose.Position.y; - int relCeilHeight = pointColl.Position.Ceiling - item.Pose.Position.y; + auto pointColl = GetPointCollision(item); + int relFloorHeight = pointColl.GetFloorHeight() - item.Pose.Position.y; + int relCeilHeight = pointColl.GetCeilingHeight() - item.Pose.Position.y; int verticalVel = item.ItemFlags[0]; @@ -57,8 +60,8 @@ namespace TEN::Entities::Traps { item.Pose.Position.y += verticalVel; - if (pointColl.RoomNumber != item.RoomNumber) - ItemNewRoom(itemNumber, pointColl.RoomNumber); + if (pointColl.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); SoundEffect(SFX_TR4_ROLLING_BALL, &item.Pose); } diff --git a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp index b7d4ba146..5049c604c 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/debris.h" @@ -14,6 +15,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; // NOTES: @@ -47,8 +49,8 @@ namespace TEN::Entities::Traps int forwardVel = item.ItemFlags[0]; auto bounds = GameBoundingBox(&item); - auto pointColl0 = GetCollision(&item, item.Pose.Orientation.y, (forwardVel >= 0) ? bounds.Z2 : bounds.Z1, bounds.Y2); - auto pointColl1 = GetCollision(&item, item.Pose.Orientation.y, (forwardVel >= 0) ? bounds.Z2 : bounds.Z1, bounds.Y2, (bounds.X2 - bounds.X1) / 2); + auto pointColl0 = GetPointCollision(item, item.Pose.Orientation.y, (forwardVel >= 0) ? bounds.Z2 : bounds.Z1, bounds.Y2); + auto pointColl1 = GetPointCollision(item, item.Pose.Orientation.y, (forwardVel >= 0) ? bounds.Z2 : bounds.Z1, bounds.Y2, (bounds.X2 - bounds.X1) / 2); if (GetCollidedObjects(&item, CLICK(1), true, CollidedItems, CollidedMeshes, true)) { @@ -76,18 +78,18 @@ namespace TEN::Entities::Traps // Stop moving. if (!item.TriggerFlags || - pointColl0.Block->IsWall(item.Pose.Position.x, item.Pose.Position.z) || - pointColl0.Block->Stopper || - pointColl1.Block->IsWall(item.Pose.Position.x, item.Pose.Position.z) || - pointColl1.Block->Stopper) + pointColl0.GetSector().IsWall(item.Pose.Position.x, item.Pose.Position.z) || + pointColl0.GetSector().Stopper || + pointColl1.GetSector().IsWall(item.Pose.Position.x, item.Pose.Position.z) || + pointColl1.GetSector().Stopper) { auto& room = g_Level.Rooms[item.RoomNumber]; for (auto& mesh : room.mesh) { - if ((abs(pointColl0.Coordinates.x - mesh.pos.Position.x) < BLOCK(1) && - abs(pointColl0.Coordinates.z - mesh.pos.Position.z) < BLOCK(1)) || - abs(pointColl1.Coordinates.x - mesh.pos.Position.x) < BLOCK(1) && - abs(pointColl1.Coordinates.z - mesh.pos.Position.z) < BLOCK(1) && + if ((abs(pointColl0.GetPosition().x - mesh.pos.Position.x) < BLOCK(1) && + abs(pointColl0.GetPosition().z - mesh.pos.Position.z) < BLOCK(1)) || + abs(pointColl1.GetPosition().x - mesh.pos.Position.x) < BLOCK(1) && + abs(pointColl1.GetPosition().z - mesh.pos.Position.z) < BLOCK(1) && StaticObjects[mesh.staticNumber].shatterType != ShatterType::None) { if (mesh.HitPoints != 0) @@ -109,8 +111,8 @@ namespace TEN::Entities::Traps item.Pose.Position = Geometry::TranslatePoint(item.Pose.Position, item.Pose.Orientation.y, forwardVel); item.Status = ITEM_ACTIVE; - if (pointColl0.RoomNumber != item.RoomNumber) - ItemNewRoom(itemNumber, pointColl0.RoomNumber); + if (pointColl0.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl0.GetRoomNumber()); SoundEffect(SFX_TR4_ROLLING_BALL, &item.Pose); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp index 9512dc756..27a6b96e5 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp @@ -2,6 +2,7 @@ #include "tr4_joby_spikes.h" #include "Specific/level.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/animation.h" #include "Sound/sound.h" @@ -9,6 +10,8 @@ #include "Game/effects/effects.h" #include "Game/items.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::TR4 { void InitializeJobySpikes(short itemNumber) @@ -22,13 +25,13 @@ namespace TEN::Entities::TR4 item->Pose.Orientation.y = GetRandomControl() * 1024; item->ItemFlags[2] = GetRandomControl() & 1; - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); // TODO: Check this optimized division. - //v6 = 1321528399i64 * ((probe.Position.Floor - probe.Position.Ceiling) << 12); + //v6 = 1321528399i64 * ((probe.GetFloorHeight() - probe.GetCeilingHeight()) << 12); //item->itemFlags[3] = (HIDWORD(v6) >> 31) + (SHIDWORD(v6) >> 10); - item->ItemFlags[3] = (short)((probe.Position.Floor - probe.Position.Ceiling) * 1024 * 12 / 13); + item->ItemFlags[3] = (short)((probe.GetFloorHeight() - probe.GetCeilingHeight()) * 1024 * 12 / 13); } void JobySpikesControl(short itemNumber) diff --git a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp index 34d56af4d..74fc1e265 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp @@ -3,10 +3,13 @@ #include "Specific/level.h" #include "Sound/sound.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/items.h" #include "Game/animation.h" #include "Math/Math.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::TR4 { void InitializeSlicerDicer(short itemNumber) @@ -38,7 +41,7 @@ namespace TEN::Entities::TR4 item->TriggerFlags += 170; - auto probedRoomNumber = GetCollision(item).RoomNumber; + auto probedRoomNumber = GetPointCollision(*item).GetRoomNumber(); if (item->RoomNumber != probedRoomNumber) ItemNewRoom(itemNumber, probedRoomNumber); diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp index 463ef1ef8..87dcbb8eb 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/tomb4fx.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -11,6 +12,8 @@ #include "Specific/level.h" #include "Math/Math.h" +using namespace TEN::Collision::PointCollision; + namespace TEN::Entities::TR4 { constexpr auto TEETH_SPIKE_HARM_DAMAGE_CONSTANT = 8; @@ -150,7 +153,7 @@ namespace TEN::Entities::TR4 if (LaraItem->HitPoints <= 0 && Lara.Context.Vehicle == NO_ITEM) { - int heightFromFloor = GetCollision(LaraItem).Position.Floor - LaraItem->Pose.Position.y; + int heightFromFloor = GetPointCollision(*LaraItem).GetFloorHeight() - LaraItem->Pose.Position.y; if (item->Pose.Position.y >= LaraItem->Pose.Position.y && heightFromFloor < CLICK(1) && intersection == ContainmentType::CONTAINS) diff --git a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp index 25012ecac..d364c8368 100644 --- a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp +++ b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp @@ -608,7 +608,7 @@ namespace TEN::Entities::Vehicles motorbike->MomentumAngle = motorbikeItem->Pose.Orientation.y; } - floorHeight = GetCollision(motorbikeItem).Position.Floor; + floorHeight = GetPointCollision(*motorbikeItem).GetFloorHeight(); if (motorbikeItem->Pose.Position.y >= floorHeight) speed = motorbikeItem->Animation.Velocity.z * phd_cos(motorbikeItem->Pose.Orientation.x); else @@ -704,7 +704,7 @@ namespace TEN::Entities::Vehicles if (rot1) rot2 = rot1; - floorHeight = GetCollision(motorbikeItem).Position.Floor; + floorHeight = GetPointCollision(*motorbikeItem).GetFloorHeight(); if (floorHeight < (motorbikeItem->Pose.Position.y - CLICK(1))) DoMotorbikeShift(motorbikeItem, (Vector3i*)&motorbikeItem->Pose, &oldPos); @@ -747,18 +747,18 @@ namespace TEN::Entities::Vehicles auto* lara = GetLaraInfo(laraItem); short angle = motorbikeItem->Pose.Orientation.y + ANGLE(90.0f); - auto collResult = GetCollision(motorbikeItem, angle, MOTORBIKE_RADIUS); + auto collResult = GetPointCollision(*motorbikeItem, angle, MOTORBIKE_RADIUS); - if (collResult.Position.FloorSlope || collResult.Position.Floor == NO_HEIGHT) // Was previously set to -NO_HEIGHT by TokyoSU -- Lwmte 23.08.21 + if (collResult.IsIllegalFloor() || collResult.GetFloorHeight() == NO_HEIGHT) // Was previously set to -NO_HEIGHT by TokyoSU -- Lwmte 23.08.21 return false; - if (abs(collResult.Position.Floor - motorbikeItem->Pose.Position.y) > CLICK(1)) + if (abs(collResult.GetFloorHeight() - motorbikeItem->Pose.Position.y) > CLICK(1)) return false; - if ((collResult.Position.Ceiling - motorbikeItem->Pose.Position.y) > -LARA_HEIGHT) + if ((collResult.GetCeilingHeight() - motorbikeItem->Pose.Position.y) > -LARA_HEIGHT) return false; - if ((collResult.Position.Floor - collResult.Position.Ceiling) < LARA_HEIGHT) + if ((collResult.GetFloorHeight() - collResult.GetCeilingHeight()) < LARA_HEIGHT) return false; return true; @@ -1164,7 +1164,7 @@ namespace TEN::Entities::Vehicles int heightFrontRight = GetVehicleHeight(motorbikeItem, MOTORBIKE_FRONT, CLICK(0.5f), true, &frontRight); int heightFrontMiddle = GetVehicleHeight(motorbikeItem, -MOTORBIKE_FRONT, 0, true, &frontMiddle); - auto probe = GetCollision(motorbikeItem); + auto probe = GetPointCollision(*motorbikeItem); TestTriggers(motorbikeItem, true); TestTriggers(motorbikeItem, false); @@ -1189,7 +1189,7 @@ namespace TEN::Entities::Vehicles DrawMotorbikeLight(motorbikeItem); motorbikeItem->MeshBits.Set(MotorbikeHeadLightJoints); - drive = MotorbikeUserControl(motorbikeItem, laraItem, probe.Position.Floor, &pitch); + drive = MotorbikeUserControl(motorbikeItem, laraItem, probe.GetFloorHeight(), &pitch); HandleVehicleSpeedometer(motorbikeItem->Animation.Velocity.z, MOTORBIKE_ACCEL_MAX / (float)VEHICLE_VELOCITY_SCALE); } else @@ -1226,14 +1226,14 @@ namespace TEN::Entities::Vehicles if (motorbike->Velocity < MOTORBIKE_ACCEL_1) DrawMotorBikeSmoke(motorbikeItem, laraItem); - motorbikeItem->Floor = probe.Position.Floor; + motorbikeItem->Floor = probe.GetFloorHeight(); int rotation = motorbike->Velocity / 4; motorbike->LeftWheelRotation -= rotation; motorbike->RightWheelsRotation -= rotation; int newY = motorbikeItem->Pose.Position.y; - motorbikeItem->Animation.Velocity.y = DoMotorBikeDynamics(probe.Position.Floor, motorbikeItem->Animation.Velocity.y, &motorbikeItem->Pose.Position.y, 0); + motorbikeItem->Animation.Velocity.y = DoMotorBikeDynamics(probe.GetFloorHeight(), motorbikeItem->Animation.Velocity.y, &motorbikeItem->Pose.Position.y, 0); motorbike->Velocity = DoVehicleWaterMovement(motorbikeItem, laraItem, motorbike->Velocity, MOTORBIKE_RADIUS, &motorbike->TurnRate, MOTORBIKE_WAKE_OFFSET); int r1 = (frontRight.y + frontLeft.y) / 2; @@ -1267,10 +1267,10 @@ namespace TEN::Entities::Vehicles motorbikeItem->Pose.Orientation.x += (xRot - motorbikeItem->Pose.Orientation.x) / 4; motorbikeItem->Pose.Orientation.z += (zRot - motorbikeItem->Pose.Orientation.z) / 4; - if (probe.RoomNumber != motorbikeItem->RoomNumber) + if (probe.GetRoomNumber() != motorbikeItem->RoomNumber) { - ItemNewRoom(lara->Context.Vehicle, probe.RoomNumber); - ItemNewRoom(laraItem->Index, probe.RoomNumber); + ItemNewRoom(lara->Context.Vehicle, probe.GetRoomNumber()); + ItemNewRoom(laraItem->Index, probe.GetRoomNumber()); } laraItem->Pose = motorbikeItem->Pose; diff --git a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp index f617f9c76..3739b4108 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp @@ -4,6 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/effects.h" @@ -19,6 +20,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + using namespace TEN::Math; namespace TEN::Entities::Creatures::TR5 @@ -486,11 +489,11 @@ namespace TEN::Entities::Creatures::TR5 TranslateItem(item, item->Pose.Orientation, item->Animation.Velocity.z); - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); - if (item->Pose.Position.y < probe.Position.Floor && - item->Pose.Position.y > probe.Position.Ceiling && - TestEnvironment(ENV_FLAG_WATER, probe.RoomNumber)) + if (item->Pose.Position.y < probe.GetFloorHeight() && + item->Pose.Position.y > probe.GetCeilingHeight() && + TestEnvironment(ENV_FLAG_WATER, probe.GetRoomNumber())) { if (ItemNearLara(item->Pose.Position, 200)) { @@ -506,8 +509,8 @@ namespace TEN::Entities::Creatures::TR5 // if (ItemNearLara(&item->pos, 400) && Lara.anxiety < 0xE0) // Lara.anxiety += 32; - if (probe.RoomNumber != item->RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + if (probe.GetRoomNumber() != item->RoomNumber) + ItemNewRoom(itemNumber, probe.GetRoomNumber()); auto pos1 = GetJointPosition(item, 0, Vector3i(0, 0, -64)); auto pos2 = GetJointPosition(item, 0, Vector3i(0, 0, -64 << ((GlobalCounter & 1) + 2))); diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index 67c9b2bbd..da785bfd8 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -259,7 +259,7 @@ void RollingBallControl(short itemNumber) } } - auto roomNumber = GetCollision(item).RoomNumber; + auto roomNumber = GetPointCollision(*item).GetRoomNumber(); if (item->RoomNumber != roomNumber) { diff --git a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp index 5fa94b726..220ac21c6 100644 --- a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -11,8 +12,8 @@ #include "Renderer/Renderer.h" #include "Sound/sound.h" -using namespace TEN::Renderer; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::PointCollision; using namespace TEN::Math; using namespace TEN::Renderer; @@ -85,14 +86,14 @@ namespace TEN::Entities::Generic if (distToPortal <= speed) UpdateBridgeItem(*item); - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); - item->Floor = probe.Position.Floor; + item->Floor = probe.GetFloorHeight(); - if (probe.RoomNumber != item->RoomNumber) + if (probe.GetRoomNumber() != item->RoomNumber) { UpdateBridgeItem(*item, true); - ItemNewRoom(itemNumber, probe.RoomNumber); + ItemNewRoom(itemNumber, probe.GetRoomNumber()); UpdateBridgeItem(*item); } } diff --git a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp index ad6020acf..bb716d60d 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp @@ -3,12 +3,14 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/PointCollision.h" #include "Game/effects/effects.h" #include "Game/effects/item_fx.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Effects::Items; namespace TEN::Traps::TR5 @@ -85,8 +87,8 @@ namespace TEN::Traps::TR5 auto& item = g_Level.Items[itemNumber]; // Initialize barrier height. - auto pointColl = GetCollision(&item); - float barrierHeight = item.Pose.Position.y - pointColl.Position.Ceiling; + auto pointColl = GetPointCollision(item); + float barrierHeight = item.Pose.Position.y - pointColl.GetCeilingHeight(); item.ItemFlags[0] = barrierHeight; // Initialize barrier effect. diff --git a/TombEngine/Objects/TR5/Trap/ZipLine.cpp b/TombEngine/Objects/TR5/Trap/ZipLine.cpp index 252103105..d18a4dcd4 100644 --- a/TombEngine/Objects/TR5/Trap/ZipLine.cpp +++ b/TombEngine/Objects/TR5/Trap/ZipLine.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" +#include "Game/collision/PointCollision.h" #include "Game/control/box.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -12,6 +13,7 @@ #include "Sound/sound.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::PointCollision; using namespace TEN::Input; using namespace TEN::Math; @@ -129,13 +131,13 @@ namespace TEN::Traps::TR5 zipLineItem.Pose.Position.y += ((int)zipLineItem.Animation.Velocity.y >> 2); int vPos = zipLineItem.Pose.Position.y + CLICK(0.25f); - auto pointColl = GetCollision(&zipLineItem, zipLineItem.Pose.Orientation.y, zipLineItem.Animation.Velocity.y); + auto pointColl = GetPointCollision(zipLineItem, zipLineItem.Pose.Orientation.y, zipLineItem.Animation.Velocity.y); // Update zip line room number. - if (pointColl.RoomNumber != zipLineItem.RoomNumber) - ItemNewRoom(itemNumber, pointColl.RoomNumber); + if (pointColl.GetRoomNumber() != zipLineItem.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); - if (pointColl.Position.Floor <= (vPos + CLICK(1)) || pointColl.Position.Ceiling >= (vPos - CLICK(1))) + if (pointColl.GetFloorHeight() <= (vPos + CLICK(1)) || pointColl.GetCeilingHeight() >= (vPos - CLICK(1))) { // Dismount. if (laraItem.Animation.ActiveState == LS_ZIP_LINE) diff --git a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp index 7d722d741..ddb99803a 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp @@ -3,11 +3,14 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/PointCollision.h" #include "Game/control/control.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Specific/level.h" +using namespace TEN::Collision::PointCollision; + void FallingCeilingControl(short itemNumber) { auto* item = &g_Level.Items[itemNumber]; @@ -29,12 +32,12 @@ void FallingCeilingControl(short itemNumber) RemoveActiveItem(itemNumber); else { - auto probe = GetCollision(item); + auto probe = GetPointCollision(*item); - item->Floor = probe.Position.Floor; + item->Floor = probe.GetFloorHeight(); - if (probe.RoomNumber != item->RoomNumber) - ItemNewRoom(itemNumber, probe.RoomNumber); + if (probe.GetRoomNumber() != item->RoomNumber) + ItemNewRoom(itemNumber, probe.GetRoomNumber()); if (item->Animation.ActiveState == 1) { From 389ba72c44b83d9e365c48f5e5dda3656f877bfd Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 23 Feb 2024 21:56:33 +1100 Subject: [PATCH 059/410] Remove debug code --- TombEngine/Game/Lara/lara.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 9268b5f46..c8715618a 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -125,15 +125,6 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) } } - auto pointColl = GetPointCollision(*item, -Vector3::UnitY, coll->Setup.Height / 2); - - auto origin = item->Pose.Position + Vector3i(0, -BLOCK(1), 0); - g_Renderer.AddDebugLine(origin.ToVector3(), Geometry::TranslatePoint(origin, pointColl.GetFloorNormal(), BLOCK(0.5f)).ToVector3(), Vector4(0, 1, 0, 1)); - g_Renderer.AddDebugLine(origin.ToVector3(), Geometry::TranslatePoint(origin, pointColl.GetCeilingNormal(), BLOCK(0.5f)).ToVector3(), Vector4(1, 0, 0, 1)); - - g_Renderer.PrintDebugMessage("Floor bridge: %d", pointColl.GetFloorBridgeItemNumber()); - g_Renderer.PrintDebugMessage("Ceiling bridge: %d", pointColl.GetCeilingBridgeItemNumber()); - //---------- // Alert nearby creatures. From e84ddfa36dd8cd5acfa753346ea4164962015c60 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 5 Mar 2024 09:25:26 +0100 Subject: [PATCH 060/410] First experiment with 60 fps --- Documentation/output.xml | 10806 ++++++++-------- TombEngine/Game/Lara/lara.cpp | 8 + TombEngine/Game/Lara/lara.h | 1 + TombEngine/Game/camera.cpp | 1 + TombEngine/Game/camera.h | 1 + TombEngine/Game/control/control.cpp | 64 +- TombEngine/Game/control/control.h | 2 +- TombEngine/Renderer/Renderer.cpp | 5 +- TombEngine/Renderer/Renderer.h | 8 +- TombEngine/Renderer/RendererDraw.cpp | 42 +- TombEngine/Renderer/RendererFrame.cpp | 24 +- TombEngine/Renderer/RendererHelper.cpp | 5 +- TombEngine/Renderer/RendererLara.cpp | 4 +- TombEngine/Renderer/Structures/RendererItem.h | 14 + TombEngine/Specific/clock.cpp | 107 +- TombEngine/Specific/clock.h | 50 +- 16 files changed, 5647 insertions(+), 5495 deletions(-) diff --git a/Documentation/output.xml b/Documentation/output.xml index 70dc8a903..2e3a40b3c 100644 --- a/Documentation/output.xml +++ b/Documentation/output.xml @@ -1,5403 +1,5403 @@ - - - Color - Color - - - R - int - red component - - - G - int - green component - - - B - int - blue component - - - - - Color - A new Color object. - - - - - - Color - Color - - - R - int - red component - - - G - int - green component - - - B - int - blue component - - - A - int - alpha component (255 is opaque, 0 is invisible) - - - - - Color - A new Color object. - - - - - - Color - tostring - - - color - Color - this color - - - - - string - A string showing the r, g, b, and a values of the color - - - - - - View.DisplaySprite - DisplaySprite - Create a DisplaySprite object. - - - ID - Objects.ObjID - of the sprite sequence object. - - - int - int - spriteID ID of the sprite in the sequence. - - - pos - Vec2 - Display position in percent. - - - rot - float - Rotation in degrees. - - - scale - Vec2 - Horizontal and vertical scale in percent. Scaling is interpreted by the DisplaySpriteEnum.ScaleMode passed to the Draw() function call. - - - color - Color - Color. __Default: Color(255, 255, 255, 255)__ - - - - - DisplaySprite - A new DisplaySprite object. - - - - - - View.DisplaySprite - DisplaySprite - GetObjectID - Get the object ID of the sprite sequence object used by the display sprite. - () - - - Objects.ObjID - Sprite sequence object ID. - - - - - - View.DisplaySprite - DisplaySprite - GetSpriteID - Get the sprite ID in the sprite sequence object used by the display sprite. - () - - - int - Sprite ID in the sprite sequence object. - - - - - - View.DisplaySprite - DisplaySprite - GetPosition - Get the display position of the display sprite in percent. - () - - - Vec2 - Display position in percent. - - - - - - View.DisplaySprite - DisplaySprite - GetRotation - Get the rotation of the display sprite in degrees. - () - - - float - Rotation in degrees. - - - - - - View.DisplaySprite - DisplaySprite - GetScale - Get the horizontal and vertical scale of the display sprite in percent. - () - - - Vec2 - Horizontal and vertical scale in percent. - - - - - - View.DisplaySprite - DisplaySprite - GetColor - Get the color of the display sprite. - () - - - Color - Color. - - - - - - View.DisplaySprite - DisplaySprite - SetObjectID - Set the sprite sequence object ID used by the display sprite. - (Objects.ObjID) - - - New - Objects.ObjID - sprite sequence object ID. - - - - - - View.DisplaySprite - DisplaySprite - SetSpriteID - Set the sprite ID in the sprite sequence object used by the display sprite. - (int) - - - New - int - sprite ID in the sprite sequence object. - - - - - - View.DisplaySprite - DisplaySprite - SetPosition - Set the display position of the display sprite in percent. - (Vec2) - - - New - Vec2 - display position in percent. - - - - - - View.DisplaySprite - DisplaySprite - SetRotation - Set the rotation of the display sprite in degrees. - (float) - - - New - float - rotation in degrees. - - - - - - View.DisplaySprite - DisplaySprite - SetScale - Set the horizontal and vertical scale of the display sprite in percent. - (Vec2) - - - New - float - horizontal and vertical scale in percent. - - - - - - View.DisplaySprite - DisplaySprite - SetColor - Set the color of the display sprite. - (Color) - - - New - float - color. - - - - - - View.DisplaySprite - DisplaySprite - Draw - Draw the display sprite in display space for the current frame. - - - priority - int - Draw priority. Can be thought of as a layer, with higher values having precedence. __Default: 0__ - - - alignMode - View.AlignMode - Align mode interpreting an offset from the sprite's position. __Default: View.AlignMode.CENTER__ - - - scaleMode - View.ScaleMode - Scale mode interpreting the display sprite's horizontal and vertical scale. __Default: View.ScaleMode.FIT__ - - - blendMode - Effects.BlendID - Blend mode. __Default: Effects.BlendID.ALPHABLEND__ - - - - - - Effects - EmitLightningArc - Emit a lightning arc. - - - src - Vec3 - - - dest - Vec3 - - - color - Color - (default Color(255, 255, 255)) - - - lifetime - float - Lifetime in seconds. Clamped to [0, 4.233] for now because of strange internal maths. (default 1.0) - - - amplitude - int - "strength" of the lightning - the higher the value, the "taller" the arcs. Clamped to [1, 255]. (default 20) - - - beamWidth - int - Clamped to [1, 127]. (default 2) - - - detail - int - Higher numbers equal more segments, but it's not a 1:1 correlation. Clamped to [1, 127]. (default 10) - - - smooth - bool - If true, the arc will have large, smooth curves; if false, it will have small, jagged spikes. (default false) - - - endDrift - bool - If true, the end of the arc will be able to gradually drift away from its destination in a random direction (default false) - - - - - - Effects - EmitParticle - Emit a particle. - See the sprite editor in WadTool for DEFAULT_SPRITES to see a list of sprite indices. - - - pos - Vec3 - - - velocity - Vec3 - - - spriteIndex - int - an index of a sprite in DEFAULT_SPRITES object. - - - gravity - int - (default 0) Specifies whether particle will fall (positive values) or ascend (negative values) over time. Clamped to [-32768, 32767], but values between -1000 and 1000 are recommended; values too high or too low (e.g. under -2000 or above 2000) will cause the velocity of the particle to "wrap around" and switch directions. - - - rot - float - (default 0) specifies a speed with which it will rotate (0 = no rotation, negative = anticlockwise rotation, positive = clockwise rotation). - - - startColor - Color - (default Color(255, 255, 255)) color at start of life - - - endColor - Color - (default Color(255, 255, 255)) color to fade to - at the time of writing this fade will finish long before the end of the particle's life due to internal maths - - - blendMode - Effects.BlendID - (default TEN.Effects.BlendID.ALPHABLEND) How will we blend this with its surroundings? - - - startSize - int - (default 10) Size on spawn. A value of 15 is approximately the size of Lara's head. - - - endSize - int - (default 0) Size on death - the particle will linearly shrink or grow to this size during its lifespan - - - lifetime - float - (default 2) Lifespan in seconds - - - damage - bool - (default false) specifies whether particle can damage Lara (does a very small amount of damage, like the small lava emitters in TR1) - - - poison - bool - (default false) specifies whether particle can poison Lara - - - - - - Effects - EmitShockwave - Emit a shockwave, similar to that seen when a harpy projectile hits something. - - - pos - Vec3 - Origin position - - - innerRadius - int - (default 0) Initial inner radius of the shockwave circle - 128 will be approx a click, 512 approx a block - - - outerRadius - int - (default 128) Initial outer radius of the shockwave circle - - - color - Color - (default Color(255, 255, 255)) - - - lifetime - float - (default 1.0) Lifetime in seconds (max 8.5 because of inner maths weirdness) - - - speed - int - (default 50) Initial speed of the shockwave's expansion (the shockwave will always slow as it goes) - - - angle - int - (default 0) Angle about the X axis - a value of 90 will cause the shockwave to be entirely vertical - - - hurtsLara - bool - (default false) If true, the shockwave will hurt Lara, with the damage being relative to the shockwave's current speed - - - - - - Effects - EmitLight - Emit dynamic light that lasts for a single frame. - If you want a light that sticks around, you must call this each frame. - - - pos - Vec3 - - - color - Color - (default Color(255, 255, 255)) - - - radius - int - (default 20) corresponds loosely to both intensity and range - - - - - - Effects - EmitBlood - Emit blood. - - - pos - Vec3 - - - count - int - (default 1) "amount" of blood. Higher numbers won't add more blood but will make it more "flickery", with higher numbers turning it into a kind of red orb. - - - - - - Effects - EmitFire - Emit fire for one frame. - Will not hurt Lara. Call this each frame if you want a continuous fire. - - - pos - Vec3 - - - size - float - (default 1.0) - - - - - - Effects - MakeExplosion - Make an explosion. - Does not hurt Lara - - - pos - Vec3 - - - size - float - (default 512.0) this will not be the size of the sprites, but rather the distance between the origin and any additional sprites - - - shockwave - bool - (default false) if true, create a very faint white shockwave which will not hurt Lara - - - - - - Effects - MakeEarthquake - Make an earthquake - - - strength - int - (default 100) How strong should the earthquake be? Increasing this value also increases the lifespan of the earthquake. - - - - - - Flow - AddLevel - Add a level to the Flow. - - - level - Flow.Level - a level object - - - - - - Flow - SetIntroImagePath - Image to show when loading the game. - Must be a .jpg or .png image. - - - path - string - the path to the image, relative to the TombEngine exe - - - - - - Flow - SetTitleScreenImagePath - Image to show in the background of the title screen. - Must be a .jpg or .png image. -__(not yet implemented)__ - - - path - string - the path to the image, relative to the TombEngine exe - - - - - - Flow - EnableLaraInTitle - Enable or disable Lara drawing in title flyby. - Must be true or false - - - enabled - bool - true or false - - - - - - Flow - EnableLevelSelect - Enable or disable level selection in title flyby. - Must be true or false - - - enabled - bool - true or false - - - - - - Flow - EnableLoadSave - Enable or disable saving and loading of savegames. - - - enabled - bool - true or false. - - - - - - Flow - EnableFlyCheat - Enable or disable DOZY mode (fly cheat). - Must be true or false - - - enabled - bool - true or false - - - - - - Flow - EnablePointFilter - Enable or disable point texture filter. - Must be true or false - - - enabled - bool - true or false - - - - - - Flow - EnableMassPickup - Enable or disable mass pickup. - Must be true or false - - - enabled - bool - true or false - - - - - - Flow - GetLevel - Returns the level by index. - Indices depend on the order in which AddLevel was called; the first added will -have an ID of 0, the second an ID of 1, and so on. - - - index - int - of the level - - - - - Flow.Level - the level indicated by the id - - - - - - Flow - GetCurrentLevel - Returns the level that the game control is running in that moment. - - - Flow.Level - the current level - - - - - - Flow - EndLevel - Finishes the current level, with optional level index and start position index provided. - If level index is not provided or is zero, jumps to next level. If level index is more than -level count, jumps to title. If LARA\_START\_POS objects are present in level, player will be -teleported to such object with OCB similar to provided second argument. - - - index - int - level index (default 0) - - - startPos - int - player start position (default 0) - - - - - - Flow - GetGameStatus - Get current game status, such as normal game loop, exiting to title, etc. - - - Flow.GameStatus - the current game status - - - - - - Flow - SaveGame - Save the game to a savegame slot. - - - slotID - int - ID of the savegame slot to save to. - - - - - - Flow - LoadGame - Load the game from a savegame slot. - - - slotID - int - ID of the savegame slot to load from. - - - - - - Flow - DeleteSaveGame - Delete a savegame. - - - slotID - int - ID of the savegame slot to clear. - - - - - - Flow - DoesSaveGameExist - Check if a savegame exists. - - - slotID - int - ID of the savegame slot to check. - - - - - bool - true if the savegame exists, false if not. - - - - - - Flow - GetSecretCount - Returns the player's current per-game secret count. - - - int - Current game secret count. - - - - - - Flow - SetSecretCount - Sets the player's current per-game secret count. - - - count - int - new secret count. - - - - - - Flow - AddSecret - Adds one secret to current level secret count and also plays secret music track. - The index argument corresponds to the secret's unique ID, the same that would go in a secret trigger's Param. - - - index - int - an index of current level's secret (must be from 0 to 31). - - - - - - Flow - SetTotalSecretCount - Total number of secrets in game. - Must be an integer value (0 means no secrets). - - - total - int - number of secrets - - - - - - Flow - SetSettings - - - settings - Flow.Settings - a settings object - - - - - - Flow - SetAnimations - - - animations - Flow.Animations - an animations object - - - - - - Flow - SetStrings - Set string variable keys and their translations. - - - table - tab - array-style table with strings - - - - - - Flow - GetString - Get translated string. - - - string - key - key for translated string - - - - - - Flow - SetLanguageNames - Set language names for translations. - Specify which translations in the strings table correspond to which languages. - - - table - tab - array-style table with language names - - - - - - Flow.Fog - Fog - - - color - Color - RGB color - - - Min - int - Distance fog starts (in Sectors) - - - Max - int - Distance fog ends (in Sectors) - - - - - Fog - A fog object. - - - - - - Flow.InventoryItem - InventoryItem - Create an InventoryItem. - - - nameKey - string - key for the item's (localised) name.
-Corresponds to an entry in strings.lua.
-
- - objectID - Objects.ObjID - object ID of the inventory object to change - - - yOffset - float - y-axis offset (positive values move the item down).
-A value of about 100 will cause the item to display directly below its usual position.
-
- - scale - float - item size (1 being standard size).
-A value of 0.5 will cause the item to render at half the size, -and a value of 2 will cause the item to render at twice the size.
-
- - rot - Rotation - rotation around x, y, and z axes - - - axis - RotationAxis - Axis to rotate around when the item is observed at in the inventory.
-Note that this is entirely separate from the `rot` field described above. -Must one of the following: - X - Y - Z -e.g. `myItem.rotAxisWhenCurrent = RotationAxis.X`
-
- - meshBits - int - __Not currently implemented__ (will have no effect regardless of what you set it to) - - - action - ItemAction - is this usable, equippable, combineable or examinable?
-Must be one of: - EQUIP - USE - COMBINE - EXAMINE -e.g. `myItem.action = ItemAction.EXAMINE`
-
-
- - - InventoryItem - an InventoryItem - - -
- - - Flow.Level - Level - Make a new Level object. - - - Level - a Level object - - - - - - Flow.SkyLayer - SkyLayer - - - color - Color - RGB color - - - speed - int - cloud speed - - - - - SkyLayer - A SkyLayer object. - - - - - - Input - Vibrate - Vibrate the game controller if the function is available and the setting is on. - - - strength - float - Vibration strength. - - - time - float - __(default 0.3)__ Vibration time in seconds. - - - - - - Input - KeyIsHeld - Check if an action key is being held. - - - action - Input.ActionID - Action ID to check. - - - - - - Input - KeyIsHit - Check if an action key is being hit or clicked. - - - action - Input.ActionID - Action ID to check. - - - - - - Input - KeyPush - Simulate an action key push. - - - action - Input.ActionID - Action ID to push. - - - - - - Input - KeyClear - Clear an action key. - - - action - Input.ActionID - Action ID to clear. - - - - - - Input - GetMouseDisplayPosition - Get the display position of the cursor in percent. - () - - - Vec2 - Cursor display position in percent. - - - - - - Inventory - GiveItem - Add an item to the player's inventory. - - - objectID - Objects.ObjID - Object ID of the item to add. - - - count - int - The amount of items to add. Default is the yield from a single pickup, e.g. 1 from a medipack, 12 from a flare pack. - - - addToPickupSummary - bool - If true, display the item in the pickup summary. Default is false. - - - - - - Inventory - TakeItem - Remove an item from the player's inventory. - - - Object - Objects.ObjID - ID of the item to remove. - - - count - int - The amount of items to remove. Default is the yield from a single pickup, e.g. 1 from a medipack, 12 from a flare pack. - - - - - - Inventory - GetItemCount - Get the amount of an item held in the player's inventory. - - - objectID - Objects.ObjID - Object ID of the item to check. - - - - - int - The amount of items. -1 indicates infinity. - - - - - - Inventory - SetItemCount - Set the amount of an item in the player's inventory. - - - objectID - Objects.ObjID - Object ID of the item amount to set. - - - count - int - The amount of items to set. -1 indicates infinity. - - - - - - Logic - AddCallback - Register a function as a callback. - - - point - CallbackPoint - When should the callback be called? - - - func - LevelFunc - The function to be called (must be in the `LevelFuncs` hierarchy). Will receive, as an argument, the time in seconds since the last frame. - - - - - - Logic - RemoveCallback - Deregister a function as a callback. - Will have no effect if the function was not registered as a callback - - - point - CallbackPoint - The callback point the function was registered with. See @{AddCallback} - - - func - LevelFunc - The function to remove; must be in the LevelFuncs hierarchy. - - - - - - Logic - HandleEvent - Attempt to find an event set and execute a particular event from it. - - - name - string - Name of the event set to find. - - - type - EventType - Event to execute. - - - activator - Objects.Moveable - Optional activator. Default is the player object. - - - - - - Logic - EnableEvent - Attempt to find an event set and enable specified event in it. - - - name - string - Name of the event set to find. - - - type - EventType - Event to enable. - - - - - - Logic - DisableEvent - Attempt to find an event set and disable specified event in it. - - - name - string - Name of the event set to find. - - - type - EventType - Event to disable. - - - - - - Objects.AIObject - AIObject - GetPosition - Get the object's position - - - Vec3 - a copy of the object's position - - - - - - Objects.AIObject - AIObject - SetPosition - Set the object's position - - - position - Vec3 - the new position of the object - - - - - - Objects.AIObject - AIObject - GetRotationY - Get the object's Y-axis rotation. - To the best of my knowledge, the rotation of an AIObject has no effect. - - - number - the object's Y-axis rotation - - - - - - Objects.AIObject - AIObject - SetRotationY - Set the object's Y-axis rotation. - To the best of my knowledge, the rotation of an AIObject has no effect. - - - rotation - number - The object's new Y-axis rotation - - - - - - Objects.AIObject - AIObject - GetName - Get the object's unique string identifier - - - string - the object's name - - - - - - Objects.AIObject - AIObject - SetName - Set the object's name (its unique string identifier) - - - name - string - The object's new name - - - - - - Objects.AIObject - AIObject - GetRoom - Get the current room of the object - - - Room - current room of the object - - - - - - Objects.AIObject - AIObject - GetRoomNumber - Get the current room number of the object - - - int - number representing the current room of the object - - - - - - Objects.AIObject - AIObject - SetRoomNumber - Set room number of the object - This is used in conjunction with SetPosition to teleport the object to a new room. - - - ID - int - the ID of the new room - - - - - - Objects.AIObject - AIObject - GetObjectID - Retrieve the object ID - - - int - a number representing the ID of the object - - - - - - Objects.AIObject - AIObject - SetObjectID - Change the object's ID. - This will change the type of AI object it is. - Note that a baddy will gain the behaviour of the tile it's on _before_ said baddy is triggered. - This means that changing the type of an AI object beneath a moveable will have no effect. - Instead, this function can be used to change an object that the baddy isn't standing on. - For example, you could have a pair of AI_GUARD objects, and change one or the other two - AI_PATROL_1 based on whether the player has a certain item or not. - - - ID - Objects.ObjID - the new ID - - - - - - Objects.Camera - Camera - GetPosition - Get the camera's position - - - Vec3 - a copy of the camera's position - - - - - - Objects.Camera - Camera - SetPosition - Set the camera's position - - - position - Vec3 - the new position of the camera - - - - - - Objects.Camera - Camera - GetName - Get the camera's unique string identifier - - - string - the camera's name - - - - - - Objects.Camera - Camera - SetName - Set the camera's name (its unique string identifier) - - - name - string - The camera's new name - - - - - - Objects.Camera - Camera - GetRoom - Get the current room of the camera - - - Room - current room of the camera - - - - - - Objects.Camera - Camera - GetRoomNumber - Get the current room number of the camera - - - int - number representing the current room of the camera - - - - - - Objects.Camera - Camera - SetRoomNumber - Set room of camera - This is used in conjunction with SetPosition to teleport the camera to a new room. - - - ID - int - the ID of the new room - - - - - - Objects.Camera - Camera - PlayCamera - Active the camera during that frame. - - - Target - Moveable - If you put a moveable, the camera will look at it. Otherwise, it will look at Lara. - - - - - - Objects.LaraObject - LaraObject - SetPoison - Set Lara poison - - - Poison - int - ; maximum value is 128 (default 0) - - - - - - Objects.LaraObject - LaraObject - GetPoison - Get poison potency of Lara - - - int - current poison potency - - - - - - Objects.LaraObject - LaraObject - SetAir - Set air value of Lara - - - Air - int - value to give Lara. Maximum value is 1800. - - - - - - Objects.LaraObject - LaraObject - GetAir - Get air value of Lara - - - int - current air value - - - - - - Objects.LaraObject - LaraObject - SetWet - Set wetness value of Lara (causes dripping) - - - Wetness - int - value. Maximum 255 - - - - - - Objects.LaraObject - LaraObject - GetWet - Get wetness value of Lara - - - int - current wetness value - - - - - - Objects.LaraObject - LaraObject - SetStamina - Set sprint energy value of Lara - - - stamina - int - to give to Lara; maximum value is 120. - - - - - - Objects.LaraObject - LaraObject - GetStamina - Get stamina value of Lara - - - int - current sprint value - - - - - - Objects.LaraObject - Moveable - GetAirborne - Get the moveable's airborne status - - - (bool) - true if Lara state must react to aerial forces. - - - - - - Objects.LaraObject - Moveable - SetAirborne - Set the moveable's airborne status - - - New - (bool) - airborn status for Lara. - - - - - - Objects.LaraObject - LaraObject - UndrawWeapon - Lara will undraw her weapon if it is drawn and throw away a flare if she is currently holding one. - - - - Objects.LaraObject - LaraObject - ThrowAwayTorch - Lara will throw away the torch if she currently holds one in her hand. - - - - Objects.LaraObject - LaraObject - GetHandStatus - Get actual hand status of Lara - - - int - hand status 0=HandsFree, 1=Busy(climbing,etc), 2=WeaponDraw, 3=WeaponUndraw, 4=WeaponInHand. - - - - - - Objects.LaraObject - LaraObject - GetWeaponType - Get actual weapon type of Lara - - - int - weapon type 0=None, 1=Pistols, 2=Revolver, 3=Uzi, 4=Shotgun, 5=HK, 6=Crossbow, 7=Flare, 8=Torch, 9=GrenadeLauncher, 10=Harpoon, 11=RocketLauncher. - - - - - - Objects.LaraObject - LaraObject - SetWeaponType - Set Lara weapon type - - - weaponType - LaraWeaponType - Must be one of: - NONE - PISTOLS - REVOLVER - UZI - SHOTGUN - HK - CROSSBOW - FLARE - TORCH - GRENADELAUNCHER - HARPOONGUN - ROCKETLAUNCHER - - - activate - bool - true = let her also draw the weapons, set torch lit. false = let Laras new weapons remain holstered until she draws them, set torch unlit. - - - - - - Objects.LaraObject - LaraObject - GetAmmoType - Get player weapon ammo type. - - - int - player weapon ammo type - - - - - - Objects.LaraObject - LaraObject - GetAmmoCount - Get current weapon's ammo count - - - int - current ammo count (-1 if infinite) - - - - - - Objects.LaraObject - LaraObject - GetVehicle - Get current vehicle, if it exists - - - Objects.Moveable - current vehicle (nil if no vehicle present) - - - - - - Objects.LaraObject - LaraObject - GetTarget - Get the player's current targeted moveable (if it exists). - - - Objects.Moveable - Target moveable (nil if the player is not currently targeting a moveable). - - - - - - Objects.LaraObject - LaraObject - GetInteractedMoveable - Get the player's current interacted moveable (if it exists). - - - Objects.Moveable - Interacted moveable (nil if the player is not interacting with a moveable). - - - - - - Objects.LaraObject - LaraObject - TorchIsLit - Get current light state of the torch, if it exists - - - bool - is torch currently lit or not? (false if no torch exists) - - - - - - Objects.Moveable - Moveable - For more information on each parameter, see the -associated getters and setters. - If you do not know what to set for these, -most can just be ignored (see usage). - - - object - Objects.ObjID - ID - - - name - string - Lua name of the item - - - position - Vec3 - position in level - - - rotation - Rotation - rotation about x, y, and z axes (default Rotation(0, 0, 0)) - - - roomID - int - room ID item is in (default: calculated automatically) - - - animNumber - int - anim number - - - frameNumber - int - frame number - - - hp - int - HP of item - - - OCB - int - ocb of item - - - AIBits - table - table with AI bits (default { 0, 0, 0, 0, 0, 0 }) - - - - - Moveable - A new Moveable object (a wrapper around the new object) - - - - - - Objects.Moveable - Moveable - Explode - Explode item. - This also kills and disables item. - - - - Objects.Moveable - Moveable - Shatter - Shatter item. - This also kills and disables item. - - - - Objects.Moveable - Moveable - SetEffect - Set effect to moveable - - - effect - Effects.EffectID - Type of effect to assign. - - - timeout - float - time (in seconds) after which effect turns off (optional). - - - - - - Objects.Moveable - Moveable - SetCustomEffect - Set custom colored burn effect to moveable - - - Color1 - Color - color the primary color of the effect (also used for lighting). - - - Color2 - Color - color the secondary color of the effect. - - - timeout - float - time (in seconds) after which effect turns off (optional). - - - - - - Objects.Moveable - Moveable - GetEffect - Get current moveable effect - - - Effects.EffectID - effect type currently assigned to moveable. - - - - - - Objects.Moveable - Moveable - GetStatus - Get the moveable's status. - () - - - Objects.MoveableStatus - The moveable's status. - - - - - - Objects.Moveable - Moveable - SetStatus - Set the moveable's status. - () - - - status - Objects.MoveableStatus - The new status of the moveable. - - - - - - Objects.Moveable - Moveable - SetOnHit - Set the name of the function to be called when the moveable is shot by Lara. - Note that this will be triggered twice when shot with both pistols at once. - - - callback - function - function in LevelFuncs hierarchy to call when moveable is shot - - - - - - Objects.Moveable - Moveable - SetOnKilled - Set the name of the function to be called when the moveable is destroyed/killed - Note that enemy death often occurs at the end of an animation, and not at the exact moment - the enemy's HP becomes zero. - - - callback - function - function in LevelFuncs hierarchy to call when enemy is killed - - - - - - Objects.Moveable - Moveable - GetObjectID - Retrieve the object ID - - - int - a number representing the ID of the object - - - - - - Objects.Moveable - Moveable - SetObjectID - Change the object's ID. - This will literally change the object. - - - ID - Objects.ObjID - the new ID - - - - - - Objects.Moveable - Moveable - GetState - Retrieve the index of the current state. - This corresponds to the number shown in the item's state ID field in WadTool. - - - int - the index of the active state - - - - - - Objects.Moveable - Moveable - SetState - Set the object's state to the one specified by the given index. - Performs no bounds checking. *Ensure the number given is correct, else - object may end up in corrupted animation state.* - - - index - int - the index of the desired state - - - - - - Objects.Moveable - Moveable - GetAnim - Retrieve the index of the current animation. - This corresponds to the number shown in the item's animation list in WadTool. - - - int - the index of the active animation - - - - - - Objects.Moveable - Moveable - SetAnim - Set the object's animation to the one specified by the given index. - Performs no bounds checking. *Ensure the number given is correct, else - object may end up in corrupted animation state.* - - - index - int - the index of the desired anim - - - - - - Objects.Moveable - Moveable - GetFrame - Retrieve frame number. - This is the current frame of the object's active animation. - - - int - the current frame of the active animation - - - - - - Objects.Moveable - Moveable - SetVelocity - Set the object's velocity to specified value. - In most cases, only Z and Y components are used as forward and vertical velocity. - In some cases, primarily NPCs, X component is used as side velocity. - - - velocity - Vec3 - velocity represented as vector - - - - - - Objects.Moveable - Moveable - GetVelocity - Get the object's velocity. - In most cases, only Z and Y components are used as forward and vertical velocity. - In some cases, primarily NPCs, X component is used as side velocity. - - - Vec3 - current object velocity - - - - - - Objects.Moveable - Moveable - SetFrame - Set frame number. - This will move the animation to the given frame. - The number of frames in an animation can be seen under the heading "End frame" in - the WadTool animation editor. If the animation has no frames, the only valid argument - is -1. - - - frame - int - the new frame number - - - - - - Objects.Moveable - Moveable - GetSlotHP - Get HP definded for that object type (hit points/health points) (Read Only). - - - ID - int - of the moveable slot type. - - - - - - Objects.Moveable - Moveable - GetOCB - Get OCB (object code bit) of the moveable - - - int - the moveable's current OCB value - - - - - - Objects.Moveable - Moveable - SetOCB - Set OCB (object code bit) of the moveable - - - OCB - int - the new value for the moveable's OCB - - - - - - Objects.Moveable - Moveable - GetItemFlags - Get the value stored in ItemFlags[index] - - - index - int - of the ItemFlags, can be between 0 and 7. - - - - - int - the value contained in the ItemFlags[index] - - - - - - Objects.Moveable - Moveable - SetItemFlags - Stores a value in ItemFlags[index] - - - value - short - to store in the moveable's ItemFlags[index] - - - index - int - of the ItemFlags where store the value. - - - - - - Objects.Moveable - Moveable - GetColor - Get the moveable's color - - - Color - a copy of the moveable's color - - - - - - Objects.Moveable - Moveable - SetColor - Set the moveable's color - - - color - Color - the new color of the moveable - - - - - - Objects.Moveable - Moveable - GetHitStatus - Get the hit status of the object - - - bool - true if the moveable was hit by something in the last gameplay frame, false otherwise - - - - - - Objects.Moveable - Moveable - GetActive - Determine whether the moveable is active or not - - - bool - true if the moveable is active - - - - - - Objects.Moveable - Moveable - GetJointPosition - Get the object's joint position - - - index - int - of a joint to get position - - - - - Vec3 - a copy of the moveable's position - - - - - - Objects.Moveable - Moveable - GetRotation - Get the moveable's rotation - - - Rotation - a copy of the moveable's rotation - - - - - - Objects.Moveable - Moveable - SetRotation - Set the moveable's rotation - - - rotation - Rotation - The moveable's new rotation - - - - - - Objects.Moveable - Moveable - GetName - Get the moveable's name (its unique string identifier) - e.g. - "door\_back\_room" or "cracked\_greek\_statue" - This corresponds with the "Lua Name" field in an object's properties in Tomb Editor. - - - string - the moveable's name - - - - - - Objects.Moveable - Moveable - SetName - Set the moveable's name (its unique string identifier) - e.g. - "door\_back\_room" or "cracked\_greek\_statue" - It cannot be blank and cannot share a name with any existing object. - - - name - string - the new moveable's name - - - - - bool - true if we successfully set the name, false otherwise (e.g. if another object has the name already) - - - - - - Objects.Moveable - Moveable - GetValid - Test if the object is in a valid state (i.e. - has not been destroyed through Lua or killed by Lara). - - - bool - valid true if the object is still not destroyed - - - - - - Objects.Moveable - Moveable - Destroy - Destroy the moveable. - This will mean it can no longer be used, except to re-initialize it with another object. - - - - Objects.Moveable - Moveable - AttachObjCamera - Attach camera to an object. - - - mesh - int - of a target moveable to use as a camera target - - - target - Moveable - moveable to attach camera to - - - mesh - int - of a target moveable to use as a camera target - - - - - - Objects.Moveable - Moveable - AnimFromObject - Borrow animation from an object - - - ObjectID - Objects.ObjID - to take animation and stateID from, - - - animNumber - int - animation from object - - - stateID - int - state from object - - - - - - Objects.Moveable - Moveable - SetOnCollidedWithObject - Set the function to be called when this moveable collides with another moveable - - - func - function - callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. - - - - - - Objects.Moveable - Moveable - SetOnCollidedWithRoom - Set the function called when this moveable collides with room geometry (e.g. - a wall or floor). This function can take an argument that holds the @{Moveable} that collided with geometry. - - - func - function - callback function to be called (must be in LevelFuncs hierarchy) - - - - - - Objects.Moveable - Moveable - GetPosition - Get the object's position - - - Vec3 - a copy of the moveable's position - - - - - - Objects.Moveable - Moveable - SetPosition - Set the moveable's position - If you are moving a moveable whose behaviour involves knowledge of room geometry, - (e.g. - a BADDY1, which uses it for pathfinding), then the second argument should - be true (or omitted, as true is the default). Otherwise, said moveable will not behave correctly. - - - position - Vec3 - the new position of the moveable - - - updateRoom - bool - Will room changes be automatically detected? Set to false if you are using overlapping rooms (default: true) - - - - - - Objects.Moveable - Moveable - GetHP - Get current HP (hit points/health points) - - - int - the amount of HP the moveable currently has - - - - - - Objects.Moveable - Moveable - SetHP - Set current HP (hit points/health points) - Clamped to [0, 32767] for "intelligent" entities (i.e. - anything with AI); clamped to [-32767, 32767] otherwise. - - - HP - int - the amount of HP to give the moveable - - - - - - Objects.Moveable - Moveable - GetLocationAI - Get the location value stored in the Enemy AI - - - short - the value contained in the LocationAI of the creature. - - - - - - Objects.Moveable - Moveable - SetLocationAI - Updates the location in the enemy AI with the given value. - - - value - short - to store. - - - - - - Objects.Moveable - Moveable - GetAIBits - Get AIBits of object - This will return a table with six values, each corresponding to - an active behaviour. - If the object is in a certain AI mode, the table will - have a *1* in the corresponding cell. Otherwise, the cell will hold - a *0*. - -
1 - guard -
2 - ambush -
3 - patrol 1 -
4 - modify -
5 - follow -
6 - patrol 2
- - - table - a table of AI bits - - -
- - - Objects.Moveable - Moveable - SetAIBits - Set AIBits of object - Use this to force a moveable into a certain AI mode or modes, as if a certain nullmesh - (or more than one) had suddenly spawned beneath their feet. - - - bits - table - the table of AI bits - - - - - - Objects.Moveable - Moveable - GetEndFrame - Get the end frame number of the moveable's active animation. - This is the "End Frame" set in WADTool for the animation.() - - - int - End frame number of the active animation. - - - - - - Objects.Moveable - Moveable - GetRoom - Get the current room of the object - - - Objects.Room - current room of the object - - - - - - Objects.Moveable - Moveable - GetRoomNumber - Get the current room number of the object - - - int - number representing the current room of the object - - - - - - Objects.Moveable - Moveable - SetRoomNumber - Set the room ID of a moveable. - Use this if not using SetPosition's automatic room update - for example, when dealing with overlapping rooms. - - - roomID - int - New room's ID. - - - - - - Objects.Moveable - Moveable - GetMeshVisible - Get state of specified mesh visibility of object - Returns true if specified mesh is visible on an object, and false - if it is not visible. - - - index - int - index of a mesh - - - - - bool - visibility status - - - - - - Objects.Moveable - Moveable - SetMeshVisible - Makes specified mesh visible or invisible - Use this to show or hide a specified mesh of an object. - - - index - int - index of a mesh - - - isVisible - bool - true if you want the mesh to be visible, false otherwise - - - - - - Objects.Moveable - Moveable - ShatterMesh - Shatters specified mesh and makes it invisible - Note that you can re-enable mesh later by using SetMeshVisible(). - - - index - int - index of a mesh - - - - - - Objects.Moveable - Moveable - GetMeshSwapped - Get state of specified mesh swap of object - Returns true if specified mesh is swapped on an object, and false - if it is not swapped. - - - index - int - index of a mesh - - - - - bool - mesh swap status - - - - - - Objects.Moveable - Moveable - SwapMesh - Set state of specified mesh swap of object - Use this to swap specified mesh of an object. - - - index - int - index of a mesh - - - slotIndex - int - index of a slot to get meshswap from - - - swapIndex - int - index of a mesh from meshswap slot to use - - - - - - Objects.Moveable - Moveable - UnswapMesh - Set state of specified mesh swap of object - Use this to bring back original unswapped mesh - - - index - int - index of a mesh to unswap - - - - - - Objects.Moveable - Moveable - Enable - Enable the item, as if a trigger for it had been stepped on. - - - - Objects.Moveable - Moveable - Disable - Disable the item, as if an antitrigger for it had been stepped on (i.e. - it will close an open door or extinguish a flame emitter). - Note that this will not trigger an OnKilled callback. - - - - Objects.Moveable - Moveable - MakeInvisible - Make the item invisible. - Alias for `Moveable:SetVisible(false)`. - - - - Objects.Moveable - Moveable - SetVisible - Set the item's visibility. - __An invisible item will have collision turned off, as if it no longer exists in the game world__. - - - visible - bool - true if the caller should become visible, false if it should become invisible - - - - - - Objects - GetMoveableByName - Get a moveable by its name. - - - name - string - the unique name of the Moveable as set in, or generated by, Tomb Editor - - - - - Moveable - a non-owning Moveable referencing the item. - - - - - - Objects - GetStaticByName - Get a Static by its name. - - - name - string - the unique name of the mesh as set in, or generated by, Tomb Editor - - - - - Static - a non-owning Static referencing the mesh. - - - - - - Objects - GetMoveablesBySlot - Get moveables by its slot. - - - slot - Objects.ObjID - the unique slot of the Moveable, e.g. `Objects.ObjID.ANIMATING1` - - - - - table - table of Moveables referencing the given slot. - - - - - - Objects - GetStaticsBySlot - Get statics by its slot. - - - slot - int - the unique slot of the mesh like 10 - - - - - table - table of Statics referencing the given slot ID. - - - - - - Objects - GetRoomsByTag - Get rooms by tag. - - - tag - string - to select rooms by - - - - - table - table of Rooms containing the given tag. - - - - - - Objects - GetCameraByName - Get a Camera by its name. - - - name - string - the unique name of the camera as set in, or generated by, Tomb Editor - - - - - Camera - a non-owning Camera referencing the camera. - - - - - - Objects - GetSinkByName - Get a Sink by its name. - - - name - string - the unique name of the sink as set in, or generated by, Tomb Editor - - - - - Sink - a non-owning Sink referencing the sink. - - - - - - Objects - GetSoundSourceByName - Get a SoundSource by its name. - - - name - string - the unique name of the sound source as set in, or generated by, Tomb Editor - - - - - SoundSource - a non-owning SoundSource referencing the sound source. - - - - - - Objects - GetAIObjectByName - Get an AIObject by its name. - - - name - string - the unique name of the AIObject as set in, or generated by, Tomb Editor - - - - - AIObject - a non-owning SoundSource referencing the AI moveable. - - - - - - Objects - GetVolumeByName - Get a Volume by its name. - - - name - string - the unique name of the volume as set in, or generated by, Tomb Editor - - - - - Volume - a non-owning Volume referencing the room. - - - - - - Objects - GetRoomByName - Get a Room by its name. - - - name - string - the unique name of the room as set in Tomb Editor - - - - - Room - a non-owning Room referencing the room. - - - - - - Objects.Room - Room - GetActive - Determine whether the room is active or not - - - bool - true if the room is active - - - - - - Objects.Room - Room - GetColor - Get the room's ambient light color. - - - Color - ambient light color of the room - - - - - - Objects.Room - Room - GetReverbType - Get the room's reverb type. - - - Objects.RoomReverb - room's reverb type - - - - - - Objects.Room - Room - SetReverbType - Set the room's reverb type. - - - new - Objects.RoomReverb - reverb type of the room - - - - - - Objects.Room - Room - GetName - Get the room's unique string identifier. - - - string - the room's name - - - - - - Objects.Room - Room - SetName - Set the room's name (its unique string identifier). - - - name - string - The room's new name - - - - - - Objects.Room - Room - GetFlag - Get the room's specified flag value (true or false). - - - flagID - Objects.RoomFlagID - The room's flag ID - - - - - bool - the room's specified flag value - - - - - - Objects.Room - Room - SetFlag - Set the room's specified flag value. - - - flagID - Objects.RoomFlagID - The room's flag ID - - - the - bool - room's new flag value - - - - - - Objects.Room - Room - IsTagPresent - Checks if specified tag is set for this room. - - - tag - string - A text tag to check (case sensitive) - - - - - bool - true if tag is present, false if not - - - - - - Objects.Sink - Sink - GetPosition - Get the sink's position - - - Vec3 - a copy of the sink's position - - - - - - Objects.Sink - Sink - SetPosition - Set the sink's position - - - position - Vec3 - the new position of the sink - - - - - - Objects.Sink - Sink - GetName - Get the sink's unique string identifier - e.g. - "strong\_river\_current" or "propeller\_death\_sink" - - - string - the sink's name - - - - - - Objects.Sink - Sink - SetName - Set the sink's name (its unique string identifier) - - - name - string - The sink's new name - - - - - - Objects.Sink - Sink - GetStrength - Get the sink's strength - - - int - the sink's current strength - - - - - - Objects.Sink - Sink - SetStrength - Set the strength of the sink - Higher numbers provide stronger currents. - Will be clamped to [1, 32]. - - - strength - int - The sink's new strength - - - - - - Objects.SoundSource - SoundSource - GetPosition - Get the sound source's position - - - Vec3 - a copy of the sound source's position - - - - - - Objects.SoundSource - SoundSource - SetPosition - Set the sound source's position - - - position - Vec3 - the new position of the sound source - - - - - - Objects.SoundSource - SoundSource - GetName - Get the sound source's unique string identifier - - - string - the sound source's name - - - - - - Objects.SoundSource - SoundSource - SetName - Set the sound source's name (its unique string identifier) - - - name - string - The sound source's new name - - - - - - Objects.SoundSource - SoundSource - GetSoundID - Get the sound source's unique int identifier - - - int - the ID of the sound - - - - - - Objects.SoundSource - SoundSource - SetSoundID - Set the sound source's ID - __TODO__ this and getSoundID should use enums - - - name - int - The sound source's new name - - - - - - Objects.Static - Static - Enable - Enable the static, for cases when it was shattered or manually disabled before. - - - - Objects.Static - Static - Disable - Disable the static - - - - Objects.Static - Static - GetActive - Get static mesh visibility - - - bool - visibility state - - - - - - Objects.Static - Static - GetSolid - Get static mesh solid collision state - - - bool - solid collision state (true if solid, false if soft) - - - - - - Objects.Static - Static - SetSolid - Set static mesh solid collision state - - - solidState - bool - if set, collision will be solid, if not, will be soft - - - - - - Objects.Static - Static - GetPosition - Get the static's position - - - Vec3 - a copy of the static's position - - - - - - Objects.Static - Static - SetPosition - Set the static's position - - - position - Vec3 - the new position of the static - - - - - - Objects.Static - Static - GetRotation - Get the static's rotation - - - Rotation - a copy of the static's rotation - - - - - - Objects.Static - Static - SetRotation - Set the static's rotation - - - rotation - Rotation - the static's new rotation - - - - - - Objects.Static - Static - GetScale - Get the static's scale - - - float - current static scale - - - - - - Objects.Static - Static - SetScale - Set the static's scale - - - scale - Scale - the static's new scale - - - - - - Objects.Static - Static - GetName - Get the static's unique string identifier - - - string - the static's name - - - - - - Objects.Static - Static - SetName - Set the static's name (its unique string identifier) - e.g. - "my\_vase" or "oldrubble" - - - name - string - The static's new name - - - - - - Objects.Static - Static - GetSlot - Get the static's slot number (as listed in Tomb Editor and WadTool) - - - string - the static's slot number - - - - - - Objects.Static - Static - SetSlot - Set the static's slot number (as listed in Tomb Editor and WadTool) - - - slot - int - The static's slot number - - - - - - Objects.Static - Static - GetColor - Get the static's color - - - Color - a copy of the static's color - - - - - - Objects.Static - Static - SetColor - Set the static's color - - - color - Color - the new color of the static - - - - - - Objects.Static - Static - Shatter - Shatter static mesh - - - - Objects.Volume - Volume - Enable - Enable the volume. - - - - Objects.Volume - Volume - Disable - Disable the volume. - - - - Objects.Volume - Volume - GetActive - Determine whether the volume is active or not - - - bool - true if the volume is active - - - - - - Objects.Volume - Volume - GetPosition - Get the volume's position. - - - Vec3 - a copy of the volume's position - - - - - - Objects.Volume - Volume - SetPosition - Set the volume's position. - - - position - Vec3 - the new position of the volume - - - - - - Objects.Volume - Volume - GetRotation - Get the volume's rotation. - - - Rotation - a copy of the volume's rotation - - - - - - Objects.Volume - Volume - SetRotation - Set the volume's rotation. - - - rotation - Rotation - the volume's new rotation - - - - - - Objects.Volume - Volume - GetScale - Get the volume's scale (separately on all 3 axes). - - - Vec3 - current volume scale - - - - - - Objects.Volume - Volume - SetScale - Set the volume's scale (separately on all 3 axes). - - - scale - Vec3 - the volume's new scale - - - - - - Objects.Volume - Volume - GetName - Get the volume's unique string identifier. - - - string - the volume's name - - - - - - Objects.Volume - Volume - SetName - Set the volume's name (its unique string identifier). - - - name - string - The volume's new name - - - - - - Objects.Volume - Volume - ClearActivators - Clear activator list for volumes (makes volume trigger everything again) - - - - Objects.Volume - Volume - IsMoveableInside - Check if specified moveable is inside the volume - - - Moveable - Objects.Moveable - which should be checked for containment - - - - - bool - state of the moveable, true if contained, false if not - - - - - - Rotation - Rotation - - - x - float - X angle component. - - - y - float - Y angle component. - - - z - float - Z angle component. - - - - - Rotation - A Rotation. - - - - - - Rotation - tostring - - - rotation - Rotation - this Rotation. - - - - - string - A string showing the X, Y, and Z angle components of the Rotation. - - - - - - Sound - PlayAudioTrack - Play an audio track - - - name - string - of track (without file extension) to play - - - type - Sound.SoundTrackType - of the audio track to play - - - - - - Sound - SetAmbientTrack - Set and play an ambient track - - - name - string - of track (without file extension) to play - - - - - - Sound - StopAudioTracks - Stop any audio tracks currently playing - - - - Sound - StopAudioTrack - Stop audio track that is currently playing - - - type - Sound.SoundTrackType - of the audio track - - - - - - Sound - GetAudioTrackLoudness - Get current loudness level for specified track type - - - type - Sound.SoundTrackType - of the audio track - - - - - float - current loudness of a specified audio track - - - - - - Sound - PlaySound - Play sound effect - - - sound - int - ID to play. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. - - - position - Vec3 - The 3D position of the sound, i.e. where the sound "comes from". If not given, the sound will not be positional. - - - - - - Sound - StopSound - Stop sound effect - - - sound - int - ID to play. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. - - - - - - Sound - IsSoundPlaying - Check if the sound effect is playing - - - Sound - int - ID to check. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. - - - - - - Sound - IsAudioTrackPlaying - Check if the audio track is playing - - - Track - string - filename to check. Should be without extension and without full directory path. - - - - - - Sound - GetCurrentSubtitle - Get current subtitle string for a voice track currently playing. - Subtitle file must be in .srt format, have same filename as voice track, and be placed in same directory as voice track. -Returns nil if no voice track is playing or no subtitle present. - - - string - current subtitle string - - - - - - Strings.DisplayString - DisplayString - Create a DisplayString. - For use in @{Strings.ShowString|ShowString} and @{Strings.HideString|HideString}. - - - string - string - The string to display or key of the translated string. - - - Position - Vec2 - of the string in pixel coordinates. - - - scale - float - size of the string, relative to the default size. __Default: 1.0__ - - - color - Color - the color of the text. __Default: white__ - - - translated - bool - If false or omitted, the input string argument will be displayed. -If true, the string argument will be the key of a translated string specified in strings.lua. __Default: false__. - - - flags - table - A table of string display options. Can be empty or omitted. The possible values and their effects are: - TEN.Strings.DisplayStringOption.CENTER: set the horizontal origin point to the center of the string. - TEN.Strings.DisplayStringOption.RIGHT: set the horizontal origin point to right of the string. - TEN.Strings.DisplayStringOption.SHADOW: give the string a small shadow. - TEN.Strings.DisplayStringOption.BLINK: blink the string. -__Default: empty__ - - - - - DisplayString - A new DisplayString object. - - - - - - Strings.DisplayString - DisplayString - GetColor - Get the display string's color - - - Color - a copy of the display string's color - - - - - - Strings.DisplayString - DisplayString - SetColor - Set the display string's color - - - color - Color - the new color of the display string - - - - - - Strings.DisplayString - DisplayString - GetKey - Get the string key to use. - If `isTranslated` is true when @{DisplayString} - is called, this will be the string key for the translation that will be displayed. - If false or omitted, this will be the string that's displayed.() - - - string - the string to use - - - - - - Strings.DisplayString - DisplayString - SetKey - Set the string key to use. - If `isTranslated` is true when @{DisplayString} - is called, this will be the string key for the translation that will be displayed. - If false or omitted, this will be the string that's displayed.() - - - string - string - the new key for the display string - - - - - - Strings.DisplayString - DisplayString - SetScale - Set the scale of the string. - () - - - scale - float - New scale of the string relative to the default size. - - - - - - Strings.DisplayString - DisplayString - GetScale - Get the scale of the string. - () - - - float - Scale. - - - - - - Strings.DisplayString - DisplayString - SetPosition - Set the position of the string. - Screen-space coordinates are expected.() - - - pos - Vec2 - New position in pixel coordinates. - - - - - - Strings.DisplayString - DisplayString - GetPosition - Get the position of the string. - Screen-space coordinates are returned.() - - - Vec2 - pos Position in pixel coordinates. - - - - - - Strings.DisplayString - DisplayString - SetFlags - Set the display string's flags - () - - - table - table - the new table with display flags options - - - - - - Strings.DisplayString - DisplayString - SetTranslated - Set translated parameter of the string - - - shouldTranslate - bool - if true, the string's key will be used as the key for the translation that will be displayed. - If false, the key itself will be displayed - - - - - - Strings - ShowString - Show some text on-screen. - - - str - DisplayString - the string object to draw - - - time - float - the time in seconds for which to show the string. -If not given, the string will have an "infinite" life, and will show -until @{HideString} is called or until the level is finished. -Default: nil (i.e. infinite) - - - - - - Strings - HideString - Hide some on-screen text. - - - str - DisplayString - the string object to hide. Must previously have been shown -with a call to @{ShowString}, or this function will have no effect. - - - - - - Strings - IsStringDisplaying - Checks if the string is shown - - - str - DisplayString - the string object to be checked - - - - - bool - true if it is shown, false if it is hidden - - - - - - Util - HasLineOfSight - Determine if there is a clear line of sight between two positions. - NOTE: Limited to room geometry. Objects are ignored.() - - - roomID - float - Room ID of the first position's room. - - - posA - Vec3 - First position. - - - posB - Vec3 - Second position. - - - - - bool - __true__ if there is a line of sight, __false__ if not. - - - - - - Util - CalculateDistance - Calculate the distance between two positions. - - - posA - Vec3 - First position. - - - posB - Vec3 - Second position. - - - - - float - Distance between two positions. - - - - - - Util - CalculateHorizontalDistance - Calculate the horizontal distance between two positions. - - - posA - Vec3 - First position. - - - posB - Vec3 - Second position. - - - - - float - Horizontal distance between the two positions. - - - - - - Util - GetDisplayPosition - Get the projected display space position of a 3D world position. - Returns nil if the world position is behind the camera view. - - - worldPos - Vec3 - 3D world position. - - - - - Vec2 - Projected display space position in percent. - - - - - - Util - PercentToScreen - Translate a pair display position coordinates to pixel coordinates. - To be used with @{Strings.DisplayString:SetPosition} and @{Strings.DisplayString}. - - - x - float - X component of the display position. - - - y - float - Y component of the display position. - - - - - int - x X coordinate in pixels. - - - int - y Y coordinate in pixels. - - - - - - Util - ScreenToPercent - Translate a pair of pixel coordinates to display position coordinates. - To be used with @{Strings.DisplayString:GetPosition}. - - - x - int - X pixel coordinate to translate to display position. - - - y - int - Y pixel coordinate to translate to display position. - - - - - float - x X component of display position. - - - float - y Y component of display position. - - - - - - Util - PickMoveableByDisplayPosition - Pick a moveable by the given display position. - - - Display - Vec2 - space position in percent. - - - - - Objects.Moveable - Picked moveable (nil if no moveable was found under the cursor). - - - - - - Util - PickStaticByDisplayPosition - Pick a static mesh by the given display position. - - - Display - Vec2 - space position in percent. - - - - - Objects.Static - Picked static mesh (nil if no static mesh was found under the cursor). - - - - - - Util - PrintLog - Write messages within the Log file - - - message - string - to be displayed within the Log - - - logLevel - Misc.LogLevel - log level to be displayed - - - allowSpam - bool - true allows spamming of the message - - - - - - Vec2 - Vec2 - Create a Vec2 object. - (x, y) - - - x - float - X component. - - - y - float - Y component. - - - - - Vec2 - A new Vec2 object. - - - - - - Vec2 - Vec - Create a Vec2 object. - (value) - - - value - float - X and Z component. - - - - - Vec2 - A new Vec2 object. - - - - - - Vec2 - tostring - Metafunction. - Use tostring(vector). - - - This - Vec2 - Vec2. - - - - - string - A string showing the X and Y components of the Vec2. - - - - - - Vec2 - Vec2 - Normalize - Get a copy of this Vec2 normalized to length 1. - () - - - Vec2 - Normalized vector. - - - - - - Vec2 - Vec2 - Rotate - Get a copy of this Vec2 rotated by the input rotation in degrees. - (rot) - - - rot - float - Rotation in degrees. - - - - - Vec2 - Rotated Vec2. - - - - - - Vec2 - Vec2 - Lerp - Get the linearly interpolated Vec2 between this Vec2 and the input Vec2 according to the input interpolation alpha. - (vector) - - - vector - Vec2 - Target interpolation vector. - - - alpha - float - Interpolation alpha in the range [0, 1]. - - - - - Vec2 - Linearly interpolated vector - - - - - - Vec2 - Vec2 - Cross - Get the cross product of this Vec2 and the input Vec2. - (vector) - - - vector - Vec2 - Input vector. - - - - - Vec2 - Cross product. - - - - - - Vec2 - Vec2 - Dot - Get the dot product of this Vec2 and the input Vec2. - (vector) - - - vector - Vec2 - Input vector. - - - - - float - Dot product. - - - - - - Vec2 - Vec2 - Distance - Get the distance between this Vec2 and the input Vec2. - (vector) - - - vector - Vec2 - Input vector. - - - - - float - Distance. - - - - - - Vec2 - Vec2 - Length - Get the length of this Vec2. - () - - - float - Length. - - - - - - Vec3 - Vec3 - Create a Vec3 object. - (x, y, z) - - - x - float - X component. - - - y - float - Y component. - - - z - float - Z component. - - - - - Vec3 - A new Vec3 object. - - - - - - Vec3 - Vec3 - Create a Vec3 object. - (value) - - - value - float - X, Y, and Z component. - - - - - Vec3 - A new Vec3 object. - - - - - - Vec3 - Vec3 - Normalize - Get a copy of this Vec3 normalized to length 1. - () - - - Vec3 - Normalized vector. - - - - - - Vec3 - Vec3 - Rotate - Get a copy of this Vec3 rotated by the input Rotation object. - (rot) - - - rot - Rotation - Rotation object. - - - - - Vec3 - Rotated Vec3. - - - - - - Vec3 - Vec3 - Lerp - Get the linearly interpolated Vec3 between this Vec3 and the input Vec3 according to the input interpolation alpha. - (vector) - - - vector - Vec3 - Target interpolation vector. - - - alpha - float - Interpolation alpha in the range [0, 1]. - - - - - Vec3 - Linearly interpolated vector - - - - - - Vec3 - Vec3 - Cross - Get the cross product of this Vec3 and the input Vec3. - (vector) - - - vector - Vec3 - Input vector. - - - - - Vec3 - Cross product. - - - - - - Vec3 - Vec3 - Dot - Get the dot product of this Vec3 and the input Vec3. - (vector) - - - vector - Vec3 - Input vector. - - - - - float - Dot product. - - - - - - Vec3 - Vec3 - Distance - Get the distance between this Vec3 and the input Vec3. - (vector) - - - vector - Vec3 - Input vector. - - - - - float - Distance. - - - - - - Vec3 - Vec3 - Length - Get the length of this Vec3. - () - - - float - Length. - - - - - - Vec3 - tostring - Metafunction. - Use tostring(vector). - - - This - Vec3 - Vec3. - - - - - string - A string showing the X, Y, and Z components of the Vec3. - - - - - - View - FadeIn - Do a full-screen fade-in from black. - - - speed - float - (default 1.0). Speed in "amount" per second. A value of 1 will make the fade take one second. - - - - - - View - FadeOut - Do a full-screen fade-to-black. - The screen will remain black until a call to FadeIn. - - - speed - float - (default 1.0). Speed in "amount" per second. A value of 1 will make the fade take one second. - - - - - - View - SetCineBars - Move black cinematic bars in from the top and bottom of the game window. - - - height - float - __(default 30)__ Percentage of the screen to be covered - - - speed - float - __(default 30)__ Coverage percent per second - - - - - - View - SetFOV - Set field of view. - - - angle - float - in degrees (clamped to [10, 170]) - - - - - - View - GetFOV - Get field of view. - - - float - current FOV angle in degrees - - - - - - View - GetCameraType - Shows the mode of the game camera. - - - View.CameraType - value used by the Main Camera. - - - - - - View - GetCameraRoom - Gets current room where camera is positioned. - - - Objects.Room - current room of the camera - - - - - - View - SetPostProcessMode - Sets the post-process effect mode, like negative or monochrome. - - - effect - View.PostProcessMode - type to set. - - - - - - View - SetPostProcessStrength - Sets the post-process effect strength. - - - strength - float - (default 1.0). How strong the effect is. - - - - - - View - SetPostProcessTint - Sets the post-process tint. - - - tint - Color - value to use. - - - - - - View - GetCameraPosition - Gets current camera position. - - - Vec3 - current camera position - - - - - - View - GetCameraTarget - Gets current camera target. - - - Vec3 - current camera target - - - - - - View - PlayFlyBy - Enable FlyBy with specific ID - - - flyby - short - (ID of flyby) - - - - - - View - ResetObjCamera - Reset object camera back to Lara and deactivate object camera. - - - - View - FlashScreen - Flash screen. - - - color - Color - (default Color(255, 255, 255)) - - - speed - float - (default 1.0). Speed in "amount" per second. Value of 1 will make flash take one second. Clamped to [0.005, 1.0]. - - - - - - View - GetAspectRatio - Get the display resolution's aspect ratio. - - - float - Display resolution's aspect ratio. - - - - - - EventSequence - Create - Create (but do not start) a new event sequence. - - - name - string - A label to give the sequence; used to retrieve the timer later as well as internally by TEN. - - - loop - bool - if true, the sequence will start again from its first timer once its final function has been called - - - timerFormat - ?table|bool - same as in Timer. This is mainly for debugging. __This will not work properly if another sequence or timer is showing a countdown.__ - - - ... - ... - a variable number of pairs of arguments - a time in seconds, followed by the function (must be defined in the LevelFuncs table) to call once the time has elapsed, followed by another duration in seconds, another function name, etc. You can specify a function either by its name as a string, or by a table with the function name as the first member, followed by its arguments (see above example). - - - - - EventSequence - The inactive sequence. - - - - - - EventSequence - Get - Get an event sequence by its name. - - - name - string - The label that was given to the sequence when it was created - - - - - EventSequence - The sequence - - - - - - EventSequence - mySequence - SetPaused - Pause or unpause the sequence. - If showing the remaining time on-screen, its color will be set to yellow (paused) or white (unpaused). - - - p - bool - if true, the sequence will be paused; if false, it will be unpaused - - - - - - EventSequence - mySequence - IsPaused - Get whether or not the sequence is paused - - - bool - true if the timer is paused, false if otherwise - - - - - - EventSequence - mySequence - Start - Begin or unpause a sequence. - If showing the remaining time on-screen, its color will be set to white. - - - - EventSequence - mySequence - Stop - Stop the sequence. - - - - EventSequence - mySequence - IsActive - Get whether or not the sequence is active - - - bool - true if the sequence is active, false if otherwise - - - - - - Timer - Create - Create (but do not start) a new timer. - You have the option of displaying the remaining time on the clock. Timer format details: - - - name - string - A label to give this timer; used to retrieve the timer later. __Do not give your timers a name beginning with __TEN, as this is reserved for timers used by other internal libaries__. - - - totalTime - number - The duration of the timer, in seconds - - - loop - bool - if true, the timer will start again immediately after the time has elapsed - - - timerFormat - ?table|bool - If a table is given, the remaining time will be shown as a string, formatted according to the values in the table. If true, the remaining seconds, rounded up, will show at the bottom of the screen. If false, the remaining time will not be shown on screen. - - - func - func - The LevelFunc function to call when the time is up - - - ... - ... - a variable number of arguments with which the above function will be called - - - - - Timer - The timer in its paused state - - - - - - Timer - Get - Get a timer by its name. - - - name - string - The label that was given to the timer when it was created - - - - - Timer - The timer - - - - - - Timer - myTimer - SetFunction - Give the timer a new function and args - - - func - function - The LevelFunc member to call when the time is up - - - ... - ... - a variable number of arguments with which the above function will be called - - - - - - Timer - myTimer - Start - Begin or unpause a timer. - If showing the remaining time on-screen, its color will be set to white. - - - - Timer - myTimer - Stop - Stop the timer. - - - - Timer - myTimer - IsActive - Get whether or not the timer is active - - - bool - true if the timer is active, false if otherwise - - - - - - Timer - myTimer - SetPaused - Pause or unpause the timer. - If showing the remaining time on-screen, its color will be set to yellow (paused) or white (unpaused). - - - p - bool - if true, the timer will be paused; if false, it would be unpaused - - - - - - Timer - myTimer - IsPaused - Get whether or not the timer is paused - - - bool - true if the timer is paused, false if otherwise - - - - - - Timer - myTimer - GetRemainingTime - Get the remaining time for a timer. - - - float - the time in seconds remaining on the clock - - - - - - Timer - myTimer - SetRemainingTime - Set the remaining time for a timer - - - remainingTime - number - the new time remaining for the timer - - - - - - Timer - myTimer - GetTotalTime - Get the total time for a timer. - This is the amount of time the timer will start with, as well as when starting a new loop - - - float - the timer's total time - - - - - - Timer - myTimer - SetTotalTime - Set the total time for a timer - - - totalTime - number - timer's new total time - - - - - - Timer - myTimer - SetLooping - Set whether or not the timer loops - - - looping - bool - whether or not the timer loops - - - + + + Color + Color + + + R + int + red component + + + G + int + green component + + + B + int + blue component + + + + + Color + A new Color object. + + + + + + Color + Color + + + R + int + red component + + + G + int + green component + + + B + int + blue component + + + A + int + alpha component (255 is opaque, 0 is invisible) + + + + + Color + A new Color object. + + + + + + Color + tostring + + + color + Color + this color + + + + + string + A string showing the r, g, b, and a values of the color + + + + + + View.DisplaySprite + DisplaySprite + Create a DisplaySprite object. + + + ID + Objects.ObjID + of the sprite sequence object. + + + int + int + spriteID ID of the sprite in the sequence. + + + pos + Vec2 + Display position in percent. + + + rot + float + Rotation in degrees. + + + scale + Vec2 + Horizontal and vertical scale in percent. Scaling is interpreted by the DisplaySpriteEnum.ScaleMode passed to the Draw() function call. + + + color + Color + Color. __Default: Color(255, 255, 255, 255)__ + + + + + DisplaySprite + A new DisplaySprite object. + + + + + + View.DisplaySprite + DisplaySprite + GetObjectID + Get the object ID of the sprite sequence object used by the display sprite. + () + + + Objects.ObjID + Sprite sequence object ID. + + + + + + View.DisplaySprite + DisplaySprite + GetSpriteID + Get the sprite ID in the sprite sequence object used by the display sprite. + () + + + int + Sprite ID in the sprite sequence object. + + + + + + View.DisplaySprite + DisplaySprite + GetPosition + Get the display position of the display sprite in percent. + () + + + Vec2 + Display position in percent. + + + + + + View.DisplaySprite + DisplaySprite + GetRotation + Get the rotation of the display sprite in degrees. + () + + + float + Rotation in degrees. + + + + + + View.DisplaySprite + DisplaySprite + GetScale + Get the horizontal and vertical scale of the display sprite in percent. + () + + + Vec2 + Horizontal and vertical scale in percent. + + + + + + View.DisplaySprite + DisplaySprite + GetColor + Get the color of the display sprite. + () + + + Color + Color. + + + + + + View.DisplaySprite + DisplaySprite + SetObjectID + Set the sprite sequence object ID used by the display sprite. + (Objects.ObjID) + + + New + Objects.ObjID + sprite sequence object ID. + + + + + + View.DisplaySprite + DisplaySprite + SetSpriteID + Set the sprite ID in the sprite sequence object used by the display sprite. + (int) + + + New + int + sprite ID in the sprite sequence object. + + + + + + View.DisplaySprite + DisplaySprite + SetPosition + Set the display position of the display sprite in percent. + (Vec2) + + + New + Vec2 + display position in percent. + + + + + + View.DisplaySprite + DisplaySprite + SetRotation + Set the rotation of the display sprite in degrees. + (float) + + + New + float + rotation in degrees. + + + + + + View.DisplaySprite + DisplaySprite + SetScale + Set the horizontal and vertical scale of the display sprite in percent. + (Vec2) + + + New + float + horizontal and vertical scale in percent. + + + + + + View.DisplaySprite + DisplaySprite + SetColor + Set the color of the display sprite. + (Color) + + + New + float + color. + + + + + + View.DisplaySprite + DisplaySprite + Draw + Draw the display sprite in display space for the current frame. + + + priority + int + Draw priority. Can be thought of as a layer, with higher values having precedence. __Default: 0__ + + + alignMode + View.AlignMode + Align mode interpreting an offset from the sprite's position. __Default: View.AlignMode.CENTER__ + + + scaleMode + View.ScaleMode + Scale mode interpreting the display sprite's horizontal and vertical scale. __Default: View.ScaleMode.FIT__ + + + blendMode + Effects.BlendID + Blend mode. __Default: Effects.BlendID.ALPHABLEND__ + + + + + + Effects + EmitLightningArc + Emit a lightning arc. + + + src + Vec3 + + + dest + Vec3 + + + color + Color + (default Color(255, 255, 255)) + + + lifetime + float + Lifetime in seconds. Clamped to [0, 4.233] for now because of strange internal maths. (default 1.0) + + + amplitude + int + "strength" of the lightning - the higher the value, the "taller" the arcs. Clamped to [1, 255]. (default 20) + + + beamWidth + int + Clamped to [1, 127]. (default 2) + + + detail + int + Higher numbers equal more segments, but it's not a 1:1 correlation. Clamped to [1, 127]. (default 10) + + + smooth + bool + If true, the arc will have large, smooth curves; if false, it will have small, jagged spikes. (default false) + + + endDrift + bool + If true, the end of the arc will be able to gradually drift away from its destination in a random direction (default false) + + + + + + Effects + EmitParticle + Emit a particle. + See the sprite editor in WadTool for DEFAULT_SPRITES to see a list of sprite indices. + + + pos + Vec3 + + + velocity + Vec3 + + + spriteIndex + int + an index of a sprite in DEFAULT_SPRITES object. + + + gravity + int + (default 0) Specifies whether particle will fall (positive values) or ascend (negative values) over time. Clamped to [-32768, 32767], but values between -1000 and 1000 are recommended; values too high or too low (e.g. under -2000 or above 2000) will cause the velocity of the particle to "wrap around" and switch directions. + + + rot + float + (default 0) specifies a speed with which it will rotate (0 = no rotation, negative = anticlockwise rotation, positive = clockwise rotation). + + + startColor + Color + (default Color(255, 255, 255)) color at start of life + + + endColor + Color + (default Color(255, 255, 255)) color to fade to - at the time of writing this fade will finish long before the end of the particle's life due to internal maths + + + blendMode + Effects.BlendID + (default TEN.Effects.BlendID.ALPHABLEND) How will we blend this with its surroundings? + + + startSize + int + (default 10) Size on spawn. A value of 15 is approximately the size of Lara's head. + + + endSize + int + (default 0) Size on death - the particle will linearly shrink or grow to this size during its lifespan + + + lifetime + float + (default 2) Lifespan in seconds + + + damage + bool + (default false) specifies whether particle can damage Lara (does a very small amount of damage, like the small lava emitters in TR1) + + + poison + bool + (default false) specifies whether particle can poison Lara + + + + + + Effects + EmitShockwave + Emit a shockwave, similar to that seen when a harpy projectile hits something. + + + pos + Vec3 + Origin position + + + innerRadius + int + (default 0) Initial inner radius of the shockwave circle - 128 will be approx a click, 512 approx a block + + + outerRadius + int + (default 128) Initial outer radius of the shockwave circle + + + color + Color + (default Color(255, 255, 255)) + + + lifetime + float + (default 1.0) Lifetime in seconds (max 8.5 because of inner maths weirdness) + + + speed + int + (default 50) Initial speed of the shockwave's expansion (the shockwave will always slow as it goes) + + + angle + int + (default 0) Angle about the X axis - a value of 90 will cause the shockwave to be entirely vertical + + + hurtsLara + bool + (default false) If true, the shockwave will hurt Lara, with the damage being relative to the shockwave's current speed + + + + + + Effects + EmitLight + Emit dynamic light that lasts for a single frame. + If you want a light that sticks around, you must call this each frame. + + + pos + Vec3 + + + color + Color + (default Color(255, 255, 255)) + + + radius + int + (default 20) corresponds loosely to both intensity and range + + + + + + Effects + EmitBlood + Emit blood. + + + pos + Vec3 + + + count + int + (default 1) "amount" of blood. Higher numbers won't add more blood but will make it more "flickery", with higher numbers turning it into a kind of red orb. + + + + + + Effects + EmitFire + Emit fire for one frame. + Will not hurt Lara. Call this each frame if you want a continuous fire. + + + pos + Vec3 + + + size + float + (default 1.0) + + + + + + Effects + MakeExplosion + Make an explosion. + Does not hurt Lara + + + pos + Vec3 + + + size + float + (default 512.0) this will not be the size of the sprites, but rather the distance between the origin and any additional sprites + + + shockwave + bool + (default false) if true, create a very faint white shockwave which will not hurt Lara + + + + + + Effects + MakeEarthquake + Make an earthquake + + + strength + int + (default 100) How strong should the earthquake be? Increasing this value also increases the lifespan of the earthquake. + + + + + + Flow + AddLevel + Add a level to the Flow. + + + level + Flow.Level + a level object + + + + + + Flow + SetIntroImagePath + Image to show when loading the game. + Must be a .jpg or .png image. + + + path + string + the path to the image, relative to the TombEngine exe + + + + + + Flow + SetTitleScreenImagePath + Image to show in the background of the title screen. + Must be a .jpg or .png image. +__(not yet implemented)__ + + + path + string + the path to the image, relative to the TombEngine exe + + + + + + Flow + EnableLaraInTitle + Enable or disable Lara drawing in title flyby. + Must be true or false + + + enabled + bool + true or false + + + + + + Flow + EnableLevelSelect + Enable or disable level selection in title flyby. + Must be true or false + + + enabled + bool + true or false + + + + + + Flow + EnableLoadSave + Enable or disable saving and loading of savegames. + + + enabled + bool + true or false. + + + + + + Flow + EnableFlyCheat + Enable or disable DOZY mode (fly cheat). + Must be true or false + + + enabled + bool + true or false + + + + + + Flow + EnablePointFilter + Enable or disable point texture filter. + Must be true or false + + + enabled + bool + true or false + + + + + + Flow + EnableMassPickup + Enable or disable mass pickup. + Must be true or false + + + enabled + bool + true or false + + + + + + Flow + GetLevel + Returns the level by index. + Indices depend on the order in which AddLevel was called; the first added will +have an ID of 0, the second an ID of 1, and so on. + + + index + int + of the level + + + + + Flow.Level + the level indicated by the id + + + + + + Flow + GetCurrentLevel + Returns the level that the game control is running in that moment. + + + Flow.Level + the current level + + + + + + Flow + EndLevel + Finishes the current level, with optional level index and start position index provided. + If level index is not provided or is zero, jumps to next level. If level index is more than +level count, jumps to title. If LARA\_START\_POS objects are present in level, player will be +teleported to such object with OCB similar to provided second argument. + + + index + int + level index (default 0) + + + startPos + int + player start position (default 0) + + + + + + Flow + GetGameStatus + Get current game status, such as normal game loop, exiting to title, etc. + + + Flow.GameStatus + the current game status + + + + + + Flow + SaveGame + Save the game to a savegame slot. + + + slotID + int + ID of the savegame slot to save to. + + + + + + Flow + LoadGame + Load the game from a savegame slot. + + + slotID + int + ID of the savegame slot to load from. + + + + + + Flow + DeleteSaveGame + Delete a savegame. + + + slotID + int + ID of the savegame slot to clear. + + + + + + Flow + DoesSaveGameExist + Check if a savegame exists. + + + slotID + int + ID of the savegame slot to check. + + + + + bool + true if the savegame exists, false if not. + + + + + + Flow + GetSecretCount + Returns the player's current per-game secret count. + + + int + Current game secret count. + + + + + + Flow + SetSecretCount + Sets the player's current per-game secret count. + + + count + int + new secret count. + + + + + + Flow + AddSecret + Adds one secret to current level secret count and also plays secret music track. + The index argument corresponds to the secret's unique ID, the same that would go in a secret trigger's Param. + + + index + int + an index of current level's secret (must be from 0 to 31). + + + + + + Flow + SetTotalSecretCount + Total number of secrets in game. + Must be an integer value (0 means no secrets). + + + total + int + number of secrets + + + + + + Flow + SetSettings + + + settings + Flow.Settings + a settings object + + + + + + Flow + SetAnimations + + + animations + Flow.Animations + an animations object + + + + + + Flow + SetStrings + Set string variable keys and their translations. + + + table + tab + array-style table with strings + + + + + + Flow + GetString + Get translated string. + + + string + key + key for translated string + + + + + + Flow + SetLanguageNames + Set language names for translations. + Specify which translations in the strings table correspond to which languages. + + + table + tab + array-style table with language names + + + + + + Flow.Fog + Fog + + + color + Color + RGB color + + + Min + int + Distance fog starts (in Sectors) + + + Max + int + Distance fog ends (in Sectors) + + + + + Fog + A fog object. + + + + + + Flow.InventoryItem + InventoryItem + Create an InventoryItem. + + + nameKey + string + key for the item's (localised) name.
+Corresponds to an entry in strings.lua.
+
+ + objectID + Objects.ObjID + object ID of the inventory object to change + + + yOffset + float + y-axis offset (positive values move the item down).
+A value of about 100 will cause the item to display directly below its usual position.
+
+ + scale + float + item size (1 being standard size).
+A value of 0.5 will cause the item to render at half the size, +and a value of 2 will cause the item to render at twice the size.
+
+ + rot + Rotation + rotation around x, y, and z axes + + + axis + RotationAxis + Axis to rotate around when the item is observed at in the inventory.
+Note that this is entirely separate from the `rot` field described above. +Must one of the following: + X + Y + Z +e.g. `myItem.rotAxisWhenCurrent = RotationAxis.X`
+
+ + meshBits + int + __Not currently implemented__ (will have no effect regardless of what you set it to) + + + action + ItemAction + is this usable, equippable, combineable or examinable?
+Must be one of: + EQUIP + USE + COMBINE + EXAMINE +e.g. `myItem.action = ItemAction.EXAMINE`
+
+
+ + + InventoryItem + an InventoryItem + + +
+ + + Flow.Level + Level + Make a new Level object. + + + Level + a Level object + + + + + + Flow.SkyLayer + SkyLayer + + + color + Color + RGB color + + + speed + int + cloud speed + + + + + SkyLayer + A SkyLayer object. + + + + + + Input + Vibrate + Vibrate the game controller if the function is available and the setting is on. + + + strength + float + Vibration strength. + + + time + float + __(default 0.3)__ Vibration time in seconds. + + + + + + Input + KeyIsHeld + Check if an action key is being held. + + + action + Input.ActionID + Action ID to check. + + + + + + Input + KeyIsHit + Check if an action key is being hit or clicked. + + + action + Input.ActionID + Action ID to check. + + + + + + Input + KeyPush + Simulate an action key push. + + + action + Input.ActionID + Action ID to push. + + + + + + Input + KeyClear + Clear an action key. + + + action + Input.ActionID + Action ID to clear. + + + + + + Input + GetMouseDisplayPosition + Get the display position of the cursor in percent. + () + + + Vec2 + Cursor display position in percent. + + + + + + Inventory + GiveItem + Add an item to the player's inventory. + + + objectID + Objects.ObjID + Object ID of the item to add. + + + count + int + The amount of items to add. Default is the yield from a single pickup, e.g. 1 from a medipack, 12 from a flare pack. + + + addToPickupSummary + bool + If true, display the item in the pickup summary. Default is false. + + + + + + Inventory + TakeItem + Remove an item from the player's inventory. + + + Object + Objects.ObjID + ID of the item to remove. + + + count + int + The amount of items to remove. Default is the yield from a single pickup, e.g. 1 from a medipack, 12 from a flare pack. + + + + + + Inventory + GetItemCount + Get the amount of an item held in the player's inventory. + + + objectID + Objects.ObjID + Object ID of the item to check. + + + + + int + The amount of items. -1 indicates infinity. + + + + + + Inventory + SetItemCount + Set the amount of an item in the player's inventory. + + + objectID + Objects.ObjID + Object ID of the item amount to set. + + + count + int + The amount of items to set. -1 indicates infinity. + + + + + + Logic + AddCallback + Register a function as a callback. + + + point + CallbackPoint + When should the callback be called? + + + func + LevelFunc + The function to be called (must be in the `LevelFuncs` hierarchy). Will receive, as an argument, the time in seconds since the last frame. + + + + + + Logic + RemoveCallback + Deregister a function as a callback. + Will have no effect if the function was not registered as a callback + + + point + CallbackPoint + The callback point the function was registered with. See @{AddCallback} + + + func + LevelFunc + The function to remove; must be in the LevelFuncs hierarchy. + + + + + + Logic + HandleEvent + Attempt to find an event set and execute a particular event from it. + + + name + string + Name of the event set to find. + + + type + EventType + Event to execute. + + + activator + Objects.Moveable + Optional activator. Default is the player object. + + + + + + Logic + EnableEvent + Attempt to find an event set and enable specified event in it. + + + name + string + Name of the event set to find. + + + type + EventType + Event to enable. + + + + + + Logic + DisableEvent + Attempt to find an event set and disable specified event in it. + + + name + string + Name of the event set to find. + + + type + EventType + Event to disable. + + + + + + Objects.AIObject + AIObject + GetPosition + Get the object's position + + + Vec3 + a copy of the object's position + + + + + + Objects.AIObject + AIObject + SetPosition + Set the object's position + + + position + Vec3 + the new position of the object + + + + + + Objects.AIObject + AIObject + GetRotationY + Get the object's Y-axis rotation. + To the best of my knowledge, the rotation of an AIObject has no effect. + + + number + the object's Y-axis rotation + + + + + + Objects.AIObject + AIObject + SetRotationY + Set the object's Y-axis rotation. + To the best of my knowledge, the rotation of an AIObject has no effect. + + + rotation + number + The object's new Y-axis rotation + + + + + + Objects.AIObject + AIObject + GetName + Get the object's unique string identifier + + + string + the object's name + + + + + + Objects.AIObject + AIObject + SetName + Set the object's name (its unique string identifier) + + + name + string + The object's new name + + + + + + Objects.AIObject + AIObject + GetRoom + Get the current room of the object + + + Room + current room of the object + + + + + + Objects.AIObject + AIObject + GetRoomNumber + Get the current room number of the object + + + int + number representing the current room of the object + + + + + + Objects.AIObject + AIObject + SetRoomNumber + Set room number of the object + This is used in conjunction with SetPosition to teleport the object to a new room. + + + ID + int + the ID of the new room + + + + + + Objects.AIObject + AIObject + GetObjectID + Retrieve the object ID + + + int + a number representing the ID of the object + + + + + + Objects.AIObject + AIObject + SetObjectID + Change the object's ID. + This will change the type of AI object it is. + Note that a baddy will gain the behaviour of the tile it's on _before_ said baddy is triggered. + This means that changing the type of an AI object beneath a moveable will have no effect. + Instead, this function can be used to change an object that the baddy isn't standing on. + For example, you could have a pair of AI_GUARD objects, and change one or the other two + AI_PATROL_1 based on whether the player has a certain item or not. + + + ID + Objects.ObjID + the new ID + + + + + + Objects.Camera + Camera + GetPosition + Get the camera's position + + + Vec3 + a copy of the camera's position + + + + + + Objects.Camera + Camera + SetPosition + Set the camera's position + + + position + Vec3 + the new position of the camera + + + + + + Objects.Camera + Camera + GetName + Get the camera's unique string identifier + + + string + the camera's name + + + + + + Objects.Camera + Camera + SetName + Set the camera's name (its unique string identifier) + + + name + string + The camera's new name + + + + + + Objects.Camera + Camera + GetRoom + Get the current room of the camera + + + Room + current room of the camera + + + + + + Objects.Camera + Camera + GetRoomNumber + Get the current room number of the camera + + + int + number representing the current room of the camera + + + + + + Objects.Camera + Camera + SetRoomNumber + Set room of camera + This is used in conjunction with SetPosition to teleport the camera to a new room. + + + ID + int + the ID of the new room + + + + + + Objects.Camera + Camera + PlayCamera + Active the camera during that frame. + + + Target + Moveable + If you put a moveable, the camera will look at it. Otherwise, it will look at Lara. + + + + + + Objects.LaraObject + LaraObject + SetPoison + Set Lara poison + + + Poison + int + ; maximum value is 128 (default 0) + + + + + + Objects.LaraObject + LaraObject + GetPoison + Get poison potency of Lara + + + int + current poison potency + + + + + + Objects.LaraObject + LaraObject + SetAir + Set air value of Lara + + + Air + int + value to give Lara. Maximum value is 1800. + + + + + + Objects.LaraObject + LaraObject + GetAir + Get air value of Lara + + + int + current air value + + + + + + Objects.LaraObject + LaraObject + SetWet + Set wetness value of Lara (causes dripping) + + + Wetness + int + value. Maximum 255 + + + + + + Objects.LaraObject + LaraObject + GetWet + Get wetness value of Lara + + + int + current wetness value + + + + + + Objects.LaraObject + LaraObject + SetStamina + Set sprint energy value of Lara + + + stamina + int + to give to Lara; maximum value is 120. + + + + + + Objects.LaraObject + LaraObject + GetStamina + Get stamina value of Lara + + + int + current sprint value + + + + + + Objects.LaraObject + Moveable + GetAirborne + Get the moveable's airborne status + + + (bool) + true if Lara state must react to aerial forces. + + + + + + Objects.LaraObject + Moveable + SetAirborne + Set the moveable's airborne status + + + New + (bool) + airborn status for Lara. + + + + + + Objects.LaraObject + LaraObject + UndrawWeapon + Lara will undraw her weapon if it is drawn and throw away a flare if she is currently holding one. + + + + Objects.LaraObject + LaraObject + ThrowAwayTorch + Lara will throw away the torch if she currently holds one in her hand. + + + + Objects.LaraObject + LaraObject + GetHandStatus + Get actual hand status of Lara + + + int + hand status 0=HandsFree, 1=Busy(climbing,etc), 2=WeaponDraw, 3=WeaponUndraw, 4=WeaponInHand. + + + + + + Objects.LaraObject + LaraObject + GetWeaponType + Get actual weapon type of Lara + + + int + weapon type 0=None, 1=Pistols, 2=Revolver, 3=Uzi, 4=Shotgun, 5=HK, 6=Crossbow, 7=Flare, 8=Torch, 9=GrenadeLauncher, 10=Harpoon, 11=RocketLauncher. + + + + + + Objects.LaraObject + LaraObject + SetWeaponType + Set Lara weapon type + + + weaponType + LaraWeaponType + Must be one of: + NONE + PISTOLS + REVOLVER + UZI + SHOTGUN + HK + CROSSBOW + FLARE + TORCH + GRENADELAUNCHER + HARPOONGUN + ROCKETLAUNCHER + + + activate + bool + true = let her also draw the weapons, set torch lit. false = let Laras new weapons remain holstered until she draws them, set torch unlit. + + + + + + Objects.LaraObject + LaraObject + GetAmmoType + Get player weapon ammo type. + + + int + player weapon ammo type + + + + + + Objects.LaraObject + LaraObject + GetAmmoCount + Get current weapon's ammo count + + + int + current ammo count (-1 if infinite) + + + + + + Objects.LaraObject + LaraObject + GetVehicle + Get current vehicle, if it exists + + + Objects.Moveable + current vehicle (nil if no vehicle present) + + + + + + Objects.LaraObject + LaraObject + GetTarget + Get the player's current targeted moveable (if it exists). + + + Objects.Moveable + Target moveable (nil if the player is not currently targeting a moveable). + + + + + + Objects.LaraObject + LaraObject + GetInteractedMoveable + Get the player's current interacted moveable (if it exists). + + + Objects.Moveable + Interacted moveable (nil if the player is not interacting with a moveable). + + + + + + Objects.LaraObject + LaraObject + TorchIsLit + Get current light state of the torch, if it exists + + + bool + is torch currently lit or not? (false if no torch exists) + + + + + + Objects.Moveable + Moveable + For more information on each parameter, see the +associated getters and setters. + If you do not know what to set for these, +most can just be ignored (see usage). + + + object + Objects.ObjID + ID + + + name + string + Lua name of the item + + + position + Vec3 + position in level + + + rotation + Rotation + rotation about x, y, and z axes (default Rotation(0, 0, 0)) + + + roomID + int + room ID item is in (default: calculated automatically) + + + animNumber + int + anim number + + + frameNumber + int + frame number + + + hp + int + HP of item + + + OCB + int + ocb of item + + + AIBits + table + table with AI bits (default { 0, 0, 0, 0, 0, 0 }) + + + + + Moveable + A new Moveable object (a wrapper around the new object) + + + + + + Objects.Moveable + Moveable + Explode + Explode item. + This also kills and disables item. + + + + Objects.Moveable + Moveable + Shatter + Shatter item. + This also kills and disables item. + + + + Objects.Moveable + Moveable + SetEffect + Set effect to moveable + + + effect + Effects.EffectID + Type of effect to assign. + + + timeout + float + time (in seconds) after which effect turns off (optional). + + + + + + Objects.Moveable + Moveable + SetCustomEffect + Set custom colored burn effect to moveable + + + Color1 + Color + color the primary color of the effect (also used for lighting). + + + Color2 + Color + color the secondary color of the effect. + + + timeout + float + time (in seconds) after which effect turns off (optional). + + + + + + Objects.Moveable + Moveable + GetEffect + Get current moveable effect + + + Effects.EffectID + effect type currently assigned to moveable. + + + + + + Objects.Moveable + Moveable + GetStatus + Get the moveable's status. + () + + + Objects.MoveableStatus + The moveable's status. + + + + + + Objects.Moveable + Moveable + SetStatus + Set the moveable's status. + () + + + status + Objects.MoveableStatus + The new status of the moveable. + + + + + + Objects.Moveable + Moveable + SetOnHit + Set the name of the function to be called when the moveable is shot by Lara. + Note that this will be triggered twice when shot with both pistols at once. + + + callback + function + function in LevelFuncs hierarchy to call when moveable is shot + + + + + + Objects.Moveable + Moveable + SetOnKilled + Set the name of the function to be called when the moveable is destroyed/killed + Note that enemy death often occurs at the end of an animation, and not at the exact moment + the enemy's HP becomes zero. + + + callback + function + function in LevelFuncs hierarchy to call when enemy is killed + + + + + + Objects.Moveable + Moveable + GetObjectID + Retrieve the object ID + + + int + a number representing the ID of the object + + + + + + Objects.Moveable + Moveable + SetObjectID + Change the object's ID. + This will literally change the object. + + + ID + Objects.ObjID + the new ID + + + + + + Objects.Moveable + Moveable + GetState + Retrieve the index of the current state. + This corresponds to the number shown in the item's state ID field in WadTool. + + + int + the index of the active state + + + + + + Objects.Moveable + Moveable + SetState + Set the object's state to the one specified by the given index. + Performs no bounds checking. *Ensure the number given is correct, else + object may end up in corrupted animation state.* + + + index + int + the index of the desired state + + + + + + Objects.Moveable + Moveable + GetAnim + Retrieve the index of the current animation. + This corresponds to the number shown in the item's animation list in WadTool. + + + int + the index of the active animation + + + + + + Objects.Moveable + Moveable + SetAnim + Set the object's animation to the one specified by the given index. + Performs no bounds checking. *Ensure the number given is correct, else + object may end up in corrupted animation state.* + + + index + int + the index of the desired anim + + + + + + Objects.Moveable + Moveable + GetFrame + Retrieve frame number. + This is the current frame of the object's active animation. + + + int + the current frame of the active animation + + + + + + Objects.Moveable + Moveable + SetVelocity + Set the object's velocity to specified value. + In most cases, only Z and Y components are used as forward and vertical velocity. + In some cases, primarily NPCs, X component is used as side velocity. + + + velocity + Vec3 + velocity represented as vector + + + + + + Objects.Moveable + Moveable + GetVelocity + Get the object's velocity. + In most cases, only Z and Y components are used as forward and vertical velocity. + In some cases, primarily NPCs, X component is used as side velocity. + + + Vec3 + current object velocity + + + + + + Objects.Moveable + Moveable + SetFrame + Set frame number. + This will move the animation to the given frame. + The number of frames in an animation can be seen under the heading "End frame" in + the WadTool animation editor. If the animation has no frames, the only valid argument + is -1. + + + frame + int + the new frame number + + + + + + Objects.Moveable + Moveable + GetSlotHP + Get HP definded for that object type (hit points/health points) (Read Only). + + + ID + int + of the moveable slot type. + + + + + + Objects.Moveable + Moveable + GetOCB + Get OCB (object code bit) of the moveable + + + int + the moveable's current OCB value + + + + + + Objects.Moveable + Moveable + SetOCB + Set OCB (object code bit) of the moveable + + + OCB + int + the new value for the moveable's OCB + + + + + + Objects.Moveable + Moveable + GetItemFlags + Get the value stored in ItemFlags[index] + + + index + int + of the ItemFlags, can be between 0 and 7. + + + + + int + the value contained in the ItemFlags[index] + + + + + + Objects.Moveable + Moveable + SetItemFlags + Stores a value in ItemFlags[index] + + + value + short + to store in the moveable's ItemFlags[index] + + + index + int + of the ItemFlags where store the value. + + + + + + Objects.Moveable + Moveable + GetColor + Get the moveable's color + + + Color + a copy of the moveable's color + + + + + + Objects.Moveable + Moveable + SetColor + Set the moveable's color + + + color + Color + the new color of the moveable + + + + + + Objects.Moveable + Moveable + GetHitStatus + Get the hit status of the object + + + bool + true if the moveable was hit by something in the last gameplay frame, false otherwise + + + + + + Objects.Moveable + Moveable + GetActive + Determine whether the moveable is active or not + + + bool + true if the moveable is active + + + + + + Objects.Moveable + Moveable + GetJointPosition + Get the object's joint position + + + index + int + of a joint to get position + + + + + Vec3 + a copy of the moveable's position + + + + + + Objects.Moveable + Moveable + GetRotation + Get the moveable's rotation + + + Rotation + a copy of the moveable's rotation + + + + + + Objects.Moveable + Moveable + SetRotation + Set the moveable's rotation + + + rotation + Rotation + The moveable's new rotation + + + + + + Objects.Moveable + Moveable + GetName + Get the moveable's name (its unique string identifier) + e.g. + "door\_back\_room" or "cracked\_greek\_statue" + This corresponds with the "Lua Name" field in an object's properties in Tomb Editor. + + + string + the moveable's name + + + + + + Objects.Moveable + Moveable + SetName + Set the moveable's name (its unique string identifier) + e.g. + "door\_back\_room" or "cracked\_greek\_statue" + It cannot be blank and cannot share a name with any existing object. + + + name + string + the new moveable's name + + + + + bool + true if we successfully set the name, false otherwise (e.g. if another object has the name already) + + + + + + Objects.Moveable + Moveable + GetValid + Test if the object is in a valid state (i.e. + has not been destroyed through Lua or killed by Lara). + + + bool + valid true if the object is still not destroyed + + + + + + Objects.Moveable + Moveable + Destroy + Destroy the moveable. + This will mean it can no longer be used, except to re-initialize it with another object. + + + + Objects.Moveable + Moveable + AttachObjCamera + Attach camera to an object. + + + mesh + int + of a target moveable to use as a camera target + + + target + Moveable + moveable to attach camera to + + + mesh + int + of a target moveable to use as a camera target + + + + + + Objects.Moveable + Moveable + AnimFromObject + Borrow animation from an object + + + ObjectID + Objects.ObjID + to take animation and stateID from, + + + animNumber + int + animation from object + + + stateID + int + state from object + + + + + + Objects.Moveable + Moveable + SetOnCollidedWithObject + Set the function to be called when this moveable collides with another moveable + + + func + function + callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. + + + + + + Objects.Moveable + Moveable + SetOnCollidedWithRoom + Set the function called when this moveable collides with room geometry (e.g. + a wall or floor). This function can take an argument that holds the @{Moveable} that collided with geometry. + + + func + function + callback function to be called (must be in LevelFuncs hierarchy) + + + + + + Objects.Moveable + Moveable + GetPosition + Get the object's position + + + Vec3 + a copy of the moveable's position + + + + + + Objects.Moveable + Moveable + SetPosition + Set the moveable's position + If you are moving a moveable whose behaviour involves knowledge of room geometry, + (e.g. + a BADDY1, which uses it for pathfinding), then the second argument should + be true (or omitted, as true is the default). Otherwise, said moveable will not behave correctly. + + + position + Vec3 + the new position of the moveable + + + updateRoom + bool + Will room changes be automatically detected? Set to false if you are using overlapping rooms (default: true) + + + + + + Objects.Moveable + Moveable + GetHP + Get current HP (hit points/health points) + + + int + the amount of HP the moveable currently has + + + + + + Objects.Moveable + Moveable + SetHP + Set current HP (hit points/health points) + Clamped to [0, 32767] for "intelligent" entities (i.e. + anything with AI); clamped to [-32767, 32767] otherwise. + + + HP + int + the amount of HP to give the moveable + + + + + + Objects.Moveable + Moveable + GetLocationAI + Get the location value stored in the Enemy AI + + + short + the value contained in the LocationAI of the creature. + + + + + + Objects.Moveable + Moveable + SetLocationAI + Updates the location in the enemy AI with the given value. + + + value + short + to store. + + + + + + Objects.Moveable + Moveable + GetAIBits + Get AIBits of object + This will return a table with six values, each corresponding to + an active behaviour. + If the object is in a certain AI mode, the table will + have a *1* in the corresponding cell. Otherwise, the cell will hold + a *0*. + +
1 - guard +
2 - ambush +
3 - patrol 1 +
4 - modify +
5 - follow +
6 - patrol 2
+ + + table + a table of AI bits + + +
+ + + Objects.Moveable + Moveable + SetAIBits + Set AIBits of object + Use this to force a moveable into a certain AI mode or modes, as if a certain nullmesh + (or more than one) had suddenly spawned beneath their feet. + + + bits + table + the table of AI bits + + + + + + Objects.Moveable + Moveable + GetEndFrame + Get the end frame number of the moveable's active animation. + This is the "End Frame" set in WADTool for the animation.() + + + int + End frame number of the active animation. + + + + + + Objects.Moveable + Moveable + GetRoom + Get the current room of the object + + + Objects.Room + current room of the object + + + + + + Objects.Moveable + Moveable + GetRoomNumber + Get the current room number of the object + + + int + number representing the current room of the object + + + + + + Objects.Moveable + Moveable + SetRoomNumber + Set the room ID of a moveable. + Use this if not using SetPosition's automatic room update - for example, when dealing with overlapping rooms. + + + roomID + int + New room's ID. + + + + + + Objects.Moveable + Moveable + GetMeshVisible + Get state of specified mesh visibility of object + Returns true if specified mesh is visible on an object, and false + if it is not visible. + + + index + int + index of a mesh + + + + + bool + visibility status + + + + + + Objects.Moveable + Moveable + SetMeshVisible + Makes specified mesh visible or invisible + Use this to show or hide a specified mesh of an object. + + + index + int + index of a mesh + + + isVisible + bool + true if you want the mesh to be visible, false otherwise + + + + + + Objects.Moveable + Moveable + ShatterMesh + Shatters specified mesh and makes it invisible + Note that you can re-enable mesh later by using SetMeshVisible(). + + + index + int + index of a mesh + + + + + + Objects.Moveable + Moveable + GetMeshSwapped + Get state of specified mesh swap of object + Returns true if specified mesh is swapped on an object, and false + if it is not swapped. + + + index + int + index of a mesh + + + + + bool + mesh swap status + + + + + + Objects.Moveable + Moveable + SwapMesh + Set state of specified mesh swap of object + Use this to swap specified mesh of an object. + + + index + int + index of a mesh + + + slotIndex + int + index of a slot to get meshswap from + + + swapIndex + int + index of a mesh from meshswap slot to use + + + + + + Objects.Moveable + Moveable + UnswapMesh + Set state of specified mesh swap of object + Use this to bring back original unswapped mesh + + + index + int + index of a mesh to unswap + + + + + + Objects.Moveable + Moveable + Enable + Enable the item, as if a trigger for it had been stepped on. + + + + Objects.Moveable + Moveable + Disable + Disable the item, as if an antitrigger for it had been stepped on (i.e. + it will close an open door or extinguish a flame emitter). + Note that this will not trigger an OnKilled callback. + + + + Objects.Moveable + Moveable + MakeInvisible + Make the item invisible. + Alias for `Moveable:SetVisible(false)`. + + + + Objects.Moveable + Moveable + SetVisible + Set the item's visibility. + __An invisible item will have collision turned off, as if it no longer exists in the game world__. + + + visible + bool + true if the caller should become visible, false if it should become invisible + + + + + + Objects + GetMoveableByName + Get a moveable by its name. + + + name + string + the unique name of the Moveable as set in, or generated by, Tomb Editor + + + + + Moveable + a non-owning Moveable referencing the item. + + + + + + Objects + GetStaticByName + Get a Static by its name. + + + name + string + the unique name of the mesh as set in, or generated by, Tomb Editor + + + + + Static + a non-owning Static referencing the mesh. + + + + + + Objects + GetMoveablesBySlot + Get moveables by its slot. + + + slot + Objects.ObjID + the unique slot of the Moveable, e.g. `Objects.ObjID.ANIMATING1` + + + + + table + table of Moveables referencing the given slot. + + + + + + Objects + GetStaticsBySlot + Get statics by its slot. + + + slot + int + the unique slot of the mesh like 10 + + + + + table + table of Statics referencing the given slot ID. + + + + + + Objects + GetRoomsByTag + Get rooms by tag. + + + tag + string + to select rooms by + + + + + table + table of Rooms containing the given tag. + + + + + + Objects + GetCameraByName + Get a Camera by its name. + + + name + string + the unique name of the camera as set in, or generated by, Tomb Editor + + + + + Camera + a non-owning Camera referencing the camera. + + + + + + Objects + GetSinkByName + Get a Sink by its name. + + + name + string + the unique name of the sink as set in, or generated by, Tomb Editor + + + + + Sink + a non-owning Sink referencing the sink. + + + + + + Objects + GetSoundSourceByName + Get a SoundSource by its name. + + + name + string + the unique name of the sound source as set in, or generated by, Tomb Editor + + + + + SoundSource + a non-owning SoundSource referencing the sound source. + + + + + + Objects + GetAIObjectByName + Get an AIObject by its name. + + + name + string + the unique name of the AIObject as set in, or generated by, Tomb Editor + + + + + AIObject + a non-owning SoundSource referencing the AI moveable. + + + + + + Objects + GetVolumeByName + Get a Volume by its name. + + + name + string + the unique name of the volume as set in, or generated by, Tomb Editor + + + + + Volume + a non-owning Volume referencing the room. + + + + + + Objects + GetRoomByName + Get a Room by its name. + + + name + string + the unique name of the room as set in Tomb Editor + + + + + Room + a non-owning Room referencing the room. + + + + + + Objects.Room + Room + GetActive + Determine whether the room is active or not + + + bool + true if the room is active + + + + + + Objects.Room + Room + GetColor + Get the room's ambient light color. + + + Color + ambient light color of the room + + + + + + Objects.Room + Room + GetReverbType + Get the room's reverb type. + + + Objects.RoomReverb + room's reverb type + + + + + + Objects.Room + Room + SetReverbType + Set the room's reverb type. + + + new + Objects.RoomReverb + reverb type of the room + + + + + + Objects.Room + Room + GetName + Get the room's unique string identifier. + + + string + the room's name + + + + + + Objects.Room + Room + SetName + Set the room's name (its unique string identifier). + + + name + string + The room's new name + + + + + + Objects.Room + Room + GetFlag + Get the room's specified flag value (true or false). + + + flagID + Objects.RoomFlagID + The room's flag ID + + + + + bool + the room's specified flag value + + + + + + Objects.Room + Room + SetFlag + Set the room's specified flag value. + + + flagID + Objects.RoomFlagID + The room's flag ID + + + the + bool + room's new flag value + + + + + + Objects.Room + Room + IsTagPresent + Checks if specified tag is set for this room. + + + tag + string + A text tag to check (case sensitive) + + + + + bool + true if tag is present, false if not + + + + + + Objects.Sink + Sink + GetPosition + Get the sink's position + + + Vec3 + a copy of the sink's position + + + + + + Objects.Sink + Sink + SetPosition + Set the sink's position + + + position + Vec3 + the new position of the sink + + + + + + Objects.Sink + Sink + GetName + Get the sink's unique string identifier + e.g. + "strong\_river\_current" or "propeller\_death\_sink" + + + string + the sink's name + + + + + + Objects.Sink + Sink + SetName + Set the sink's name (its unique string identifier) + + + name + string + The sink's new name + + + + + + Objects.Sink + Sink + GetStrength + Get the sink's strength + + + int + the sink's current strength + + + + + + Objects.Sink + Sink + SetStrength + Set the strength of the sink + Higher numbers provide stronger currents. + Will be clamped to [1, 32]. + + + strength + int + The sink's new strength + + + + + + Objects.SoundSource + SoundSource + GetPosition + Get the sound source's position + + + Vec3 + a copy of the sound source's position + + + + + + Objects.SoundSource + SoundSource + SetPosition + Set the sound source's position + + + position + Vec3 + the new position of the sound source + + + + + + Objects.SoundSource + SoundSource + GetName + Get the sound source's unique string identifier + + + string + the sound source's name + + + + + + Objects.SoundSource + SoundSource + SetName + Set the sound source's name (its unique string identifier) + + + name + string + The sound source's new name + + + + + + Objects.SoundSource + SoundSource + GetSoundID + Get the sound source's unique int identifier + + + int + the ID of the sound + + + + + + Objects.SoundSource + SoundSource + SetSoundID + Set the sound source's ID + __TODO__ this and getSoundID should use enums + + + name + int + The sound source's new name + + + + + + Objects.Static + Static + Enable + Enable the static, for cases when it was shattered or manually disabled before. + + + + Objects.Static + Static + Disable + Disable the static + + + + Objects.Static + Static + GetActive + Get static mesh visibility + + + bool + visibility state + + + + + + Objects.Static + Static + GetSolid + Get static mesh solid collision state + + + bool + solid collision state (true if solid, false if soft) + + + + + + Objects.Static + Static + SetSolid + Set static mesh solid collision state + + + solidState + bool + if set, collision will be solid, if not, will be soft + + + + + + Objects.Static + Static + GetPosition + Get the static's position + + + Vec3 + a copy of the static's position + + + + + + Objects.Static + Static + SetPosition + Set the static's position + + + position + Vec3 + the new position of the static + + + + + + Objects.Static + Static + GetRotation + Get the static's rotation + + + Rotation + a copy of the static's rotation + + + + + + Objects.Static + Static + SetRotation + Set the static's rotation + + + rotation + Rotation + the static's new rotation + + + + + + Objects.Static + Static + GetScale + Get the static's scale + + + float + current static scale + + + + + + Objects.Static + Static + SetScale + Set the static's scale + + + scale + Scale + the static's new scale + + + + + + Objects.Static + Static + GetName + Get the static's unique string identifier + + + string + the static's name + + + + + + Objects.Static + Static + SetName + Set the static's name (its unique string identifier) + e.g. + "my\_vase" or "oldrubble" + + + name + string + The static's new name + + + + + + Objects.Static + Static + GetSlot + Get the static's slot number (as listed in Tomb Editor and WadTool) + + + string + the static's slot number + + + + + + Objects.Static + Static + SetSlot + Set the static's slot number (as listed in Tomb Editor and WadTool) + + + slot + int + The static's slot number + + + + + + Objects.Static + Static + GetColor + Get the static's color + + + Color + a copy of the static's color + + + + + + Objects.Static + Static + SetColor + Set the static's color + + + color + Color + the new color of the static + + + + + + Objects.Static + Static + Shatter + Shatter static mesh + + + + Objects.Volume + Volume + Enable + Enable the volume. + + + + Objects.Volume + Volume + Disable + Disable the volume. + + + + Objects.Volume + Volume + GetActive + Determine whether the volume is active or not + + + bool + true if the volume is active + + + + + + Objects.Volume + Volume + GetPosition + Get the volume's position. + + + Vec3 + a copy of the volume's position + + + + + + Objects.Volume + Volume + SetPosition + Set the volume's position. + + + position + Vec3 + the new position of the volume + + + + + + Objects.Volume + Volume + GetRotation + Get the volume's rotation. + + + Rotation + a copy of the volume's rotation + + + + + + Objects.Volume + Volume + SetRotation + Set the volume's rotation. + + + rotation + Rotation + the volume's new rotation + + + + + + Objects.Volume + Volume + GetScale + Get the volume's scale (separately on all 3 axes). + + + Vec3 + current volume scale + + + + + + Objects.Volume + Volume + SetScale + Set the volume's scale (separately on all 3 axes). + + + scale + Vec3 + the volume's new scale + + + + + + Objects.Volume + Volume + GetName + Get the volume's unique string identifier. + + + string + the volume's name + + + + + + Objects.Volume + Volume + SetName + Set the volume's name (its unique string identifier). + + + name + string + The volume's new name + + + + + + Objects.Volume + Volume + ClearActivators + Clear activator list for volumes (makes volume trigger everything again) + + + + Objects.Volume + Volume + IsMoveableInside + Check if specified moveable is inside the volume + + + Moveable + Objects.Moveable + which should be checked for containment + + + + + bool + state of the moveable, true if contained, false if not + + + + + + Rotation + Rotation + + + x + float + X angle component. + + + y + float + Y angle component. + + + z + float + Z angle component. + + + + + Rotation + A Rotation. + + + + + + Rotation + tostring + + + rotation + Rotation + this Rotation. + + + + + string + A string showing the X, Y, and Z angle components of the Rotation. + + + + + + Sound + PlayAudioTrack + Play an audio track + + + name + string + of track (without file extension) to play + + + type + Sound.SoundTrackType + of the audio track to play + + + + + + Sound + SetAmbientTrack + Set and play an ambient track + + + name + string + of track (without file extension) to play + + + + + + Sound + StopAudioTracks + Stop any audio tracks currently playing + + + + Sound + StopAudioTrack + Stop audio track that is currently playing + + + type + Sound.SoundTrackType + of the audio track + + + + + + Sound + GetAudioTrackLoudness + Get current loudness level for specified track type + + + type + Sound.SoundTrackType + of the audio track + + + + + float + current loudness of a specified audio track + + + + + + Sound + PlaySound + Play sound effect + + + sound + int + ID to play. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. + + + position + Vec3 + The 3D position of the sound, i.e. where the sound "comes from". If not given, the sound will not be positional. + + + + + + Sound + StopSound + Stop sound effect + + + sound + int + ID to play. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. + + + + + + Sound + IsSoundPlaying + Check if the sound effect is playing + + + Sound + int + ID to check. Corresponds to the value in the sound XML file or Tomb Editor's "Sound Infos" window. + + + + + + Sound + IsAudioTrackPlaying + Check if the audio track is playing + + + Track + string + filename to check. Should be without extension and without full directory path. + + + + + + Sound + GetCurrentSubtitle + Get current subtitle string for a voice track currently playing. + Subtitle file must be in .srt format, have same filename as voice track, and be placed in same directory as voice track. +Returns nil if no voice track is playing or no subtitle present. + + + string + current subtitle string + + + + + + Strings.DisplayString + DisplayString + Create a DisplayString. + For use in @{Strings.ShowString|ShowString} and @{Strings.HideString|HideString}. + + + string + string + The string to display or key of the translated string. + + + Position + Vec2 + of the string in pixel coordinates. + + + scale + float + size of the string, relative to the default size. __Default: 1.0__ + + + color + Color + the color of the text. __Default: white__ + + + translated + bool + If false or omitted, the input string argument will be displayed. +If true, the string argument will be the key of a translated string specified in strings.lua. __Default: false__. + + + flags + table + A table of string display options. Can be empty or omitted. The possible values and their effects are: + TEN.Strings.DisplayStringOption.CENTER: set the horizontal origin point to the center of the string. + TEN.Strings.DisplayStringOption.RIGHT: set the horizontal origin point to right of the string. + TEN.Strings.DisplayStringOption.SHADOW: give the string a small shadow. + TEN.Strings.DisplayStringOption.BLINK: blink the string. +__Default: empty__ + + + + + DisplayString + A new DisplayString object. + + + + + + Strings.DisplayString + DisplayString + GetColor + Get the display string's color + + + Color + a copy of the display string's color + + + + + + Strings.DisplayString + DisplayString + SetColor + Set the display string's color + + + color + Color + the new color of the display string + + + + + + Strings.DisplayString + DisplayString + GetKey + Get the string key to use. + If `isTranslated` is true when @{DisplayString} + is called, this will be the string key for the translation that will be displayed. + If false or omitted, this will be the string that's displayed.() + + + string + the string to use + + + + + + Strings.DisplayString + DisplayString + SetKey + Set the string key to use. + If `isTranslated` is true when @{DisplayString} + is called, this will be the string key for the translation that will be displayed. + If false or omitted, this will be the string that's displayed.() + + + string + string + the new key for the display string + + + + + + Strings.DisplayString + DisplayString + SetScale + Set the scale of the string. + () + + + scale + float + New scale of the string relative to the default size. + + + + + + Strings.DisplayString + DisplayString + GetScale + Get the scale of the string. + () + + + float + Scale. + + + + + + Strings.DisplayString + DisplayString + SetPosition + Set the position of the string. + Screen-space coordinates are expected.() + + + pos + Vec2 + New position in pixel coordinates. + + + + + + Strings.DisplayString + DisplayString + GetPosition + Get the position of the string. + Screen-space coordinates are returned.() + + + Vec2 + pos Position in pixel coordinates. + + + + + + Strings.DisplayString + DisplayString + SetFlags + Set the display string's flags + () + + + table + table + the new table with display flags options + + + + + + Strings.DisplayString + DisplayString + SetTranslated + Set translated parameter of the string + + + shouldTranslate + bool + if true, the string's key will be used as the key for the translation that will be displayed. + If false, the key itself will be displayed + + + + + + Strings + ShowString + Show some text on-screen. + + + str + DisplayString + the string object to draw + + + time + float + the time in seconds for which to show the string. +If not given, the string will have an "infinite" life, and will show +until @{HideString} is called or until the level is finished. +Default: nil (i.e. infinite) + + + + + + Strings + HideString + Hide some on-screen text. + + + str + DisplayString + the string object to hide. Must previously have been shown +with a call to @{ShowString}, or this function will have no effect. + + + + + + Strings + IsStringDisplaying + Checks if the string is shown + + + str + DisplayString + the string object to be checked + + + + + bool + true if it is shown, false if it is hidden + + + + + + Util + HasLineOfSight + Determine if there is a clear line of sight between two positions. + NOTE: Limited to room geometry. Objects are ignored.() + + + roomID + float + Room ID of the first position's room. + + + posA + Vec3 + First position. + + + posB + Vec3 + Second position. + + + + + bool + __true__ if there is a line of sight, __false__ if not. + + + + + + Util + CalculateDistance + Calculate the distance between two positions. + + + posA + Vec3 + First position. + + + posB + Vec3 + Second position. + + + + + float + Distance between two positions. + + + + + + Util + CalculateHorizontalDistance + Calculate the horizontal distance between two positions. + + + posA + Vec3 + First position. + + + posB + Vec3 + Second position. + + + + + float + Horizontal distance between the two positions. + + + + + + Util + GetDisplayPosition + Get the projected display space position of a 3D world position. + Returns nil if the world position is behind the camera view. + + + worldPos + Vec3 + 3D world position. + + + + + Vec2 + Projected display space position in percent. + + + + + + Util + PercentToScreen + Translate a pair display position coordinates to pixel coordinates. + To be used with @{Strings.DisplayString:SetPosition} and @{Strings.DisplayString}. + + + x + float + X component of the display position. + + + y + float + Y component of the display position. + + + + + int + x X coordinate in pixels. + + + int + y Y coordinate in pixels. + + + + + + Util + ScreenToPercent + Translate a pair of pixel coordinates to display position coordinates. + To be used with @{Strings.DisplayString:GetPosition}. + + + x + int + X pixel coordinate to translate to display position. + + + y + int + Y pixel coordinate to translate to display position. + + + + + float + x X component of display position. + + + float + y Y component of display position. + + + + + + Util + PickMoveableByDisplayPosition + Pick a moveable by the given display position. + + + Display + Vec2 + space position in percent. + + + + + Objects.Moveable + Picked moveable (nil if no moveable was found under the cursor). + + + + + + Util + PickStaticByDisplayPosition + Pick a static mesh by the given display position. + + + Display + Vec2 + space position in percent. + + + + + Objects.Static + Picked static mesh (nil if no static mesh was found under the cursor). + + + + + + Util + PrintLog + Write messages within the Log file + + + message + string + to be displayed within the Log + + + logLevel + Misc.LogLevel + log level to be displayed + + + allowSpam + bool + true allows spamming of the message + + + + + + Vec2 + Vec2 + Create a Vec2 object. + (x, y) + + + x + float + X component. + + + y + float + Y component. + + + + + Vec2 + A new Vec2 object. + + + + + + Vec2 + Vec + Create a Vec2 object. + (value) + + + value + float + X and Z component. + + + + + Vec2 + A new Vec2 object. + + + + + + Vec2 + tostring + Metafunction. + Use tostring(vector). + + + This + Vec2 + Vec2. + + + + + string + A string showing the X and Y components of the Vec2. + + + + + + Vec2 + Vec2 + Normalize + Get a copy of this Vec2 normalized to length 1. + () + + + Vec2 + Normalized vector. + + + + + + Vec2 + Vec2 + Rotate + Get a copy of this Vec2 rotated by the input rotation in degrees. + (rot) + + + rot + float + Rotation in degrees. + + + + + Vec2 + Rotated Vec2. + + + + + + Vec2 + Vec2 + Lerp + Get the linearly interpolated Vec2 between this Vec2 and the input Vec2 according to the input interpolation alpha. + (vector) + + + vector + Vec2 + Target interpolation vector. + + + alpha + float + Interpolation alpha in the range [0, 1]. + + + + + Vec2 + Linearly interpolated vector + + + + + + Vec2 + Vec2 + Cross + Get the cross product of this Vec2 and the input Vec2. + (vector) + + + vector + Vec2 + Input vector. + + + + + Vec2 + Cross product. + + + + + + Vec2 + Vec2 + Dot + Get the dot product of this Vec2 and the input Vec2. + (vector) + + + vector + Vec2 + Input vector. + + + + + float + Dot product. + + + + + + Vec2 + Vec2 + Distance + Get the distance between this Vec2 and the input Vec2. + (vector) + + + vector + Vec2 + Input vector. + + + + + float + Distance. + + + + + + Vec2 + Vec2 + Length + Get the length of this Vec2. + () + + + float + Length. + + + + + + Vec3 + Vec3 + Create a Vec3 object. + (x, y, z) + + + x + float + X component. + + + y + float + Y component. + + + z + float + Z component. + + + + + Vec3 + A new Vec3 object. + + + + + + Vec3 + Vec3 + Create a Vec3 object. + (value) + + + value + float + X, Y, and Z component. + + + + + Vec3 + A new Vec3 object. + + + + + + Vec3 + Vec3 + Normalize + Get a copy of this Vec3 normalized to length 1. + () + + + Vec3 + Normalized vector. + + + + + + Vec3 + Vec3 + Rotate + Get a copy of this Vec3 rotated by the input Rotation object. + (rot) + + + rot + Rotation + Rotation object. + + + + + Vec3 + Rotated Vec3. + + + + + + Vec3 + Vec3 + Lerp + Get the linearly interpolated Vec3 between this Vec3 and the input Vec3 according to the input interpolation alpha. + (vector) + + + vector + Vec3 + Target interpolation vector. + + + alpha + float + Interpolation alpha in the range [0, 1]. + + + + + Vec3 + Linearly interpolated vector + + + + + + Vec3 + Vec3 + Cross + Get the cross product of this Vec3 and the input Vec3. + (vector) + + + vector + Vec3 + Input vector. + + + + + Vec3 + Cross product. + + + + + + Vec3 + Vec3 + Dot + Get the dot product of this Vec3 and the input Vec3. + (vector) + + + vector + Vec3 + Input vector. + + + + + float + Dot product. + + + + + + Vec3 + Vec3 + Distance + Get the distance between this Vec3 and the input Vec3. + (vector) + + + vector + Vec3 + Input vector. + + + + + float + Distance. + + + + + + Vec3 + Vec3 + Length + Get the length of this Vec3. + () + + + float + Length. + + + + + + Vec3 + tostring + Metafunction. + Use tostring(vector). + + + This + Vec3 + Vec3. + + + + + string + A string showing the X, Y, and Z components of the Vec3. + + + + + + View + FadeIn + Do a full-screen fade-in from black. + + + speed + float + (default 1.0). Speed in "amount" per second. A value of 1 will make the fade take one second. + + + + + + View + FadeOut + Do a full-screen fade-to-black. + The screen will remain black until a call to FadeIn. + + + speed + float + (default 1.0). Speed in "amount" per second. A value of 1 will make the fade take one second. + + + + + + View + SetCineBars + Move black cinematic bars in from the top and bottom of the game window. + + + height + float + __(default 30)__ Percentage of the screen to be covered + + + speed + float + __(default 30)__ Coverage percent per second + + + + + + View + SetFOV + Set field of view. + + + angle + float + in degrees (clamped to [10, 170]) + + + + + + View + GetFOV + Get field of view. + + + float + current FOV angle in degrees + + + + + + View + GetCameraType + Shows the mode of the game camera. + + + View.CameraType + value used by the Main Camera. + + + + + + View + GetCameraRoom + Gets current room where camera is positioned. + + + Objects.Room + current room of the camera + + + + + + View + SetPostProcessMode + Sets the post-process effect mode, like negative or monochrome. + + + effect + View.PostProcessMode + type to set. + + + + + + View + SetPostProcessStrength + Sets the post-process effect strength. + + + strength + float + (default 1.0). How strong the effect is. + + + + + + View + SetPostProcessTint + Sets the post-process tint. + + + tint + Color + value to use. + + + + + + View + GetCameraPosition + Gets current camera position. + + + Vec3 + current camera position + + + + + + View + GetCameraTarget + Gets current camera target. + + + Vec3 + current camera target + + + + + + View + PlayFlyBy + Enable FlyBy with specific ID + + + flyby + short + (ID of flyby) + + + + + + View + ResetObjCamera + Reset object camera back to Lara and deactivate object camera. + + + + View + FlashScreen + Flash screen. + + + color + Color + (default Color(255, 255, 255)) + + + speed + float + (default 1.0). Speed in "amount" per second. Value of 1 will make flash take one second. Clamped to [0.005, 1.0]. + + + + + + View + GetAspectRatio + Get the display resolution's aspect ratio. + + + float + Display resolution's aspect ratio. + + + + + + EventSequence + Create + Create (but do not start) a new event sequence. + + + name + string + A label to give the sequence; used to retrieve the timer later as well as internally by TEN. + + + loop + bool + if true, the sequence will start again from its first timer once its final function has been called + + + timerFormat + ?table|bool + same as in Timer. This is mainly for debugging. __This will not work properly if another sequence or timer is showing a countdown.__ + + + ... + ... + a variable number of pairs of arguments - a time in seconds, followed by the function (must be defined in the LevelFuncs table) to call once the time has elapsed, followed by another duration in seconds, another function name, etc. You can specify a function either by its name as a string, or by a table with the function name as the first member, followed by its arguments (see above example). + + + + + EventSequence + The inactive sequence. + + + + + + EventSequence + Get + Get an event sequence by its name. + + + name + string + The label that was given to the sequence when it was created + + + + + EventSequence + The sequence + + + + + + EventSequence + mySequence + SetPaused + Pause or unpause the sequence. + If showing the remaining time on-screen, its color will be set to yellow (paused) or white (unpaused). + + + p + bool + if true, the sequence will be paused; if false, it will be unpaused + + + + + + EventSequence + mySequence + IsPaused + Get whether or not the sequence is paused + + + bool + true if the timer is paused, false if otherwise + + + + + + EventSequence + mySequence + Start + Begin or unpause a sequence. + If showing the remaining time on-screen, its color will be set to white. + + + + EventSequence + mySequence + Stop + Stop the sequence. + + + + EventSequence + mySequence + IsActive + Get whether or not the sequence is active + + + bool + true if the sequence is active, false if otherwise + + + + + + Timer + Create + Create (but do not start) a new timer. + You have the option of displaying the remaining time on the clock. Timer format details: + + + name + string + A label to give this timer; used to retrieve the timer later. __Do not give your timers a name beginning with __TEN, as this is reserved for timers used by other internal libaries__. + + + totalTime + number + The duration of the timer, in seconds + + + loop + bool + if true, the timer will start again immediately after the time has elapsed + + + timerFormat + ?table|bool + If a table is given, the remaining time will be shown as a string, formatted according to the values in the table. If true, the remaining seconds, rounded up, will show at the bottom of the screen. If false, the remaining time will not be shown on screen. + + + func + func + The LevelFunc function to call when the time is up + + + ... + ... + a variable number of arguments with which the above function will be called + + + + + Timer + The timer in its paused state + + + + + + Timer + Get + Get a timer by its name. + + + name + string + The label that was given to the timer when it was created + + + + + Timer + The timer + + + + + + Timer + myTimer + SetFunction + Give the timer a new function and args + + + func + function + The LevelFunc member to call when the time is up + + + ... + ... + a variable number of arguments with which the above function will be called + + + + + + Timer + myTimer + Start + Begin or unpause a timer. + If showing the remaining time on-screen, its color will be set to white. + + + + Timer + myTimer + Stop + Stop the timer. + + + + Timer + myTimer + IsActive + Get whether or not the timer is active + + + bool + true if the timer is active, false if otherwise + + + + + + Timer + myTimer + SetPaused + Pause or unpause the timer. + If showing the remaining time on-screen, its color will be set to yellow (paused) or white (unpaused). + + + p + bool + if true, the timer will be paused; if false, it would be unpaused + + + + + + Timer + myTimer + IsPaused + Get whether or not the timer is paused + + + bool + true if the timer is paused, false if otherwise + + + + + + Timer + myTimer + GetRemainingTime + Get the remaining time for a timer. + + + float + the time in seconds remaining on the clock + + + + + + Timer + myTimer + SetRemainingTime + Set the remaining time for a timer + + + remainingTime + number + the new time remaining for the timer + + + + + + Timer + myTimer + GetTotalTime + Get the total time for a timer. + This is the amount of time the timer will start with, as well as when starting a new loop + + + float + the timer's total time + + + + + + Timer + myTimer + SetTotalTime + Set the total time for a timer + + + totalTime + number + timer's new total time + + + + + + Timer + myTimer + SetLooping + Set whether or not the timer loops + + + looping + bool + whether or not the timer loops + + + diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 5579a81da..41dd4d775 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -58,6 +58,7 @@ using namespace TEN::Gui; using TEN::Renderer::g_Renderer; LaraInfo Lara = {}; +LaraInfo OldLara = {}; ItemInfo* LaraItem; CollisionInfo LaraCollision = {}; @@ -621,6 +622,13 @@ void UpdateLara(ItemInfo* item, bool isTitle) // Control player. InItemControlLoop = true; + + // Copy current state to old state for interpolation + //memcpy(&item->OldPose, &item->Pose, sizeof(Pose)); + //memcpy(&item->OldLocation, &item->Location, sizeof(Vector3i)); + //memcpy(&item->OldAnimation, &item->Animation, sizeof(EntityAnimationData)); + //memcpy(&OldLara, &Lara, sizeof(LaraInfo)); + LaraControl(item, &LaraCollision); HandlePlayerFlyCheat(*item); InItemControlLoop = false; diff --git a/TombEngine/Game/Lara/lara.h b/TombEngine/Game/Lara/lara.h index 184a82cb3..b2562147b 100644 --- a/TombEngine/Game/Lara/lara.h +++ b/TombEngine/Game/Lara/lara.h @@ -94,6 +94,7 @@ constexpr auto SWIM_WATER_DEPTH = CLICK(2.75f); constexpr auto SLOPE_DIFFERENCE = 60; extern LaraInfo Lara; +extern LaraInfo OldLara; extern ItemInfo* LaraItem; extern CollisionInfo LaraCollision; diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 1fd9628d4..ee176e7d7 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -58,6 +58,7 @@ GameVector LookCamPosition; GameVector LookCamTarget; Vector3i CamOldPos; CAMERA_INFO Camera; +CAMERA_INFO PreviousCamera; ObjectCameraInfo ItemCamera; GameVector ForcedFixedCamera; int UseForcedFixedCamera; diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 504a59ed4..55453957b 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -66,6 +66,7 @@ constexpr auto FADE_SCREEN_SPEED = 16.0f / 255.0f; constexpr auto DEFAULT_FOV = 80.0f; extern CAMERA_INFO Camera; +extern CAMERA_INFO PreviousCamera; extern GameVector ForcedFixedCamera; extern int UseForcedFixedCamera; extern CameraType BinocularOldCamera; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 9977f8877..cd0ee8f09 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -110,7 +110,7 @@ short NextFxFree; int ControlPhaseTime; -int DrawPhase(bool isTitle) +int DrawPhase(bool isTitle, float interpolateFactor) { if (isTitle) { @@ -118,13 +118,13 @@ int DrawPhase(bool isTitle) } else { - g_Renderer.Render(); + g_Renderer.Render(interpolateFactor); } // Clear display sprites. ClearDisplaySprites(); - Camera.numberFrames = g_Renderer.Synchronize(); + //Camera.numberFrames = g_Renderer.Synchronize(); return Camera.numberFrames; } @@ -149,8 +149,10 @@ GameStatus ControlPhase(int numFrames) bool isFirstTime = true; static int framesCount = 0; - for (framesCount += numFrames; framesCount > 0; framesCount -= LOOP_FRAME_COUNT) + //for (framesCount += numFrames; framesCount > 0; framesCount -= LOOP_FRAME_COUNT) { + g_Renderer.SaveOldState(); + // Controls are polled before OnLoop, so input data could be // overwritten by script API methods. HandleControls(isTitle); @@ -548,12 +550,46 @@ GameStatus DoGameLoop(int levelIndex) // Before entering actual game loop, ControlPhase must be // called once to sort out various runtime shenanigangs (e.g. hair). + status = ControlPhase(numFrames); + LARGE_INTEGER lastTime; + LARGE_INTEGER currentTime; + LARGE_INTEGER lastDrawTime; + LARGE_INTEGER currentDrawTime; + double controlLag = 0; + double drawLag = 0; + double frameTime = 0; + constexpr auto controlFrameTime = 1000.0f / 30.0f; + constexpr auto drawFrameTime = 1000.0f / 60.0f; + + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + + QueryPerformanceCounter(&lastTime); + QueryPerformanceCounter(&lastDrawTime); + + int controlCalls = 0; + int drawCalls = 0; + + memcpy(&PreviousCamera , &Camera, sizeof(CAMERA_INFO)); + while (DoTheGame) { - status = ControlPhase(numFrames); + QueryPerformanceCounter(¤tTime); + frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; + lastTime = currentTime; + controlLag += frameTime; + //while (controlLag >= controlFrameTime) + if (controlLag >= controlFrameTime) + { + memcpy(&PreviousCamera, &Camera, sizeof(CAMERA_INFO)); + status = ControlPhase(0); + controlLag -= controlFrameTime; + controlCalls++; + } + if (!levelIndex) { UpdateInputActions(LaraItem); @@ -590,7 +626,23 @@ GameStatus DoGameLoop(int levelIndex) } } - numFrames = DrawPhase(!levelIndex); + QueryPerformanceCounter(¤tDrawTime); + frameTime = (currentDrawTime.QuadPart - lastDrawTime.QuadPart) * 1000.0 / frequency.QuadPart; + lastDrawTime = currentDrawTime; + drawLag += frameTime; + + //if (drawLag >= drawFrameTime) + { + float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + //printf("%f\n", interpolateFactor); + + numFrames = DrawPhase(!levelIndex, interpolateFactor); + drawLag -= drawFrameTime; + drawCalls++; + } + + + Sound_UpdateScene(); } diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index 805104c5a..be2af5736 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -74,7 +74,7 @@ extern int ControlPhaseTime; extern std::vector OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE]; -int DrawPhase(bool isTitle); +int DrawPhase(bool isTitle, float interpolateFactor); GameStatus ControlPhase(int numFrames); GameStatus DoLevel(int levelIndex, bool loadGame = false); diff --git a/TombEngine/Renderer/Renderer.cpp b/TombEngine/Renderer/Renderer.cpp index e7bfe0859..2092630a2 100644 --- a/TombEngine/Renderer/Renderer.cpp +++ b/TombEngine/Renderer/Renderer.cpp @@ -18,7 +18,10 @@ namespace TEN::Renderer using namespace Utils; Renderer g_Renderer; - Renderer::Renderer() : _gameCamera({0, 0, 0}, {0, 0, 1}, {0, 1, 0}, 1, 1, 0, 1, 10, 90) + Renderer::Renderer() : + _gameCamera({0, 0, 0}, {0, 0, 1}, {0, 1, 0}, 1, 1, 0, 1, 10, 90), + _oldGameCamera({ 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, 1, 1, 0, 1, 10, 90), + _currentGameCamera({ 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, 1, 1, 0, 1, 10, 90) { } diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index d6f0442d7..efc25a7d2 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -160,6 +160,8 @@ namespace TEN::Renderer // Constant buffers RenderView _gameCamera; + RenderView _oldGameCamera; + RenderView _currentGameCamera; ConstantBuffer _cbCameraMatrices; CItemBuffer _stItem; ConstantBuffer _cbItem; @@ -373,6 +375,8 @@ namespace TEN::Renderer VertexBuffer _sortedPolygonsVertexBuffer; IndexBuffer _sortedPolygonsIndexBuffer; + float _interpolationFactor = 0.0f; + // Private functions void ApplySMAA(RenderTarget2D* renderTarget, RenderView& view); void ApplyFXAA(RenderTarget2D* renderTarget, RenderView& view); @@ -580,7 +584,7 @@ namespace TEN::Renderer void DrawBar(float percent, const RendererHudBar& bar, GAME_OBJECT_ID textureSlot, int frame, bool poison); void Create(); void Initialize(int w, int h, bool windowed, HWND handle); - void Render(); + void Render(float interpolateFactor); void RenderTitle(); void Lock(); bool PrepareDataForTheRenderer(); @@ -632,7 +636,7 @@ namespace TEN::Renderer void SetLoadingScreen(std::wstring& fileName); void SetTextureOrDefault(Texture2D& texture, std::wstring path); std::string GetDefaultAdapterName(); - + void SaveOldState(); Vector2i GetScreenResolution() const; std::optional Get2DPosition(const Vector3& pos) const; Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 5ff0ba82b..4a9357491 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2168,10 +2168,10 @@ namespace TEN::Renderer RendererObject& moveableObj = *_moveableObjects[item->ObjectNumber]; // Bind item main properties - _stItem.World = item->World; + _stItem.World = item->InterpolatedWorld; // item->World; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; - memcpy(_stItem.BonesMatrices, item->AnimationTransforms, sizeof(Matrix) * MAX_BONES); + memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) _stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode; @@ -2720,9 +2720,45 @@ namespace TEN::Renderer _context->ClearDepthStencilView(depthTarget, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } - void Renderer::Render() + void Renderer::Render(float interpolateFactor) { //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); + + /*RenderView oldCamera = RenderView( + &PreviousCamera, + 0, + TO_RAD(CurrentFOV / 1.333333f) , + 32, 100*1024, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); + + RenderView newCamera = RenderView( + &Camera, + 0, + TO_RAD(CurrentFOV / 1.333333f), + 32, 100 * 1024, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); + + _gameCamera.Camera = oldCamera.Camera; + _gameCamera.Camera.WorldPosition = Vector3::Lerp(oldCamera.Camera.WorldPosition, newCamera.Camera.WorldPosition, interpolateFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(oldCamera.Camera.WorldDirection, newCamera.Camera.WorldDirection, interpolateFactor); + _gameCamera.Camera.View = Matrix::Lerp(oldCamera.Camera.View, newCamera.Camera.View, interpolateFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(oldCamera.Camera.Projection, newCamera.Camera.Projection, interpolateFactor); + _gameCamera.Camera.View = _gameCamera.Camera.View * _gameCamera.Camera.Projection; +*/ + + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolateFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolateFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolateFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpolateFactor); + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; + _gameCamera.Camera.Frustum=_currentGameCamera.Camera.Frustum; + _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; + _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; + _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; + _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; + + _interpolationFactor = interpolateFactor; + + //_gameCamera = _currentGameCamera; RenderScene(&_backBuffer, true, _gameCamera); _context->ClearState(); _swapChain->Present(1, 0); diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index f56578d0a..06e39d24d 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -380,11 +380,18 @@ namespace TEN::Renderer newItem->ObjectNumber = item->ObjectNumber; newItem->Color = item->Model.Color; newItem->Position = item->Pose.Position.ToVector3(); - newItem->Translation = Matrix::CreateTranslation(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); + newItem->Translation = Matrix::CreateTranslation(newItem->Position.x, newItem->Position.y, newItem->Position.z); newItem->Rotation = item->Pose.Orientation.ToRotationMatrix(); newItem->Scale = Matrix::CreateScale(1.0f); newItem->World = newItem->Rotation * newItem->Translation; + newItem->InterpolatedPosition = Vector3::Lerp(newItem->OldPosition, newItem->Position, _interpolationFactor); + newItem->InterpolatedTranslation = Matrix::Lerp(newItem->OldTranslation, newItem->Translation, _interpolationFactor); + newItem->InterpolatedRotation = Matrix::Lerp(newItem->InterpolatedRotation, newItem->Rotation, _interpolationFactor); + newItem->InterpolatedWorld = Matrix::Lerp(newItem->OldWorld, newItem->World, _interpolationFactor); + for (int j = 0; j < MAX_BONES; j++) + newItem->InterpolatedAnimationTransforms[j] = Matrix::Lerp(newItem->OldAnimationTransforms[j], newItem->AnimationTransforms[j], _interpolationFactor); + CalculateLightFades(newItem); CollectLightsForItem(newItem); @@ -832,5 +839,20 @@ namespace TEN::Renderer _items[i].DoneAnimations = false; } + + void Renderer::SaveOldState() + { + for (int i = 0; i < NUM_ITEMS; i++) + { + _items[i].OldPosition = _items[i].Position; + _items[i].OldWorld = _items[i].World; + _items[i].OldTranslation = _items[i].Translation; + _items[i].OldRotation = _items[i].Rotation; + _items[i].OldScale = _items[i].Scale; + for (int j = 0; j < MAX_BONES; j++) + _items[i].OldAnimationTransforms[j] = _items[i].AnimationTransforms[j]; + } + } + } // namespace TEN::Renderer diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 490a0b48d..4ef1310fc 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -79,7 +79,7 @@ namespace TEN::Renderer { auto offset0 = frameData.FramePtr0->Offset; auto rotMatrix = Matrix::CreateFromQuaternion(frameData.FramePtr0->BoneOrientations[bonePtr->Index]); - + if (frameData.Alpha != 0.0f) { auto offset1 = frameData.FramePtr1->Offset; @@ -362,6 +362,9 @@ namespace TEN::Renderer farView = DEFAULT_FAR_VIEW; farView = farView; + + _oldGameCamera = _currentGameCamera; + _currentGameCamera = RenderView(cam, roll, fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); _gameCamera = RenderView(cam, roll, fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); } diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index bccc49e04..4539999d8 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -302,10 +302,10 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa RendererRoom* room = &_rooms[LaraItem->RoomNumber]; - _stItem.World = _laraWorldMatrix; + _stItem.World = item->InterpolatedWorld; // _laraWorldMatrix; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; - memcpy(_stItem.BonesMatrices, laraObj.AnimationTransforms.data(), laraObj.AnimationTransforms.size() * sizeof(Matrix)); + memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, laraObj.AnimationTransforms.size() * sizeof(Matrix)); for (int k = 0; k < laraSkin.ObjectMeshes.size(); k++) { _stItem.BoneLightModes[k] = (int)GetMesh(nativeItem->Model.MeshIndex[k])->LightMode; diff --git a/TombEngine/Renderer/Structures/RendererItem.h b/TombEngine/Renderer/Structures/RendererItem.h index 078b6177b..d4840a0e8 100644 --- a/TombEngine/Renderer/Structures/RendererItem.h +++ b/TombEngine/Renderer/Structures/RendererItem.h @@ -20,6 +20,20 @@ namespace TEN::Renderer::Structures Matrix Scale; Matrix AnimationTransforms[MAX_BONES]; + Vector3 OldPosition; + Matrix OldWorld; + Matrix OldTranslation; + Matrix OldRotation; + Matrix OldScale; + Matrix OldAnimationTransforms[MAX_BONES]; + + Vector3 InterpolatedPosition; + Matrix InterpolatedWorld; + Matrix InterpolatedTranslation; + Matrix InterpolatedRotation; + Matrix InterpolatedScale; + Matrix InterpolatedAnimationTransforms[MAX_BONES]; + int RoomNumber = NO_ROOM; int PrevRoomNumber = NO_ROOM; Vector4 Color; diff --git a/TombEngine/Specific/clock.cpp b/TombEngine/Specific/clock.cpp index 4812b9511..e1a04f259 100644 --- a/TombEngine/Specific/clock.cpp +++ b/TombEngine/Specific/clock.cpp @@ -1,52 +1,57 @@ -#include "framework.h" -#include "Specific/clock.h" - -LARGE_INTEGER PerformanceCount; -double LdFreq; -double LdSync; - -bool TimeReset() -{ - LARGE_INTEGER fq; - QueryPerformanceCounter(&fq); - LdSync = (double)fq.LowPart + (double)fq.HighPart * (double)0xffffffff; - LdSync /= LdFreq; - return true; -} - -bool TimeInit() -{ - LARGE_INTEGER fq; - if (!QueryPerformanceFrequency(&fq)) - return false; - LdFreq = (double)fq.LowPart + (double)fq.HighPart * (double)0xFFFFFFFF; - LdFreq /= 60.0; - TimeReset(); - return true; -} - -int Sync() -{ - LARGE_INTEGER ct; - double dCounter; - QueryPerformanceCounter(&ct); - dCounter = (double)ct.LowPart + (double)ct.HighPart * (double)0xFFFFFFFF; - dCounter /= LdFreq; - long nFrames = long(dCounter) - long(LdSync); - LdSync = dCounter; - return nFrames; -} - -GameTime GetGameTime(int frameCount) -{ - GameTime result = {}; - - auto seconds = GameTimer / FPS; - - result.Days = (seconds / (DAY_UNIT * TIME_UNIT * TIME_UNIT)); - result.Hours = (seconds % (DAY_UNIT * TIME_UNIT * TIME_UNIT)) / (TIME_UNIT * TIME_UNIT); - result.Minutes = (seconds / TIME_UNIT) % TIME_UNIT; - result.Seconds = (seconds % TIME_UNIT); - - return result; +#include "framework.h" +#include "Specific/clock.h" + +LARGE_INTEGER PerformanceCount; +double LdFreq; +double LdSync; + +bool TimeReset() +{ + LARGE_INTEGER fq; + QueryPerformanceCounter(&fq); + LdSync = (double)fq.LowPart + (double)fq.HighPart * (double)0xffffffff; + LdSync /= LdFreq; + return true; +} + +bool TimeInit() +{ + LARGE_INTEGER fq; + if (!QueryPerformanceFrequency(&fq)) + return false; + LdFreq = (double)fq.LowPart + (double)fq.HighPart * (double)0xFFFFFFFF; + LdFreq /= 60.0; + TimeReset(); + return true; +} + +int Sync() +{ + LARGE_INTEGER ct; + double dCounter; + QueryPerformanceCounter(&ct); + dCounter = (double)ct.LowPart + (double)ct.HighPart * (double)0xFFFFFFFF; + dCounter /= LdFreq; + long nFrames = long(dCounter) - long(LdSync); + LdSync = dCounter; + return nFrames; +} + +double Clock_GetCurrent() +{ + return 0; +} + +GameTime GetGameTime(int frameCount) +{ + GameTime result = {}; + + auto seconds = GameTimer / FPS; + + result.Days = (seconds / (DAY_UNIT * TIME_UNIT * TIME_UNIT)); + result.Hours = (seconds % (DAY_UNIT * TIME_UNIT * TIME_UNIT)) / (TIME_UNIT * TIME_UNIT); + result.Minutes = (seconds / TIME_UNIT) % TIME_UNIT; + result.Seconds = (seconds % TIME_UNIT); + + return result; } \ No newline at end of file diff --git a/TombEngine/Specific/clock.h b/TombEngine/Specific/clock.h index 2fd36373b..9b0a1a9ad 100644 --- a/TombEngine/Specific/clock.h +++ b/TombEngine/Specific/clock.h @@ -1,24 +1,26 @@ -#pragma once -#include "Game/control/control.h" - -// This might not be the exact amount of time that has passed, but giving it a -// value of 1/30 keeps it in lock-step with the rest of the game logic, -// which assumes 30 iterations per second. -constexpr auto FPS = 30; -constexpr auto DELTA_TIME = 1.0f / FPS; -constexpr auto TIME_UNIT = 60; -constexpr auto DAY_UNIT = 24; - -struct GameTime -{ - int Days; - int Hours; - int Minutes; - int Seconds; -}; - -int Sync(); -bool TimeInit(); -bool TimeReset(); - -GameTime GetGameTime(int frameCount); +#pragma once +#include "Game/control/control.h" + +// This might not be the exact amount of time that has passed, but giving it a +// value of 1/30 keeps it in lock-step with the rest of the game logic, +// which assumes 30 iterations per second. +constexpr auto FPS = 30; +constexpr auto DELTA_TIME = 1.0f / FPS; +constexpr auto TIME_UNIT = 60; +constexpr auto DAY_UNIT = 24; + +struct GameTime +{ + int Days; + int Hours; + int Minutes; + int Seconds; +}; + +int Sync(); +bool TimeInit(); +bool TimeReset(); + +double Clock_GetCurrent(); + +GameTime GetGameTime(int frameCount); From f9589155d589c698a36211029e7bf29ca44fea97 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 5 Mar 2024 09:53:12 +0100 Subject: [PATCH 061/410] Fixed horizon flickering --- TombEngine/Renderer/RendererDraw.cpp | 8 +++++--- TombEngine/Renderer/RendererLara.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 4a9357491..f054d28ec 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2660,8 +2660,10 @@ namespace TEN::Renderer { auto weather = TEN::Effects::Environment::Weather; - auto translation = Matrix::CreateTranslation(Camera.pos.x + weather.SkyPosition(s) - i * SKY_SIZE, - Camera.pos.y - 1536.0f, Camera.pos.z); + auto translation = Matrix::CreateTranslation( + renderView.Camera.WorldPosition.x + weather.SkyPosition(s) - i * SKY_SIZE, + renderView.Camera.WorldPosition.y - 1536.0f, + renderView.Camera.WorldPosition.z); auto world = rotation * translation; _stStatic.World = (rotation * translation); @@ -2685,7 +2687,7 @@ namespace TEN::Renderer auto& moveableObj = *_moveableObjects[ID_HORIZON]; - _stStatic.World = Matrix::CreateTranslation(Camera.pos.x, Camera.pos.y, Camera.pos.z); + _stStatic.World = Matrix::CreateTranslation(renderView.Camera.WorldPosition); _stStatic.Color = Vector4::One; _stStatic.ApplyFogBulbs = 1; _cbStatic.UpdateData(_stStatic, _context.Get()); diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index 4539999d8..b294e5735 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -345,7 +345,7 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render // First matrix is Lara's head matrix, then all hair unit segment matrices. // Bones are adjusted at load time to account for this. _stItem.World = Matrix::Identity; - _stItem.BonesMatrices[0] = itemToDraw->AnimationTransforms[LM_HEAD] * _laraWorldMatrix; + _stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimationTransforms[LM_HEAD] * _laraWorldMatrix; for (int i = 0; i < unit.Segments.size(); i++) { From 96d08f41e79c8eff4ebc0d46cfed297af77ee79d Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 6 Mar 2024 14:50:16 +0100 Subject: [PATCH 062/410] Fixed lag logic --- TombEngine/Game/control/control.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index cd0ee8f09..27a5dd646 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -581,8 +581,8 @@ GameStatus DoGameLoop(int levelIndex) lastTime = currentTime; controlLag += frameTime; - //while (controlLag >= controlFrameTime) - if (controlLag >= controlFrameTime) + while (controlLag >= controlFrameTime) + //if (controlLag >= controlFrameTime) { memcpy(&PreviousCamera, &Camera, sizeof(CAMERA_INFO)); status = ControlPhase(0); From c44e4d40be15abd474d0cfa6f66718dea4400515 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 7 Mar 2024 06:16:12 +0100 Subject: [PATCH 063/410] Clock reset on window focus change, inventory and pause menu --- TombEngine/Game/control/control.cpp | 258 ++++++++++++++-------------- TombEngine/Game/control/control.h | 2 + TombEngine/Game/gui.cpp | 11 ++ TombEngine/Specific/winmain.cpp | 6 + TombEngine/Specific/winmain.h | 80 ++++----- 5 files changed, 187 insertions(+), 170 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 27a5dd646..2972de79b 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -145,124 +145,123 @@ GameStatus ControlPhase(int numFrames) } g_GameStringsHandler->ProcessDisplayStrings(DELTA_TIME); - + bool isFirstTime = true; static int framesCount = 0; - //for (framesCount += numFrames; framesCount > 0; framesCount -= LOOP_FRAME_COUNT) + // Save current state to old variables for interpolation + SaveOldState(); + g_Renderer.SaveOldState(); + + // Controls are polled before OnLoop, so input data could be + // overwritten by script API methods. + HandleControls(isTitle); + + // Pre-loop script and event handling. + g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate + HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index); + + // Control lock is processed after handling scripts, because builder may want to + // process input externally, while still locking Lara from input. + if (!isTitle && Lara.Control.IsLocked) + ClearAllActions(); + + // Handle inventory / pause / load / save screens. + auto result = HandleMenuCalls(isTitle); + if (result != GameStatus::Normal) + return result; + + // Handle global input events. + result = HandleGlobalInputEvents(isTitle); + if (result != GameStatus::Normal) + return result; + + // Queued input actions are read again and cleared after UI + // interrupts are processed, so first frame after exiting UI + // will still register it. + ApplyActionQueue(); + ClearActionQueue(); + + UpdateAllItems(); + UpdateAllEffects(); + UpdateLara(LaraItem, isTitle); + + g_GameScriptEntities->TestCollidingObjects(); + + if (UseSpotCam) { - g_Renderer.SaveOldState(); + // Draw flyby cameras. + CalculateSpotCameras(); + } + else + { + // Do the standard camera. + TrackCameraInit = false; + CalculateCamera(LaraCollision); + } - // Controls are polled before OnLoop, so input data could be - // overwritten by script API methods. - HandleControls(isTitle); + // Update oscillator seed. + Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX; - // Pre-loop script and event handling. - g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate - HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index); + // Smash shatters and clear stopper flags under them. + UpdateShatters(); - // Control lock is processed after handling scripts, because builder may want to - // process input externally, while still locking Lara from input. - if (!isTitle && Lara.Control.IsLocked) - ClearAllActions(); + // Update weather. + Weather.Update(); - // Handle inventory / pause / load / save screens. - auto result = HandleMenuCalls(isTitle); - if (result != GameStatus::Normal) - return result; + // Update effects. + StreamerEffect.Update(); + UpdateSparks(); + UpdateFireSparks(); + UpdateSmoke(); + UpdateBlood(); + UpdateBubbles(); + UpdateDebris(); + UpdateGunShells(); + UpdateFootprints(); + UpdateSplashes(); + UpdateElectricityArcs(); + UpdateHelicalLasers(); + UpdateDrips(); + UpdateRats(); + UpdateRipples(); + UpdateBats(); + UpdateSpiders(); + UpdateSparkParticles(); + UpdateSmokeParticles(); + UpdateSimpleParticles(); + UpdateExplosionParticles(); + UpdateShockwaves(); + UpdateBeetleSwarm(); + UpdateLocusts(); + UpdateUnderwaterBloodParticles(); - // Handle global input events. - result = HandleGlobalInputEvents(isTitle); - if (result != GameStatus::Normal) - return result; + // Update HUD. + g_Hud.Update(*LaraItem); + UpdateFadeScreenAndCinematicBars(); - // Queued input actions are read again and cleared after UI - // interrupts are processed, so first frame after exiting UI - // will still register it. - ApplyActionQueue(); - ClearActionQueue(); + // Rumble screen (like in submarine level of TRC). + if (g_GameFlow->GetLevel(CurrentLevel)->Rumble) + RumbleScreen(); - UpdateAllItems(); - UpdateAllEffects(); - UpdateLara(LaraItem, isTitle); + PlaySoundSources(); + DoFlipEffect(FlipEffect, LaraItem); - g_GameScriptEntities->TestCollidingObjects(); + // Post-loop script and event handling. + g_GameScript->OnLoop(DELTA_TIME, true); - if (UseSpotCam) - { - // Draw flyby cameras. - CalculateSpotCameras(); - } - else - { - // Do the standard camera. - TrackCameraInit = false; - CalculateCamera(LaraCollision); - } + // Clear savegame loaded flag. + JustLoaded = false; - // Update oscillator seed. - Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX; + // Update timers. + GameTimer++; + GlobalCounter++; - // Smash shatters and clear stopper flags under them. - UpdateShatters(); - - // Update weather. - Weather.Update(); - - // Update effects. - StreamerEffect.Update(); - UpdateSparks(); - UpdateFireSparks(); - UpdateSmoke(); - UpdateBlood(); - UpdateBubbles(); - UpdateDebris(); - UpdateGunShells(); - UpdateFootprints(); - UpdateSplashes(); - UpdateElectricityArcs(); - UpdateHelicalLasers(); - UpdateDrips(); - UpdateRats(); - UpdateRipples(); - UpdateBats(); - UpdateSpiders(); - UpdateSparkParticles(); - UpdateSmokeParticles(); - UpdateSimpleParticles(); - UpdateExplosionParticles(); - UpdateShockwaves(); - UpdateBeetleSwarm(); - UpdateLocusts(); - UpdateUnderwaterBloodParticles(); - - // Update HUD. - g_Hud.Update(*LaraItem); - UpdateFadeScreenAndCinematicBars(); - - // Rumble screen (like in submarine level of TRC). - if (g_GameFlow->GetLevel(CurrentLevel)->Rumble) - RumbleScreen(); - - PlaySoundSources(); - DoFlipEffect(FlipEffect, LaraItem); - - // Post-loop script and event handling. - g_GameScript->OnLoop(DELTA_TIME, true); - - // Clear savegame loaded flag. - JustLoaded = false; - - // Update timers. - GameTimer++; - GlobalCounter++; - - // Add renderer objects on the first processed frame. - if (isFirstTime) - { - g_Renderer.Lock(); - isFirstTime = false; - } + // Add renderer objects on the first processed frame. + if (isFirstTime) + { + g_Renderer.Lock(); + isFirstTime = false; } using ns = std::chrono::nanoseconds; @@ -555,19 +554,13 @@ GameStatus DoGameLoop(int levelIndex) LARGE_INTEGER lastTime; LARGE_INTEGER currentTime; - LARGE_INTEGER lastDrawTime; - LARGE_INTEGER currentDrawTime; double controlLag = 0; - double drawLag = 0; double frameTime = 0; constexpr auto controlFrameTime = 1000.0f / 30.0f; - constexpr auto drawFrameTime = 1000.0f / 60.0f; LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter(&lastTime); - QueryPerformanceCounter(&lastDrawTime); int controlCalls = 0; int drawCalls = 0; @@ -576,20 +569,30 @@ GameStatus DoGameLoop(int levelIndex) while (DoTheGame) { - QueryPerformanceCounter(¤tTime); - frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; - lastTime = currentTime; - controlLag += frameTime; + if (App.ResetClock) + { + App.ResetClock = false; + QueryPerformanceCounter(&lastTime); + currentTime = lastTime; + controlLag = 0; + frameTime = 0; + } + else + { + QueryPerformanceCounter(¤tTime); + frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; + lastTime = currentTime; + controlLag += frameTime; + } while (controlLag >= controlFrameTime) - //if (controlLag >= controlFrameTime) { memcpy(&PreviousCamera, &Camera, sizeof(CAMERA_INFO)); status = ControlPhase(0); controlLag -= controlFrameTime; controlCalls++; } - + if (!levelIndex) { UpdateInputActions(LaraItem); @@ -626,27 +629,15 @@ GameStatus DoGameLoop(int levelIndex) } } - QueryPerformanceCounter(¤tDrawTime); - frameTime = (currentDrawTime.QuadPart - lastDrawTime.QuadPart) * 1000.0 / frequency.QuadPart; - lastDrawTime = currentDrawTime; - drawLag += frameTime; - - //if (drawLag >= drawFrameTime) - { - float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); - //printf("%f\n", interpolateFactor); - - numFrames = DrawPhase(!levelIndex, interpolateFactor); - drawLag -= drawFrameTime; - drawCalls++; - } - - + float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + DrawPhase(!levelIndex, interpolateFactor); + drawCalls++; Sound_UpdateScene(); } EndGameLoop(levelIndex, status); + return status; } @@ -659,6 +650,11 @@ void EndGameLoop(int levelIndex, GameStatus reason) StopRumble(); } +void SaveOldState() +{ + +} + void HandleControls(bool isTitle) { // Poll input devices and update input variables. diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index be2af5736..0f88acb1d 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -98,4 +98,6 @@ void InitializeOrLoadGame(bool loadGame); void InitializeScripting(int levelIndex, bool loadGame); void DeInitializeScripting(int levelIndex); +void SaveOldState(); + unsigned CALLBACK GameMain(void*); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index bc1b82c6e..745254ae6 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -25,6 +25,7 @@ #include "Specific/configuration.h" #include "Specific/level.h" #include "Specific/trutils.h" +#include "Specific/winmain.h" using namespace TEN::Input; using namespace TEN::Renderer; @@ -1166,6 +1167,7 @@ namespace TEN::Gui case Menu::Display: HandleDisplaySettingsInput(true); + App.ResetClock = true; return InventoryResult::None; case Menu::GeneralActions: @@ -1173,10 +1175,12 @@ namespace TEN::Gui case Menu::QuickActions: case Menu::MenuActions: HandleControlSettingsInput(item, true); + App.ResetClock = true; return InventoryResult::None; case Menu::OtherSettings: HandleOtherSettingsInput(true); + App.ResetClock = true; return InventoryResult::None; } @@ -1242,6 +1246,7 @@ namespace TEN::Gui case PauseMenuOption::ExitToTitle: SetInventoryMode(InventoryMode::None); + App.ResetClock = true; return InventoryResult::ExitToTitle; break; } @@ -1259,6 +1264,7 @@ namespace TEN::Gui } } + App.ResetClock = true; return InventoryResult::None; } @@ -3315,7 +3321,10 @@ namespace TEN::Gui while (!exitLoop) { if (ThreadEnded) + { + App.ResetClock = true; return false; + } TimeInMenu++; GameTimer++; @@ -3402,6 +3411,8 @@ namespace TEN::Gui lara->Inventory.IsBusy = lara->Inventory.OldBusy; SetInventoryMode(InventoryMode::None); + App.ResetClock = true; + return doLoad; } diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp index fe1cd8bc3..3a3d7438b 100644 --- a/TombEngine/Specific/winmain.cpp +++ b/TombEngine/Specific/winmain.cpp @@ -165,6 +165,12 @@ LRESULT CALLBACK WinAppProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) return 0; } + if (msg == WM_ACTIVATEAPP) + { + App.ResetClock = true; + return DefWindowProcA(hWnd, msg, wParam, (LPARAM)lParam); + } + if (msg > WM_CLOSE) { if (msg == WM_COMMAND) diff --git a/TombEngine/Specific/winmain.h b/TombEngine/Specific/winmain.h index 5162e48c9..80427898b 100644 --- a/TombEngine/Specific/winmain.h +++ b/TombEngine/Specific/winmain.h @@ -1,40 +1,42 @@ -#pragma once -#pragma comment(linker,"/manifestdependency:\"" \ - "type='win32' " \ - "name='Microsoft.Windows.Common-Controls' " \ - "version='6.0.0.0' " \ - "processorArchitecture='*' " \ - "publicKeyToken='6595b64144ccf1df' " \ - "language='*'\"") - -#include -#include - -#include "Math/Math.h" - -using namespace TEN::Math; - -struct WINAPP -{ - HINSTANCE hInstance; - int nFillMode; - WNDCLASS WindowClass; - HWND WindowHandle; - bool bNoFocus; - bool isInScene; -}; - -extern bool DebugMode; -extern HWND WindowsHandle; - -// return handle -#define BeginThread(function, threadid) _beginthreadex(0, 0, &function, 0, 0, &threadid) -#define EndThread() _endthreadex(1) - -void WinProcMsg(); -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd); -void WinClose(); -LRESULT CALLBACK WinAppProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -void CALLBACK HandleWmCommand(unsigned short wParam); -Vector2i GetScreenResolution(); +#pragma once +#pragma comment(linker,"/manifestdependency:\"" \ + "type='win32' " \ + "name='Microsoft.Windows.Common-Controls' " \ + "version='6.0.0.0' " \ + "processorArchitecture='*' " \ + "publicKeyToken='6595b64144ccf1df' " \ + "language='*'\"") + +#include +#include + +#include "Math/Math.h" + +using namespace TEN::Math; + +struct WINAPP +{ + HINSTANCE hInstance; + int nFillMode; + WNDCLASS WindowClass; + HWND WindowHandle; + bool bNoFocus; + bool isInScene; + bool ResetClock; +}; + +extern bool DebugMode; +extern HWND WindowsHandle; +extern WINAPP App; + +// return handle +#define BeginThread(function, threadid) _beginthreadex(0, 0, &function, 0, 0, &threadid) +#define EndThread() _endthreadex(1) + +void WinProcMsg(); +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd); +void WinClose(); +LRESULT CALLBACK WinAppProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +void CALLBACK HandleWmCommand(unsigned short wParam); +Vector2i GetScreenResolution(); std::vector GetAllSupportedScreenResolutions(); \ No newline at end of file From 118c6d6105842861723e13ff256835be1c2ad0f5 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 10 Mar 2024 15:05:02 +1100 Subject: [PATCH 064/410] Fix final bug; remove debug code --- TombEngine/Game/Lara/lara.cpp | 60 -------------------- TombEngine/Game/Lara/lara_collide.cpp | 25 ++++---- TombEngine/Game/Lara/lara_collide.h | 5 -- TombEngine/Game/collision/PointCollision.cpp | 13 ++--- TombEngine/Game/collision/collide_room.h | 14 +++-- 5 files changed, 29 insertions(+), 88 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index c8715618a..efff5745f 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -63,70 +63,10 @@ LaraInfo Lara = {}; ItemInfo* LaraItem; CollisionInfo LaraCollision = {}; -//---------debug -#include -#include "Specific/Input/Input.h" -//---------- - void LaraControl(ItemInfo* item, CollisionInfo* coll) { auto& player = GetLaraInfo(*item); - //---------debug - - static int bridgeItemNumber = NO_ITEM; - if (coll->LastBridgeItemNumber != NO_ITEM) - bridgeItemNumber = coll->LastBridgeItemNumber; - - if (bridgeItemNumber != NO_ITEM) - { - constexpr auto TRANSLATE_STEP = BLOCK(0.1f); - - auto& bridgeItem = g_Level.Items[bridgeItemNumber]; - - // Move bridge. - if (KeyMap[OIS::KeyCode::KC_K]) - { - auto rotMatrix = EulerAngles(0, Camera.actualAngle, 0).ToRotationMatrix(); - auto offset = Vector3(AxisMap[(int)InputAxis::Mouse].x, 0.0f, -AxisMap[(int)InputAxis::Mouse].y) * 1000; - bridgeItem.Pose.Position += Vector3::Transform(offset, rotMatrix); - - UpdateItemRoom(bridgeItem.Index); - UpdateBridgeItem(bridgeItem); - } - else if (KeyMap[OIS::KeyCode::KC_L]) - { - auto offset = Vector3(0.0f, AxisMap[(int)InputAxis::Mouse].y, 0.0f) * 1000; - bridgeItem.Pose.Position += offset; - - UpdateItemRoom(bridgeItem.Index); - UpdateBridgeItem(bridgeItem); - } - // Rotate bridge. - else if (KeyMap[OIS::KeyCode::KC_H]) - { - auto rotMatrix = EulerAngles(0, Camera.actualAngle, 0).ToRotationMatrix(); - auto offset = Vector3(AxisMap[(int)InputAxis::Mouse].x, 0.0f, -AxisMap[(int)InputAxis::Mouse].y) * 10000; - offset = Vector3::Transform(offset, rotMatrix); - - auto rot = EulerAngles(-AxisMap[(int)InputAxis::Mouse].x * 10000, 0.0f, -AxisMap[(int)InputAxis::Mouse].y * 10000); - bridgeItem.Pose.Orientation += rot; - - UpdateItemRoom(bridgeItem.Index); - UpdateBridgeItem(bridgeItem); - } - else if (KeyMap[OIS::KeyCode::KC_J]) - { - auto rot = EulerAngles(0.0f, AxisMap[(int)InputAxis::Mouse].y * 10000, 0.0f); - bridgeItem.Pose.Orientation += rot; - - UpdateItemRoom(bridgeItem.Index); - UpdateBridgeItem(bridgeItem); - } - } - - //---------- - // Alert nearby creatures. if (player.Control.Weapon.HasFired) { diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index 358dc2c1d..1d60e2795 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -24,6 +24,11 @@ using namespace TEN::Collision::PointCollision; using namespace TEN::Entities::Player; using namespace TEN::Input; +constexpr auto DEFLECT_STRAIGHT_ANGLE = ANGLE(5.0f); +constexpr auto DEFLECT_DIAGONAL_ANGLE = ANGLE(12.0f); +constexpr auto DEFLECT_STRAIGHT_ANGLE_CRAWL = ANGLE(2.0f); +constexpr auto DEFLECT_DIAGONAL_ANGLE_CRAWL = ANGLE(5.0f); + // ----------------------------- // COLLISION TEST FUNCTIONS // For State Control & Collision @@ -45,12 +50,12 @@ bool LaraDeflectEdge(ItemInfo* item, CollisionInfo* coll) if (coll->CollisionType == CT_LEFT) { ShiftItem(item, coll); - item->Pose.Orientation.y += ANGLE(coll->DiagonalStepAtLeft() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y += coll->DiagonalStepAtLeft() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE; } else if (coll->CollisionType == CT_RIGHT) { ShiftItem(item, coll); - item->Pose.Orientation.y -= ANGLE(coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y -= coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE; } else if (coll->LastBridgeItemNumber != NO_ITEM) { @@ -120,11 +125,11 @@ bool LaraDeflectEdgeJump(ItemInfo* item, CollisionInfo* coll) switch (coll->CollisionType) { case CT_LEFT: - item->Pose.Orientation.y += ANGLE(DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y += DEFLECT_STRAIGHT_ANGLE; break; case CT_RIGHT: - item->Pose.Orientation.y -= ANGLE(DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y -= DEFLECT_STRAIGHT_ANGLE; break; case CT_TOP: @@ -156,11 +161,11 @@ void LaraSlideEdgeJump(ItemInfo* item, CollisionInfo* coll) switch (coll->CollisionType) { case CT_LEFT: - item->Pose.Orientation.y += ANGLE(DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y += DEFLECT_STRAIGHT_ANGLE; break; case CT_RIGHT: - item->Pose.Orientation.y -= ANGLE(DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y -= DEFLECT_STRAIGHT_ANGLE; break; case CT_TOP: @@ -198,12 +203,12 @@ bool LaraDeflectEdgeCrawl(ItemInfo* item, CollisionInfo* coll) if (coll->CollisionType == CT_LEFT) { ShiftItem(item, coll); - item->Pose.Orientation.y += ANGLE(coll->DiagonalStepAtLeft() ? DEFLECT_DIAGONAL_ANGLE_CRAWL : DEFLECT_STRAIGHT_ANGLE_CRAWL); + item->Pose.Orientation.y += coll->DiagonalStepAtLeft() ? DEFLECT_DIAGONAL_ANGLE_CRAWL : DEFLECT_STRAIGHT_ANGLE_CRAWL; } else if (coll->CollisionType == CT_RIGHT) { ShiftItem(item, coll); - item->Pose.Orientation.y -= ANGLE(coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE_CRAWL : DEFLECT_STRAIGHT_ANGLE_CRAWL); + item->Pose.Orientation.y -= coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE_CRAWL : DEFLECT_STRAIGHT_ANGLE_CRAWL; } return false; @@ -229,12 +234,12 @@ bool LaraDeflectEdgeMonkey(ItemInfo* item, CollisionInfo* coll) if (coll->CollisionType == CT_LEFT) { ShiftItem(item, coll); - item->Pose.Orientation.y += ANGLE(coll->DiagonalStepAtLeft() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y += coll->DiagonalStepAtLeft() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE; } else if (coll->CollisionType == CT_RIGHT) { ShiftItem(item, coll); - item->Pose.Orientation.y -= ANGLE(coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE); + item->Pose.Orientation.y -= coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE; } return false; diff --git a/TombEngine/Game/Lara/lara_collide.h b/TombEngine/Game/Lara/lara_collide.h index 79a25d9ad..41a6bf3b1 100644 --- a/TombEngine/Game/Lara/lara_collide.h +++ b/TombEngine/Game/Lara/lara_collide.h @@ -3,11 +3,6 @@ struct ItemInfo; struct CollisionInfo; -constexpr auto DEFLECT_STRAIGHT_ANGLE = 5.0f; -constexpr auto DEFLECT_DIAGONAL_ANGLE = 12.0f; -constexpr auto DEFLECT_STRAIGHT_ANGLE_CRAWL = 2.0f; -constexpr auto DEFLECT_DIAGONAL_ANGLE_CRAWL = 5.0f; - // ----------------------------- // COLLISION TEST FUNCTIONS // For State Control & Collision diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 42e34c183..7c596723f 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -14,9 +14,6 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Room; using namespace TEN::Math; -// TODO -// BUG: Grabbing diagonal ledges stopped working. Lara deflects. Minor error somewhere. - namespace TEN::Collision::PointCollision { PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) @@ -57,9 +54,10 @@ namespace TEN::Collision::PointCollision auto roomNumberBelow = bottomSectorPtr->GetNextRoomNumber(_position, true); while (roomNumberBelow.has_value()) { - auto& room = g_Level.Rooms[roomNumberBelow.value_or(bottomSectorPtr->RoomNumber)]; - bottomSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); + int roomNumber = roomNumberBelow.value_or(bottomSectorPtr->RoomNumber); + auto& room = g_Level.Rooms[roomNumber]; + bottomSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); roomNumberBelow = bottomSectorPtr->GetNextRoomNumber(_position, true); } _bottomSectorPtr = bottomSectorPtr; @@ -77,9 +75,10 @@ namespace TEN::Collision::PointCollision auto roomNumberAbove = topSectorPtr->GetNextRoomNumber(_position, false); while (roomNumberAbove.has_value()) { - auto& room = g_Level.Rooms[roomNumberAbove.value_or(topSectorPtr->RoomNumber)]; - topSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); + int roomNumber = roomNumberAbove.value_or(topSectorPtr->RoomNumber); + auto& room = g_Level.Rooms[roomNumber]; + topSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); roomNumberAbove = topSectorPtr->GetNextRoomNumber(_position, false); } _topSectorPtr = topSectorPtr; diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 363545bc5..06c8b71cc 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -1,4 +1,5 @@ #pragma once +#include "Game/collision/floordata.h" #include "Math/Math.h" #include "Objects/game_object_ids.h" @@ -8,13 +9,14 @@ struct ItemInfo; struct MESH_INFO; struct ROOM_INFO; +using namespace TEN::Collision::Floordata; using namespace TEN::Math; constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBound. constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound. constexpr auto COLLISION_CHECK_DISTANCE = BLOCK(8); -constexpr auto DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE = ANGLE(45.0f * 0.75f); +constexpr auto DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE = ANGLE(36.0f); constexpr auto DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE = ANGLE(45.0f); enum CollisionType @@ -47,13 +49,13 @@ struct CollisionPositionData int Floor = 0; int Ceiling = 0; int Bridge = 0; - float SplitAngle = 0.0f; + short SplitAngle = 0; bool FloorSlope = false; bool CeilingSlope = false; bool DiagonalStep = false; - bool HasDiagonalSplit() { return ((SplitAngle == (45.0f * RADIAN)) || (SplitAngle == (135.0f * RADIAN))); } - bool HasFlippedDiagonalSplit() { return (HasDiagonalSplit() && (SplitAngle != (45.0f * RADIAN))); } + bool HasDiagonalSplit() { return ((SplitAngle == SectorSurfaceData::SPLIT_ANGLE_0) || (SplitAngle == SectorSurfaceData::SPLIT_ANGLE_1)); } + bool HasFlippedDiagonalSplit() { return (HasDiagonalSplit() && (SplitAngle != SectorSurfaceData::SPLIT_ANGLE_0)); } }; struct CollisionSetupData @@ -112,8 +114,8 @@ struct CollisionInfo bool HitStatic = false; bool HitTallObject = false; - bool TriangleAtRight() { return ((MiddleRight.SplitAngle != 0.0f) && (MiddleRight.SplitAngle == Middle.SplitAngle)); } - bool TriangleAtLeft() { return ((MiddleLeft.SplitAngle != 0.0f) && (MiddleLeft.SplitAngle == Middle.SplitAngle)); } + bool TriangleAtRight() { return ((MiddleRight.SplitAngle != 0) && (MiddleRight.SplitAngle == Middle.SplitAngle)); } + bool TriangleAtLeft() { return ((MiddleLeft.SplitAngle != 0) && (MiddleLeft.SplitAngle == Middle.SplitAngle)); } bool DiagonalStepAtRight() { return (MiddleRight.DiagonalStep && TriangleAtRight() && (NearestLedgeAngle % ANGLE(90.0f))); } bool DiagonalStepAtLeft() { return (MiddleLeft.DiagonalStep && TriangleAtLeft() && (NearestLedgeAngle % ANGLE(90.0f))); } }; From 2366bcbd1d8bdaf3c7983cefa419aa242a21ad01 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 10 Mar 2024 15:49:42 +1100 Subject: [PATCH 065/410] Update comment; rename methods --- TombEngine/Game/collision/PointCollision.cpp | 20 ++++++++------------ TombEngine/Game/collision/PointCollision.h | 8 ++++---- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/PointCollision.cpp index 7c596723f..9bdb931cc 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/PointCollision.cpp @@ -241,25 +241,25 @@ namespace TEN::Collision::PointCollision return GetTopSector().IsSurfaceDiagonalStep(false); } - bool PointCollisionData::IsFloorDiagonalSplit() + bool PointCollisionData::IsDiagonalFloorSplit() { float splitAngle = GetBottomSector().FloorSurface.SplitAngle; return (splitAngle == SectorSurfaceData::SPLIT_ANGLE_0 || splitAngle == SectorSurfaceData::SPLIT_ANGLE_1); } - bool PointCollisionData::IsCeilingDiagonalSplit() + bool PointCollisionData::IsDiagonalCeilingSplit() { float splitAngle = GetTopSector().CeilingSurface.SplitAngle; return (splitAngle == SectorSurfaceData::SPLIT_ANGLE_0 || splitAngle == SectorSurfaceData::SPLIT_ANGLE_1); } - bool PointCollisionData::IsFloorFlippedDiagonalSplit() + bool PointCollisionData::IsFlippedDiagonalFloorSplit() { float splitAngle = GetBottomSector().FloorSurface.SplitAngle; return (IsDiagonalFloorStep() && splitAngle == SectorSurfaceData::SPLIT_ANGLE_1); } - bool PointCollisionData::IsCeilingFlippedDiagonalSplit() + bool PointCollisionData::IsFlippedDiagonalCeilingSplit() { float splitAngle = GetTopSector().CeilingSurface.SplitAngle; return (IsDiagonalCeilingStep() && splitAngle == SectorSurfaceData::SPLIT_ANGLE_1); @@ -339,15 +339,11 @@ namespace TEN::Collision::PointCollision PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) { - // TEMP HACK - // GetPointCollision() takes arguments for a *current* position and room number. - // However, since some calls to the old GetPointCollision() function had *projected* - // positions passed to it, the room number had be corrected to account for such cases. - // These are primarily found in camera.cpp. - short correctedRoomNumber = roomNumber; - GetFloor(pos.x, pos.y, pos.z, &correctedRoomNumber); + // HACK: Ensure room number is correct if position extends to another room. + // Accounts for some calls to this function which directly pass offset position instead of using dedicated overloads to probe. + GetFloor(pos.x, pos.y, pos.z, (short*)&roomNumber); - return PointCollisionData(pos, correctedRoomNumber); + return PointCollisionData(pos, roomNumber); } PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber, const Vector3& dir, float dist) diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/PointCollision.h index cc031d4ab..b5717cec0 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/PointCollision.h @@ -61,10 +61,10 @@ namespace TEN::Collision::PointCollision bool IsIllegalCeiling(); bool IsDiagonalFloorStep(); bool IsDiagonalCeilingStep(); - bool IsFloorDiagonalSplit(); - bool IsCeilingDiagonalSplit(); - bool IsFloorFlippedDiagonalSplit(); - bool IsCeilingFlippedDiagonalSplit(); + bool IsDiagonalFloorSplit(); + bool IsDiagonalCeilingSplit(); + bool IsFlippedDiagonalFloorSplit(); + bool IsFlippedDiagonalCeilingSplit(); bool TestEnvironmentFlag(RoomEnvFlags envFlag); From e17543c49736b7d9039c351ec15cd68a7e8fbecf Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 27 Mar 2024 16:38:55 +1100 Subject: [PATCH 066/410] Update comments --- TombEngine/Game/collision/collide_room.h | 35 +++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 3a83e31d5..c2c018073 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -60,26 +60,29 @@ struct CollisionPositionData struct CollisionSetupData { - CollisionProbeMode Mode = CollisionProbeMode::Quadrants; // Probe rotation mode - int Radius = 0; // Collision bounds horizontal size - int Height = 0; // Collision bounds vertical size - short ForwardAngle = 0; // Forward angle direction + // Collider parameters. + CollisionProbeMode Mode = CollisionProbeMode::Quadrants; + int Radius = 0; + int Height = 0; + short ForwardAngle = 0; - int LowerFloorBound = 0; // Borderline floor step-up height - int UpperFloorBound = 0; // Borderline floor step-down height - int LowerCeilingBound = 0; // Borderline ceiling step-up height - int UpperCeilingBound = 0; // Borderline ceiling step-down height + // Borderline step heights. + int LowerFloorBound = 0; + int UpperFloorBound = 0; + int LowerCeilingBound = 0; + int UpperCeilingBound = 0; - bool BlockFloorSlopeUp = false; // Treat steep slopes as walls - bool BlockFloorSlopeDown = false; // Treat steep slopes as pits - bool BlockCeilingSlope = false; // Treat steep slopes on ceilings as walls - bool BlockDeathFloorDown = false; // Treat death sectors as pits - bool BlockMonkeySwingEdge = false; // Treat non-monkey sectors as walls + // Blocker flags. + bool BlockFloorSlopeUp = false; + bool BlockFloorSlopeDown = false; + bool BlockCeilingSlope = false; + bool BlockDeathFloorDown = false; + bool BlockMonkeySwingEdge = false; - bool EnableObjectPush = false; // Can be pushed by objects - bool EnableSpasm = false; // Convulse when pushed + bool EnableObjectPush = false; + bool EnableSpasm = false; - // Preserve previous parameters to restore later. + // Previous parameters. Vector3i PrevPosition = Vector3i::Zero; GAME_OBJECT_ID PrevAnimObjectID = ID_NO_OBJECT; int PrevAnimNumber = 0; From d9d89b4139cbdde0f3fe9964cba2e56c93fadaaa Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 27 Mar 2024 16:40:37 +1100 Subject: [PATCH 067/410] Add comment --- TombEngine/Game/collision/collide_room.h | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index c2c018073..a748ef8c2 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -79,6 +79,7 @@ struct CollisionSetupData bool BlockDeathFloorDown = false; bool BlockMonkeySwingEdge = false; + // Object collision inquirers. bool EnableObjectPush = false; bool EnableSpasm = false; From 8e55fe316e2bd30e249de7bacc01257ba46e3aeb Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 27 Mar 2024 16:42:43 +1100 Subject: [PATCH 068/410] Update comments --- TombEngine/Game/collision/collide_room.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index a748ef8c2..52a215687 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -60,30 +60,30 @@ struct CollisionPositionData struct CollisionSetupData { - // Collider parameters. + // Collider parameters CollisionProbeMode Mode = CollisionProbeMode::Quadrants; int Radius = 0; int Height = 0; short ForwardAngle = 0; - // Borderline step heights. + // Borderline step heights int LowerFloorBound = 0; int UpperFloorBound = 0; int LowerCeilingBound = 0; int UpperCeilingBound = 0; - // Blocker flags. + // Blocker flags bool BlockFloorSlopeUp = false; bool BlockFloorSlopeDown = false; bool BlockCeilingSlope = false; bool BlockDeathFloorDown = false; bool BlockMonkeySwingEdge = false; - // Object collision inquirers. + // Inquirers bool EnableObjectPush = false; bool EnableSpasm = false; - // Previous parameters. + // Previous parameters Vector3i PrevPosition = Vector3i::Zero; GAME_OBJECT_ID PrevAnimObjectID = ID_NO_OBJECT; int PrevAnimNumber = 0; @@ -93,7 +93,7 @@ struct CollisionSetupData struct CollisionInfo { - CollisionSetupData Setup = {}; // In parameters + CollisionSetupData Setup = {}; CollisionPositionData Middle = {}; CollisionPositionData MiddleLeft = {}; @@ -118,6 +118,7 @@ struct CollisionInfo bool HitStatic = false; bool HitTallObject = false; + // Inquirers. bool TriangleAtRight() { return ((MiddleRight.SplitAngle != 0) && (MiddleRight.SplitAngle == Middle.SplitAngle)); } bool TriangleAtLeft() { return ((MiddleLeft.SplitAngle != 0) && (MiddleLeft.SplitAngle == Middle.SplitAngle)); } bool DiagonalStepAtRight() { return (MiddleRight.DiagonalStep && TriangleAtRight() && (NearestLedgeAngle % ANGLE(90.0f))); } From bab278f9df6ccaa232a40600eba788a040bee907 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 28 Mar 2024 19:27:02 +1100 Subject: [PATCH 069/410] Rename file and namespace --- TombEngine/Game/Lara/PlayerContext.cpp | 4 ++-- TombEngine/Game/Lara/lara.cpp | 4 ++-- TombEngine/Game/Lara/lara_climb.cpp | 4 ++-- TombEngine/Game/Lara/lara_collide.cpp | 4 ++-- TombEngine/Game/Lara/lara_flare.cpp | 4 ++-- TombEngine/Game/Lara/lara_helpers.cpp | 4 ++-- TombEngine/Game/Lara/lara_one_gun.cpp | 4 ++-- TombEngine/Game/Lara/lara_overhang.cpp | 4 ++-- TombEngine/Game/Lara/lara_tests.cpp | 4 ++-- TombEngine/Game/camera.cpp | 4 ++-- TombEngine/Game/collision/{PointCollision.cpp => Point.cpp} | 4 ++-- TombEngine/Game/collision/{PointCollision.h => Point.h} | 2 +- TombEngine/Game/collision/collide_item.cpp | 4 ++-- TombEngine/Game/collision/collide_item.h | 4 ++-- TombEngine/Game/collision/collide_room.cpp | 4 ++-- TombEngine/Game/collision/floordata.cpp | 4 ++-- TombEngine/Game/control/box.cpp | 4 ++-- TombEngine/Game/control/trigger.cpp | 4 ++-- TombEngine/Game/effects/drip.cpp | 4 ++-- TombEngine/Game/effects/effects.cpp | 4 ++-- TombEngine/Game/effects/footprint.cpp | 4 ++-- TombEngine/Game/effects/hair.cpp | 4 ++-- TombEngine/Game/effects/item_fx.cpp | 4 ++-- TombEngine/Game/effects/weather.cpp | 4 ++-- TombEngine/Game/items.cpp | 4 ++-- TombEngine/Game/missile.cpp | 4 ++-- TombEngine/Game/pickup/pickup.cpp | 4 ++-- TombEngine/Game/room.cpp | 4 ++-- TombEngine/Objects/Effects/enemy_missile.cpp | 4 ++-- TombEngine/Objects/Effects/flame_emitters.cpp | 4 ++-- TombEngine/Objects/Effects/tr5_electricity.cpp | 4 ++-- .../Objects/Generic/Object/Pushable/PushableCollision.cpp | 4 ++-- TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp | 4 ++-- TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp | 4 ++-- TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp | 4 ++-- TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp | 4 ++-- TombEngine/Objects/TR1/Entity/tr1_bear.cpp | 4 ++-- TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp | 4 ++-- TombEngine/Objects/TR1/Trap/DamoclesSword.cpp | 4 ++-- TombEngine/Objects/TR2/Entity/Dragon.cpp | 4 ++-- TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp | 4 ++-- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 4 ++-- TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 4 ++-- TombEngine/Objects/TR3/Entity/Shiva.cpp | 4 ++-- TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp | 4 ++-- TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp | 4 ++-- TombEngine/Objects/TR3/Entity/tr3_tony.cpp | 4 ++-- TombEngine/Objects/TR3/Object/corpse.cpp | 4 ++-- TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp | 4 ++-- TombEngine/Objects/TR3/Trap/train.cpp | 4 ++-- TombEngine/Objects/TR3/Vehicles/big_gun.cpp | 4 ++-- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 4 ++-- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 4 ++-- TombEngine/Objects/TR3/Vehicles/quad_bike.cpp | 4 ++-- TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp | 4 ++-- TombEngine/Objects/TR3/Vehicles/upv.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/Wraith.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_baboon.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_baddy.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_horseman.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_sas.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_setha.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp | 4 ++-- TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp | 4 ++-- TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp | 4 ++-- TombEngine/Objects/TR4/Object/tr4_mapper.cpp | 4 ++-- TombEngine/Objects/TR4/Object/tr4_senet.cpp | 4 ++-- TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp | 4 ++-- TombEngine/Objects/TR4/Trap/SpikyWall.cpp | 4 ++-- TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp | 4 ++-- TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp | 4 ++-- TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp | 4 ++-- TombEngine/Objects/TR4/Vehicles/jeep.cpp | 4 ++-- TombEngine/Objects/TR4/Vehicles/motorbike.cpp | 4 ++-- TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp | 4 ++-- TombEngine/Objects/TR5/Entity/tr5_guard.cpp | 4 ++-- TombEngine/Objects/TR5/Entity/tr5_submarine.cpp | 4 ++-- TombEngine/Objects/TR5/Object/tr5_bodypart.cpp | 4 ++-- TombEngine/Objects/TR5/Object/tr5_missile.cpp | 4 ++-- TombEngine/Objects/TR5/Object/tr5_rollingball.cpp | 4 ++-- TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp | 4 ++-- TombEngine/Objects/TR5/Trap/LaserBarrier.cpp | 4 ++-- TombEngine/Objects/TR5/Trap/ZipLine.cpp | 4 ++-- TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp | 4 ++-- TombEngine/Objects/Utils/VehicleHelpers.cpp | 4 ++-- TombEngine/TombEngine.vcxproj | 4 ++-- 88 files changed, 175 insertions(+), 175 deletions(-) rename TombEngine/Game/collision/{PointCollision.cpp => Point.cpp} (99%) rename TombEngine/Game/collision/{PointCollision.h => Point.h} (98%) diff --git a/TombEngine/Game/Lara/PlayerContext.cpp b/TombEngine/Game/Lara/PlayerContext.cpp index 63f30f3f2..6e6d4d721 100644 --- a/TombEngine/Game/Lara/PlayerContext.cpp +++ b/TombEngine/Game/Lara/PlayerContext.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/floordata.h" #include "Game/control/los.h" #include "Game/items.h" @@ -15,7 +15,7 @@ #include "Specific/Input/Input.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; namespace TEN::Entities::Player diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index d74594b3e..6823a03f6 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -24,7 +24,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/flipeffect.h" #include "Game/control/volume.h" #include "Game/effects/Hair.h" @@ -48,7 +48,7 @@ #include "Specific/winmain.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Hair; using namespace TEN::Effects::Items; diff --git a/TombEngine/Game/Lara/lara_climb.cpp b/TombEngine/Game/Lara/lara_climb.cpp index f944dde5c..68917f419 100644 --- a/TombEngine/Game/Lara/lara_climb.cpp +++ b/TombEngine/Game/Lara/lara_climb.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/items.h" @@ -15,7 +15,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; constexpr auto LADDER_TEST_MARGIN = 8; diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index 546c3b25d..d0527f388 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -20,7 +20,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Scripting/Include/ScriptInterfaceLevel.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Player; using namespace TEN::Input; diff --git a/TombEngine/Game/Lara/lara_flare.cpp b/TombEngine/Game/Lara/lara_flare.cpp index 3e8402ec2..375562969 100644 --- a/TombEngine/Game/Lara/lara_flare.cpp +++ b/TombEngine/Game/Lara/lara_flare.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/chaffFX.h" @@ -19,7 +19,7 @@ #include "Specific/clock.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; constexpr auto FLARE_LIFE_MAX = 60.0f * FPS; diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 0ab9aa44f..a84f0e5f9 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -7,7 +7,7 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/control/volume.h" #include "Game/items.h" @@ -38,7 +38,7 @@ #include "Objects/TR4/Vehicles/motorbike.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Drip; diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index 898a001f8..708cac335 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/los.h" @@ -32,7 +32,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Drip; using namespace TEN::Effects::Environment; diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index a9b81c427..9915346a5 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -4,7 +4,7 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_climb.h" @@ -18,7 +18,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Generic; using namespace TEN::Input; diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 342a69075..d8412059b 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -5,7 +5,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/control/los.h" #include "Game/items.h" @@ -23,7 +23,7 @@ #include "Specific/trutils.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Player; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 11dd4720c..e0863e650 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/los.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -23,7 +23,7 @@ #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Environment; using namespace TEN::Entities::Generic; using namespace TEN::Input; diff --git a/TombEngine/Game/collision/PointCollision.cpp b/TombEngine/Game/collision/Point.cpp similarity index 99% rename from TombEngine/Game/collision/PointCollision.cpp rename to TombEngine/Game/collision/Point.cpp index 9bdb931cc..db80021a7 100644 --- a/TombEngine/Game/collision/PointCollision.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -1,5 +1,5 @@ #include "framework.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" @@ -14,7 +14,7 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Room; using namespace TEN::Math; -namespace TEN::Collision::PointCollision +namespace TEN::Collision::Point { PointCollisionData::PointCollisionData(const Vector3i& pos, int roomNumber) { diff --git a/TombEngine/Game/collision/PointCollision.h b/TombEngine/Game/collision/Point.h similarity index 98% rename from TombEngine/Game/collision/PointCollision.h rename to TombEngine/Game/collision/Point.h index b5717cec0..318082c42 100644 --- a/TombEngine/Game/collision/PointCollision.h +++ b/TombEngine/Game/collision/Point.h @@ -8,7 +8,7 @@ struct ItemInfo; using namespace TEN::Math; -namespace TEN::Collision::PointCollision +namespace TEN::Collision::Point { class PointCollisionData { diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index de15f6b82..b212b96a8 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -5,7 +5,7 @@ #include "Game/control/los.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -23,7 +23,7 @@ #include "Sound/sound.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; using namespace TEN::Renderer; diff --git a/TombEngine/Game/collision/collide_item.h b/TombEngine/Game/collision/collide_item.h index 9f10dc584..ee9d6a8b6 100644 --- a/TombEngine/Game/collision/collide_item.h +++ b/TombEngine/Game/collision/collide_item.h @@ -1,14 +1,14 @@ #pragma once #include "Math/Math.h" -namespace TEN::Collision::PointCollision { class PointCollisionData; }; +namespace TEN::Collision::Point { class PointCollisionData; }; class FloorInfo; struct CollisionInfo; struct CollisionResult; struct ItemInfo; struct MESH_INFO; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; constexpr auto MAX_COLLIDED_OBJECTS = 1024; constexpr auto ITEM_RADIUS_YMAX = BLOCK(3); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index abc632d39..ce25ae013 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -4,7 +4,7 @@ #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/animation.h" #include "Game/Lara/lara.h" #include "Game/items.h" @@ -14,7 +14,7 @@ #include "Renderer/Renderer.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Collision::Room; using namespace TEN::Math; using namespace TEN::Renderer; diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 2724d156f..8d02233e0 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -2,7 +2,7 @@ #include "Game/collision/floordata.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/items.h" #include "Game/room.h" #include "Game/Setup.h" @@ -13,7 +13,7 @@ #include "Specific/trutils.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Generic; using namespace TEN::Math; using namespace TEN::Utils; diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 6db0d80c7..90778ecf5 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -5,7 +5,7 @@ #include "Game/camera.h" #include "Game/collision/sphere.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/control/lot.h" #include "Game/effects/smoke.h" @@ -23,7 +23,7 @@ #include "Objects/Generic/Object/Pushable/PushableObject.h" #include "Renderer/Renderer.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Collision::Room; using namespace TEN::Effects::Smoke; diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index bf323e985..0fc94666b 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -3,7 +3,7 @@ #include "Game/camera.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/flipeffect.h" #include "Game/control/box.h" #include "Game/control/lot.h" @@ -25,7 +25,7 @@ #include "Sound/sound.h" #include "Specific/clock.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Entities::Switches; diff --git a/TombEngine/Game/effects/drip.cpp b/TombEngine/Game/effects/drip.cpp index ad6ee12e2..08336ecfc 100644 --- a/TombEngine/Game/effects/drip.cpp +++ b/TombEngine/Game/effects/drip.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/Ripple.h" #include "Game/effects/weather.h" @@ -13,7 +13,7 @@ #include "Specific/clock.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Environment; using namespace TEN::Effects::Ripple; using namespace TEN::Collision::Floordata; diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 33a36982e..737b536a9 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -4,7 +4,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/Blood.h" #include "Game/effects/Bubble.h" #include "Game/effects/Drip.h" @@ -26,7 +26,7 @@ #include "Specific/clock.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Blood; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Drip; diff --git a/TombEngine/Game/effects/footprint.cpp b/TombEngine/Game/effects/footprint.cpp index d990792d9..33c50c03c 100644 --- a/TombEngine/Game/effects/footprint.cpp +++ b/TombEngine/Game/effects/footprint.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -17,7 +17,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Effects::Footprint diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index cb9a0514f..70e3278c7 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/weather.h" @@ -15,7 +15,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Environment; using TEN::Renderer::g_Renderer; diff --git a/TombEngine/Game/effects/item_fx.cpp b/TombEngine/Game/effects/item_fx.cpp index 09a127024..5261e6734 100644 --- a/TombEngine/Game/effects/item_fx.cpp +++ b/TombEngine/Game/effects/item_fx.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/smoke.h" @@ -14,7 +14,7 @@ #include "Specific/clock.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Smoke; namespace TEN::Effects::Items diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index 2ba7c761b..25ab784e2 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -3,7 +3,7 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/Ripple.h" #include "Game/effects/tomb4fx.h" @@ -14,7 +14,7 @@ #include "Specific/level.h" #include "Scripting/Include/ScriptInterfaceLevel.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Ripple; using namespace TEN::Math::Random; diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index b88cf120d..267a4fbb7 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -3,7 +3,7 @@ #include "Game/collision/floordata.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/control/volume.h" #include "Game/effects/effects.h" @@ -27,7 +27,7 @@ #include "Specific/trutils.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Collision::Room; using namespace TEN::Control::Volumes; using namespace TEN::Effects::Items; diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index d8891afa0..bf171f0be 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/effects.h" #include "Game/effects/explosion.h" @@ -16,7 +16,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision;; +using namespace TEN::Collision::Point;; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Explosion; using namespace TEN::Math; diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index 9618c1a5b..c20a0a2e3 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -5,7 +5,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/debris.h" #include "Game/Gui.h" #include "Game/Hud/Hud.h" @@ -31,7 +31,7 @@ #include "Specific/level.h" #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Generic; using namespace TEN::Hud; using namespace TEN::Input; diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index 85da187fc..3d2d36ac9 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -2,7 +2,7 @@ #include "Game/room.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/control/lot.h" #include "Game/control/volume.h" @@ -14,7 +14,7 @@ using namespace TEN::Math; using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Renderer; using namespace TEN::Utils; diff --git a/TombEngine/Objects/Effects/enemy_missile.cpp b/TombEngine/Objects/Effects/enemy_missile.cpp index f11fdeddf..286b3b43b 100644 --- a/TombEngine/Objects/Effects/enemy_missile.cpp +++ b/TombEngine/Objects/Effects/enemy_missile.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -18,7 +18,7 @@ #include "Renderer/RendererEnums.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Entities::Creatures::TR3; using namespace TEN::Entities::TR4; diff --git a/TombEngine/Objects/Effects/flame_emitters.cpp b/TombEngine/Objects/Effects/flame_emitters.cpp index 37ccc5465..d790a652f 100644 --- a/TombEngine/Objects/Effects/flame_emitters.cpp +++ b/TombEngine/Objects/Effects/flame_emitters.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" @@ -21,7 +21,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Environment; using namespace TEN::Effects::Items; diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index 973a41402..3bd02ec50 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -18,7 +18,7 @@ #include "Specific/clock.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Effects::Ripple; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index d9a06eb94..1c5b33210 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/Lara/lara.h" #include "Game/Setup.h" #include "Objects/Generic/Object/BridgeObject.h" @@ -13,7 +13,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Collision::Floordata; using namespace TEN::Entities::Generic; using namespace TEN::Input; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp index 57d9658fe..491caea4f 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/floordata.h" #include "Game/control/box.h" #include "Game/control/flipeffect.h" @@ -23,7 +23,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; namespace TEN::Entities::Generic diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp index b28869af2..f5d3592fc 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp @@ -1,12 +1,12 @@ #include "framework.h" #include "Objects/Generic/Object/Pushable/PushableSound.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Objects/Generic/Object/Pushable/PushableObject.h" #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::Generic { diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp index 833efe10d..9f56c8b8f 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp @@ -2,14 +2,14 @@ #include "Objects/Generic/Object/Pushable/PushableStack.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/Setup.h" #include "Objects/Generic/Object/Pushable/PushableBridge.h" #include "Objects/Generic/Object/Pushable/PushableObject.h" #include "Specific/level.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::Generic { diff --git a/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp b/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp index 406262f9f..9a1a87e89 100644 --- a/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp +++ b/TombEngine/Objects/Generic/Traps/crumblingPlatform.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" #include "Game/setup.h" @@ -12,7 +12,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Generic; // NOTES: diff --git a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp index fce60b3eb..8d219f369 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp @@ -2,7 +2,7 @@ #include "Objects/TR1/Entity/tr1_bear.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -14,7 +14,7 @@ #include "Math/Math.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR1 diff --git a/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp b/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp index d91999010..d9e981c69 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_doppelganger.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/control/lot.h" #include "Game/items.h" @@ -12,7 +12,7 @@ #include "Game/misc.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::Creatures::TR1 { diff --git a/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp b/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp index 50b1cccec..348827f7e 100644 --- a/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp +++ b/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp @@ -4,14 +4,14 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/Lara/lara.h" #include "Game/Setup.h" #include "Math/Math.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::Traps::TR1 diff --git a/TombEngine/Objects/TR2/Entity/Dragon.cpp b/TombEngine/Objects/TR2/Entity/Dragon.cpp index 7613ed5fb..6cab05dbf 100644 --- a/TombEngine/Objects/TR2/Entity/Dragon.cpp +++ b/TombEngine/Objects/TR2/Entity/Dragon.cpp @@ -3,7 +3,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -17,7 +17,7 @@ #include "Specific/clock.h" #include "Specific/Input/Input.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp index 50a2800e4..dc027a558 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp +++ b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -12,7 +12,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; void InitializeSpinningBlade(short itemNumber) { diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index c72777c44..cff60fb15 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -22,7 +22,7 @@ #include "Math/Math.h" #include "Sound/sound.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index 162d6df91..5f85dba8e 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -18,7 +18,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; namespace TEN::Entities::Vehicles diff --git a/TombEngine/Objects/TR3/Entity/Shiva.cpp b/TombEngine/Objects/TR3/Entity/Shiva.cpp index 1b07d640a..3d74ab035 100644 --- a/TombEngine/Objects/TR3/Entity/Shiva.cpp +++ b/TombEngine/Objects/TR3/Entity/Shiva.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/effects/effects.h" #include "Game/itemdata/creature_info.h" @@ -18,7 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp index 12bdf11a7..96f4b2a76 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/collision/sphere.h" @@ -18,7 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 diff --git a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp index 802578b2d..2b7f9bf0d 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp @@ -2,7 +2,7 @@ #include "Objects/TR3/Entity/tr3_scuba_diver.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/los.h" @@ -14,7 +14,7 @@ #include "Game/Setup.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::Creatures::TR3 { diff --git a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp index efc5feef8..27728f2a3 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -19,7 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Effects::Boss; diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp index 987c695f7..54df7cbfa 100644 --- a/TombEngine/Objects/TR3/Object/corpse.cpp +++ b/TombEngine/Objects/TR3/Object/corpse.cpp @@ -7,7 +7,7 @@ #include "Game/control/control.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/floordata.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" @@ -19,7 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Ripple; using namespace TEN::Math::Random; diff --git a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp index b823d479a..13404cbae 100644 --- a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp +++ b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/effects/item_fx.h" #include "Game/effects/spark.h" @@ -11,7 +11,7 @@ #include "Game/Lara/lara_helpers.h" #include "Game/Setup.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Collision::Floordata; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; diff --git a/TombEngine/Objects/TR3/Trap/train.cpp b/TombEngine/Objects/TR3/Trap/train.cpp index aab505f7a..0bd209b1d 100644 --- a/TombEngine/Objects/TR3/Trap/train.cpp +++ b/TombEngine/Objects/TR3/Trap/train.cpp @@ -6,7 +6,7 @@ #include "Game/control/control.h" #include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/floordata.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" @@ -17,7 +17,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; constexpr auto TRAIN_VEL = 260; diff --git a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp index b27904790..2e49fb8b9 100644 --- a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp +++ b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp @@ -6,7 +6,7 @@ #include "Game/control/box.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Game/items.h" @@ -21,7 +21,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; namespace TEN::Entities::Vehicles diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index 5b26186bf..e3ae3d7a8 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -5,7 +5,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -19,7 +19,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; namespace TEN::Entities::Vehicles diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index b3ac6e8de..888cc1ab6 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -5,7 +5,7 @@ #include "Game/camera.h" #include "Game/collision/sphere.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/spark.h" #include "Game/effects/tomb4fx.h" @@ -21,7 +21,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Spark; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp index 15b4ce4f4..8711384ef 100644 --- a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp +++ b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp @@ -5,7 +5,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" #include "Game/effects/tomb4fx.h" @@ -23,7 +23,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp index c73754806..78f938ab2 100644 --- a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp +++ b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/Bubble.h" #include "Game/effects/effects.h" @@ -20,7 +20,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Bubble; using namespace TEN::Input; diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index 5c5939548..bbd37ad60 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -6,7 +6,7 @@ #include "Game/collision/sphere.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/Bubble.h" @@ -27,7 +27,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Streamer; using namespace TEN::Input; diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index 790f0ed8c..e3e536366 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -2,7 +2,7 @@ #include "Objects/TR4/Entity/Wraith.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/flipeffect.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" @@ -19,7 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Streamer; diff --git a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp index b201ba54a..262a36d62 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp @@ -2,7 +2,7 @@ #include "Objects/TR4/Entity/tr4_baboon.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/control/control.h" @@ -16,7 +16,7 @@ #include "Game/Setup.h" #include "Math/Math.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Environment; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp index f1f808d8b..4490c0f0a 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/lot.h" @@ -19,7 +19,7 @@ #include "Math/Math.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; /* diff --git a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp index ead8f8949..c540afd27 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/control/trigger.h" @@ -18,7 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::TR4 diff --git a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp index 2b48d98b3..ef35f9efb 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/box.h" #include "Game/control/control.h" @@ -17,7 +17,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::TR4 diff --git a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp index 65633f6a2..7c94d44d5 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/volume.h" @@ -24,7 +24,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Control::Volumes; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp index ef0742ccc..03c5963c4 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp @@ -5,7 +5,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/spark.h" @@ -21,7 +21,7 @@ #include "Specific/clock.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp index 6f346fabb..b2ddd7053 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/floordata.h" #include "Game/control/box.h" #include "Game/control/lot.h" @@ -21,7 +21,7 @@ #include "Math/Math.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::TR4 diff --git a/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp b/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp index 5fd89bdb2..e6d194981 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sphinx.cpp @@ -2,7 +2,7 @@ #include "Objects/TR4/Entity/tr4_sphinx.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -14,7 +14,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::TR4 { diff --git a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp index 96b7d8ed6..6b4c44690 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -17,7 +17,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::TR4 diff --git a/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp b/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp index b48269f15..0535ae8d2 100644 --- a/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp @@ -6,10 +6,10 @@ #include "Game/animation.h" #include "Sound/sound.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/debris.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; void ClockworkBeetleControl(short itemNumber) { diff --git a/TombEngine/Objects/TR4/Object/tr4_mapper.cpp b/TombEngine/Objects/TR4/Object/tr4_mapper.cpp index e12847de8..faf2fe1f0 100644 --- a/TombEngine/Objects/TR4/Object/tr4_mapper.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_mapper.cpp @@ -2,7 +2,7 @@ #include "Objects/TR4/Object/tr4_mapper.h" #include "Specific/level.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Sound/sound.h" #include "Game/animation.h" @@ -12,7 +12,7 @@ #include "Game/items.h" #include "Renderer/RendererEnums.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::TR4 { diff --git a/TombEngine/Objects/TR4/Object/tr4_senet.cpp b/TombEngine/Objects/TR4/Object/tr4_senet.cpp index f923e964c..0568a42c6 100644 --- a/TombEngine/Objects/TR4/Object/tr4_senet.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_senet.cpp @@ -12,9 +12,9 @@ #include "Specific/level.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; int SenetPiecesNumber[6]; diff --git a/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp b/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp index 52bebb8fa..ac0bc9a2d 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -13,7 +13,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::Traps { diff --git a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp index 5049c604c..0554f13c5 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/debris.h" @@ -15,7 +15,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; // NOTES: diff --git a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp index 27a6b96e5..ea72a171b 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp @@ -2,7 +2,7 @@ #include "tr4_joby_spikes.h" #include "Specific/level.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/animation.h" #include "Sound/sound.h" @@ -10,7 +10,7 @@ #include "Game/effects/effects.h" #include "Game/items.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::TR4 { diff --git a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp index 74fc1e265..d24178af5 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp @@ -3,12 +3,12 @@ #include "Specific/level.h" #include "Sound/sound.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/items.h" #include "Game/animation.h" #include "Math/Math.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::TR4 { diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp index 87dcbb8eb..28f043852 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/tomb4fx.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -12,7 +12,7 @@ #include "Specific/level.h" #include "Math/Math.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; namespace TEN::Entities::TR4 { diff --git a/TombEngine/Objects/TR4/Vehicles/jeep.cpp b/TombEngine/Objects/TR4/Vehicles/jeep.cpp index 1a70f3fbe..d06cdbd3d 100644 --- a/TombEngine/Objects/TR4/Vehicles/jeep.cpp +++ b/TombEngine/Objects/TR4/Vehicles/jeep.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" #include "Game/effects/tomb4fx.h" @@ -23,7 +23,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; namespace TEN::Entities::Vehicles diff --git a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp index d364c8368..358878548 100644 --- a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp +++ b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp @@ -5,7 +5,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -24,7 +24,7 @@ #include "Specific/level.h" using std::vector; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; using namespace TEN::Math::Random; diff --git a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp index 1d4a94fd2..f618f3145 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" @@ -21,7 +21,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Electricity; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; diff --git a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp index ce1cc5591..b4867f799 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/effects.h" @@ -18,7 +18,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR5 diff --git a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp index 3739b4108..ee7bb7b9e 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/effects.h" @@ -20,7 +20,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp b/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp index 33baf715d..dcb5e844d 100644 --- a/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp @@ -8,12 +8,12 @@ #include "Game/Lara/lara.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/items.h" #include "Game/effects/tomb4fx.h" #include "Math/Random.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math::Random; constexpr int BODY_PART_LIFE = 64; diff --git a/TombEngine/Objects/TR5/Object/tr5_missile.cpp b/TombEngine/Objects/TR5/Object/tr5_missile.cpp index 4ee9a44af..838dd04fd 100644 --- a/TombEngine/Objects/TR5/Object/tr5_missile.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_missile.cpp @@ -2,7 +2,7 @@ #include "tr5_missile.h" #include "Game/items.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/effects.h" @@ -16,7 +16,7 @@ #include "Game/effects/item_fx.h" #include "Math/Math.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index da785bfd8..4c92f76e1 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -16,7 +16,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; constexpr auto ROLLING_BALL_MAX_VELOCITY = BLOCK(3); diff --git a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp index 220ac21c6..52cb85e20 100644 --- a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -13,7 +13,7 @@ #include "Sound/sound.h" using namespace TEN::Collision::Floordata; -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Math; using namespace TEN::Renderer; diff --git a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp index bb716d60d..cf44a2b01 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp @@ -3,14 +3,14 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/item_fx.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; namespace TEN::Traps::TR5 diff --git a/TombEngine/Objects/TR5/Trap/ZipLine.cpp b/TombEngine/Objects/TR5/Trap/ZipLine.cpp index d18a4dcd4..e53c5bcae 100644 --- a/TombEngine/Objects/TR5/Trap/ZipLine.cpp +++ b/TombEngine/Objects/TR5/Trap/ZipLine.cpp @@ -3,7 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -13,7 +13,7 @@ #include "Sound/sound.h" #include "Specific/Input/Input.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp index ddb99803a..a086231d5 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp @@ -3,13 +3,13 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Specific/level.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; void FallingCeilingControl(short itemNumber) { diff --git a/TombEngine/Objects/Utils/VehicleHelpers.cpp b/TombEngine/Objects/Utils/VehicleHelpers.cpp index d1c2a8081..ae9a5b137 100644 --- a/TombEngine/Objects/Utils/VehicleHelpers.cpp +++ b/TombEngine/Objects/Utils/VehicleHelpers.cpp @@ -2,7 +2,7 @@ #include "Objects/Utils/VehicleHelpers.h" #include "Game/collision/collide_item.h" -#include "Game/collision/PointCollision.h" +#include "Game/collision/Point.h" #include "Game/collision/sphere.h" #include "Game/effects/simple_particle.h" #include "Game/effects/Streamer.h" @@ -16,7 +16,7 @@ #include "Sound/sound.h" #include "Specific/Input/Input.h" -using namespace TEN::Collision::PointCollision; +using namespace TEN::Collision::Point; using namespace TEN::Effects::Streamer; using namespace TEN::Hud; using namespace TEN::Input; diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 496f8c5d6..e4612b226 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -337,7 +337,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - + @@ -858,7 +858,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - + From d10423c0e048dc64405cb8e2aa1bdec7891c6d89 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 11 Apr 2024 10:47:03 +0200 Subject: [PATCH 070/410] Smokes particles interpolation --- TombEngine/Game/effects/smoke.cpp | 36 ++++++++++++++++++++++ TombEngine/Game/effects/smoke.h | 4 +++ TombEngine/Renderer/RendererDrawEffect.cpp | 13 ++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/effects/smoke.cpp b/TombEngine/Game/effects/smoke.cpp index d9f6727a2..a428f893f 100644 --- a/TombEngine/Game/effects/smoke.cpp +++ b/TombEngine/Game/effects/smoke.cpp @@ -52,6 +52,12 @@ namespace TEN::Effects::Smoke continue; } + // Interpolation + s.oldPosition = s.position; + s.oldColor = s.color; + s.oldRotation = s.rotation; + s.oldSize = s.size; + s.velocity.y += s.gravity; if (s.terminalVelocity != 0) @@ -108,6 +114,11 @@ namespace TEN::Effects::Smoke s.affectedByWind = true; s.active = true; s.room = room; + + s.oldPosition = s.position; + s.oldColor = s.color; + s.oldRotation = s.rotation; + s.oldSize = s.size; } //TODO: add additional "Weapon Special" param or something. Currently initial == 2 means Rocket Launcher backwards smoke. @@ -194,6 +205,11 @@ namespace TEN::Effects::Smoke s.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4); s.angularDrag = 0.95f; s.room = roomNumber; + + s.oldPosition = s.position; + s.oldColor = s.color; + s.oldRotation = s.rotation; + s.oldSize = s.size; } void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving) @@ -217,6 +233,11 @@ namespace TEN::Effects::Smoke s.destinationSize = Random::GenerateFloat(128, 160); s.angularVelocity = Random::GenerateFloat(-1, 1); s.angularDrag = Random::GenerateFloat(0.97f, 0.999f); + + s.oldPosition = s.position; + s.oldColor = s.color; + s.oldRotation = s.rotation; + s.oldSize = s.size; } void TriggerRocketSmoke(int x, int y, int z) @@ -236,6 +257,11 @@ namespace TEN::Effects::Smoke s.destinationSize = Random::GenerateFloat(1024, 1152); s.angularVelocity = Random::GenerateFloat(-0.6f, 0.6f); s.angularDrag = Random::GenerateFloat(0.87f, 0.99f); + + s.oldPosition = s.position; + s.oldColor = s.color; + s.oldRotation = s.rotation; + s.oldSize = s.size; } void SpawnCorpseEffect(const Vector3& pos) @@ -259,6 +285,11 @@ namespace TEN::Effects::Smoke smoke.destinationSize = Random::GenerateFloat(BLOCK(1), BLOCK(1.1f)); smoke.angularVelocity = Random::GenerateFloat(-0.1f, 0.1f); smoke.angularDrag = Random::GenerateFloat(0.8f, 0.9f); + + smoke.oldPosition = smoke.position; + smoke.oldColor = smoke.color; + smoke.oldRotation = smoke.rotation; + smoke.oldSize = smoke.size; } void TriggerBreathSmoke(long x, long y, long z, short angle) @@ -282,5 +313,10 @@ namespace TEN::Effects::Smoke s.destinationSize = Random::GenerateFloat(128, 160); s.angularVelocity = Random::GenerateFloat(-0.5f, 0.5f); s.angularDrag = Random::GenerateFloat(0.95f, 0.95f); + + s.oldPosition = s.position; + s.oldColor = s.color; + s.oldRotation = s.rotation; + s.oldSize = s.size; } } diff --git a/TombEngine/Game/effects/smoke.h b/TombEngine/Game/effects/smoke.h index 33e146fd8..41fef8a8f 100644 --- a/TombEngine/Game/effects/smoke.h +++ b/TombEngine/Game/effects/smoke.h @@ -27,6 +27,10 @@ namespace TEN::Effects::Smoke float terminalVelocity; bool affectedByWind; bool active; + Vector4 oldColor; + Vector3 oldPosition; + float oldRotation; + float oldSize; }; extern std::array SmokeParticles; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index b819670a5..1106e151f 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -1295,8 +1295,17 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_SMOKE_SPRITES].meshIndex + smoke.sprite], - smoke.position, - smoke.color, smoke.rotation, 1.0f, { smoke.size, smoke.size }, BlendMode::AlphaBlend, true, view); + Vector3::Lerp(smoke.oldPosition, smoke.position, _interpolationFactor), + Vector4::Lerp(smoke.oldColor, smoke.color, _interpolationFactor), + Lerp(smoke.oldRotation, smoke.rotation, _interpolationFactor), + 1.0f, + { + Lerp(smoke.oldSize, smoke.size, _interpolationFactor), + Lerp(smoke.oldSize, smoke.size, _interpolationFactor) + }, + BlendMode::AlphaBlend, + true, + view); } } From 72b3aa9b7ea47740aa703c88bc97bfde7193f668 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 11 Apr 2024 12:08:22 +0200 Subject: [PATCH 071/410] Blood interpolation --- TombEngine/Game/effects/Blood.h | 5 +++++ TombEngine/Game/effects/tomb4fx.cpp | 14 ++++++++++++ TombEngine/Game/effects/tomb4fx.h | 7 ++++++ TombEngine/Renderer/RendererDrawEffect.cpp | 26 +++++++++++++++++----- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/effects/Blood.h b/TombEngine/Game/effects/Blood.h index 8b1e41650..820f269d0 100644 --- a/TombEngine/Game/effects/Blood.h +++ b/TombEngine/Game/effects/Blood.h @@ -14,6 +14,11 @@ namespace TEN::Effects::Blood float Init = 0.0f; float Size = 0.0f; float Opacity = 0.0f; + + Vector3 OldPosition = Vector3::Zero; + Vector4 OldColor = Vector4::Zero; + float OldSize = 0.0f; + float OldOpacity = 0.0f; }; extern std::vector UnderwaterBloodParticles; diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 2d128dc87..105662c2c 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -748,6 +748,13 @@ void TriggerBlood(int x, int y, int z, int unk, int num) int size = (GetRandomControl() & 7) + 8; blood->sSize = blood->size = size; blood->dSize = size >> 2; + + blood->oldX = blood->x; + blood->oldY = blood->y; + blood->oldZ = blood->z; + blood->oldRotAng = blood->rotAng; + blood->oldSize = blood->size; + blood->oldShade = blood->shade; } } @@ -767,6 +774,13 @@ void UpdateBlood() continue; } + blood->oldX = blood->x; + blood->oldY = blood->y; + blood->oldZ = blood->z; + blood->oldRotAng = blood->rotAng; + blood->oldSize = blood->size; + blood->oldShade = blood->shade; + if (blood->sLife - blood->life >= blood->colFadeSpeed) { if (blood->life >= blood->fadeToBlack) diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index ae58bd055..d1a089034 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -183,6 +183,13 @@ struct BLOOD_STRUCT byte sLife; byte life; byte pad; + + int oldX; + int oldY; + int oldZ; + short oldRotAng; + unsigned char oldShade; + unsigned char oldSize; }; enum class ShockwaveStyle diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 1106e151f..32bc398cd 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -767,16 +767,30 @@ namespace TEN::Renderer { BLOOD_STRUCT* blood = &Blood[i]; - if (blood->on) + if (blood->on) { if (!CheckIfSlotExists(ID_DEFAULT_SPRITES, "Blood rendering")) return; - AddSpriteBillboard(&_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_BLOOD], - Vector3(blood->x, blood->y, blood->z), - Vector4(blood->shade / 255.0f, blood->shade * 0, blood->shade * 0, 1.0f), - TO_RAD(blood->rotAng << 4), 1.0f, { blood->size * 8.0f, blood->size * 8.0f }, - BlendMode::Additive, true, view); + AddSpriteBillboard( + &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_BLOOD], + Vector3::Lerp( + Vector3(blood->oldX, blood->oldY, blood->oldZ), + Vector3(blood->x, blood->y, blood->z), + _interpolationFactor), + Vector4::Lerp( + Vector4(blood->oldShade / 255.0f, blood->oldShade * 0, blood->oldShade * 0, 1.0f), + Vector4(blood->shade / 255.0f, blood->shade * 0, blood->shade * 0, 1.0f), + _interpolationFactor + ), + TO_RAD(Lerp(blood->oldRotAng << 4, blood->rotAng << 4, _interpolationFactor)), + 1.0f, + { + Lerp(blood->oldSize, blood->size, _interpolationFactor) * 8.0f, + Lerp(blood->oldSize, blood->size, _interpolationFactor) * 8.0f }, + BlendMode::Additive, + true, + view); } } } From 44c52201d022914b007e858bdc76d853b2b05a8d Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 11 Apr 2024 14:27:53 +0200 Subject: [PATCH 072/410] Added partial support to fire and smoke interpolation --- TombEngine/Game/effects/tomb4fx.cpp | 60 ++++++++++++++++++++++ TombEngine/Game/effects/tomb4fx.h | 23 +++++++++ TombEngine/Renderer/RendererDrawEffect.cpp | 42 +++++++++++++-- 3 files changed, 120 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 105662c2c..ba9e84347 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -120,6 +120,16 @@ void TriggerGlobalStaticFlame() spark->zVel = 0; spark->flags = SP_NONE; spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 0x1F) + -128; + + spark->oldX = spark->x; + spark->oldY = spark->y; + spark->oldZ = spark->z; + spark->oldSize = spark->size; + spark->oldRotAng = spark->rotAng; + spark->oldR = spark->r; + spark->oldG = spark->g; + spark->oldB = spark->b; + spark->oldScalar = spark->scalar; } void TriggerGlobalFireSmoke() @@ -161,6 +171,16 @@ void TriggerGlobalFireSmoke() spark->gravity = -16 - (GetRandomControl() & 0xF); spark->maxYvel = -8 - (GetRandomControl() & 7); spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 0x7F) + 128; + + spark->oldX = spark->x; + spark->oldY = spark->y; + spark->oldZ = spark->z; + spark->oldSize = spark->size; + spark->oldRotAng = spark->rotAng; + spark->oldR = spark->r; + spark->oldG = spark->g; + spark->oldB = spark->b; + spark->oldScalar = spark->scalar; } void TriggerGlobalFireFlame() @@ -203,6 +223,16 @@ void TriggerGlobalFireFlame() spark->sSize = spark->size = (GetRandomControl() & 0x1F) + 128; spark->dSize = spark->size; + + spark->oldX = spark->x; + spark->oldY = spark->y; + spark->oldZ = spark->z; + spark->oldSize = spark->size; + spark->oldRotAng = spark->rotAng; + spark->oldR = spark->r; + spark->oldG = spark->g; + spark->oldB = spark->b; + spark->oldScalar = spark->scalar; } void TriggerPilotFlame(int itemNumber, int nodeIndex) @@ -394,6 +424,11 @@ void AddFire(int x, int y, int z, short roomNum, float size, short fade) fptr->z = z; fptr->roomNumber = roomNum; fptr->size = size; + + fptr->oldX = fptr->x; + fptr->oldY = fptr->y; + fptr->oldZ = fptr->z; + fptr->oldSize = fptr->size; } void ClearFires() @@ -420,6 +455,16 @@ void UpdateFireSparks() continue; } + spark->oldX = spark->x; + spark->oldY = spark->y; + spark->oldZ = spark->z; + spark->oldSize = spark->size; + spark->oldRotAng = spark->rotAng; + spark->oldR = spark->r; + spark->oldG = spark->g; + spark->oldB = spark->b; + spark->oldScalar = spark->scalar; + if (spark->sLife - spark->life < spark->colFadeSpeed) { int dl = ((spark->sLife - spark->life) << 16) / spark->colFadeSpeed; @@ -534,6 +579,14 @@ void UpdateSmoke() continue; } + spark->oldX = spark->x; + spark->oldY = spark->y; + spark->oldZ = spark->z; + spark->oldSize = spark->size; + spark->oldRotAng = spark->rotAng; + spark->oldScalar = spark->scalar; + spark->oldScalar = spark->scalar; + if (spark->sLife - spark->life >= spark->colFadeSpeed) { if (spark->life >= spark->fadeToBlack) @@ -680,6 +733,13 @@ void TriggerShatterSmoke(int x, int y, int z) spark->dSize = (GetRandomControl() & 0x3F) + 64; spark->sSize = spark->dSize >> 3; spark->size = spark->dSize >> 3; + + spark->oldX = spark->x; + spark->oldY = spark->y; + spark->oldZ = spark->z; + spark->oldSize = spark->size; + spark->oldRotAng = spark->rotAng; + spark->oldScalar = spark->scalar; } int GetFreeBlood() diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index d1a089034..f04296afe 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -56,6 +56,14 @@ struct SMOKE_SPARKS byte fxObj; byte nodeNumber; byte mirror; + + int oldX; + int oldY; + int oldZ; + unsigned char oldShade; + short oldRotAng; + unsigned char oldSize; + unsigned char oldScalar; }; struct SHOCKWAVE_STRUCT @@ -122,6 +130,11 @@ struct FIRE_LIST byte on; float size; short roomNumber; + + int oldX; + int oldY; + int oldZ; + int oldSize; }; struct FIRE_SPARKS @@ -157,6 +170,16 @@ struct FIRE_SPARKS unsigned char fadeToBlack; unsigned char sLife; unsigned char life; + + int oldX; + int oldY; + int oldZ; + int oldR; + int oldG; + int oldB; + unsigned char oldScalar; + unsigned char oldSize; + short oldRotAng; }; struct BLOOD_STRUCT diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 32bc398cd..5b4010033 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -286,6 +286,26 @@ namespace TEN::Renderer Vector4(spark->shade / 255.0f, spark->shade / 255.0f, spark->shade / 255.0f, 1.0f), TO_RAD(spark->rotAng << 4), spark->scalar, { spark->size * 4.0f, spark->size * 4.0f }, BlendMode::Additive, true, view); + + AddSpriteBillboard( + &_sprites[spark->def], + Vector3::Lerp( + Vector3(spark->oldX, spark->oldY, spark->oldZ), + Vector3(spark->x, spark->y, spark->z), + _interpolationFactor), + Vector4::Lerp( + Vector4(spark->oldShade / 255.0f, spark->oldShade / 255.0f, spark->oldShade / 255.0f, 1.0f), + Vector4(spark->shade / 255.0f, spark->shade / 255.0f, spark->shade / 255.0f, 1.0f), + _interpolationFactor), + TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), + Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), + { + Lerp(spark->oldSize, spark->size, _interpolationFactor) * 4.0f, + Lerp(spark->oldSize, spark->size, _interpolationFactor) * 4.0f + }, + BlendMode::Additive, + true, + view); } } } @@ -307,11 +327,23 @@ namespace TEN::Renderer { AddSpriteBillboard( &_sprites[spark->def], - Vector3(fire->x + spark->x * fire->size / 2, fire->y + spark->y * fire->size / 2, fire->z + spark->z * fire->size / 2), - Vector4(spark->r / 255.0f * fade, spark->g / 255.0f * fade, spark->b / 255.0f * fade, 1.0f), - TO_RAD(spark->rotAng << 4), - spark->scalar, - Vector2(spark->size * fire->size, spark->size * fire->size), BlendMode::Additive, true, view); + Vector3::Lerp( + Vector3(fire->oldX + spark->oldX * fire->oldSize / 2, fire->oldY + spark->oldY * fire->oldSize / 2, fire->oldZ + spark->oldZ * fire->oldSize / 2), + Vector3(fire->x + spark->x * fire->size / 2, fire->y + spark->y * fire->size / 2, fire->z + spark->z * fire->size / 2), + _interpolationFactor), + Vector4::Lerp( + Vector4(spark->oldR / 255.0f * fade, spark->oldG / 255.0f * fade, spark->oldB / 255.0f * fade, 1.0f), + Vector4(spark->r / 255.0f * fade, spark->g / 255.0f * fade, spark->b / 255.0f * fade, 1.0f), + _interpolationFactor), + TO_RAD((short)Lerp(spark->oldRotAng, spark->rotAng, _interpolationFactor) << 4), + Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), + Vector2::Lerp( + Vector2(spark->oldSize * fire->oldSize, spark->oldSize * fire->oldSize), + Vector2(spark->size * fire->size, spark->size * fire->size), + _interpolationFactor), + BlendMode::Additive, + true, + view); } } } From 98c8f6df913ae0234c81298db92c3da0df46443d Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 13 Apr 2024 06:02:58 +0200 Subject: [PATCH 073/410] Cleaning smoke sparks code --- TombEngine/Game/Setup.cpp | 2 +- TombEngine/Game/effects/chaffFX.cpp | 14 ++--- TombEngine/Game/effects/effects.cpp | 16 ++--- TombEngine/Game/effects/tomb4fx.cpp | 63 ++++++++----------- TombEngine/Game/effects/tomb4fx.h | 31 ++++----- TombEngine/Objects/TR4/Entity/tr4_demigod.cpp | 12 ++-- TombEngine/Objects/TR5/Entity/AutoGun.cpp | 10 ++- .../Objects/TR5/Entity/tr5_roman_statue.cpp | 16 +++-- TombEngine/Renderer/RendererDrawEffect.cpp | 16 ++--- 9 files changed, 83 insertions(+), 97 deletions(-) diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp index a427dfe71..a0b27bb4a 100644 --- a/TombEngine/Game/Setup.cpp +++ b/TombEngine/Game/Setup.cpp @@ -135,7 +135,7 @@ void InitializeGameFlags() void InitializeSpecialEffects() { memset(&FireSparks, 0, MAX_SPARKS_FIRE * sizeof(FIRE_SPARKS)); - memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SMOKE_SPARKS)); + memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SmokeSpark)); memset(&Gunshells, 0, MAX_GUNSHELL * sizeof(GUNSHELL_STRUCT)); memset(&Blood, 0, MAX_SPARKS_BLOOD * sizeof(BLOOD_STRUCT)); memset(&Splashes, 0, MAX_SPLASHES * sizeof(SPLASH_STRUCT)); diff --git a/TombEngine/Game/effects/chaffFX.cpp b/TombEngine/Game/effects/chaffFX.cpp index ed2468ce9..092cebade 100644 --- a/TombEngine/Game/effects/chaffFX.cpp +++ b/TombEngine/Game/effects/chaffFX.cpp @@ -98,7 +98,7 @@ void TriggerChaffSparkles(const Vector3i& pos, const Vector3i& vel, const Color& void TriggerChaffSmoke(const Vector3i& pos, const Vector3i& vel, int speed, bool isMoving, bool wind) { - SMOKE_SPARKS* smoke; + SmokeSpark* smoke; int rnd = 0; BYTE trans, size; @@ -133,12 +133,12 @@ void TriggerChaffSmoke(const Vector3i& pos, const Vector3i& vel, int speed, bool smoke->blendMode = BlendMode::Additive; - smoke->x = pos.x + (GetRandomControl() & 7) - 3; - smoke->y = pos.y + (GetRandomControl() & 7) - 3; - smoke->z = pos.z + (GetRandomControl() & 7) - 3; - smoke->xVel = vel.x + ((GetRandomDraw() & 63) - 32); - smoke->yVel = vel.y; - smoke->zVel = vel.z + ((GetRandomDraw() & 63) - 32); + smoke->position.x = pos.x + (GetRandomControl() & 7) - 3; + smoke->position.y = pos.y + (GetRandomControl() & 7) - 3; + smoke->position.z = pos.z + (GetRandomControl() & 7) - 3; + smoke->velocity.x = vel.x + ((GetRandomDraw() & 63) - 32); + smoke->velocity.y = vel.y; + smoke->velocity.z = vel.z + ((GetRandomDraw() & 63) - 32); smoke->friction = 4; if (GetRandomControl() & 1) diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 9913a9486..e1e04d1ab 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -1455,21 +1455,21 @@ void TriggerFlashSmoke(int x, int y, int z, short roomNumber) spark->fadeToBlack = 16; spark->blendMode = BlendMode::Additive; spark->life = spark->sLife = (GetRandomControl() & 0xF) + 64; - spark->x = (GetRandomControl() & 0x1F) + x - 16; - spark->y = (GetRandomControl() & 0x1F) + y - 16; - spark->z = (GetRandomControl() & 0x1F) + z - 16; + spark->position.x = (GetRandomControl() & 0x1F) + x - 16; + spark->position.y = (GetRandomControl() & 0x1F) + y - 16; + spark->position.z = (GetRandomControl() & 0x1F) + z - 16; if (water) { - spark->xVel = spark->yVel = GetRandomControl() & 0x3FF - 512; - spark->zVel = (GetRandomControl() & 0x3FF) - 512; + spark->velocity.x = spark->velocity.y = GetRandomControl() & 0x3FF - 512; + spark->velocity.z = (GetRandomControl() & 0x3FF) - 512; spark->friction = 68; } else { - spark->xVel = 2 * (GetRandomControl() & 0x3FF) - 1024; - spark->yVel = -512 - (GetRandomControl() & 0x3FF); - spark->zVel = 2 * (GetRandomControl() & 0x3FF) - 1024; + spark->velocity.x = 2 * (GetRandomControl() & 0x3FF) - 1024; + spark->velocity.y = -512 - (GetRandomControl() & 0x3FF); + spark->velocity.z = 2 * (GetRandomControl() & 0x3FF) - 1024; spark->friction = 85; } diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index ba9e84347..236559d4a 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -47,7 +47,7 @@ int NextBlood = 0; int NextGunShell = 0; FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; +SmokeSpark SmokeSparks[MAX_SPARKS_SMOKE]; GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; @@ -527,7 +527,7 @@ void UpdateFireSparks() int GetFreeSmokeSpark() { - SMOKE_SPARKS* spark = &SmokeSparks[NextSmokeSpark]; + SmokeSpark* spark = &SmokeSparks[NextSmokeSpark]; int sparkNum = NextSmokeSpark; short minLife = 4095; short minIndex = 0; @@ -567,7 +567,7 @@ void UpdateSmoke() { for (int i = 0; i < MAX_SPARKS_SMOKE; i++) { - SMOKE_SPARKS* spark = &SmokeSparks[i]; + SmokeSpark* spark = &SmokeSparks[i]; if (spark->on) { @@ -579,13 +579,7 @@ void UpdateSmoke() continue; } - spark->oldX = spark->x; - spark->oldY = spark->y; - spark->oldZ = spark->z; - spark->oldSize = spark->size; - spark->oldRotAng = spark->rotAng; - spark->oldScalar = spark->scalar; - spark->oldScalar = spark->scalar; + spark->StoreInterpolationData(); if (spark->sLife - spark->life >= spark->colFadeSpeed) { @@ -625,45 +619,45 @@ void UpdateSmoke() int dl = ((spark->sLife - spark->life) << 16) / spark->sLife; - spark->yVel += spark->gravity; + spark->velocity.y += spark->gravity; if (spark->maxYvel != 0) { - if (spark->yVel < 0) + if (spark->velocity.y < 0) { - if (spark->yVel < spark->maxYvel) + if (spark->velocity.y < spark->maxYvel) { - spark->yVel = spark->maxYvel; + spark->velocity.y = spark->maxYvel; } } else { - if (spark->yVel > spark->maxYvel) + if (spark->velocity.y > spark->maxYvel) { - spark->yVel = spark->maxYvel; + spark->velocity.y = spark->maxYvel; } } } if (spark->friction & 0xF) { - spark->xVel -= spark->xVel >> (spark->friction & 0xF); - spark->zVel -= spark->zVel >> (spark->friction & 0xF); + spark->velocity.x -= spark->velocity.x >> (spark->friction & 0xF); + spark->velocity.z -= spark->velocity.z >> (spark->friction & 0xF); } if (spark->friction & 0xF0) { - spark->yVel -= spark->yVel >> (spark->friction >> 4); + spark->velocity.y -= spark->velocity.y >> (spark->friction >> 4); } - spark->x += spark->xVel >> 5; - spark->y += spark->yVel >> 5; - spark->z += spark->zVel >> 5; + spark->position.x += spark->velocity.x >> 5; + spark->position.y += spark->velocity.y >> 5; + spark->position.z += spark->velocity.z >> 5; if (spark->flags & SP_WIND) { - spark->x += Weather.Wind().x; - spark->z += Weather.Wind().z; + spark->position.x += Weather.Wind().x; + spark->position.z += Weather.Wind().z; } spark->size = spark->sSize + (dl * (spark->dSize - spark->sSize) >> 16); @@ -693,7 +687,7 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini void TriggerShatterSmoke(int x, int y, int z) { - SMOKE_SPARKS* spark = &SmokeSparks[GetFreeSmokeSpark()]; + SmokeSpark* spark = &SmokeSparks[GetFreeSmokeSpark()]; spark->on = true; spark->sShade = 0; @@ -702,12 +696,12 @@ void TriggerShatterSmoke(int x, int y, int z) spark->fadeToBlack = 24 - (GetRandomControl() & 7); spark->blendMode = BlendMode::Additive; spark->life = spark->sLife = (GetRandomControl() & 7) + 48; - spark->x = (GetRandomControl() & 0x1F) + x - 16; - spark->y = (GetRandomControl() & 0x1F) + y - 16; - spark->z = (GetRandomControl() & 0x1F) + z - 16; - spark->xVel = 2 * (GetRandomControl() & 0x1FF) - 512; - spark->yVel = 2 * (GetRandomControl() & 0x1FF) - 512; - spark->zVel = 2 * (GetRandomControl() & 0x1FF) - 512; + spark->position.x = (GetRandomControl() & 0x1F) + x - 16; + spark->position.y = (GetRandomControl() & 0x1F) + y - 16; + spark->position.z = (GetRandomControl() & 0x1F) + z - 16; + spark->velocity.x = 2 * (GetRandomControl() & 0x1FF) - 512; + spark->velocity.y = 2 * (GetRandomControl() & 0x1FF) - 512; + spark->velocity.z = 2 * (GetRandomControl() & 0x1FF) - 512; spark->friction = 7; if (GetRandomControl() & 1) @@ -733,13 +727,6 @@ void TriggerShatterSmoke(int x, int y, int z) spark->dSize = (GetRandomControl() & 0x3F) + 64; spark->sSize = spark->dSize >> 3; spark->size = spark->dSize >> 3; - - spark->oldX = spark->x; - spark->oldY = spark->y; - spark->oldZ = spark->z; - spark->oldSize = spark->size; - spark->oldRotAng = spark->rotAng; - spark->oldScalar = spark->scalar; } int GetFreeBlood() diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index f04296afe..2d84e0dbc 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -25,14 +25,10 @@ enum BodyPartFlags BODY_NO_SHATTER_EFFECT = (1 << 13), // Remove shatter effect upon despawn. }; -struct SMOKE_SPARKS +struct SmokeSpark { - int x; - int y; - int z; - int xVel; - int yVel; - int zVel; + Vector3i position; + Vector3i velocity; int gravity; short rotAng; short flags; @@ -57,13 +53,20 @@ struct SMOKE_SPARKS byte nodeNumber; byte mirror; - int oldX; - int oldY; - int oldZ; - unsigned char oldShade; + Vector3i oldPosition; + byte oldShade; + byte oldSize; + byte oldScalar; short oldRotAng; - unsigned char oldSize; - unsigned char oldScalar; + + void StoreInterpolationData() + { + oldPosition = position; + oldShade = shade; + oldSize = size; + oldScalar = scalar; + oldRotAng = rotAng; + } }; struct SHOCKWAVE_STRUCT @@ -247,7 +250,7 @@ constexpr auto MAX_GUNSHELL = 24; constexpr auto MAX_SHOCKWAVE = 16; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; +extern SmokeSpark SmokeSparks[MAX_SPARKS_SMOKE]; extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; diff --git a/TombEngine/Objects/TR4/Entity/tr4_demigod.cpp b/TombEngine/Objects/TR4/Entity/tr4_demigod.cpp index 17c14ea39..4b4e1fe91 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_demigod.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_demigod.cpp @@ -290,12 +290,12 @@ namespace TEN::Entities::TR4 spark->fadeToBlack = 24 - (GetRandomControl() & 7); spark->blendMode = BlendMode::Additive; spark->life = spark->sLife = (GetRandomControl() & 7) + 48; - spark->x = (GetRandomControl() & 0x1F) + x - 16; - spark->y = (GetRandomControl() & 0x1F) + y - 16; - spark->z = (GetRandomControl() & 0x1F) + z - 16; - spark->xVel = (byte)(GetRandomControl() + 256) * phd_sin(angle); - spark->yVel = -32 - (GetRandomControl() & 0x3F); - spark->zVel = (byte)(GetRandomControl() + 256) * phd_cos(angle); + spark->position.x = (GetRandomControl() & 0x1F) + x - 16; + spark->position.y = (GetRandomControl() & 0x1F) + y - 16; + spark->position.z = (GetRandomControl() & 0x1F) + z - 16; + spark->velocity.x = (byte)(GetRandomControl() + 256) * phd_sin(angle); + spark->velocity.y = -32 - (GetRandomControl() & 0x3F); + spark->velocity.z = (byte)(GetRandomControl() + 256) * phd_cos(angle); spark->friction = 9; if (Random::TestProbability(1 / 2.0f)) diff --git a/TombEngine/Objects/TR5/Entity/AutoGun.cpp b/TombEngine/Objects/TR5/Entity/AutoGun.cpp index 6ed1cb87c..5246f727f 100644 --- a/TombEngine/Objects/TR5/Entity/AutoGun.cpp +++ b/TombEngine/Objects/TR5/Entity/AutoGun.cpp @@ -62,12 +62,10 @@ namespace TEN::Entities::Creatures::TR5 smoke.fadeToBlack = 32; smoke.blendMode = BlendMode::Additive; smoke.life = smoke.sLife = Random::GenerateInt(40, 44); - smoke.x = smokePos.x; - smoke.y = smokePos.y; - smoke.z = smokePos.z; - smoke.xVel = 0; - smoke.yVel = 0; - smoke.zVel = 0; + smoke.position.x = smokePos.x; + smoke.position.y = smokePos.y; + smoke.position.z = smokePos.z; + smoke.velocity = Vector3i::Zero; smoke.friction = 4; smoke.flags = SP_ROTATE; smoke.rotAng = Random::GenerateInt(0, 4096); diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index 72a8d3aa8..d78e551b2 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -112,12 +112,16 @@ namespace TEN::Entities::Creatures::TR5 spark->dShade = (GetRandomControl() & 0xF) + 64; spark->blendMode = BlendMode::Additive; spark->life = spark->sLife = (GetRandomControl() & 3) + 64; - spark->x = (GetRandomControl() & 0x1F) + pos->x - 16; - spark->y = (GetRandomControl() & 0x1F) + pos->y - 16; - spark->z = (GetRandomControl() & 0x1F) + pos->z - 16; - spark->xVel = (GetRandomControl() & 0x7F) - 64; - spark->yVel = 0; - spark->zVel = (GetRandomControl() & 0x7F) - 64; + spark->position = Vector3i( + (GetRandomControl() & 0x1F) + pos->x - 16, + (GetRandomControl() & 0x1F) + pos->y - 16, + (GetRandomControl() & 0x1F) + pos->z - 16 + ); + spark->velocity = Vector3i( + (GetRandomControl() & 0x7F) - 64, + 0, + (GetRandomControl() & 0x7F) - 64 + ); spark->friction = 4; spark->flags = SP_ROTATE; spark->rotAng = GetRandomControl() & 0xFFF; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 5b4010033..7d390adeb 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -48,7 +48,7 @@ using namespace TEN::Traps::TR5; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; +extern SmokeSpark SmokeSparks[MAX_SPARKS_SMOKE]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; extern FIRE_LIST Fires[MAX_FIRE_LIST]; extern Particle Particles[MAX_PARTICLES]; @@ -277,21 +277,15 @@ namespace TEN::Renderer { for (int i = 0; i < 32; i++) { - SMOKE_SPARKS* spark = &SmokeSparks[i]; + SmokeSpark* spark = &SmokeSparks[i]; if (spark->on) { - AddSpriteBillboard(&_sprites[spark->def], - Vector3(spark->x, spark->y, spark->z), - Vector4(spark->shade / 255.0f, spark->shade / 255.0f, spark->shade / 255.0f, 1.0f), - TO_RAD(spark->rotAng << 4), spark->scalar, { spark->size * 4.0f, spark->size * 4.0f }, - BlendMode::Additive, true, view); - AddSpriteBillboard( &_sprites[spark->def], Vector3::Lerp( - Vector3(spark->oldX, spark->oldY, spark->oldZ), - Vector3(spark->x, spark->y, spark->z), + Vector3(spark->oldPosition.x, spark->oldPosition.y, spark->oldPosition.z), + Vector3(spark->position.x, spark->position.y, spark->position.z), _interpolationFactor), Vector4::Lerp( Vector4(spark->oldShade / 255.0f, spark->oldShade / 255.0f, spark->oldShade / 255.0f, 1.0f), @@ -335,7 +329,7 @@ namespace TEN::Renderer Vector4(spark->oldR / 255.0f * fade, spark->oldG / 255.0f * fade, spark->oldB / 255.0f * fade, 1.0f), Vector4(spark->r / 255.0f * fade, spark->g / 255.0f * fade, spark->b / 255.0f * fade, 1.0f), _interpolationFactor), - TO_RAD((short)Lerp(spark->oldRotAng, spark->rotAng, _interpolationFactor) << 4), + TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), Vector2::Lerp( Vector2(spark->oldSize * fire->oldSize, spark->oldSize * fire->oldSize), From f4a5644dc0afb0e0731e36c97f9500570ceaa08b Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 15 Apr 2024 08:33:10 +0200 Subject: [PATCH 074/410] Gunshells interpolation --- TombEngine/Game/Setup.cpp | 4 ++-- TombEngine/Game/effects/chaffFX.cpp | 2 +- TombEngine/Game/effects/tomb4fx.cpp | 14 ++++++++------ TombEngine/Game/effects/tomb4fx.h | 15 +++++++++++---- TombEngine/Renderer/RendererDraw.cpp | 12 +++++++++++- TombEngine/Renderer/RendererDrawEffect.cpp | 4 ++-- 6 files changed, 35 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp index a0b27bb4a..20eaa6b14 100644 --- a/TombEngine/Game/Setup.cpp +++ b/TombEngine/Game/Setup.cpp @@ -135,8 +135,8 @@ void InitializeGameFlags() void InitializeSpecialEffects() { memset(&FireSparks, 0, MAX_SPARKS_FIRE * sizeof(FIRE_SPARKS)); - memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SmokeSpark)); - memset(&Gunshells, 0, MAX_GUNSHELL * sizeof(GUNSHELL_STRUCT)); + memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SmokeSparkInfo)); + memset(&Gunshells, 0, MAX_GUNSHELL * sizeof(GunshellInfo)); memset(&Blood, 0, MAX_SPARKS_BLOOD * sizeof(BLOOD_STRUCT)); memset(&Splashes, 0, MAX_SPLASHES * sizeof(SPLASH_STRUCT)); memset(&ShockWaves, 0, MAX_SHOCKWAVE * sizeof(SHOCKWAVE_STRUCT)); diff --git a/TombEngine/Game/effects/chaffFX.cpp b/TombEngine/Game/effects/chaffFX.cpp index 092cebade..4b4674204 100644 --- a/TombEngine/Game/effects/chaffFX.cpp +++ b/TombEngine/Game/effects/chaffFX.cpp @@ -98,7 +98,7 @@ void TriggerChaffSparkles(const Vector3i& pos, const Vector3i& vel, const Color& void TriggerChaffSmoke(const Vector3i& pos, const Vector3i& vel, int speed, bool isMoving, bool wind) { - SmokeSpark* smoke; + SmokeSparkInfo* smoke; int rnd = 0; BYTE trans, size; diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 236559d4a..d1191322c 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -47,8 +47,8 @@ int NextBlood = 0; int NextGunShell = 0; FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -SmokeSpark SmokeSparks[MAX_SPARKS_SMOKE]; -GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; +SmokeSparkInfo SmokeSparks[MAX_SPARKS_SMOKE]; +GunshellInfo Gunshells[MAX_GUNSHELL]; BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; FIRE_LIST Fires[MAX_FIRE_LIST]; @@ -527,7 +527,7 @@ void UpdateFireSparks() int GetFreeSmokeSpark() { - SmokeSpark* spark = &SmokeSparks[NextSmokeSpark]; + SmokeSparkInfo* spark = &SmokeSparks[NextSmokeSpark]; int sparkNum = NextSmokeSpark; short minLife = 4095; short minIndex = 0; @@ -567,7 +567,7 @@ void UpdateSmoke() { for (int i = 0; i < MAX_SPARKS_SMOKE; i++) { - SmokeSpark* spark = &SmokeSparks[i]; + SmokeSparkInfo* spark = &SmokeSparks[i]; if (spark->on) { @@ -687,7 +687,7 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini void TriggerShatterSmoke(int x, int y, int z) { - SmokeSpark* spark = &SmokeSparks[GetFreeSmokeSpark()]; + SmokeSparkInfo* spark = &SmokeSparks[GetFreeSmokeSpark()]; spark->on = true; spark->sShade = 0; @@ -878,7 +878,7 @@ int GetFreeGunshell() while (true) { - GUNSHELL_STRUCT* gs = &Gunshells[NextGunShell]; + GunshellInfo* gs = &Gunshells[NextGunShell]; if (!gs->counter) break; @@ -1018,6 +1018,8 @@ void UpdateGunShells() if (gunshell->counter) { + gunshell->StoreInterpolationData(); + auto prevPos = gunshell->pos.Position; gunshell->counter--; diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index 2d84e0dbc..cada0ccfa 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -25,7 +25,7 @@ enum BodyPartFlags BODY_NO_SHATTER_EFFECT = (1 << 13), // Remove shatter effect upon despawn. }; -struct SmokeSpark +struct SmokeSparkInfo { Vector3i position; Vector3i velocity; @@ -97,7 +97,7 @@ struct SHOCKWAVE_STRUCT bool HasLight = false; }; -struct GUNSHELL_STRUCT +struct GunshellInfo { Pose pos; short fallspeed; @@ -106,6 +106,13 @@ struct GUNSHELL_STRUCT short counter; short dirXrot; short objectNumber; + + Pose oldPos; + + void StoreInterpolationData() + { + oldPos = pos; + } }; struct DRIP_STRUCT @@ -250,8 +257,8 @@ constexpr auto MAX_GUNSHELL = 24; constexpr auto MAX_SHOCKWAVE = 16; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -extern SmokeSpark SmokeSparks[MAX_SPARKS_SMOKE]; -extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; +extern SmokeSparkInfo SmokeSparks[MAX_SPARKS_SMOKE]; +extern GunshellInfo Gunshells[MAX_GUNSHELL]; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; extern FIRE_LIST Fires[MAX_FIRE_LIST]; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 404dca789..fd7969397 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -39,7 +39,7 @@ using namespace TEN::Entities::Generic; using namespace TEN::Hud; using namespace TEN::Renderer::Structures; -extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; +extern GunshellInfo Gunshells[MAX_GUNSHELL]; namespace TEN::Renderer { @@ -276,6 +276,16 @@ namespace TEN::Renderer Matrix rotation = gunshell->pos.Orientation.ToRotationMatrix(); Matrix world = rotation * translation; + Matrix oldTranslation = Matrix::CreateTranslation( + gunshell->oldPos.Position.x, + gunshell->oldPos.Position.y, + gunshell->oldPos.Position.z + ); + Matrix oldRotation = gunshell->oldPos.Orientation.ToRotationMatrix(); + Matrix oldWorld = oldRotation * oldTranslation; + + world = Matrix::Lerp(oldWorld, world, _interpolationFactor); + _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].World = world; _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].Ambient = room.AmbientLight; _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].Color = room.AmbientLight; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 7d390adeb..a165679ba 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -48,7 +48,7 @@ using namespace TEN::Traps::TR5; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -extern SmokeSpark SmokeSparks[MAX_SPARKS_SMOKE]; +extern SmokeSparkInfo SmokeSparks[MAX_SPARKS_SMOKE]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; extern FIRE_LIST Fires[MAX_FIRE_LIST]; extern Particle Particles[MAX_PARTICLES]; @@ -277,7 +277,7 @@ namespace TEN::Renderer { for (int i = 0; i < 32; i++) { - SmokeSpark* spark = &SmokeSparks[i]; + SmokeSparkInfo* spark = &SmokeSparks[i]; if (spark->on) { From d5526be20852dbae7a9f90f161856e45298cf756 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 15 Apr 2024 11:08:41 +0200 Subject: [PATCH 075/410] Improved fires and flares interpolation; Fixed fast blinking of dynamic lights; --- Documentation/output.xml | 130 ++++++++++---------- TombEngine/Game/control/control.cpp | 2 + TombEngine/Game/effects/tomb4fx.cpp | 131 ++++++++------------- TombEngine/Game/effects/tomb4fx.h | 47 ++++---- TombEngine/Renderer/Renderer.h | 2 +- TombEngine/Renderer/RendererDraw.cpp | 2 - TombEngine/Renderer/RendererDrawEffect.cpp | 25 +++- 7 files changed, 162 insertions(+), 177 deletions(-) diff --git a/Documentation/output.xml b/Documentation/output.xml index 96faf84ae..deacfcb96 100644 --- a/Documentation/output.xml +++ b/Documentation/output.xml @@ -1931,9 +1931,9 @@ e.g. `myItem.action = ItemAction.EXAMINE` Objects.Moveable Moveable - For more information on each parameter, see the -associated getters and setters. - If you do not know what to set for these, + Used to generate a new moveable dynamically at runtime. + For more information on each parameter, see the +associated getters and setters. If you do not know what to set for these, most can just be ignored (see usage). @@ -1954,7 +1954,7 @@ most can just be ignored (see usage). rotation Rotation - rotation about x, y, and z axes (default Rotation(0, 0, 0)) + rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) roomID @@ -1964,7 +1964,7 @@ most can just be ignored (see usage). animNumber int - anim number + animation number frameNumber @@ -2096,66 +2096,6 @@ most can just be ignored (see usage). - - Objects.Moveable - Moveable - SetOnHit - Set the name of the function to be called when the moveable is shot by Lara. - Note that this will be triggered twice when shot with both pistols at once. - - - callback - function - function in LevelFuncs hierarchy to call when moveable is shot - - - - - - Objects.Moveable - Moveable - SetOnCollidedWithObject - Set the function to be called when this moveable collides with another moveable - - - func - function - callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. - - - - - - Objects.Moveable - Moveable - SetOnCollidedWithRoom - Set the function called when this moveable collides with room geometry (e.g. - a wall or floor). This function can take an argument that holds the @{Moveable} that collided with geometry. - - - func - function - callback function to be called (must be in LevelFuncs hierarchy) - - - - - - Objects.Moveable - Moveable - SetOnKilled - Set the name of the function to be called when the moveable is destroyed/killed - Note that enemy death often occurs at the end of an animation, and not at the exact moment - the enemy's HP becomes zero. - - - callback - function - function in LevelFuncs hierarchy to call when enemy is killed - - - - Objects.Moveable Moveable @@ -2624,6 +2564,66 @@ most can just be ignored (see usage). + + Objects.Moveable + Moveable + SetOnHit + Set the name of the function to be called when the moveable is shot by Lara. + Note that this will be triggered twice when shot with both pistols at once. + + + callback + function + function in LevelFuncs hierarchy to call when moveable is shot + + + + + + Objects.Moveable + Moveable + SetOnCollidedWithObject + Set the function to be called when this moveable collides with another moveable + + + func + function + callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. + + + + + + Objects.Moveable + Moveable + SetOnCollidedWithRoom + Set the function called when this moveable collides with room geometry (e.g. + a wall or floor). This function can take an argument that holds the @{Moveable} that collided with geometry. + + + func + function + callback function to be called (must be in LevelFuncs hierarchy) + + + + + + Objects.Moveable + Moveable + SetOnKilled + Set the name of the function to be called when the moveable is destroyed/killed + Note that enemy death often occurs at the end of an animation, and not at the exact moment + the enemy's HP becomes zero. + + + callback + function + function in LevelFuncs hierarchy to call when enemy is killed + + + + Objects.Moveable Moveable diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index a8ce63314..f904d35cb 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -137,6 +137,8 @@ GameStatus ControlPhase(int numFrames) bool isTitle = (CurrentLevel == 0); + ClearFires(); + g_Renderer.ClearDynamicLights(); RegeneratePickups(); numFrames = std::clamp(numFrames, 0, 10); diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index d1191322c..886a240c4 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -109,27 +109,17 @@ void TriggerGlobalStaticFlame() spark->fadeToBlack = 0; spark->life = 8; spark->sLife = 8; - spark->y = 0; - spark->x = (GetRandomControl() & 7) - 4; + spark->position = Vector3i( + (GetRandomControl() & 7) - 4, + 0, + (GetRandomControl() & 7) - 4 + ); spark->maxYvel = 0; spark->gravity = 0; - spark->z = (GetRandomControl() & 7) - 4; spark->friction = 0; - spark->xVel = 0; - spark->yVel = 0; - spark->zVel = 0; + spark->velocity = Vector3i::Zero; spark->flags = SP_NONE; spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 0x1F) + -128; - - spark->oldX = spark->x; - spark->oldY = spark->y; - spark->oldZ = spark->z; - spark->oldSize = spark->size; - spark->oldRotAng = spark->rotAng; - spark->oldR = spark->r; - spark->oldG = spark->g; - spark->oldB = spark->b; - spark->oldScalar = spark->scalar; } void TriggerGlobalFireSmoke() @@ -146,12 +136,16 @@ void TriggerGlobalFireSmoke() spark->fadeToBlack = 16; spark->colFadeSpeed = (GetRandomControl() & 7) + 32; spark->life = spark->sLife = (GetRandomControl() & 0xF) + 57; - spark->x = (GetRandomControl() & 0xF) - 8; - spark->y = -256 - (GetRandomControl() & 0x7F); - spark->z = (GetRandomControl() & 0xF) - 8; - spark->xVel = (GetRandomControl() & 0xFF) - 128; - spark->yVel = -16 - (GetRandomControl() & 0xF); - spark->zVel = (GetRandomControl() & 0xFF) - 128; + spark->position = Vector3i( + (GetRandomControl() & 0xF) - 8, + -256 - (GetRandomControl() & 0x7F), + (GetRandomControl() & 0xF) - 8 + ); + spark->velocity = Vector3i( + (GetRandomControl() & 0xFF) - 128, + -16 - (GetRandomControl() & 0xF), + (GetRandomControl() & 0xFF) - 128 + ); spark->friction = 4; if (GetRandomControl() & 1) @@ -171,16 +165,6 @@ void TriggerGlobalFireSmoke() spark->gravity = -16 - (GetRandomControl() & 0xF); spark->maxYvel = -8 - (GetRandomControl() & 7); spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 0x7F) + 128; - - spark->oldX = spark->x; - spark->oldY = spark->y; - spark->oldZ = spark->z; - spark->oldSize = spark->size; - spark->oldRotAng = spark->rotAng; - spark->oldR = spark->r; - spark->oldG = spark->g; - spark->oldB = spark->b; - spark->oldScalar = spark->scalar; } void TriggerGlobalFireFlame() @@ -197,12 +181,16 @@ void TriggerGlobalFireFlame() spark->fadeToBlack = 8; spark->colFadeSpeed = (GetRandomControl() & 3) + 8; spark->life = spark->sLife = (GetRandomControl() & 7) + 32; - spark->y = 0; - spark->x = 4 * (GetRandomControl() & 0x1F) - 64; - spark->z = 4 * (GetRandomControl() & 0x1F) - 64; - spark->xVel = 2 * (GetRandomControl() & 0xFF) - 256; - spark->yVel = -16 - (GetRandomControl() & 0xF); - spark->zVel = 2 * (GetRandomControl() & 0xFF) - 256; + spark->position = Vector3i( + 4 * (GetRandomControl() & 0x1F) - 64, + 0, + 4 * (GetRandomControl() & 0x1F) - 64 + ); + spark->velocity = Vector3i( + 2 * (GetRandomControl() & 0xFF) - 256, + -16 - (GetRandomControl() & 0xF), + 2 * (GetRandomControl() & 0xFF) - 256 + ); spark->friction = 5; spark->gravity = -32 - (GetRandomControl() & 0x1F); spark->maxYvel = -16 - (GetRandomControl() & 7); @@ -223,16 +211,6 @@ void TriggerGlobalFireFlame() spark->sSize = spark->size = (GetRandomControl() & 0x1F) + 128; spark->dSize = spark->size; - - spark->oldX = spark->x; - spark->oldY = spark->y; - spark->oldZ = spark->z; - spark->oldSize = spark->size; - spark->oldRotAng = spark->rotAng; - spark->oldR = spark->r; - spark->oldG = spark->g; - spark->oldB = spark->b; - spark->oldScalar = spark->scalar; } void TriggerPilotFlame(int itemNumber, int nodeIndex) @@ -419,16 +397,11 @@ void AddFire(int x, int y, int z, short roomNum, float size, short fade) else fptr->on = 1; - fptr->x = x; - fptr->y = y; - fptr->z = z; + fptr->position = Vector3i(x, y, z); fptr->roomNumber = roomNum; fptr->size = size; - fptr->oldX = fptr->x; - fptr->oldY = fptr->y; - fptr->oldZ = fptr->z; - fptr->oldSize = fptr->size; + fptr->StoreInterpolationData(); } void ClearFires() @@ -455,39 +428,33 @@ void UpdateFireSparks() continue; } - spark->oldX = spark->x; - spark->oldY = spark->y; - spark->oldZ = spark->z; - spark->oldSize = spark->size; - spark->oldRotAng = spark->rotAng; - spark->oldR = spark->r; - spark->oldG = spark->g; - spark->oldB = spark->b; - spark->oldScalar = spark->scalar; + spark->StoreInterpolationData(); if (spark->sLife - spark->life < spark->colFadeSpeed) { int dl = ((spark->sLife - spark->life) << 16) / spark->colFadeSpeed; - spark->r = spark->sR + (dl * (spark->dR - spark->sR) >> 16); - spark->g = spark->sG + (dl * (spark->dG - spark->sG) >> 16); - spark->b = spark->sB + (dl * (spark->dB - spark->sB) >> 16); + spark->color = Vector3i( + spark->sR + (dl * (spark->dR - spark->sR) >> 16), + spark->sG + (dl * (spark->dG - spark->sG) >> 16), + spark->sB + (dl * (spark->dB - spark->sB) >> 16) + ); } else if (spark->life >= spark->fadeToBlack) { - spark->r = spark->dR; - spark->g = spark->dG; - spark->b = spark->dB; + spark->color = Vector3i(spark->dR, spark->dG, spark->dB); } else { int dl = ((spark->life - spark->fadeToBlack) << 16) / spark->fadeToBlack + 0x10000; - spark->r = dl * spark->dR >> 16; - spark->g = dl * spark->dG >> 16; - spark->b = dl * spark->dB >> 16; + spark->color = Vector3i( + dl * spark->dR >> 16, + dl * spark->dG >> 16, + dl * spark->dB >> 16 + ); - if (spark->r < 8 && spark->g < 8 && spark->b < 8) + if (spark->color.x < 8 && spark->color.y < 8 && spark->color.z < 8) { spark->on = false; continue; @@ -502,23 +469,21 @@ void UpdateFireSparks() spark->def = sprite; int dl = ((spark->sLife - spark->life) << 16) / spark->sLife; - spark->yVel += spark->gravity; + spark->velocity.y += spark->gravity; if (spark->maxYvel) { - if ((spark->yVel < 0 && spark->yVel < (spark->maxYvel << 5)) || - (spark->yVel > 0 && spark->yVel > (spark->maxYvel << 5))) - spark->yVel = spark->maxYvel << 5; + if ((spark->velocity.y < 0 && spark->velocity.y < (spark->maxYvel << 5)) || + (spark->velocity.y > 0 && spark->velocity.y > (spark->maxYvel << 5))) + spark->velocity.y = spark->maxYvel << 5; } if (spark->friction) { - spark->xVel -= spark->xVel >> spark->friction; - spark->zVel -= spark->zVel >> spark->friction; + spark->velocity.x -= spark->velocity.x >> spark->friction; + spark->velocity.z -= spark->velocity.z >> spark->friction; } - spark->x += spark->xVel / 48; - spark->y += spark->yVel / 48; - spark->z += spark->zVel / 48; + spark->position += spark->velocity / 48; spark->size = spark->sSize + ((dl * (spark->dSize - spark->sSize)) / 65536); } diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index cada0ccfa..da63cb1cc 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -134,27 +134,28 @@ struct DRIP_STRUCT struct FIRE_LIST { - int x; - int y; - int z; + Vector3i position; byte on; float size; short roomNumber; - int oldX; - int oldY; - int oldZ; - int oldSize; + Vector3i oldPosition; + float oldSize; + byte oldOn; + + void StoreInterpolationData() + { + oldPosition = position; + oldSize = size; + oldOn = on; + } }; struct FIRE_SPARKS { - short x; - short y; - short z; - short xVel; - short yVel; - short zVel; + Vector3i position; + Vector3i velocity; + Vector3i color; short gravity; short rotAng; short flags; @@ -173,23 +174,25 @@ struct FIRE_SPARKS unsigned char dR; unsigned char dG; unsigned char dB; - unsigned char r; - unsigned char g; - unsigned char b; unsigned char colFadeSpeed; unsigned char fadeToBlack; unsigned char sLife; unsigned char life; - int oldX; - int oldY; - int oldZ; - int oldR; - int oldG; - int oldB; + Vector3i oldPosition; + Vector3i oldColor; unsigned char oldScalar; unsigned char oldSize; short oldRotAng; + + void StoreInterpolationData() + { + oldPosition = position; + oldColor = color; + oldScalar = scalar; + oldSize = size; + oldRotAng = rotAng; + } }; struct BLOOD_STRUCT diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index ab4f9977c..30c1386b0 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -404,7 +404,6 @@ namespace TEN::Renderer void CalculateLightFades(RendererItem* item); void CollectEffects(short roomNumber); void ClearSceneItems(); - void ClearDynamicLights(); void ClearShadowMap(); void CalculateSSAO(RenderView& view); void UpdateItemAnimations(RenderView& view); @@ -613,6 +612,7 @@ namespace TEN::Renderer void SetFullScreen(); bool IsFullsScreen(); void RenderTitleImage(); + void ClearDynamicLights(); void AddLine2D(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index fd7969397..b5f99e81c 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1634,8 +1634,6 @@ namespace TEN::Renderer { ResetAnimations(); - ClearFires(); - ClearDynamicLights(); ClearSceneItems(); ClearShadowMap(); diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index a165679ba..2e353c16d 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -312,22 +312,39 @@ namespace TEN::Renderer auto* fire = &Fires[k]; if (fire->on) { + auto oldFade = fire->oldOn == 1 ? 1.0f : (float)(255 - fire->oldOn) / 255.0f; auto fade = fire->on == 1 ? 1.0f : (float)(255 - fire->on) / 255.0f; + fade = Lerp(oldFade, fade, _interpolationFactor); for (int i = 0; i < MAX_SPARKS_FIRE; i++) { auto* spark = &FireSparks[i]; + if (spark->on) { AddSpriteBillboard( &_sprites[spark->def], Vector3::Lerp( - Vector3(fire->oldX + spark->oldX * fire->oldSize / 2, fire->oldY + spark->oldY * fire->oldSize / 2, fire->oldZ + spark->oldZ * fire->oldSize / 2), - Vector3(fire->x + spark->x * fire->size / 2, fire->y + spark->y * fire->size / 2, fire->z + spark->z * fire->size / 2), + Vector3( + fire->oldPosition.x + spark->oldPosition.x * fire->oldSize / 2, + fire->oldPosition.y + spark->oldPosition.y * fire->oldSize / 2, + fire->oldPosition.z + spark->oldPosition.z * fire->oldSize / 2), + Vector3( + fire->position.x + spark->position.x * fire->size / 2, + fire->position.y + spark->position.y * fire->size / 2, + fire->position.z + spark->position.z * fire->size / 2), _interpolationFactor), Vector4::Lerp( - Vector4(spark->oldR / 255.0f * fade, spark->oldG / 255.0f * fade, spark->oldB / 255.0f * fade, 1.0f), - Vector4(spark->r / 255.0f * fade, spark->g / 255.0f * fade, spark->b / 255.0f * fade, 1.0f), + Vector4( + spark->oldColor.x / 255.0f * fade, + spark->oldColor.y / 255.0f * fade, + spark->oldColor.z / 255.0f * fade, + 1.0f), + Vector4( + spark->color.x / 255.0f * fade, + spark->color.y / 255.0f * fade, + spark->color.z / 255.0f * fade, + 1.0f), _interpolationFactor), TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), From c455fc6a39ff22d1c7a8398e2afd49652e89b96d Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 16 Apr 2024 16:50:49 +1000 Subject: [PATCH 076/410] Merge --- Documentation/Changes.txt | 9 +- Documentation/doc/1 modules/Flow.html | 59 ++ .../doc/2 classes/Objects.Moveable.html | 149 +++-- .../doc/2 classes/Objects.Volume.html | 516 +++++++++--------- Documentation/doc/4 enums/Objects.ObjID.html | 4 +- Documentation/doc/index.html | 2 +- Documentation/output.xml | 289 +++++----- Scripts/Engine/Timer.lua | 10 +- TombEngine/Game/Hud/StatusBars.cpp | 2 +- TombEngine/Game/Hud/TargetHighlighter.cpp | 6 +- TombEngine/Game/Lara/PlayerContext.cpp | 2 +- TombEngine/Game/Lara/lara.cpp | 22 +- TombEngine/Game/Lara/lara_collide.cpp | 8 +- TombEngine/Game/Lara/lara_fire.cpp | 10 +- TombEngine/Game/Lara/lara_fire.h | 2 +- TombEngine/Game/Lara/lara_flare.cpp | 8 +- TombEngine/Game/Lara/lara_helpers.cpp | 18 +- TombEngine/Game/Lara/lara_initialise.cpp | 42 +- TombEngine/Game/Lara/lara_one_gun.cpp | 56 +- TombEngine/Game/Lara/lara_overhang.cpp | 2 +- TombEngine/Game/Lara/lara_struct.h | 2 +- TombEngine/Game/Lara/lara_tests.cpp | 20 +- TombEngine/Game/Setup.cpp | 4 +- TombEngine/Game/animation.cpp | 12 +- TombEngine/Game/animation.h | 19 +- TombEngine/Game/collision/Point.cpp | 8 +- TombEngine/Game/collision/collide_item.cpp | 280 +++++----- TombEngine/Game/collision/collide_item.h | 29 +- TombEngine/Game/collision/collide_room.cpp | 14 +- TombEngine/Game/collision/floordata.cpp | 8 +- TombEngine/Game/control/box.cpp | 102 ++-- TombEngine/Game/control/box.h | 2 - TombEngine/Game/control/control.cpp | 9 +- TombEngine/Game/control/flipeffect.cpp | 8 +- TombEngine/Game/control/los.cpp | 8 +- TombEngine/Game/control/lot.cpp | 20 +- TombEngine/Game/control/trigger.cpp | 53 +- TombEngine/Game/effects/tomb4fx.cpp | 2 +- TombEngine/Game/gui.cpp | 16 +- TombEngine/Game/items.cpp | 88 +-- TombEngine/Game/items.h | 194 +++---- TombEngine/Game/misc.cpp | 91 ++- TombEngine/Game/misc.h | 1 + TombEngine/Game/missile.cpp | 6 +- TombEngine/Game/pickup/pickup.cpp | 94 ++-- TombEngine/Game/room.cpp | 16 +- TombEngine/Game/savegame.cpp | 56 +- TombEngine/Game/spotcam.cpp | 317 +++++++---- TombEngine/Game/spotcam.h | 25 +- TombEngine/Math/Geometry.cpp | 5 + TombEngine/Math/Geometry.h | 3 + TombEngine/Math/Math.cpp | 2 + TombEngine/Math/Random.cpp | 29 +- TombEngine/Math/Random.h | 3 + TombEngine/Objects/Effects/Boss.cpp | 4 +- TombEngine/Objects/Effects/flame_emitters.cpp | 17 +- TombEngine/Objects/Effects/tr4_locusts.cpp | 4 +- .../Objects/Effects/tr5_electricity.cpp | 49 +- .../Objects/Generic/Doors/generic_doors.cpp | 22 +- .../Object/Pushable/PushableBridge.cpp | 2 +- .../Object/Pushable/PushableCollision.cpp | 40 +- .../Generic/Object/Pushable/PushableInfo.cpp | 4 +- .../Generic/Object/Pushable/PushableStack.cpp | 32 +- .../Object/Pushable/PushableStates.cpp | 32 +- .../Objects/Generic/Object/burning_torch.cpp | 28 +- .../Generic/Switches/crowbar_switch.cpp | 4 +- .../Objects/Generic/Traps/dart_emitter.cpp | 2 +- TombEngine/Objects/Generic/puzzles_keys.cpp | 20 +- TombEngine/Objects/TR1/Entity/Cowboy.cpp | 4 +- TombEngine/Objects/TR1/Entity/Kold.cpp | 4 +- .../Objects/TR1/Entity/SkateboardKid.cpp | 13 +- TombEngine/Objects/TR1/Entity/tr1_ape.cpp | 4 +- TombEngine/Objects/TR1/Entity/tr1_bear.cpp | 10 +- TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp | 8 +- TombEngine/Objects/TR1/Entity/tr1_centaur.cpp | 8 +- TombEngine/Objects/TR1/Entity/tr1_natla.cpp | 4 +- .../Objects/TR1/Entity/tr1_winged_mutant.cpp | 6 +- TombEngine/Objects/TR1/Entity/tr1_wolf.cpp | 12 +- TombEngine/Objects/TR2/Entity/Dragon.cpp | 8 +- .../Objects/TR2/Entity/tr2_eagle_or_crow.cpp | 2 +- .../Objects/TR2/Entity/tr2_knife_thrower.cpp | 2 +- TombEngine/Objects/TR2/Entity/tr2_rat.cpp | 6 +- .../Objects/TR2/Entity/tr2_silencer.cpp | 4 +- TombEngine/Objects/TR2/Entity/tr2_skidman.cpp | 6 +- TombEngine/Objects/TR2/Entity/tr2_yeti.cpp | 2 +- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 4 +- TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 6 +- .../Objects/TR3/Entity/Compsognathus.cpp | 25 +- TombEngine/Objects/TR3/Entity/FishSwarm.cpp | 427 +++++++++++++++ TombEngine/Objects/TR3/Entity/FishSwarm.h | 37 ++ TombEngine/Objects/TR3/Entity/Lizard.cpp | 4 +- TombEngine/Objects/TR3/Entity/PunaBoss.cpp | 22 +- TombEngine/Objects/TR3/Entity/Shiva.cpp | 2 +- TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp | 2 +- TombEngine/Objects/TR3/Entity/WaspMutant.cpp | 4 +- TombEngine/Objects/TR3/Entity/Winston.cpp | 6 +- TombEngine/Objects/TR3/Entity/tr3_civvy.cpp | 4 +- .../Objects/TR3/Entity/tr3_claw_mutant.cpp | 4 +- .../Objects/TR3/Entity/tr3_fish_emitter.cpp | 424 -------------- .../Objects/TR3/Entity/tr3_fish_emitter.h | 9 - .../Objects/TR3/Entity/tr3_flamethrower.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_monkey.cpp | 22 +- TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp | 4 +- .../Objects/TR3/Entity/tr3_mp_stick.cpp | 6 +- TombEngine/Objects/TR3/Entity/tr3_raptor.cpp | 4 +- .../Objects/TR3/Entity/tr3_scuba_diver.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_tiger.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_tony.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_trex.cpp | 2 +- .../Objects/TR3/Entity/tr3_tribesman.cpp | 2 +- TombEngine/Objects/TR3/Object/corpse.cpp | 77 +-- TombEngine/Objects/TR3/Object/corpse.h | 14 +- .../Objects/TR3/Trap/ElectricCleaner.cpp | 112 +--- TombEngine/Objects/TR3/Vehicles/big_gun.cpp | 4 +- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 12 +- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 18 +- TombEngine/Objects/TR3/Vehicles/quad_bike.cpp | 4 +- .../Objects/TR3/Vehicles/rubber_boat.cpp | 6 +- TombEngine/Objects/TR3/Vehicles/upv.cpp | 6 +- TombEngine/Objects/TR3/fish.h | 24 - TombEngine/Objects/TR3/tr3_objects.cpp | 15 +- TombEngine/Objects/TR4/Entity/Wraith.cpp | 8 +- TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_baboon.cpp | 10 +- TombEngine/Objects/TR4/Entity/tr4_baddy.cpp | 8 +- .../Objects/TR4/Entity/tr4_beetle_swarm.cpp | 4 +- .../Objects/TR4/Entity/tr4_big_beetle.cpp | 4 +- .../Objects/TR4/Entity/tr4_big_scorpion.cpp | 6 +- .../Objects/TR4/Entity/tr4_crocodile.cpp | 14 +- TombEngine/Objects/TR4/Entity/tr4_dog.cpp | 2 +- .../Objects/TR4/Entity/tr4_enemy_jeep.cpp | 6 +- TombEngine/Objects/TR4/Entity/tr4_guide.cpp | 6 +- TombEngine/Objects/TR4/Entity/tr4_harpy.cpp | 4 +- .../Objects/TR4/Entity/tr4_horseman.cpp | 12 +- TombEngine/Objects/TR4/Entity/tr4_mutant.cpp | 4 +- TombEngine/Objects/TR4/Entity/tr4_sas.cpp | 16 +- TombEngine/Objects/TR4/Entity/tr4_setha.cpp | 2 +- .../Objects/TR4/Entity/tr4_skeleton.cpp | 6 +- TombEngine/Objects/TR4/Entity/tr4_troops.cpp | 4 +- .../Objects/TR4/Entity/tr4_von_croy.cpp | 2 +- .../Objects/TR4/Entity/tr4_wild_boar.cpp | 2 +- .../TR4/Object/tr4_clockwork_beetle.cpp | 10 +- .../Objects/TR4/Object/tr4_element_puzzle.cpp | 4 +- TombEngine/Objects/TR4/Object/tr4_obelisk.cpp | 4 +- TombEngine/Objects/TR4/Object/tr4_senet.cpp | 2 +- TombEngine/Objects/TR4/Trap/SpikyWall.cpp | 18 +- TombEngine/Objects/TR4/Trap/SquishyBlock.cpp | 221 ++++++++ TombEngine/Objects/TR4/Trap/SquishyBlock.h | 13 + TombEngine/Objects/TR4/Trap/tr4_hammer.cpp | 12 +- TombEngine/Objects/TR4/Trap/tr4_mine.cpp | 2 +- .../Objects/TR4/Trap/tr4_teethspike.cpp | 2 +- TombEngine/Objects/TR4/Vehicles/jeep.cpp | 4 +- TombEngine/Objects/TR4/Vehicles/motorbike.cpp | 8 +- TombEngine/Objects/TR4/tr4_objects.cpp | 18 + .../Objects/TR5/Emitter/tr5_bats_emitter.cpp | 4 +- .../Objects/TR5/Emitter/tr5_rats_emitter.cpp | 2 +- .../TR5/Emitter/tr5_spider_emitter.cpp | 4 +- TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp | 2 +- .../Objects/TR5/Entity/tr5_doberman.cpp | 2 +- .../Objects/TR5/Entity/tr5_gladiator.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_guard.cpp | 14 +- TombEngine/Objects/TR5/Entity/tr5_hydra.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_imp.cpp | 4 +- TombEngine/Objects/TR5/Entity/tr5_larson.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_lion.cpp | 2 +- .../Objects/TR5/Entity/tr5_roman_statue.cpp | 4 +- .../Objects/TR5/Entity/tr5_submarine.cpp | 6 +- .../Objects/TR5/Object/tr5_raisingblock.cpp | 2 +- .../Objects/TR5/Object/tr5_rollingball.cpp | 2 +- .../Objects/TR5/Shatter/tr5_smashobject.cpp | 6 +- TombEngine/Objects/TR5/Trap/LaserBeam.cpp | 15 +- TombEngine/Objects/TR5/Trap/tr5_explosion.cpp | 52 +- TombEngine/Objects/game_object_ids.h | 4 +- .../ConstantBuffers/InstancedStaticBuffer.h | 2 +- TombEngine/Renderer/Renderer.cpp | 2 +- TombEngine/Renderer/Renderer.h | 5 +- TombEngine/Renderer/RendererDraw.cpp | 289 +++++++--- TombEngine/Renderer/RendererFrame.cpp | 10 +- TombEngine/Renderer/RendererInit.cpp | 2 +- TombEngine/Renderer/RendererSprites.cpp | 3 +- TombEngine/Resources.rc | 8 +- .../Scripting/Internal/ReservedScriptNames.h | 1 + .../Internal/TEN/Effects/EffectsFunctions.cpp | 2 +- .../Internal/TEN/Flow/FlowHandler.cpp | 39 +- .../Scripting/Internal/TEN/Flow/FlowHandler.h | 3 +- .../TEN/Objects/AIObject/AIObject.cpp | 8 +- .../TEN/Objects/Camera/CameraObject.cpp | 8 +- .../Internal/TEN/Objects/Lara/LaraObject.cpp | 4 +- .../TEN/Objects/Moveable/MoveableObject.cpp | 167 +++--- .../Internal/TEN/Objects/ObjectIDs.h | 8 +- .../Internal/TEN/Objects/ObjectsHandler.cpp | 35 +- .../Internal/TEN/Objects/Room/RoomObject.cpp | 8 +- .../Internal/TEN/Objects/Sink/SinkObject.cpp | 8 +- .../Objects/SoundSource/SoundSourceObject.cpp | 8 +- .../TEN/Objects/Static/StaticObject.cpp | 8 +- .../TEN/Objects/Volume/VolumeObject.cpp | 221 ++++---- .../TEN/Objects/Volume/VolumeObject.h | 45 +- TombEngine/Specific/clock.cpp | 68 ++- TombEngine/Specific/clock.h | 14 +- TombEngine/Specific/level.cpp | 15 +- .../flatbuffers/ten_savegame_generated.h | 345 ++++++++++-- .../Specific/savegame/schema/ten_savegame.fbs | 16 + TombEngine/TombEngine.vcxproj | 7 +- 203 files changed, 3690 insertions(+), 2685 deletions(-) create mode 100644 TombEngine/Objects/TR3/Entity/FishSwarm.cpp create mode 100644 TombEngine/Objects/TR3/Entity/FishSwarm.h delete mode 100644 TombEngine/Objects/TR3/Entity/tr3_fish_emitter.cpp delete mode 100644 TombEngine/Objects/TR3/Entity/tr3_fish_emitter.h delete mode 100644 TombEngine/Objects/TR3/fish.h create mode 100644 TombEngine/Objects/TR4/Trap/SquishyBlock.cpp create mode 100644 TombEngine/Objects/TR4/Trap/SquishyBlock.h diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index cbbb93f4b..796c56194 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -2,6 +2,7 @@ Version 1.4 =========== * Fixed drawing of display sprites in title level. +* Fixed drawing of smoke sprites and various other sprites. * Fixed player holster state and current vehicle not preserved correctly on level jump. * Fixed fade-in and fade-out effects not canceling correctly when next level is loaded. * Fixed shadows still being visible after shattering a moveable. @@ -15,15 +16,19 @@ Version 1.4 - Wall spikes will shatter any shatter in its path. - Wall spikes can be stopped by normal antitrigger or with a volume. * Added hub system to preserve level state on level jumps. -* Added ember emitter object. +* Added ember emitter. +* Added fish emitter. * Added laser beam object. * Added TR2 dragon. -* Added TR3 Winston (requires updated TEN Winston .wad2). +* Added TR3 Winston (requires updated TEN .wad2 on TombEngine.com). +* Added TR4 squishy blocks (requires updated TEN .wad2 on TombEngine.com). Lua API changes: * Added resetHub flag to Flow.Level, which allows to reset hub data. +* Added Flow.GetFlipMapStatus() function to get current flipmap status. * Added Moveable:GetMeshCount() function to get number of moveable meshes. * Added Static:GetHP() and Static:SetHP() functions to change shatterable static mesh hit points. +* Fixed Moveable:SetOnCollidedWithObject() callback. Version 1.3 =========== diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index df72adc0c..47dd024fe 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -195,6 +195,14 @@ scripts too.

SetTotalSecretCount(total) Total number of secrets in game. + + FlipMap(flipmap) + Do FlipMap with specific group ID. + + + GetFlipMapStatus([index]) + Get current FlipMap status for specific group ID. +

settings.lua

@@ -734,6 +742,57 @@ Must be an integer value (0 means no secrets). + +
+ + FlipMap(flipmap) +
+
+ Do FlipMap with specific group ID. + + + +

Parameters:

+
    +
  • flipmap + int + (ID of flipmap group to actuvate / deactivate) +
  • +
+ + + + + +
+
+ + GetFlipMapStatus([index]) +
+
+ Get current FlipMap status for specific group ID. + + + +

Parameters:

+
    +
  • index + int + Flipmap group ID to check. If no group specified or group is -1, function returns overall flipmap status (on or off). + (optional) +
  • +
+ +

Returns:

+
    + + int + Status of the flipmap group (true means on, false means off). +
+ + + +

settings.lua

diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index 2aa6c0cbd..5eb0c2962 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -108,9 +108,8 @@ pickups, and Lara herself (see also Functions
- - + + @@ -139,16 +138,6 @@ associated getters and setters. - - - - - - - - @@ -274,12 +263,22 @@ associated getters and setters. + + + + + + + + @@ -391,11 +390,12 @@ associated getters and setters.
- Moveable(object, name, position[, rotation][, roomID][, animNumber=0][, frameNumber=0][, hp=10][, OCB=0][, AIBits]) + Moveable(object, name, position, rotation, roomID, animNumber, frameNumber, hp, OCB, AIBits)
- For more information on each parameter, see the -associated getters and setters. If you do not know what to set for these, + Used to generate a new moveable dynamically at runtime.
+For more information on each parameter, see the +associated getters and setters. If you do not know what to set for these, most can just be ignored (see usage). @@ -416,38 +416,31 @@ most can just be ignored (see usage).
  • rotation Rotation - rotation about x, y, and z axes (default Rotation(0, 0, 0)) - (optional) + rotation rotation about x, y, and z axes (default Rotation(0, 0, 0))
  • roomID int room ID item is in (default: calculated automatically) - (optional)
  • animNumber int - anim number - (default 0) + animation number
  • frameNumber int frame number - (default 0)
  • hp int HP of item - (default 10)
  • OCB int ocb of item - (default 0)
  • AIBits table table with AI bits (default { 0, 0, 0, 0, 0, 0 }) - (optional)
  • @@ -465,7 +458,7 @@ most can just be ignored (see usage).
    local item = Moveable(
     	TEN.Objects.ObjID.PISTOLS_ITEM, -- object id
     	"test", -- name
    -	Vec3(18907, 0, 21201))
    + Vec3(18907, 0, 21201)) -- position
    @@ -618,58 +611,6 @@ most can just be ignored (see usage). - -
    - - Moveable:SetOnHit(callback) -
    -
    - Set the name of the function to be called when the moveable is shot by Lara. - Note that this will be triggered twice when shot with both pistols at once. - - - -

    Parameters:

    -
      -
    • callback - function - function in LevelFuncs hierarchy to call when moveable is shot -
    • -
    - - - - - -
    -
    - - Moveable:SetOnKilled(callback) -
    -
    - Set the name of the function to be called when the moveable is destroyed/killed - Note that enemy death often occurs at the end of an animation, and not at the exact moment - the enemy's HP becomes zero. - - - -

    Parameters:

    -
      -
    • callback - function - function in LevelFuncs hierarchy to call when enemy is killed -
    • -
    - - - - -

    Usage:

    -
      -
      LevelFuncs.baddyKilled = function(theBaddy) print("You killed a baddy!") end
      -baddy:SetOnKilled(LevelFuncs.baddyKilled)
      -
    -
    @@ -1372,6 +1313,29 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM) + +
    + + Moveable:SetOnHit(callback) +
    +
    + Set the name of the function to be called when the moveable is shot by Lara. + Note that this will be triggered twice when shot with both pistols at once. + + + +

    Parameters:

    +
      +
    • callback + function + function in LevelFuncs hierarchy to call when moveable is shot +
    • +
    + + + + +
    @@ -1430,6 +1394,35 @@ baddy:SetOnCollidedWithObject(LevelFuncs.objCollided) baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided) + +
    + + Moveable:SetOnKilled(callback) +
    +
    + Set the name of the function to be called when the moveable is destroyed/killed + Note that enemy death often occurs at the end of an animation, and not at the exact moment + the enemy's HP becomes zero. + + + +

    Parameters:

    +
      +
    • callback + function + function in LevelFuncs hierarchy to call when enemy is killed +
    • +
    + + + + +

    Usage:

    +
      +
      LevelFuncs.baddyKilled = function(theBaddy) print("You killed a baddy!") end
      +baddy:SetOnKilled(LevelFuncs.baddyKilled)
      +
    +
    diff --git a/Documentation/doc/2 classes/Objects.Volume.html b/Documentation/doc/2 classes/Objects.Volume.html index f7ff425f2..9f5fa9fb2 100644 --- a/Documentation/doc/2 classes/Objects.Volume.html +++ b/Documentation/doc/2 classes/Objects.Volume.html @@ -100,7 +100,7 @@

    Class Objects.Volume

    -

    Volumes

    +

    Activator volume.

    @@ -109,56 +109,56 @@

    Functions

    Moveable(object, name, position[, rotation][, roomID][, animNumber=0][, frameNumber=0][, hp=10][, OCB=0][, AIBits])For more information on each parameter, see the -associated getters and setters.Moveable(object, name, position, rotation, roomID, animNumber, frameNumber, hp, OCB, AIBits)Used to generate a new moveable dynamically at runtime.
    Moveable:Explode()
    Moveable:SetStatus(status) Set the moveable's status.
    Moveable:SetOnHit(callback)Set the name of the function to be called when the moveable is shot by Lara.
    Moveable:SetOnKilled(callback)Set the name of the function to be called when the moveable is destroyed/killed - Note that enemy death often occurs at the end of an animation, and not at the exact moment - the enemy's HP becomes zero.
    Moveable:GetObjectID() Borrow animation from an object
    Moveable:SetOnHit(callback)Set the name of the function to be called when the moveable is shot by Lara.
    Moveable:SetOnCollidedWithObject(func) Set the function to be called when this moveable collides with another moveable
    Moveable:SetOnCollidedWithRoom(func) Set the function called when this moveable collides with room geometry (e.g.
    Moveable:SetOnKilled(callback)Set the name of the function to be called when the moveable is destroyed/killed + Note that enemy death often occurs at the end of an animation, and not at the exact moment + the enemy's HP becomes zero.
    Moveable:GetPosition()
    - - - - - - - - - - + + - - - - - + - - - - - + - - - - - - - - - + - + - - + + + + + + + + + + + + + + - + + + + + + + + + + + + +
    Volume:Enable()Enable the volume.
    Volume:Disable()Disable the volume.
    Volume:GetActive()Determine whether the volume is active or notVolume:GetName()Get the unique string identifier of this volume.
    Volume:GetPosition()Get the volume's position.
    Volume:SetPosition(position)Set the volume's position.Get the position of this volume.
    Volume:GetRotation()Get the volume's rotation.
    Volume:SetRotation(rotation)Set the volume's rotation.Get the rotation of this volume.
    Volume:GetScale()Get the volume's scale (separately on all 3 axes).
    Volume:SetScale(scale)Set the volume's scale (separately on all 3 axes).
    Volume:GetName()Get the volume's unique string identifier.Get this scale of this volume.
    Volume:SetName(name)Set the volume's name (its unique string identifier).Set the unique string identifier of this volume.
    Volume:ClearActivators()Clear activator list for volumes (makes volume trigger everything again)Volume:SetPosition(pos)Set the position of this volume.
    Volume:SetRotation(rot)Set the rotation of this volume.
    Volume:SetScale(scale)Set the scale of the volume.
    Volume:GetActive()Determine if this volume is active.
    Volume:IsMoveableInside(Moveable)Check if specified moveable is inside the volumeDetermine if a moveable is inside this volume.
    Volume:Enable()Enable this volume.
    Volume:Disable()Disable this volume.
    Volume:ClearActivators()Clear the activators for this volume, allowing it to trigger again.
    @@ -169,12 +169,233 @@

    Functions

    +
    + + Volume:GetName() +
    +
    + Get the unique string identifier of this volume. () + + + + +

    Returns:

    +
      + + string + Name. +
    + + + + +
    +
    + + Volume:GetPosition() +
    +
    + Get the position of this volume. () + + + + +

    Returns:

    +
      + + Vec3 + Position. +
    + + + + +
    +
    + + Volume:GetRotation() +
    +
    + Get the rotation of this volume. () + + + + +

    Returns:

    +
      + + Rotation + Rotation. +
    + + + + +
    +
    + + Volume:GetScale() +
    +
    + Get this scale of this volume. () + + + + +

    Returns:

    +
      + + Vec3 + Scale. +
    + + + + +
    +
    + + Volume:SetName(name) +
    +
    + Set the unique string identifier of this volume. () + + + +

    Parameters:

    +
      +
    • name + string + New name. +
    • +
    + + + + + +
    +
    + + Volume:SetPosition(pos) +
    +
    + Set the position of this volume. () + + + +

    Parameters:

    +
      +
    • pos + Vec3 + New position. +
    • +
    + + + + + +
    +
    + + Volume:SetRotation(rot) +
    +
    + Set the rotation of this volume. () + + + +

    Parameters:

    + + + + + + +
    +
    + + Volume:SetScale(scale) +
    +
    + Set the scale of the volume. () + + + +

    Parameters:

    +
      +
    • scale + Vec3 + New scale. +
    • +
    + + + + + +
    +
    + + Volume:GetActive() +
    +
    + Determine if this volume is active. () + + + + +

    Returns:

    +
      + + bool + Boolean representing active status. +
    + + + + +
    +
    + + Volume:IsMoveableInside(Moveable) +
    +
    + Determine if a moveable is inside this volume. () + + + +

    Parameters:

    +
      +
    • Moveable + Moveable + to be checked for containment. +
    • +
    + +

    Returns:

    +
      + + bool + Boolean representing containment status. +
    + + + + +
    Volume:Enable()
    - Enable the volume. + Enable this volume. () @@ -189,7 +410,7 @@ Volume:Disable()
    - Disable the volume. + Disable this volume. () @@ -198,206 +419,13 @@ -
    -
    - - Volume:GetActive() -
    -
    - Determine whether the volume is active or not - - - - -

    Returns:

    -
      - - bool - true if the volume is active -
    - - - - -
    -
    - - Volume:GetPosition() -
    -
    - Get the volume's position. - - - - -

    Returns:

    -
      - - Vec3 - a copy of the volume's position -
    - - - - -
    -
    - - Volume:SetPosition(position) -
    -
    - Set the volume's position. - - - -

    Parameters:

    -
      -
    • position - Vec3 - the new position of the volume -
    • -
    - - - - - -
    -
    - - Volume:GetRotation() -
    -
    - Get the volume's rotation. - - - - -

    Returns:

    -
      - - Rotation - a copy of the volume's rotation -
    - - - - -
    -
    - - Volume:SetRotation(rotation) -
    -
    - Set the volume's rotation. - - - -

    Parameters:

    -
      -
    • rotation - Rotation - the volume's new rotation -
    • -
    - - - - - -
    -
    - - Volume:GetScale() -
    -
    - Get the volume's scale (separately on all 3 axes). - - - - -

    Returns:

    -
      - - Vec3 - current volume scale -
    - - - - -
    -
    - - Volume:SetScale(scale) -
    -
    - Set the volume's scale (separately on all 3 axes). - - - -

    Parameters:

    -
      -
    • scale - Vec3 - the volume's new scale -
    • -
    - - - - - -
    -
    - - Volume:GetName() -
    -
    - Get the volume's unique string identifier. - - - - -

    Returns:

    -
      - - string - the volume's name -
    - - - - -
    -
    - - Volume:SetName(name) -
    -
    - Set the volume's name (its unique string identifier). - - - -

    Parameters:

    -
      -
    • name - string - The volume's new name -
    • -
    - - - - -
    Volume:ClearActivators()
    - Clear activator list for volumes (makes volume trigger everything again) + Clear the activators for this volume, allowing it to trigger again. () @@ -406,34 +434,6 @@ -
    -
    - - Volume:IsMoveableInside(Moveable) -
    -
    - Check if specified moveable is inside the volume - - - -

    Parameters:

    -
      -
    • Moveable - Moveable - which should be checked for containment -
    • -
    - -

    Returns:

    -
      - - bool - state of the moveable, true if contained, false if not -
    - - - -
    diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index db14eef45..a4e71b10a 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -462,8 +462,8 @@ SEARCH_OBJECT4 SARCOPHAGUS ENEMY_PIECE EXPANDING_PLATFORM -SQUISHY_BLOCK1 -SQUISHY_BLOCK2 +SQUISHY_BLOCK_HORIZONTAL +SQUISHY_BLOCK_VERTICAL LASER_BEAM MINE_DETECTOR MAP diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index 75857d49e..28889444d 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -233,7 +233,7 @@ local door = GetMoveableByName("door_type4_14") Objects.Volume - Volumes + Activator volume. Strings.DisplayString diff --git a/Documentation/output.xml b/Documentation/output.xml index d2c1f4a79..7f960b6df 100644 --- a/Documentation/output.xml +++ b/Documentation/output.xml @@ -892,6 +892,38 @@ teleported to such object with OCB similar to provided second argument.
    + + Flow + FlipMap + Do FlipMap with specific group ID. + + + flipmap + int + (ID of flipmap group to actuvate / deactivate) + + + + + + Flow + GetFlipMapStatus + Get current FlipMap status for specific group ID. + + + index + int + Flipmap group ID to check. If no group specified or group is -1, function returns overall flipmap status (on or off). + + + + + int + Status of the flipmap group (true means on, false means off). + + + + Flow SetSettings @@ -1899,9 +1931,9 @@ e.g. `myItem.action = ItemAction.EXAMINE` Objects.Moveable Moveable - For more information on each parameter, see the -associated getters and setters. - If you do not know what to set for these, + Used to generate a new moveable dynamically at runtime. + For more information on each parameter, see the +associated getters and setters. If you do not know what to set for these, most can just be ignored (see usage). @@ -1922,7 +1954,7 @@ most can just be ignored (see usage). rotation Rotation - rotation about x, y, and z axes (default Rotation(0, 0, 0)) + rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) roomID @@ -1932,7 +1964,7 @@ most can just be ignored (see usage). animNumber int - anim number + animation number frameNumber @@ -2064,37 +2096,6 @@ most can just be ignored (see usage). - - Objects.Moveable - Moveable - SetOnHit - Set the name of the function to be called when the moveable is shot by Lara. - Note that this will be triggered twice when shot with both pistols at once. - - - callback - function - function in LevelFuncs hierarchy to call when moveable is shot - - - - - - Objects.Moveable - Moveable - SetOnKilled - Set the name of the function to be called when the moveable is destroyed/killed - Note that enemy death often occurs at the end of an animation, and not at the exact moment - the enemy's HP becomes zero. - - - callback - function - function in LevelFuncs hierarchy to call when enemy is killed - - - - Objects.Moveable Moveable @@ -2563,6 +2564,21 @@ most can just be ignored (see usage). + + Objects.Moveable + Moveable + SetOnHit + Set the name of the function to be called when the moveable is shot by Lara. + Note that this will be triggered twice when shot with both pistols at once. + + + callback + function + function in LevelFuncs hierarchy to call when moveable is shot + + + + Objects.Moveable Moveable @@ -2592,6 +2608,22 @@ most can just be ignored (see usage). + + Objects.Moveable + Moveable + SetOnKilled + Set the name of the function to be called when the moveable is destroyed/killed + Note that enemy death often occurs at the end of an animation, and not at the exact moment + the enemy's HP becomes zero. + + + callback + function + function in LevelFuncs hierarchy to call when enemy is killed + + + + Objects.Moveable Moveable @@ -3695,26 +3727,13 @@ most can just be ignored (see usage). Objects.Volume Volume - Enable - Enable the volume. - - - - Objects.Volume - Volume - Disable - Disable the volume. - - - - Objects.Volume - Volume - GetActive - Determine whether the volume is active or not + GetName + Get the unique string identifier of this volume. + () - bool - true if the volume is active + string + Name. @@ -3723,92 +3742,40 @@ most can just be ignored (see usage). Objects.Volume Volume GetPosition - Get the volume's position. + Get the position of this volume. + () Vec3 - a copy of the volume's position + Position. - - Objects.Volume - Volume - SetPosition - Set the volume's position. - - - position - Vec3 - the new position of the volume - - - - Objects.Volume Volume GetRotation - Get the volume's rotation. + Get the rotation of this volume. + () Rotation - a copy of the volume's rotation + Rotation. - - Objects.Volume - Volume - SetRotation - Set the volume's rotation. - - - rotation - Rotation - the volume's new rotation - - - - Objects.Volume Volume GetScale - Get the volume's scale (separately on all 3 axes). + Get this scale of this volume. + () Vec3 - current volume scale - - - - - - Objects.Volume - Volume - SetScale - Set the volume's scale (separately on all 3 axes). - - - scale - Vec3 - the volume's new scale - - - - - - Objects.Volume - Volume - GetName - Get the volume's unique string identifier. - - - string - the volume's name + Scale. @@ -3817,12 +3784,13 @@ most can just be ignored (see usage). Objects.Volume Volume SetName - Set the volume's name (its unique string identifier). + Set the unique string identifier of this volume. + () name string - The volume's new name + New name. @@ -3830,30 +3798,107 @@ most can just be ignored (see usage). Objects.Volume Volume - ClearActivators - Clear activator list for volumes (makes volume trigger everything again) + SetPosition + Set the position of this volume. + () + + + pos + Vec3 + New position. + + + + + + Objects.Volume + Volume + SetRotation + Set the rotation of this volume. + () + + + rot + Rotation + New rotation. + + + + + + Objects.Volume + Volume + SetScale + Set the scale of the volume. + () + + + scale + Vec3 + New scale. + + + + + + Objects.Volume + Volume + GetActive + Determine if this volume is active. + () + + + bool + Boolean representing active status. + + Objects.Volume Volume IsMoveableInside - Check if specified moveable is inside the volume + Determine if a moveable is inside this volume. + () Moveable Objects.Moveable - which should be checked for containment + to be checked for containment. bool - state of the moveable, true if contained, false if not + Boolean representing containment status. + + Objects.Volume + Volume + Enable + Enable this volume. + () + + + + Objects.Volume + Volume + Disable + Disable this volume. + () + + + + Objects.Volume + Volume + ClearActivators + Clear the activators for this volume, allowing it to trigger again. + () + + Rotation Rotation diff --git a/Scripts/Engine/Timer.lua b/Scripts/Engine/Timer.lua index 72ffef812..59ce2f3a3 100644 --- a/Scripts/Engine/Timer.lua +++ b/Scripts/Engine/Timer.lua @@ -81,7 +81,7 @@ Timer = { print("Warning: a timer with name " .. name .. " already exists; overwriting it with a new one...") end - LevelVars.Engine.Timer.timers[name] ={} + LevelVars.Engine.Timer.timers[name] = {} local thisTimer = LevelVars.Engine.Timer.timers[name] thisTimer.name = name thisTimer.totalTime = totalTime @@ -98,6 +98,14 @@ Timer = { end return obj end; + + Delete = function(name) + if LevelVars.Engine.Timer.timers[name] then + LevelVars.Engine.Timer.timers[name] = nil + else + print("Warning: a timer with name " .. name .. " does not exist and can't be deleted.") + end + end; --- Get a timer by its name. -- @string name The label that was given to the timer when it was created diff --git a/TombEngine/Game/Hud/StatusBars.cpp b/TombEngine/Game/Hud/StatusBars.cpp index 46f6b0ce5..b9ab5a415 100644 --- a/TombEngine/Game/Hud/StatusBars.cpp +++ b/TombEngine/Game/Hud/StatusBars.cpp @@ -109,7 +109,7 @@ namespace TEN::Hud } // HACK: Special case for UPV as it sets player.Control.WaterStatus to WaterStatus::Dry. - if (player.Context.Vehicle != NO_ITEM) + if (player.Context.Vehicle != NO_VALUE) { const auto& vehicleItem = g_Level.Items[player.Context.Vehicle]; if (vehicleItem.ObjectNumber == ID_UPV) diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 2957dc5be..34638f991 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -181,7 +181,8 @@ namespace TEN::Hud continue; // Collect item number. - itemNumbers.push_back(itemPtr->Index); + if (itemPtr->HitPoints != NOT_TARGETABLE) + itemNumbers.push_back(itemPtr->Index); // Find crosshair at item number key. auto it = _crosshairs.find(itemPtr->Index); @@ -190,8 +191,7 @@ namespace TEN::Hud // Set crosshair as primary or peripheral. auto& crosshair = it->second; - if (player.TargetEntity != nullptr && - itemPtr->Index == player.TargetEntity->Index) + if (player.TargetEntity != nullptr && itemPtr->Index == player.TargetEntity->Index) { crosshair.SetPrimary(); } diff --git a/TombEngine/Game/Lara/PlayerContext.cpp b/TombEngine/Game/Lara/PlayerContext.cpp index 6e6d4d721..5832264dc 100644 --- a/TombEngine/Game/Lara/PlayerContext.cpp +++ b/TombEngine/Game/Lara/PlayerContext.cpp @@ -109,7 +109,7 @@ namespace TEN::Entities::Player if (!(IsHeld(In::Flare) || IsHeld(In::Draw)) && // Avoid unsightly concurrent actions. (player.Control.Weapon.GunType != LaraWeaponType::Flare || // Not handling flare. player.Flare.Life) && // OR flare is still active. - player.Context.Vehicle == NO_ITEM) // Not in a vehicle. + player.Context.Vehicle == NO_VALUE) // Not in a vehicle. { return true; } diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index fe9d8d088..05d0c9567 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -91,7 +91,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) } if (!player.Control.IsLocked) - player.LocationPad = -1; + player.LocationPad = NO_VALUE; // FAILSAFE: Force hand status reset. if (item->Animation.AnimNumber == LA_STAND_IDLE && @@ -109,14 +109,14 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) auto water = GetPlayerWaterData(*item); player.Context.WaterSurfaceDist = -water.HeightFromWater; - if (player.Context.Vehicle == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE) SpawnPlayerWaterSurfaceEffects(*item, water.WaterHeight, water.WaterDepth); bool isWaterOnHeadspace = false; // TODO: Move unrelated handling elsewhere. // Handle environment state transition. - if (player.Context.Vehicle == NO_ITEM && player.ExtraAnim == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE && player.ExtraAnim == NO_VALUE) { switch (player.Control.WaterStatus) { @@ -367,7 +367,7 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll) // Handle look-around. if (((IsHeld(In::Look) && CanPlayerLookAround(*item)) || (player.Control.Look.IsUsingBinoculars || player.Control.Look.IsUsingLasersight)) && - player.ExtraAnim == NO_ITEM) + player.ExtraAnim == NO_VALUE) { HandlePlayerLookAround(*item); } @@ -382,19 +382,17 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll) if (HandleLaraVehicle(item, coll)) return; - // Handle player behavior state control. HandlePlayerBehaviorState(*item, *coll, PlayerBehaviorStateRoutineType::Control); - HandleLaraMovementParameters(item, coll); AnimateItem(item); - if (player.ExtraAnim == NO_ITEM) + if (player.ExtraAnim == NO_VALUE) { // Check for collision with items. DoObjectCollision(item, coll); // Handle player behavior state collision. - if (player.Context.Vehicle == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE) HandlePlayerBehaviorState(*item, *coll, PlayerBehaviorStateRoutineType::Collision); } @@ -468,7 +466,7 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll) DoObjectCollision(item, coll); - if (player.Context.Vehicle == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE) HandlePlayerBehaviorState(*item, *coll, PlayerBehaviorStateRoutineType::Collision); UpdateLaraRoom(item, LARA_RADIUS); @@ -571,7 +569,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll) DoObjectCollision(item, coll); - if (player.Context.Vehicle == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE) HandlePlayerBehaviorState(*item, *coll, PlayerBehaviorStateRoutineType::Collision); UpdateLaraRoom(item, 0); @@ -638,9 +636,9 @@ void UpdateLara(ItemInfo* item, bool isTitle) if (isTitle) ActionMap = actionMap; - if (g_Gui.GetInventoryItemChosen() != NO_ITEM) + if (g_Gui.GetInventoryItemChosen() != NO_VALUE) { - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); SayNo(); } diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index d0527f388..1ffd4202d 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -57,7 +57,7 @@ bool LaraDeflectEdge(ItemInfo* item, CollisionInfo* coll) ShiftItem(item, coll); item->Pose.Orientation.y -= coll->DiagonalStepAtRight() ? DEFLECT_DIAGONAL_ANGLE : DEFLECT_STRAIGHT_ANGLE; } - else if (coll->LastBridgeItemNumber != NO_ITEM) + else if (coll->LastBridgeItemNumber != NO_VALUE) { ShiftItem(item, coll); } @@ -652,7 +652,7 @@ void LaraSwimCollision(ItemInfo* item, CollisionInfo* coll) return; } - if (lara->ExtraAnim == NO_ITEM) + if (lara->ExtraAnim == NO_VALUE) TestLaraWaterDepth(item, coll); } @@ -760,8 +760,8 @@ bool TestLaraObjectCollision(ItemInfo* item, short headingAngle, int forward, in item->Pose.Position.y += down; item->Pose.Position.z += phd_cos(item->Pose.Orientation.y + headingAngle) * forward + phd_sin(headingAngle + ANGLE(90.0f) * sideSign) * abs(right); - bool result = GetCollidedObjects(item, LARA_RADIUS, true, CollidedItems, CollidedMeshes, 0); + bool isCollided = !GetCollidedObjects(*item, true, false).IsEmpty(); item->Pose = prevPose; - return result; + return isCollided; } diff --git a/TombEngine/Game/Lara/lara_fire.cpp b/TombEngine/Game/Lara/lara_fire.cpp index b6a7ca140..5bac95a04 100644 --- a/TombEngine/Game/Lara/lara_fire.cpp +++ b/TombEngine/Game/Lara/lara_fire.cpp @@ -571,7 +571,7 @@ void HandleWeapon(ItemInfo& laraItem) player.Control.Weapon.RequestGunType = LaraWeaponType::Flare; } else if (player.Control.Weapon.RequestGunType == LaraWeaponType::Flare || - (player.Context.Vehicle == NO_ITEM && + (player.Context.Vehicle == NO_VALUE && (player.Control.Weapon.RequestGunType == LaraWeaponType::HarpoonGun || player.Control.WaterStatus == WaterStatus::Dry || (player.Control.WaterStatus == WaterStatus::Wade && @@ -760,7 +760,7 @@ void HandleWeapon(ItemInfo& laraItem) case HandStatus::Free: if (player.Control.Weapon.GunType == LaraWeaponType::Flare) { - if (player.Context.Vehicle != NO_ITEM || TestState(laraItem.Animation.ActiveState, FlarePoseStates)) + if (player.Context.Vehicle != NO_VALUE || TestState(laraItem.Animation.ActiveState, FlarePoseStates)) { if (player.Flare.ControlLeft) { @@ -792,7 +792,7 @@ void HandleWeapon(ItemInfo& laraItem) { if (laraItem.Model.MeshIndex[LM_LHAND] == Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND) { - player.Flare.ControlLeft = (player.Context.Vehicle != NO_ITEM || TestState(laraItem.Animation.ActiveState, FlarePoseStates)); + player.Flare.ControlLeft = (player.Context.Vehicle != NO_VALUE || TestState(laraItem.Animation.ActiveState, FlarePoseStates)); if (Contains(UnavailableFlarePoseAnims, laraItem.Animation.AnimNumber)) player.Flare.ControlLeft = false; @@ -843,7 +843,7 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, Ite auto ray = Ray(origin, directionNorm); int num = GetSpheres(&targetEntity, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - int bestJointIndex = NO_JOINT; + int bestJointIndex = NO_VALUE; float bestDistance = INFINITY; for (int i = 0; i < num; i++) { @@ -917,7 +917,7 @@ void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo) for (auto* creaturePtr : ActiveCreatures) { // Continue loop if no item. - if (creaturePtr->ItemNumber == NO_ITEM) + if (creaturePtr->ItemNumber == NO_VALUE) continue; auto& item = g_Level.Items[creaturePtr->ItemNumber]; diff --git a/TombEngine/Game/Lara/lara_fire.h b/TombEngine/Game/Lara/lara_fire.h index ceeb66975..662d4b359 100644 --- a/TombEngine/Game/Lara/lara_fire.h +++ b/TombEngine/Game/Lara/lara_fire.h @@ -61,6 +61,6 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, Ite void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo); void LaraTargetInfo(ItemInfo& laraItem, const WeaponInfo& weaponInfo); -void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, int damage, bool isExplosive, int bestJointIndex = NO_JOINT); +void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, int damage, bool isExplosive, int bestJointIndex = NO_VALUE); void SmashItem(short itemNumber); diff --git a/TombEngine/Game/Lara/lara_flare.cpp b/TombEngine/Game/Lara/lara_flare.cpp index 375562969..2cab1151e 100644 --- a/TombEngine/Game/Lara/lara_flare.cpp +++ b/TombEngine/Game/Lara/lara_flare.cpp @@ -123,7 +123,7 @@ void UndrawFlare(ItemInfo& laraItem) player.Flare.ControlLeft = true; if (laraItem.Animation.TargetState == LS_IDLE && - player.Context.Vehicle == NO_ITEM) + player.Context.Vehicle == NO_VALUE) { if (laraItem.Animation.AnimNumber == LA_STAND_IDLE) { @@ -311,7 +311,7 @@ void CreateFlare(ItemInfo& laraItem, GAME_OBJECT_ID objectID, bool isThrown) const auto& lara = *GetLaraInfo(&laraItem); auto itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto& flareItem = g_Level.Items[itemNumber]; @@ -326,10 +326,10 @@ void CreateFlare(ItemInfo& laraItem, GAME_OBJECT_ID objectID, bool isThrown) flareItem.Pose.Position = pos; int floorHeight = GetPointCollision(pos, laraItem.RoomNumber).GetFloorHeight(); - auto hasCollided = GetCollidedObjects(&flareItem, 0, true, CollidedItems, CollidedMeshes, true); + auto isCollided = !GetCollidedObjects(flareItem, true, true).IsEmpty(); bool hasLanded = false; - if (floorHeight < pos.y || hasCollided) + if (floorHeight < pos.y || isCollided) { hasLanded = true; flareItem.Pose.Position.x = laraItem.Pose.Position.x + 320 * phd_sin(flareItem.Pose.Orientation.y); diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index a84f0e5f9..d38ee2e44 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -144,7 +144,7 @@ void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWa else if (player.Status.Air < LARA_AIR_MAX && item.HitPoints >= 0) { // HACK: Special case for UPV. - if (player.Context.Vehicle == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE) { player.Status.Air += 10; if (player.Status.Air > LARA_AIR_MAX) @@ -157,7 +157,7 @@ void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWa if (player.Control.WaterStatus == WaterStatus::Dry) { // HACK: Special case for UPV. - if (player.Context.Vehicle != NO_ITEM) + if (player.Context.Vehicle != NO_VALUE) { const auto& vehicleItem = g_Level.Items[player.Context.Vehicle]; if (vehicleItem.ObjectNumber == ID_UPV) @@ -650,7 +650,7 @@ void HandlePlayerLookAround(ItemInfo& item, bool invertXAxis) player.ExtraHeadRot = player.Control.Look.Orientation / 2; if (player.Control.HandStatus != HandStatus::Busy && !player.LeftArm.Locked && !player.RightArm.Locked && - player.Context.Vehicle == NO_ITEM) + player.Context.Vehicle == NO_VALUE) { player.ExtraTorsoRot = player.ExtraHeadRot; } @@ -662,12 +662,12 @@ bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll) { auto* lara = GetLaraInfo(item); - if (lara->Context.Vehicle == NO_ITEM) + if (lara->Context.Vehicle == NO_VALUE) return false; if (!g_Level.Items[lara->Context.Vehicle].Active) { - lara->Context.Vehicle = NO_ITEM; + lara->Context.Vehicle = NO_VALUE; item->Animation.IsAirborne = true; SetAnimation(item, LA_FALL_START); return false; @@ -927,7 +927,7 @@ void HandlePlayerFlyCheat(ItemInfo& item) static bool dbFlyCheat = true; if (KeyMap[OIS::KeyCode::KC_O] && dbFlyCheat) { - if (player.Context.Vehicle == NO_ITEM) + if (player.Context.Vehicle == NO_VALUE) { GivePlayerItemsCheat(item); GivePlayerWeaponsCheat(item); @@ -1748,10 +1748,10 @@ void SetLaraVehicle(ItemInfo* item, ItemInfo* vehicle) if (vehicle == nullptr) { - if (lara->Context.Vehicle != NO_ITEM) + if (lara->Context.Vehicle != NO_VALUE) g_Level.Items[lara->Context.Vehicle].Active = false; - lara->Context.Vehicle = NO_ITEM; + lara->Context.Vehicle = NO_VALUE; } else { @@ -1788,7 +1788,7 @@ void ResetPlayerLookAround(ItemInfo& item, float alpha) if (player.Control.HandStatus != HandStatus::Busy && !player.LeftArm.Locked && !player.RightArm.Locked && - player.Context.Vehicle == NO_ITEM) + player.Context.Vehicle == NO_VALUE) { player.ExtraTorsoRot = player.ExtraHeadRot; } diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 278e90e06..622d6c6c9 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -1,6 +1,7 @@ #include "framework.h" #include "Game/Lara/lara_initialise.h" +#include "Game/collision/Point.h" #include "Game/Hud/Hud.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -18,6 +19,7 @@ #include "Objects/TR4/Vehicles/motorbike.h" #include "Specific/level.h" +using namespace TEN::Collision::Point; using namespace TEN::Entities::Player; using namespace TEN::Hud; @@ -29,14 +31,14 @@ GAME_OBJECT_ID PlayerVehicleObjectID = GAME_OBJECT_ID::ID_NO_OBJECT; void BackupLara() { - if (LaraItem == nullptr || LaraItem->Index == NO_ITEM) + if (LaraItem == nullptr || LaraItem->Index == NO_VALUE) return; PlayerHitPoints = LaraItem->HitPoints; memcpy(&PlayerBackup, &Lara, sizeof(LaraInfo)); memcpy(&PlayerAnim, &LaraItem->Animation, sizeof(EntityAnimationData)); - if (Lara.Context.Vehicle != NO_ITEM) + if (Lara.Context.Vehicle != NO_VALUE) { PlayerVehicleObjectID = g_Level.Items[Lara.Context.Vehicle].ObjectNumber; } @@ -48,15 +50,15 @@ void BackupLara() void InitializeLara(bool restore) { - if (LaraItem == nullptr || LaraItem->Index == NO_ITEM) + if (LaraItem == nullptr || LaraItem->Index == NO_VALUE) return; ZeroMemory(&Lara, sizeof(LaraInfo)); LaraItem->Data = &Lara; - Lara.Context = PlayerContext(*LaraItem, LaraCollision); - LaraItem->Collidable = false; + + Lara.Context = PlayerContext(*LaraItem, LaraCollision); Lara.Status.Air = LARA_AIR_MAX; Lara.Status.Exposure = LARA_EXPOSURE_MAX; @@ -64,15 +66,15 @@ void InitializeLara(bool restore) Lara.Status.Stamina = LARA_STAMINA_MAX; Lara.Control.Look.Mode = LookMode::None; - Lara.HitDirection = -1; - Lara.Control.Weapon.WeaponItem = NO_ITEM; + Lara.HitDirection = NO_VALUE; + Lara.Control.Weapon.WeaponItem = NO_VALUE; Lara.Context.WaterSurfaceDist = 100; - Lara.ExtraAnim = NO_ITEM; - Lara.Context.Vehicle = NO_ITEM; - Lara.Location = -1; - Lara.HighestLocation = -1; - Lara.Control.Rope.Ptr = -1; + Lara.ExtraAnim = NO_VALUE; + Lara.Context.Vehicle = NO_VALUE; + Lara.Location = NO_VALUE; + Lara.HighestLocation = NO_VALUE; + Lara.Control.Rope.Ptr = NO_VALUE; Lara.Control.HandStatus = HandStatus::Free; InitializePlayerStateMachine(); @@ -131,8 +133,8 @@ void InitializeLaraAnims(ItemInfo* item) player.Control.WaterStatus = WaterStatus::Dry; // Allow player to start in crawl idle anim if start position is too low. - auto pointColl = GetCollision(item); - if (abs(pointColl.Position.Ceiling - pointColl.Position.Floor) < LARA_HEIGHT) + auto pointColl = GetPointCollision(*item); + if (abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()) < LARA_HEIGHT) { SetAnimation(item, LA_CRAWL_IDLE); player.Control.IsLow = @@ -160,18 +162,10 @@ void InitializeLaraStartPosition(ItemInfo& playerItem) if (!item.TriggerFlags || item.TriggerFlags != RequiredStartPos) continue; - // HACK: For some reason, player can't be immediately updated and moved on loading. - // Need to simulate "game loop" happening so that its position actually updates on next loop. - // However, room number must be also be manually set in advance, so that startup anim detection - // won't fail (otherwise player may start crouching because probe uses previous room number). - - InItemControlLoop = true; - playerItem.Pose = item.Pose; - playerItem.RoomNumber = item.RoomNumber; - ItemNewRoom(playerItem.Index, item.RoomNumber); - InItemControlLoop = false; + if (playerItem.RoomNumber != item.RoomNumber) + ItemNewRoom(playerItem.Index, item.RoomNumber); TENLog("Player start position has been set according to start position of object with ID " + std::to_string(item.TriggerFlags) + ".", LogLevel::Info); break; diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index 708cac335..ae115a197 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -443,7 +443,7 @@ void DrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType) ItemInfo* weaponItemPtr = nullptr; - if (player.Control.Weapon.WeaponItem == NO_ITEM) + if (player.Control.Weapon.WeaponItem == NO_VALUE) { player.Control.Weapon.WeaponItem = CreateItem(); weaponItemPtr = &g_Level.Items[player.Control.Weapon.WeaponItem]; @@ -514,7 +514,7 @@ void UndrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType) if (item.Status == ITEM_DEACTIVATED) { KillItem(player.Control.Weapon.WeaponItem); - player.Control.Weapon.WeaponItem = NO_ITEM; + player.Control.Weapon.WeaponItem = NO_VALUE; player.Control.HandStatus = HandStatus::Free; player.TargetEntity = nullptr; player.LeftArm.Locked = @@ -574,7 +574,7 @@ bool FireHarpoon(ItemInfo& laraItem, const std::optional& pose) player.Control.Weapon.HasFired = true; int itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return false; auto& harpoonItem = g_Level.Items[itemNumber]; @@ -682,7 +682,7 @@ void FireGrenade(ItemInfo& laraItem) player.Control.Weapon.HasFired = true; short itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto& grenadeItem = g_Level.Items[itemNumber]; @@ -733,7 +733,7 @@ void FireGrenade(ItemInfo& laraItem) grenadeItem.Animation.Velocity.z = GRENADE_VELOCITY; grenadeItem.Animation.ActiveState = grenadeItem.Pose.Orientation.x; grenadeItem.Animation.TargetState = grenadeItem.Pose.Orientation.y; - grenadeItem.Animation.RequiredState = NO_STATE; + grenadeItem.Animation.RequiredState = NO_VALUE; grenadeItem.HitPoints = GRENADE_TIME; grenadeItem.ItemFlags[0] = (int)WeaponAmmoType::Ammo2; @@ -783,7 +783,7 @@ void GrenadeControl(short itemNumber) if (grenadeItem.Animation.Velocity.z) { grenadeItem.Pose.Orientation.z += (short((grenadeItem.Animation.Velocity.z / 16) + 3.0f) * ANGLE(1.0f)); - if (grenadeItem.Animation.RequiredState != NO_STATE) + if (grenadeItem.Animation.RequiredState != NO_VALUE) { grenadeItem.Pose.Orientation.y += (short((grenadeItem.Animation.Velocity.z / 4) + 3.0f) * ANGLE(1.0f)); } @@ -801,7 +801,7 @@ void GrenadeControl(short itemNumber) if (grenadeItem.Animation.Velocity.z) { grenadeItem.Pose.Orientation.z += (short((grenadeItem.Animation.Velocity.z / 4) + 7.0f) * ANGLE(1.0f)); - if (grenadeItem.Animation.RequiredState != NO_STATE) + if (grenadeItem.Animation.RequiredState != NO_VALUE) { grenadeItem.Pose.Orientation.y += (short((grenadeItem.Animation.Velocity.z / 2) + 7.0f) * ANGLE(1.0f)); } @@ -865,7 +865,7 @@ void FireRocket(ItemInfo& laraItem) player.Control.Weapon.HasFired = true; short itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto& rocketItem = g_Level.Items[itemNumber]; @@ -1004,7 +1004,7 @@ void FireCrossbow(ItemInfo& laraItem, const std::optional& pose) player.Control.Weapon.HasFired = true; short itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto& boltItem = g_Level.Items[itemNumber]; @@ -1383,7 +1383,7 @@ bool EmitFromProjectile(ItemInfo& projectile, ProjectileType type) { // Trigger a new fragment in the case of GRENADE_SUPER until itemFlags[1] is > 0. int grenadeItemNumber = CreateItem(); - if (grenadeItemNumber == NO_ITEM) + if (grenadeItemNumber == NO_VALUE) return true; auto& grenadeItem = g_Level.Items[grenadeItemNumber]; @@ -1406,7 +1406,7 @@ bool EmitFromProjectile(ItemInfo& projectile, ProjectileType type) grenadeItem.Animation.Velocity.z = 64.0f; grenadeItem.Animation.ActiveState = grenadeItem.Pose.Orientation.x; grenadeItem.Animation.TargetState = grenadeItem.Pose.Orientation.y; - grenadeItem.Animation.RequiredState = NO_STATE; + grenadeItem.Animation.RequiredState = NO_VALUE; AddActiveItem(grenadeItemNumber); @@ -1558,42 +1558,34 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p } // Found possible collided items and statics. - GetCollidedObjects(&projectile, radius, true, &CollidedItems[0], &CollidedMeshes[0], false); - - // If no collided items and meshes are found, exit the loop. - if (!CollidedItems[0] && !CollidedMeshes[0]) + auto collObjects = GetCollidedObjects(projectile, true, false, radius); + if (collObjects.IsEmpty()) break; - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + // Run through statics. + for (auto* staticPtr : collObjects.StaticPtrs) { - auto* meshPtr = CollidedMeshes[i]; - if (!meshPtr) - break; - hasHit = hasHitNotByEmitter = doShatter = true; doExplosion = isExplosive; - if (StaticObjects[meshPtr->staticNumber].shatterType == ShatterType::None) + if (StaticObjects[staticPtr->staticNumber].shatterType == ShatterType::None) continue; - meshPtr->HitPoints -= damage; - if (meshPtr->HitPoints <= 0) - ShatterObject(nullptr, meshPtr, -128, projectile.RoomNumber, 0); + staticPtr->HitPoints -= damage; + if (staticPtr->HitPoints <= 0) + ShatterObject(nullptr, staticPtr, -128, projectile.RoomNumber, 0); if (!isExplosive) continue; - TriggerExplosionSparks(meshPtr->pos.Position.x, meshPtr->pos.Position.y, meshPtr->pos.Position.z, 3, -2, 0, projectile.RoomNumber); - auto pose = Pose(meshPtr->pos.Position.x, meshPtr->pos.Position.y - 128, meshPtr->pos.Position.z, 0, meshPtr->pos.Orientation.y, 0); + TriggerExplosionSparks(staticPtr->pos.Position.x, staticPtr->pos.Position.y, staticPtr->pos.Position.z, 3, -2, 0, projectile.RoomNumber); + auto pose = Pose(staticPtr->pos.Position.x, staticPtr->pos.Position.y - 128, staticPtr->pos.Position.z, 0, staticPtr->pos.Orientation.y, 0); TriggerShockwave(&pose, 40, 176, 64, 0, 96, 128, 16, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); } - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + // Run through items. + for (auto* itemPtr : collObjects.ItemPtrs) { - auto* itemPtr = CollidedItems[i]; - if (itemPtr == nullptr) - break; -# // Object was already affected by collision, skip it. if (std::find(affectedObjects.begin(), affectedObjects.end(), itemPtr->Index) != affectedObjects.end()) continue; @@ -1656,7 +1648,7 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p SmashObject(itemPtr->Index); KillItem(itemPtr->Index); } - else if (currentObject.collision && !(itemPtr->Status & ITEM_INVISIBLE)) + else if (currentObject.collision && itemPtr->Status != ITEM_INVISIBLE) { doShatter = hasHit = true; doExplosion = isExplosive; diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index 9915346a5..4af8eee62 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -133,7 +133,7 @@ short FindBridge(int tiltGrade, short orient, Vector3i& pos, int* returnHeight, } } - return NO_ITEM; + return NO_VALUE; } // Get the signed difference between two orientations. diff --git a/TombEngine/Game/Lara/lara_struct.h b/TombEngine/Game/Lara/lara_struct.h index fdaaf8354..fa21dd987 100644 --- a/TombEngine/Game/Lara/lara_struct.h +++ b/TombEngine/Game/Lara/lara_struct.h @@ -1360,7 +1360,7 @@ struct LaraInfo int HitFrame = 0; // Frame index. int HitDirection = 0; // Cardinal direction. - // Item number? Only ever set to NO_ITEM or 1. Probably anim object ID. Might not be needed since AnimObjectID is kept in item.Animation. + // Item number? Only ever set to NO_VALUE or 1. Probably anim object ID. Might not be needed since AnimObjectID is kept in item.Animation. int ExtraAnim = 0; signed char Location = 0; diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index d8412059b..4612b0217 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -926,7 +926,7 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) return false; int frontFloor = coll->Front.Floor + LARA_HEIGHT_TREAD; - if (coll->Front.Bridge == NO_ITEM && + if (coll->Front.Bridge == NO_VALUE && (frontFloor <= -CLICK(2) || frontFloor > CLICK(1.25f) - 4)) { @@ -934,7 +934,7 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) } // Extra bridge check. - if (coll->Front.Bridge != NO_ITEM) + if (coll->Front.Bridge != NO_VALUE) { int bridgeBorder = GetBridgeBorder(g_Level.Items[coll->Front.Bridge], false) - item->Pose.Position.y; @@ -994,7 +994,7 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) SetAnimation(item, LA_ONWATER_TO_STAND_0_STEP); } - if (coll->Front.Bridge == NO_ITEM) + if (coll->Front.Bridge == NO_VALUE) UpdateLaraRoom(item, -LARA_HEIGHT / 2); else UpdateLaraRoom(item, -LARA_HEIGHT); @@ -1776,8 +1776,8 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl bool atLeastOnePoleCollided = false; - if (GetCollidedObjects(item, BLOCK(1), true, CollidedItems, nullptr, false) && - CollidedItems[0] != nullptr) + auto collObjects = GetCollidedObjects(*item, true, false, BLOCK(1), ObjectCollectionMode::Items); + if (!collObjects.IsEmpty()) { auto laraBox = GameBoundingBox(item).ToBoundingOrientedBox(item->Pose); @@ -1795,16 +1795,12 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl //g_Renderer.AddDebugSphere(sphere.Center, 16.0f, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); - int i = 0; - while (CollidedItems[i] != nullptr) + for (const auto* itemPtr : collObjects.ItemPtrs) { - auto*& object = CollidedItems[i]; - i++; - - if (object->ObjectNumber != ID_POLEROPE) + if (itemPtr->ObjectNumber != ID_POLEROPE) continue; - auto poleBox = GameBoundingBox(object).ToBoundingOrientedBox(object->Pose); + auto poleBox = GameBoundingBox(itemPtr).ToBoundingOrientedBox(itemPtr->Pose); poleBox.Extents = poleBox.Extents + Vector3(coll->Setup.Radius, 0.0f, coll->Setup.Radius); //g_Renderer.AddDebugBox(poleBox, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats); diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp index 3eb0b4a1e..a427dfe71 100644 --- a/TombEngine/Game/Setup.cpp +++ b/TombEngine/Game/Setup.cpp @@ -20,6 +20,7 @@ #include "Objects/Generic/Traps/falling_block.h" #include "Objects/TR1/tr1_objects.h" #include "Objects/TR2/tr2_objects.h" +#include "Objects/TR3/Entity/FishSwarm.h" #include "Objects/TR3/tr3_objects.h" #include "Objects/TR4/tr4_objects.h" #include "Objects/TR5/tr5_objects.h" @@ -153,6 +154,7 @@ void InitializeSpecialEffects() NextBlood = 0; TEN::Entities::TR4::ClearBeetleSwarm(); + TEN::Entities::Creatures::TR3::ClearFishSwarm(); } void CustomObjects() @@ -187,7 +189,7 @@ void InitializeObjects() obj->usingDrawAnimatingItem = true; obj->damageType = DamageMode::Any; obj->LotType = LotType::Basic; - obj->meshSwapSlot = NO_ITEM; + obj->meshSwapSlot = NO_VALUE; obj->isPickup = false; obj->isPuzzleHole = false; } diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index b9380fef5..68bdfeb36 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -190,7 +190,7 @@ void AnimateItem(ItemInfo* item) if (!item->IsLara()) { if (item->Animation.RequiredState == item->Animation.ActiveState) - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; } } @@ -212,7 +212,7 @@ void AnimateItem(ItemInfo* item) } if (item->Animation.RequiredState == item->Animation.ActiveState) - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; } else { @@ -229,7 +229,7 @@ void AnimateItem(ItemInfo* item) if (!item->IsLara()) { if (item->Animation.RequiredState == item->Animation.ActiveState) - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; }*/ } @@ -322,7 +322,7 @@ bool HasStateDispatch(const ItemInfo* item, int targetState) if (anim.NumStateDispatches <= 0) return false; - if (targetState == NO_STATE) + if (targetState == NO_VALUE) targetState = item->Animation.TargetState; // Iterate over animation's state dispatches. @@ -360,7 +360,7 @@ bool TestLastFrame(ItemInfo* item, int animNumber) { const auto& object = Objects[item->Animation.AnimObjectID]; - if (animNumber == NO_ANIM) + if (animNumber == NO_VALUE) animNumber = item->Animation.AnimNumber - object.animIndex; // Animation to test doesn't match; return early. @@ -463,7 +463,7 @@ const AnimData& GetAnimData(const ObjectInfo& object, int animNumber) const AnimData& GetAnimData(const ItemInfo& item, int animNumber) { - if (animNumber == NO_ANIM) + if (animNumber == NO_VALUE) return GetAnimData(item.Animation.AnimNumber); const auto& object = Objects[item.Animation.AnimObjectID]; diff --git a/TombEngine/Game/animation.h b/TombEngine/Game/animation.h index 2e0c7798d..7cf2fc000 100644 --- a/TombEngine/Game/animation.h +++ b/TombEngine/Game/animation.h @@ -16,9 +16,6 @@ struct ObjectInfo; // animNumber: Relative animation number. // animIndex: Index of animation in giant g_Level.Anims vector. -constexpr auto NO_STATE = -1; -constexpr auto NO_ANIM = -1; - enum class AnimCommandType { None, @@ -39,7 +36,7 @@ struct AnimFrame struct StateDispatchData { - int TargetState = NO_STATE; + int TargetState = NO_VALUE; int NumberRanges = 0; int RangeIndex = 0; }; @@ -48,8 +45,8 @@ struct StateDispatchRangeData { int StartFrame = 0; // g_Level.Frames base index. int EndFrame = 0; // g_Level.Frames end index. - int LinkAnimNum = NO_ANIM; // g_Level.Anims index. - int LinkFrameNum = NO_ANIM; // g_Level.Frames index. + int LinkAnimNum = NO_VALUE; // g_Level.Anims index. + int LinkFrameNum = NO_VALUE; // g_Level.Frames index. }; struct AnimData @@ -65,7 +62,7 @@ struct AnimData int frameBase = 0; // g_Level.Frames base index. int frameEnd = 0; // g_Level.Frames end index. - int JumpAnimNum = NO_ANIM; // g_Level.Anims index. + int JumpAnimNum = NO_VALUE; // g_Level.Anims index. int JumpFrameNum = 0; // g_Level.Frames index. int NumStateDispatches = 0; int StateDispatchIndex = 0; @@ -98,9 +95,9 @@ struct BoneMutator void AnimateItem(ItemInfo* item); // Inquirers -bool HasStateDispatch(const ItemInfo* item, int targetState = NO_STATE); +bool HasStateDispatch(const ItemInfo* item, int targetState = NO_VALUE); bool TestAnimNumber(const ItemInfo& item, int animNumber); -bool TestLastFrame(ItemInfo* item, int animNumber = NO_ANIM); +bool TestLastFrame(ItemInfo* item, int animNumber = NO_VALUE); bool TestAnimFrame(const ItemInfo& item, int frameStart); bool TestAnimFrameRange(const ItemInfo& item, int frameStart, int frameEnd); @@ -118,8 +115,8 @@ void SetAnimation(ItemInfo* item, int animNumber, int frameNumber = 0); // Depre const AnimData& GetAnimData(int animIndex); // Deprecated. const AnimData& GetAnimData(GAME_OBJECT_ID objectID, int animNumber); const AnimData& GetAnimData(const ObjectInfo& object, int animNumber); -const AnimData& GetAnimData(const ItemInfo& item, int animNumber = NO_ANIM); -const AnimData& GetAnimData(const ItemInfo* item, int animNumber = NO_ANIM); // Deprecated. +const AnimData& GetAnimData(const ItemInfo& item, int animNumber = NO_VALUE); +const AnimData& GetAnimData(const ItemInfo* item, int animNumber = NO_VALUE); // Deprecated. AnimFrameInterpData GetFrameInterpData(const ItemInfo& item); const AnimFrame& GetAnimFrame(const ItemInfo& item, int animNumber, int frameNumber); diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index db80021a7..19312969d 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -116,7 +116,7 @@ namespace TEN::Collision::Point return *_floorNormal; // Set floor normal. - if (GetFloorBridgeItemNumber() != NO_ITEM) + if (GetFloorBridgeItemNumber() != NO_VALUE) { _floorNormal = GetBridgeNormal(true); } @@ -134,7 +134,7 @@ namespace TEN::Collision::Point return *_ceilingNormal; // Set ceiling normal. - if (GetCeilingBridgeItemNumber() != NO_ITEM) + if (GetCeilingBridgeItemNumber() != NO_VALUE) { _ceilingNormal = GetBridgeNormal(false); } @@ -214,7 +214,7 @@ namespace TEN::Collision::Point bool PointCollisionData::IsIllegalFloor() { short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); - short illegalSlopeAngle = (GetFloorBridgeItemNumber() != NO_ITEM) ? + short illegalSlopeAngle = (GetFloorBridgeItemNumber() != NO_VALUE) ? DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE : GetBottomSector().GetSurfaceIllegalSlopeAngle(_position.x, _position.z, true); @@ -224,7 +224,7 @@ namespace TEN::Collision::Point bool PointCollisionData::IsIllegalCeiling() { short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); - short illegalSlopeAngle = (GetCeilingBridgeItemNumber() != NO_ITEM) ? + short illegalSlopeAngle = (GetCeilingBridgeItemNumber() != NO_VALUE) ? DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE : GetTopSector().GetSurfaceIllegalSlopeAngle(_position.x, _position.z, false); diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index b212b96a8..fc699db00 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -27,12 +27,11 @@ using namespace TEN::Collision::Point; using namespace TEN::Math; using namespace TEN::Renderer; -GameBoundingBox GlobalCollisionBounds; -ItemInfo* CollidedItems[MAX_COLLIDED_OBJECTS]; -MESH_INFO* CollidedMeshes[MAX_COLLIDED_OBJECTS]; - constexpr auto ANIMATED_ALIGNMENT_FRAME_COUNT_THRESHOLD = 6; +// Globals +GameBoundingBox GlobalCollisionBounds; + void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) { auto* item = &g_Level.Items[itemNumber]; @@ -104,174 +103,162 @@ void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionIn } } -bool GetCollidedObjects(ItemInfo* collidingItem, int radius, bool onlyVisible, ItemInfo** collidedItems, MESH_INFO** collidedMeshes, bool ignoreLara) +CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, bool ignorePlayer, float customRadius, ObjectCollectionMode mode) { - short numItems = 0; - short numMeshes = 0; + constexpr auto EXTENTS_LENGTH_MIN = 2.0f; + constexpr auto ROUGH_BOX_HEIGHT_MIN = BLOCK(1 / 8.0f); - // Collect all the rooms where to check - for (auto i : g_Level.Rooms[collidingItem->RoomNumber].neighbors) + auto collObjects = CollidedObjectData{}; + + int itemCount = 0; + int staticCount = 0; + + // Establish parameters of colliding item. + const auto& collidingBounds = GetBestFrame(collidingItem).BoundingBox; + auto collidingExtents = collidingBounds.GetExtents(); + auto collidingSphere = BoundingSphere(collidingBounds.GetCenter() + collidingItem.Pose.Position.ToVector3(), collidingExtents.Length()); + auto collidingCircle = Vector3(collidingSphere.Center.x, collidingSphere.Center.z, (customRadius > 0.0f) ? customRadius : std::hypot(collidingExtents.x, collidingExtents.z)); + + // Quickly discard collision if colliding item bounds are below tolerance threshold. + if (collidingSphere.Radius <= EXTENTS_LENGTH_MIN) + return collObjects; + + // Run through neighboring rooms. + const auto& room = g_Level.Rooms[collidingItem.RoomNumber]; + for (int roomNumber : room.neighbors) { - if (!g_Level.Rooms[i].Active()) + auto& neighborRoom = g_Level.Rooms[roomNumber]; + if (!neighborRoom.Active()) continue; - auto* room = &g_Level.Rooms[i]; - - if (collidedMeshes) + // Collect items. + if (mode == ObjectCollectionMode::All || + mode == ObjectCollectionMode::Items) { - for (int j = 0; j < room->mesh.size(); j++) - { - auto* mesh = &room->mesh[j]; - const auto& bBox = GetBoundsAccurate(*mesh, false); - - if (!(mesh->flags & StaticMeshFlags::SM_VISIBLE)) - continue; - - if ((collidingItem->Pose.Position.y + radius + CLICK(0.5f)) < (mesh->pos.Position.y + bBox.Y1)) - continue; - - if (collidingItem->Pose.Position.y > (mesh->pos.Position.y + bBox.Y2)) - continue; - - float sinY = phd_sin(mesh->pos.Orientation.y); - float cosY = phd_cos(mesh->pos.Orientation.y); - - float rx = ((collidingItem->Pose.Position.x - mesh->pos.Position.x) * cosY) - ((collidingItem->Pose.Position.z - mesh->pos.Position.z) * sinY); - float rz = ((collidingItem->Pose.Position.z - mesh->pos.Position.z) * cosY) + ((collidingItem->Pose.Position.x - mesh->pos.Position.x) * sinY); - - if ((radius + rx + CLICK(0.5f) < bBox.X1) || (rx - radius - CLICK(0.5f) > bBox.X2)) - continue; - - if ((radius + rz + CLICK(0.5f) < bBox.Z1) || (rz - radius - CLICK(0.5f) > bBox.Z2)) - continue; - - collidedMeshes[numMeshes++] = mesh; - - if (!radius) - { - collidedItems[0] = nullptr; - return true; - } - } - - collidedMeshes[numMeshes] = nullptr; - } - - if (collidedItems) - { - int itemNumber = room->itemNumber; - if (itemNumber != NO_ITEM) + int itemNumber = neighborRoom.itemNumber; + if (itemNumber != NO_VALUE) { do { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; + const auto& object = Objects[item.ObjectNumber]; - if (item == collidingItem || - (ignoreLara && item->ObjectNumber == ID_LARA) || - (onlyVisible && item->Status == ITEM_INVISIBLE) || - item->Flags & IFLAG_KILLED || - item->MeshBits == NO_JOINT_BITS || - (Objects[item->ObjectNumber].drawRoutine == nullptr && item->ObjectNumber != ID_LARA) || - (Objects[item->ObjectNumber].collision == nullptr && item->ObjectNumber != ID_LARA)) + itemNumber = item.NextItem; + + // Ignore player (if applicable). + if (ignorePlayer && item.IsLara()) + continue; + + // Ignore invisible item (if applicable). + if (onlyVisible && item.Status == ITEM_INVISIBLE) + continue; + + // Ignore items not feasible for collision. + if (item.Index == collidingItem.Index || + item.Flags & IFLAG_KILLED || item.MeshBits == NO_JOINT_BITS || + (object.drawRoutine == nullptr && !item.IsLara()) || + (object.collision == nullptr && !item.IsLara())) { - itemNumber = item->NextItem; continue; } - // TODO: This is awful and we need a better system. - if (item->ObjectNumber == ID_UPV && item->HitPoints == 1) + // HACK: Ignore UPV and big gun. + if ((item.ObjectNumber == ID_UPV || item.ObjectNumber == ID_BIGGUN) && item.HitPoints == 1) + continue; + + // Test rough distance to discard objects more than 6 blocks away. + float dist = Vector3i::Distance(item.Pose.Position, collidingItem.Pose.Position); + if (dist > COLLISION_CHECK_DISTANCE) + continue; + + const auto& bounds = GetBestFrame(item).BoundingBox; + auto extents = bounds.GetExtents(); + + // If item bounding box extents is below tolerance threshold, discard object. + if (extents.Length() <= EXTENTS_LENGTH_MIN) + continue; + + // Test rough vertical distance to discard objects not intersecting vertically. + if (((collidingItem.Pose.Position.y + collidingBounds.Y1) - ROUGH_BOX_HEIGHT_MIN) > + ((item.Pose.Position.y + bounds.Y2) + ROUGH_BOX_HEIGHT_MIN)) { - itemNumber = item->NextItem; continue; } - if (item->ObjectNumber == ID_BIGGUN && item->HitPoints == 1) + if (((collidingItem.Pose.Position.y + collidingBounds.Y2) + ROUGH_BOX_HEIGHT_MIN) < + ((item.Pose.Position.y + bounds.Y1) - ROUGH_BOX_HEIGHT_MIN)) { - itemNumber = item->NextItem; continue; } - int dx = collidingItem->Pose.Position.x - item->Pose.Position.x; - int dy = collidingItem->Pose.Position.y - item->Pose.Position.y; - int dz = collidingItem->Pose.Position.z - item->Pose.Position.z; + // Test rough circle intersection to discard objects not intersecting horizontally. + auto circle = Vector3(item.Pose.Position.x, item.Pose.Position.z, std::hypot(extents.x, extents.z)); + if (!Geometry::CircleIntersects(circle, collidingCircle)) + continue; - auto bounds = GetBestFrame(*item).BoundingBox; + auto box0 = bounds.ToBoundingOrientedBox(item.Pose); + auto box1 = collidingBounds.ToBoundingOrientedBox(collidingItem.Pose); - if (dx >= -BLOCK(2) && dx <= BLOCK(2) && - dy >= -BLOCK(2) && dy <= BLOCK(2) && - dz >= -BLOCK(2) && dz <= BLOCK(2) && - (collidingItem->Pose.Position.y + radius + CLICK(0.5f)) >= (item->Pose.Position.y + bounds.Y1) && - (collidingItem->Pose.Position.y - radius - CLICK(0.5f)) <= (item->Pose.Position.y + bounds.Y2)) - { - float sinY = phd_sin(item->Pose.Orientation.y); - float cosY = phd_cos(item->Pose.Orientation.y); + // Override extents if specified. + if (customRadius > 0.0f) + box1.Extents = Vector3(customRadius); - int rx = (dx * cosY) - (dz * sinY); - int rz = (dz * cosY) + (dx * sinY); - - // TODO: Modify asset to avoid hardcoded bounds change. -- Sezz 2023.04.30 - if (item->ObjectNumber == ID_TURN_SWITCH) - { - bounds.X1 = -CLICK(1); - bounds.X2 = CLICK(1); - bounds.Z1 = -CLICK(1); - bounds.Z1 = CLICK(1); - } - - if ((radius + rx + CLICK(0.5f)) >= bounds.X1 && - (rx - radius - CLICK(0.5f)) <= bounds.X2) - { - if ((radius + rz + CLICK(0.5f)) >= bounds.Z1 && - (rz - radius - CLICK(0.5f)) <= bounds.Z2) - { - collidedItems[numItems++] = item; - } - } - else - { - if ((collidingItem->Pose.Position.y + radius + CLICK(0.5f)) >= (item->Pose.Position.y + bounds.Y1) && - (collidingItem->Pose.Position.y - radius - CLICK(0.5f)) <= (item->Pose.Position.y + bounds.Y2)) - { - float sinY = phd_sin(item->Pose.Orientation.y); - float cosY = phd_cos(item->Pose.Orientation.y); - - int rx = (dx * cosY) - (dz * sinY); - int rz = (dz * cosY) + (dx * sinY); - - // TODO: Modify asset to avoid hardcoded bounds change. -- Sezz 2023.04.30 - if (item->ObjectNumber == ID_TURN_SWITCH) - { - bounds.X1 = -CLICK(1); - bounds.X2 = CLICK(1); - bounds.Z1 = -CLICK(1); - bounds.Z1 = CLICK(1); - } - - if ((radius + rx + CLICK(0.5f)) >= bounds.X1 && - (rx - radius - CLICK(0.5f)) <= bounds.X2) - { - if ((radius + rz + CLICK(0.5f)) >= bounds.Z1 && - (rz - radius - CLICK(0.5f)) <= bounds.Z2) - { - collidedItems[numItems++] = item; - - if (!radius) - return true; - } - } - } - } - } - - itemNumber = item->NextItem; + // Test accurate box intersection. + if (box0.Intersects(box1)) + collObjects.ItemPtrs.push_back(&item); } - while (itemNumber != NO_ITEM); + while (itemNumber != NO_VALUE); } + } - collidedItems[numItems] = nullptr; + // Collect statics. + if (mode == ObjectCollectionMode::All || + mode == ObjectCollectionMode::Statics) + { + for (auto& staticObj : neighborRoom.mesh) + { + // Discard invisible statics. + if (!(staticObj.flags & StaticMeshFlags::SM_VISIBLE)) + continue; + + // Test rough distance to discard statics beyond collision check threshold. + float dist = Vector3i::Distance(staticObj.pos.Position, collidingItem.Pose.Position); + if (dist > COLLISION_CHECK_DISTANCE) + continue; + + const auto& bounds = GetBoundsAccurate(staticObj, false); + + // Test rough vertical distance to discard statics not intersecting vertically. + if (((collidingItem.Pose.Position.y + collidingBounds.Y1) - ROUGH_BOX_HEIGHT_MIN) > + ((staticObj.pos.Position.y + bounds.Y2) + ROUGH_BOX_HEIGHT_MIN)) + { + continue; + } + if (((collidingItem.Pose.Position.y + collidingBounds.Y2) + ROUGH_BOX_HEIGHT_MIN) < + ((staticObj.pos.Position.y + bounds.Y1) - ROUGH_BOX_HEIGHT_MIN)) + { + continue; + } + + // Test rough circle intersection to discard statics not intersecting horizontally. + auto circle = Vector3(staticObj.pos.Position.x, staticObj.pos.Position.z, (bounds.GetExtents() * Vector3(1.0f, 0.0f, 1.0f)).Length()); + if (!Geometry::CircleIntersects(circle, collidingCircle)) + continue; + + auto box0 = bounds.ToBoundingOrientedBox(staticObj.pos.Position); + auto box1 = collidingBounds.ToBoundingOrientedBox(collidingItem.Pose); + + // Override extents if specified. + if (customRadius > 0.0f) + box1.Extents = Vector3(customRadius); + + // Test accurate box intersection. + if (box0.Intersects(box1)) + collObjects.StaticPtrs.push_back(&staticObj); + } } } - return (numItems || numMeshes); + return collObjects; } bool TestWithGlobalCollisionBounds(ItemInfo* item, ItemInfo* laraItem, CollisionInfo* coll) @@ -328,7 +315,7 @@ void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll) continue; int itemNumber = g_Level.Rooms[i].itemNumber; - while (itemNumber != NO_ITEM) + while (itemNumber != NO_VALUE) { auto* item2 = &g_Level.Items[itemNumber]; auto* object = &Objects[item2->ObjectNumber]; @@ -905,8 +892,7 @@ void ItemPushBridge(ItemInfo& item, CollisionInfo& coll) void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, PointCollisionData& pointColl) { // Store offset for bridge item into shifts if it exists. - if (coll.LastBridgeItemNumber == pointColl.GetFloorBridgeItemNumber() && - coll.LastBridgeItemNumber != NO_ITEM) + if (coll.LastBridgeItemNumber == pointColl.GetFloorBridgeItemNumber() && coll.LastBridgeItemNumber != NO_VALUE) { auto& bridgeItem = g_Level.Items[pointColl.GetFloorBridgeItemNumber()]; @@ -945,7 +931,7 @@ void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, PointCollisionData& else { coll.LastBridgeItemPose = Pose::Zero; - coll.LastBridgeItemNumber = NO_ITEM; + coll.LastBridgeItemNumber = NO_VALUE; } coll.LastBridgeItemNumber = pointColl.GetFloorBridgeItemNumber(); @@ -1831,7 +1817,7 @@ void DoObjectCollision(ItemInfo* item, CollisionInfo* coll) continue; int nextItemNumber = neighborRoom.itemNumber; - while (nextItemNumber != NO_ITEM) + while (nextItemNumber != NO_VALUE) { auto& linkItem = g_Level.Items[nextItemNumber]; int itemNumber = nextItemNumber; diff --git a/TombEngine/Game/collision/collide_item.h b/TombEngine/Game/collision/collide_item.h index ee9d6a8b6..5bd91e997 100644 --- a/TombEngine/Game/collision/collide_item.h +++ b/TombEngine/Game/collision/collide_item.h @@ -1,23 +1,26 @@ #pragma once +#include "Game/collision/Point.h" #include "Math/Math.h" -namespace TEN::Collision::Point { class PointCollisionData; }; +using namespace TEN::Collision::Point; + class FloorInfo; struct CollisionInfo; struct CollisionResult; struct ItemInfo; struct MESH_INFO; -using namespace TEN::Collision::Point; - -constexpr auto MAX_COLLIDED_OBJECTS = 1024; -constexpr auto ITEM_RADIUS_YMAX = BLOCK(3); - +constexpr auto ITEM_RADIUS_YMAX = BLOCK(3); constexpr auto VEHICLE_COLLISION_TERMINAL_VELOCITY = 30.0f; extern GameBoundingBox GlobalCollisionBounds; -extern ItemInfo* CollidedItems[MAX_COLLIDED_OBJECTS]; -extern MESH_INFO* CollidedMeshes[MAX_COLLIDED_OBJECTS]; + +enum class ObjectCollectionMode +{ + All, + Items, + Statics +}; struct ObjectCollisionBounds { @@ -25,8 +28,16 @@ struct ObjectCollisionBounds std::pair OrientConstraint = {}; }; +struct CollidedObjectData +{ + std::vector ItemPtrs = {}; + std::vector StaticPtrs = {}; + + bool IsEmpty() const { return (ItemPtrs.empty() && StaticPtrs.empty()); }; +}; + void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); -bool GetCollidedObjects(ItemInfo* collidingItem, int radius, bool onlyVisible, ItemInfo** collidedItems, MESH_INFO** collidedMeshes, bool ignoreLara); +CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, bool ignorePlayer, float customRadius = 0.0f, ObjectCollectionMode mode = ObjectCollectionMode::All); bool TestWithGlobalCollisionBounds(ItemInfo* item, ItemInfo* laraItem, CollisionInfo* coll); void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index ce25ae013..438c8fa7c 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -121,7 +121,7 @@ bool TestItemRoomCollisionAABB(ItemInfo* item) return collided; } -static CollisionPositionData GetCollisionPositionData(PointCollisionData& pointColl) +static CollisionPositionData GetCollisionPosition(PointCollisionData& pointColl) { auto collPos = CollisionPositionData{}; collPos.Floor = pointColl.GetFloorHeight(); @@ -327,7 +327,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->Middle = GetCollisionPositionData(pointColl); + coll->Middle = GetCollisionPosition(pointColl); coll->Middle.Floor = height; coll->Middle.Ceiling = ceiling; @@ -370,7 +370,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->Front = GetCollisionPositionData(pointColl); + coll->Front = GetCollisionPosition(pointColl); coll->Front.Floor = height; coll->Front.Ceiling = ceiling; @@ -418,7 +418,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->MiddleLeft = GetCollisionPositionData(pointColl); + coll->MiddleLeft = GetCollisionPosition(pointColl); coll->MiddleLeft.Floor = height; coll->MiddleLeft.Ceiling = ceiling; @@ -449,7 +449,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->FrontLeft = GetCollisionPositionData(pointColl); + coll->FrontLeft = GetCollisionPosition(pointColl); coll->FrontLeft.Floor = height; coll->FrontLeft.Ceiling = ceiling; @@ -484,7 +484,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->MiddleRight = GetCollisionPositionData(pointColl); + coll->MiddleRight = GetCollisionPosition(pointColl); coll->MiddleRight.Floor = height; coll->MiddleRight.Ceiling = ceiling; @@ -514,7 +514,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse if (ceiling != NO_HEIGHT) ceiling -= probePos.y; - coll->FrontRight = GetCollisionPositionData(pointColl); + coll->FrontRight = GetCollisionPosition(pointColl); coll->FrontRight.Floor = height; coll->FrontRight.Ceiling = ceiling; diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 8d02233e0..2bc77b462 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -318,7 +318,7 @@ int FloorInfo::GetInsideBridgeItemNumber(const Vector3i& pos, bool testFloorBord } // 2) No bridge intersection; return invalid item number. - return NO_ITEM; + return NO_VALUE; } void FloorInfo::AddBridge(int itemNumber) @@ -512,7 +512,7 @@ namespace TEN::Collision::Floordata sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z); } } - while (sectorPtr->GetInsideBridgeItemNumber(pos, isBottom, !isBottom) != NO_ITEM); + while (sectorPtr->GetInsideBridgeItemNumber(pos, isBottom, !isBottom) != NO_VALUE); return FarthestHeightData{ *sectorPtr, pos.y }; } @@ -558,7 +558,7 @@ namespace TEN::Collision::Floordata bool testCeilBorder = (pos.y == floorHeight); int insideBridgeItemNumber = sectorPtr->GetInsideBridgeItemNumber(pos, testFloorBorder, testCeilBorder); - if (insideBridgeItemNumber != NO_ITEM) + if (insideBridgeItemNumber != NO_VALUE) { if (isFloor ? (polarity <= 0) : (polarity >= 0)) { @@ -616,7 +616,7 @@ namespace TEN::Collision::Floordata bool testCeilBorder = (location.Height == floorHeight); int insideBridgeItemNumber = sectorPtr->GetInsideBridgeItemNumber(Vector3i(pos.x, location.Height, pos.z), testFloorBorder, testCeilBorder); - if (insideBridgeItemNumber != NO_ITEM) + if (insideBridgeItemNumber != NO_VALUE) { auto heightData = GetFarthestHeightData(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), isBottom); if (!heightData.has_value()) diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 90778ecf5..f4e6a43ca 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -52,7 +52,7 @@ constexpr auto FRAME_PRIO_EXP = 1.5; void DrawBox(int boxIndex, Vector3 color) { - if (boxIndex == NO_BOX) + if (boxIndex == NO_VALUE) return; auto& currBox = g_Level.Boxes[boxIndex]; @@ -75,7 +75,7 @@ void DrawBox(int boxIndex, Vector3 color) void DrawNearbyPathfinding(int boxIndex) { - if (boxIndex == NO_BOX) + if (boxIndex == NO_VALUE) return; auto& currBox = g_Level.Boxes[boxIndex]; @@ -156,13 +156,13 @@ bool SameZone(CreatureInfo* creature, ItemInfo* target) auto& roomSource = g_Level.Rooms[item.RoomNumber]; auto& boxSource = GetSector(&roomSource, item.Pose.Position.x - roomSource.x, item.Pose.Position.z - roomSource.z)->Box; - if (boxSource == NO_BOX) + if (boxSource == NO_VALUE) return false; item.BoxNumber = boxSource; auto& roomTarget = g_Level.Rooms[target->RoomNumber]; auto& boxTarget = GetSector(&roomTarget, target->Pose.Position.x - roomTarget.x, target->Pose.Position.z - roomTarget.z)->Box; - if (boxTarget == NO_BOX) + if (boxTarget == NO_VALUE) return false; target->BoxNumber = boxTarget; @@ -208,7 +208,7 @@ void AlertNearbyGuards(ItemInfo* item) for (int i = 0; i < ActiveCreatures.size(); i++) { auto* currentCreature = ActiveCreatures[i]; - if (currentCreature->ItemNumber == NO_ITEM) + if (currentCreature->ItemNumber == NO_VALUE) continue; auto* currentTarget = &g_Level.Items[currentCreature->ItemNumber + i]; @@ -233,7 +233,7 @@ void AlertAllGuards(short itemNumber) for (int i = 0; i < ActiveCreatures.size(); i++) { auto* creature = ActiveCreatures[i]; - if (creature->ItemNumber == NO_ITEM) + if (creature->ItemNumber == NO_VALUE) continue; auto* target = &g_Level.Items[creature->ItemNumber]; @@ -256,7 +256,7 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) int* zone = g_Level.Zones[(int)LOT->Zone][(int)FlipStatus].data(); int boxHeight; - if (item->BoxNumber != NO_BOX) + if (item->BoxNumber != NO_VALUE) boxHeight = g_Level.Boxes[item->BoxNumber].height; else boxHeight = item->Floor; @@ -267,7 +267,7 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) GetFloor(prevPos.x, y, prevPos.z, &roomNumber); auto* floor = GetFloor(item->Pose.Position.x, y, item->Pose.Position.z, &roomNumber); - if (floor->Box == NO_BOX) + if (floor->Box == NO_VALUE) return false; int height = g_Level.Boxes[floor->Box].height; @@ -285,13 +285,13 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) nextBox = floor->Box; } - if (nextBox == NO_BOX) + if (nextBox == NO_VALUE) nextHeight = height; else nextHeight = g_Level.Boxes[nextBox].height; - if (floor->Box == NO_BOX || !LOT->IsJumping && - (LOT->Fly == NO_FLYING && item->BoxNumber != NO_BOX && zone[item->BoxNumber] != zone[floor->Box] || + if (floor->Box == NO_VALUE || !LOT->IsJumping && + (LOT->Fly == NO_FLYING && item->BoxNumber != NO_VALUE && zone[item->BoxNumber] != zone[floor->Box] || boxHeight - height > LOT->Step || boxHeight - height < LOT->Drop)) { @@ -323,7 +323,7 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) nextBox = floor->Box; } - if (nextBox == NO_BOX) + if (nextBox == NO_VALUE) nextHeight = height; else nextHeight = g_Level.Boxes[nextBox].height; @@ -857,7 +857,7 @@ void CreatureDie(int itemNumber, bool doExplosion, int flags) bool BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumber, LOTInfo* LOT) { auto* floor = GetFloor(x, y, z, &roomNumber); - if (floor->Box == NO_BOX) + if (floor->Box == NO_VALUE) return true; if (LOT->IsJumping) @@ -912,14 +912,14 @@ int CreatureCreature(short itemNumber) } link = linked->NextItem; - } while (link != NO_ITEM); + } while (link != NO_VALUE); return 0; } bool ValidBox(ItemInfo* item, short zoneNumber, short boxNumber) { - if (boxNumber == NO_BOX) + if (boxNumber == NO_VALUE) return false; const auto& creature = *GetCreatureInfo(item); @@ -945,7 +945,7 @@ bool ValidBox(ItemInfo* item, short zoneNumber, short boxNumber) bool EscapeBox(ItemInfo* item, ItemInfo* enemy, int boxNumber) { - if (boxNumber == NO_BOX) + if (boxNumber == NO_VALUE) return false; const auto& box = g_Level.Boxes[boxNumber]; @@ -964,7 +964,7 @@ bool EscapeBox(ItemInfo* item, ItemInfo* enemy, int boxNumber) void TargetBox(LOTInfo* LOT, int boxNumber) { - if (boxNumber == NO_BOX) + if (boxNumber == NO_VALUE) return; auto* box = &g_Level.Boxes[boxNumber]; @@ -981,23 +981,23 @@ void TargetBox(LOTInfo* LOT, int boxNumber) bool UpdateLOT(LOTInfo* LOT, int depth) { - if (LOT->RequiredBox != NO_BOX && LOT->RequiredBox != LOT->TargetBox) + if (LOT->RequiredBox != NO_VALUE && LOT->RequiredBox != LOT->TargetBox) { LOT->TargetBox = LOT->RequiredBox; auto* node = &LOT->Node[LOT->RequiredBox]; - if (node->nextExpansion == NO_BOX && LOT->Tail != LOT->RequiredBox) + if (node->nextExpansion == NO_VALUE && LOT->Tail != LOT->RequiredBox) { node->nextExpansion = LOT->Head; - if (LOT->Head == NO_BOX) + if (LOT->Head == NO_VALUE) LOT->Tail = LOT->TargetBox; LOT->Head = LOT->TargetBox; } node->searchNumber = ++LOT->SearchNumber; - node->exitBox = NO_BOX; + node->exitBox = NO_VALUE; } return SearchLOT(LOT, depth); @@ -1010,9 +1010,9 @@ bool SearchLOT(LOTInfo* LOT, int depth) for (int i = 0; i < depth; i++) { - if (LOT->Head == NO_BOX) + if (LOT->Head == NO_VALUE) { - LOT->Tail = NO_BOX; + LOT->Tail = NO_VALUE; return false; } @@ -1068,7 +1068,7 @@ bool SearchLOT(LOTInfo* LOT, int depth) } } - if (expand->nextExpansion == NO_BOX && boxNumber != LOT->Tail) + if (expand->nextExpansion == NO_VALUE && boxNumber != LOT->Tail) { LOT->Node[LOT->Tail].nextExpansion = boxNumber; LOT->Tail = boxNumber; @@ -1077,7 +1077,7 @@ bool SearchLOT(LOTInfo* LOT, int depth) } LOT->Head = node->nextExpansion; - node->nextExpansion = NO_BOX; + node->nextExpansion = NO_VALUE; } return true; @@ -1143,7 +1143,7 @@ void InitializeCreature(short itemNumber) bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber) { - if (enemy == nullptr || boxNumber == NO_BOX) + if (enemy == nullptr || boxNumber == NO_VALUE) return false; auto* box = &g_Level.Boxes[boxNumber]; @@ -1305,7 +1305,7 @@ void GetAITarget(CreatureInfo* creature) if (enemy) enemyObjectNumber = enemy->ObjectNumber; else - enemyObjectNumber = NO_ITEM; + enemyObjectNumber = NO_VALUE; auto* item = &g_Level.Items[creature->ItemNumber]; @@ -1397,7 +1397,7 @@ void GetAITarget(CreatureInfo* creature) item->AIBits &= ~FOLLOW; } } - /*else if (item->objectNumber == ID_MONKEY && item->carriedItem == NO_ITEM) + /*else if (item->objectNumber == ID_MONKEY && item->carriedItem == NO_VALUE) { if (item->aiBits != MODIFY) { @@ -1465,7 +1465,7 @@ void FindAITargetObject(CreatureInfo* creature, int objectNumber, int ocb, bool room = &g_Level.Rooms[aiObject.roomNumber]; aiObject.boxNumber = GetSector(room, aiObject.pos.Position.x - room->x, aiObject.pos.Position.z - room->z)->Box; - if (item.BoxNumber == NO_BOX || aiObject.boxNumber == NO_BOX) + if (item.BoxNumber == NO_VALUE || aiObject.boxNumber == NO_VALUE) return; if (checkSameZone && (zone[item.BoxNumber] != zone[aiObject.boxNumber])) @@ -1524,7 +1524,7 @@ int TargetReachable(ItemInfo* item, ItemInfo* enemy) isReachable = abs(enemy->Pose.Position.y - pointColl.GetFloorHeight()) < bounds.GetHeight(); } - return (isReachable ? floor->Box : NO_BOX); + return (isReachable ? floor->Box : NO_VALUE); } void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) @@ -1550,15 +1550,15 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) AI->zoneNumber = zone[item->BoxNumber]; enemy->BoxNumber = TargetReachable(item, enemy); - AI->enemyZone = enemy->BoxNumber == NO_BOX ? NO_ZONE : zone[enemy->BoxNumber]; + AI->enemyZone = enemy->BoxNumber == NO_VALUE ? NO_VALUE : zone[enemy->BoxNumber]; if (!object->nonLot) { - if (enemy->BoxNumber != NO_BOX && g_Level.Boxes[enemy->BoxNumber].flags & creature->LOT.BlockMask) + if (enemy->BoxNumber != NO_VALUE && g_Level.Boxes[enemy->BoxNumber].flags & creature->LOT.BlockMask) { AI->enemyZone |= BLOCKED; } - else if (item->BoxNumber != NO_BOX && + else if (item->BoxNumber != NO_VALUE && creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH)) { AI->enemyZone |= BLOCKED; @@ -1645,7 +1645,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) TargetBox(LOT, boxNumber); creature->Mood = MoodType::Bored; } - else if (LOT->RequiredBox == NO_BOX) + else if (LOT->RequiredBox == NO_VALUE) { TargetBox(LOT, boxNumber); } @@ -1668,7 +1668,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) case MoodType::Escape: boxNumber = LOT->Node[GetRandomControl() * LOT->ZoneCount >> 15].boxNumber; - if (ValidBox(item, AI->zoneNumber, boxNumber) && LOT->RequiredBox == NO_BOX) + if (ValidBox(item, AI->zoneNumber, boxNumber) && LOT->RequiredBox == NO_VALUE) { if (EscapeBox(item, enemy, boxNumber)) { @@ -1684,7 +1684,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) break; case MoodType::Stalk: - if (LOT->RequiredBox == NO_BOX || !StalkBox(item, enemy, LOT->RequiredBox)) + if (LOT->RequiredBox == NO_VALUE || !StalkBox(item, enemy, LOT->RequiredBox)) { boxNumber = LOT->Node[GetRandomControl() * LOT->ZoneCount >> 15].boxNumber; if (ValidBox(item, AI->zoneNumber, boxNumber)) @@ -1693,7 +1693,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) { TargetBox(LOT, boxNumber); } - else if (LOT->RequiredBox == NO_BOX) + else if (LOT->RequiredBox == NO_VALUE) { TargetBox(LOT, boxNumber); if (AI->zoneNumber != AI->enemyZone) @@ -1705,7 +1705,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) break; } - if (LOT->TargetBox == NO_BOX) + if (LOT->TargetBox == NO_VALUE) TargetBox(LOT, item->BoxNumber); #ifdef CREATURE_AI_PRIORITY_OPTIMIZATION @@ -1749,10 +1749,10 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) creature->JumpAhead = false; creature->MonkeySwingAhead = false; - if (item->BoxNumber != NO_BOX) + if (item->BoxNumber != NO_VALUE) { int endBox = LOT->Node[item->BoxNumber].exitBox; - if (endBox != NO_BOX) + if (endBox != NO_VALUE) { int overlapIndex = g_Level.Boxes[item->BoxNumber].overlapIndex; int nextBox = 0; @@ -1764,7 +1764,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) { nextBox = g_Level.Overlaps[overlapIndex].box; flags = g_Level.Overlaps[overlapIndex++].flags; - } while (nextBox != NO_BOX && ((flags & BOX_END_BIT) == false) && (nextBox != endBox)); + } while (nextBox != NO_VALUE && ((flags & BOX_END_BIT) == false) && (nextBox != endBox)); } if (nextBox == endBox) @@ -1788,15 +1788,15 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) auto* enemy = creature->Enemy; auto* LOT = &creature->LOT; - if (item->BoxNumber == NO_BOX || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH)) - creature->LOT.RequiredBox = NO_BOX; + if (item->BoxNumber == NO_VALUE || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH)) + creature->LOT.RequiredBox = NO_VALUE; - if (creature->Mood != MoodType::Attack && creature->LOT.RequiredBox != NO_BOX && !ValidBox(item, AI->zoneNumber, creature->LOT.TargetBox)) + if (creature->Mood != MoodType::Attack && creature->LOT.RequiredBox != NO_VALUE && !ValidBox(item, AI->zoneNumber, creature->LOT.TargetBox)) { if (AI->zoneNumber == AI->enemyZone) creature->Mood = MoodType::Bored; - creature->LOT.RequiredBox = NO_BOX; + creature->LOT.RequiredBox = NO_VALUE; } auto mood = creature->Mood; @@ -1848,7 +1848,7 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) else if (AI->zoneNumber == AI->enemyZone) { if (AI->distance < ATTACK_RANGE || - (creature->Mood == MoodType::Stalk && LOT->RequiredBox == NO_BOX)) + (creature->Mood == MoodType::Stalk && LOT->RequiredBox == NO_VALUE)) creature->Mood = MoodType::Attack; else creature->Mood = MoodType::Stalk; @@ -1887,7 +1887,7 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) LOT = &creature->LOT; } - LOT->RequiredBox = NO_BOX; + LOT->RequiredBox = NO_VALUE; } } @@ -1898,7 +1898,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) *target = item->Pose.Position; int boxNumber = item->BoxNumber; - if (boxNumber == NO_BOX) + if (boxNumber == NO_VALUE) return TARGET_TYPE::NO_TARGET; auto* box = &g_Level.Boxes[boxNumber]; @@ -2096,9 +2096,9 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) } boxNumber = LOT->Node[boxNumber].exitBox; - if (boxNumber != NO_BOX && (g_Level.Boxes[boxNumber].flags & LOT->BlockMask)) + if (boxNumber != NO_VALUE && (g_Level.Boxes[boxNumber].flags & LOT->BlockMask)) break; - } while (boxNumber != NO_BOX); + } while (boxNumber != NO_VALUE); if (!(direction & SECONDARY_CLIP)) { @@ -2157,7 +2157,7 @@ void InitializeItemBoxData() continue; auto* floor = &room.floor[index]; - if (floor->Box == NO_BOX) + if (floor->Box == NO_VALUE) continue; if (!(g_Level.Boxes[floor->Box].flags & BLOCKED)) diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 98e26ca1e..50ceb5142 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -60,8 +60,6 @@ constexpr auto BLOCKABLE = 0x8000; constexpr auto BLOCKED = 0x4000; constexpr auto SEARCH_NUMBER = 0x7FFF; constexpr auto BLOCKED_SEARCH = 0x8000; -constexpr auto NO_BOX = -1; -constexpr auto NO_ZONE = -1; constexpr auto BOX_JUMP = 0x800; constexpr auto BOX_MONKEY = 0x2000; constexpr auto BOX_END_BIT = 0x8000; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index dc5f26866..f1a133a6d 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -44,6 +44,7 @@ #include "Objects/Generic/Object/objects.h" #include "Objects/Generic/Object/rope.h" #include "Objects/Generic/Switches/generic_switch.h" +#include "Objects/TR3/Entity/FishSwarm.h" #include "Objects/TR4/Entity/tr4_beetle_swarm.h" #include "Objects/TR5/Emitter/tr5_bats_emitter.h" #include "Objects/TR5/Emitter/tr5_rats_emitter.h" @@ -85,6 +86,7 @@ using namespace TEN::Input; using namespace TEN::Math; using namespace TEN::Renderer; using namespace TEN::Traps::TR5; +using namespace TEN::Entities::Creatures::TR3; int GameTimer = 0; int GlobalCounter = 0; @@ -232,6 +234,7 @@ GameStatus ControlPhase(int numFrames) UpdateExplosionParticles(); UpdateShockwaves(); UpdateBeetleSwarm(); + UpdateFishSwarm(); UpdateLocusts(); UpdateUnderwaterBloodParticles(); @@ -498,8 +501,8 @@ void DeInitializeScripting(int levelIndex, GameStatus reason) void InitializeOrLoadGame(bool loadGame) { - g_Gui.SetInventoryItemChosen(NO_ITEM); - g_Gui.SetEnterInventory(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); + g_Gui.SetEnterInventory(NO_VALUE); // Restore the game? if (loadGame) @@ -659,7 +662,7 @@ GameStatus HandleMenuCalls(bool isTitle) if (g_Gui.CallPause()) result = GameStatus::ExitToTitle; } - else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_ITEM) && + else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_VALUE) && LaraItem->HitPoints > 0 && !Lara.Control.Look.IsUsingBinoculars) { if (g_Gui.CallInventory(LaraItem, true)) diff --git a/TombEngine/Game/control/flipeffect.cpp b/TombEngine/Game/control/flipeffect.cpp index 32e5a683b..b128351a8 100644 --- a/TombEngine/Game/control/flipeffect.cpp +++ b/TombEngine/Game/control/flipeffect.cpp @@ -18,14 +18,17 @@ #include "Sound/sound.h" #include "Specific/level.h" #include "Objects/Generic/puzzles_keys.h" +#include "Objects/TR3/Entity/FishSwarm.h" #include "Objects/TR4/Entity/tr4_beetle_swarm.h" #include "Objects/TR5/Emitter/tr5_spider_emitter.h" #include "Objects/TR5/Emitter/tr5_rats_emitter.h" #include "Objects/Effects/tr4_locusts.h" + using namespace TEN::Effects::Environment; using namespace TEN::Effects::Footprint; using namespace TEN::Effects::Hair; +using namespace TEN::Entities::Creatures::TR3; int FlipEffect; @@ -86,6 +89,7 @@ void ClearSwarmEnemies(ItemInfo* item) ClearRats(); ClearBeetleSwarm(); ClearLocusts(); + ClearFishSwarm(); } void FlashOrange(ItemInfo* item) @@ -203,7 +207,7 @@ void LaraHandsFree(ItemInfo* item) void KillActiveBaddys(ItemInfo* item) { - if (NextItemActive != NO_ITEM) + if (NextItemActive != NO_VALUE) { short itemNumber = NextItemActive; @@ -224,7 +228,7 @@ void KillActiveBaddys(ItemInfo* item) } itemNumber = targetItem->NextActive; - } while (itemNumber != NO_ITEM); + } while (itemNumber != NO_VALUE); } FlipEffect = -1; diff --git a/TombEngine/Game/control/los.cpp b/TombEngine/Game/control/los.cpp index 870b12262..2c0ea4ec6 100644 --- a/TombEngine/Game/control/los.cpp +++ b/TombEngine/Game/control/los.cpp @@ -326,7 +326,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo int num = GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); auto ray = Ray(origin->ToVector3(), dir); float bestDistance = INFINITY; - int bestJointIndex = NO_JOINT; + int bestJointIndex = NO_VALUE; for (int i = 0; i < num; i++) { @@ -361,11 +361,11 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo const auto& weapon = Weapons[(int)Lara.Control.Weapon.GunType]; if (object->HitRoutine != nullptr) { - object->HitRoutine(*item, *LaraItem, target2, weapon.Damage, false, NO_JOINT); + object->HitRoutine(*item, *LaraItem, target2, weapon.Damage, false, NO_VALUE); } else { - DefaultItemHit(*item, *LaraItem, target2, weapon.Damage, false, NO_JOINT); + DefaultItemHit(*item, *LaraItem, target2, weapon.Damage, false, NO_VALUE); } } } @@ -668,7 +668,7 @@ int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INF } } - for (short linkNumber = room.itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem) + for (short linkNumber = room.itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) { const auto& item = g_Level.Items[linkNumber]; diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 9f125f49d..01dc1f065 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -51,7 +51,7 @@ void DisableEntityAI(short itemNumber) return; auto* creature = GetCreatureInfo(item); - creature->ItemNumber = NO_ITEM; + creature->ItemNumber = NO_VALUE; KillItem(creature->AITargetNumber); ActiveCreatures.erase(std::find(ActiveCreatures.begin(), ActiveCreatures.end(), creature)); item->Data = nullptr; @@ -90,13 +90,13 @@ void InitializeSlot(short itemNumber, bool makeTarget) creature->LOT.IsMonkeying = false; creature->LOT.Fly = NO_FLYING; creature->LOT.BlockMask = BLOCKED; - creature->AITargetNumber = NO_ITEM; + creature->AITargetNumber = NO_VALUE; creature->AITarget = nullptr; if (makeTarget) { creature->AITargetNumber = CreateItem(); - if (creature->AITargetNumber != NO_ITEM) + if (creature->AITargetNumber != NO_VALUE) creature->AITarget = &g_Level.Items[creature->AITargetNumber]; } @@ -212,7 +212,7 @@ void SetEntityTarget(short itemNum, short target) creature->AITargetNumber = target; - if (creature->AITargetNumber != NO_ITEM) + if (creature->AITargetNumber != NO_VALUE) creature->AITarget = &g_Level.Items[creature->AITargetNumber]; else creature->AITarget = nullptr; @@ -220,17 +220,17 @@ void SetEntityTarget(short itemNum, short target) void ClearLOT(LOTInfo* LOT) { - LOT->Head = NO_BOX; - LOT->Tail = NO_BOX; + LOT->Head = NO_VALUE; + LOT->Tail = NO_VALUE; LOT->SearchNumber = 0; - LOT->TargetBox = NO_BOX; - LOT->RequiredBox = NO_BOX; + LOT->TargetBox = NO_VALUE; + LOT->RequiredBox = NO_VALUE; auto* node = LOT->Node.data(); for (auto& node : LOT->Node) { - node.exitBox = NO_BOX; - node.nextExpansion = NO_BOX; + node.exitBox = NO_VALUE; + node.nextExpansion = NO_VALUE; node.searchNumber = 0; } } diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 0fc94666b..d34c99d97 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -308,15 +308,15 @@ void RefreshCamera(short type, short* data) if (!targetOk || (targetOk == 2 && Camera.item->LookedAt && Camera.item != Camera.lastItem)) Camera.item = nullptr; - if (Camera.number == -1 && Camera.timer > 0) - Camera.timer = -1; + if (Camera.number == NO_VALUE && Camera.timer > 0) + Camera.timer = NO_VALUE; } short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z) { const auto& bottomSector = GetPointCollision(Vector3i(x, y, z), floor->RoomNumber).GetBottomSector(); - if (bottomSector.TriggerIndex == -1) + if (bottomSector.TriggerIndex == NO_VALUE) return nullptr; return &g_Level.FloorData[bottomSector.TriggerIndex]; @@ -324,7 +324,7 @@ short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z) short* GetTriggerIndex(ItemInfo* item) { - auto roomNumber = item->RoomNumber; + short roomNumber = item->RoomNumber; auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); return GetTriggerIndex(floor, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); } @@ -823,7 +823,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags) { - auto roomNumber = item->RoomNumber; + short roomNumber = item->RoomNumber; auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, isHeavy, heavyFlags); @@ -844,36 +844,42 @@ void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFl void ProcessSectorFlags(ItemInfo* item) { auto pointColl = GetPointCollision(*item); - auto* sectorPtr = &GetPointCollision(*item).GetBottomSector(); + auto& sector = GetPointCollision(*item).GetBottomSector(); bool isPlayer = item->IsLara(); - // Monkeyswing and climb (only for Lara) + // Set monkeyswing and wall climb statuses for player. if (isPlayer) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - // Set climb status - if (TestLaraNearClimbableWall(item, sectorPtr)) - lara->Control.CanClimbLadder = true; + // Set wall climb status. + if (TestLaraNearClimbableWall(item, §or)) + { + player.Control.CanClimbLadder = true; + } else - lara->Control.CanClimbLadder = false; + { + player.Control.CanClimbLadder = false; + } - // Set monkeyswing status - lara->Control.CanMonkeySwing = sectorPtr->Flags.Monkeyswing; + // Set monkey swing status. + player.Control.CanMonkeySwing = sector.Flags.Monkeyswing; } - // Burn or drown item - if (sectorPtr->Flags.Death && item->Pose.Position.y == item->Floor) + // Burn or drown item. + if (sector.Flags.Death && item->Pose.Position.y == item->Floor && pointColl.GetFloorBridgeItemNumber() == NO_VALUE) { if (isPlayer) { + const auto& player = GetLaraInfo(*item); + if (!IsJumpState((LaraState)item->Animation.ActiveState) || - GetLaraInfo(item)->Control.WaterStatus != WaterStatus::Dry) + player.Control.WaterStatus != WaterStatus::Dry) { - // To allow both lava and rapids in same level, also check floor material flag. - if (sectorPtr->GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true) == MaterialType::Water && - Objects[ID_KAYAK_LARA_ANIMS].loaded) + // Check floor material. + auto material = sector.GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true); + if (material == MaterialType::Water && Objects[ID_KAYAK_LARA_ANIMS].loaded) // HACK: Allow both lava and rapids in same level. { KayakLaraRapidsDrown(item); } @@ -885,10 +891,11 @@ void ProcessSectorFlags(ItemInfo* item) } else if (Objects[item->ObjectNumber].intelligent && item->HitPoints != NOT_TARGETABLE) { - if (sectorPtr->GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true) == MaterialType::Water || - TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, sectorPtr->RoomNumber)) + auto material = sector.GetSurfaceMaterial(pointColl.GetPosition().x, pointColl.GetPosition().z, true); + if (material == MaterialType::Water || TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, sector.RoomNumber)) { - DoDamage(item, INT_MAX); // TODO: Implement correct rapids behaviour for other objects! + // TODO: Implement correct rapids behaviour for other objects. + DoDamage(item, INT_MAX); } else { diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 8d0cea30b..2d128dc87 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -1212,7 +1212,7 @@ void ExplodingDeath(short itemNumber, short flags) if (i == 0 || ((GetRandomControl() & 3) != 0 && (flags & BODY_DO_EXPLOSION))) { short fxNumber = CreateNewEffect(item->RoomNumber); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { FX_INFO* fx = &EffectList[fxNumber]; diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 4895796be..06635e097 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -1547,7 +1547,7 @@ namespace TEN::Gui Rings[(int)RingTypes::Inventory].NumObjectsInList = 0; for (int i = 0; i < INVENTORY_TABLE_SIZE; i++) - Rings[(int)RingTypes::Inventory].CurrentObjectList[i].InventoryItem = NO_ITEM; + Rings[(int)RingTypes::Inventory].CurrentObjectList[i].InventoryItem = NO_VALUE; Ammo.CurrentPistolsAmmoType = 0; Ammo.CurrentUziAmmoType = 0; @@ -1783,7 +1783,7 @@ namespace TEN::Gui Rings[(int)RingTypes::Ammo].NumObjectsInList = 0; for (int i = 0; i < INVENTORY_TABLE_SIZE; i++) - Rings[(int)RingTypes::Ammo].CurrentObjectList[i].InventoryItem = NO_ITEM; + Rings[(int)RingTypes::Ammo].CurrentObjectList[i].InventoryItem = NO_VALUE; if (!(g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young)) { @@ -1866,7 +1866,7 @@ namespace TEN::Gui { g_Gui.SetMenuToDisplay(Menu::Title); g_Gui.SetSelectedOption(0); - g_Gui.SetLastInventoryItem(NO_ITEM); + g_Gui.SetLastInventoryItem(NO_VALUE); } void GuiController::InitializeInventory(ItemInfo* item) @@ -1875,7 +1875,7 @@ namespace TEN::Gui AlterFOV(ANGLE(DEFAULT_FOV), false); lara->Inventory.IsBusy = false; - InventoryItemChosen = NO_ITEM; + InventoryItemChosen = NO_VALUE; UseItem = false; if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite()) @@ -1912,9 +1912,9 @@ namespace TEN::Gui Ammo.AmountGrenadeAmmo3 = lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo3].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo3].GetCount(); ConstructObjectList(item); - if (EnterInventory == NO_ITEM) + if (EnterInventory == NO_VALUE) { - if (LastInvItem != NO_ITEM) + if (LastInvItem != NO_VALUE) { if (IsItemInInventory(LastInvItem)) { @@ -1946,7 +1946,7 @@ namespace TEN::Gui } else { - LastInvItem = NO_ITEM; + LastInvItem = NO_VALUE; } } } @@ -3385,7 +3385,7 @@ namespace TEN::Gui if (UseItem && NoAction()) exitLoop = true; - SetEnterInventory(NO_ITEM); + SetEnterInventory(NO_VALUE); Camera.numberFrames = g_Renderer.Synchronize(); } diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 267a4fbb7..a74c65c6e 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -36,7 +36,7 @@ using namespace TEN::Input; using namespace TEN::Math; using namespace TEN::Utils; -constexpr int ITEM_DEATH_TIMEOUT = 4 * FPS; +constexpr auto ITEM_DEATH_TIMEOUT = 4 * FPS; bool ItemInfo::TestOcb(short ocbFlags) const { @@ -82,7 +82,7 @@ void ItemInfo::SetFlagField(int id, short flags) if (id < 0 || id > 7) return; - this->ItemFlags[id] = flags; + ItemFlags[id] = flags; } void ItemInfo::ClearFlags(int id, short flags) @@ -90,7 +90,7 @@ void ItemInfo::ClearFlags(int id, short flags) if (id < 0 || id > 7) return; - this->ItemFlags[id] &= ~flags; + ItemFlags[id] &= ~flags; } bool ItemInfo::TestMeshSwapFlags(unsigned int flags) @@ -109,7 +109,7 @@ bool ItemInfo::TestMeshSwapFlags(unsigned int flags) bool ItemInfo::TestMeshSwapFlags(const std::vector& flags) { - auto bits = BitField(); + auto bits = BitField::Default; bits.Set(flags); return TestMeshSwapFlags(bits.ToPackedBits()); } @@ -146,21 +146,6 @@ void ItemInfo::SetMeshSwapFlags(const std::vector& flags, bool cle SetMeshSwapFlags(bits.ToPackedBits(), clear); } -bool ItemInfo::IsLara() const -{ - return Data.is(); -} - -bool ItemInfo::IsCreature() const -{ - return Data.is(); -} - -bool ItemInfo::IsBridge() const -{ - return Contains(BRIDGE_OBJECT_IDS, ObjectNumber); -} - void ItemInfo::ResetModelToDefault() { if (Objects[ObjectNumber].nmeshes > 0) @@ -182,6 +167,21 @@ void ItemInfo::ResetModelToDefault() } } +bool ItemInfo::IsLara() const +{ + return Data.is(); +} + +bool ItemInfo::IsCreature() const +{ + return Data.is(); +} + +bool ItemInfo::IsBridge() const +{ + return Contains(BRIDGE_OBJECT_IDS, ObjectNumber); +} + bool TestState(int refState, const std::vector& stateList) { for (const auto& state : stateList) @@ -219,7 +219,7 @@ void KillItem(short const itemNumber) ItemNewRooms[2 * ItemNewRoomNo] = itemNumber | 0x8000; ItemNewRoomNo++; } - else// if (NextItemActive != NO_ITEM) + else// if (NextItemActive != NO_VALUE) { auto* item = &g_Level.Items[itemNumber]; @@ -233,7 +233,7 @@ void KillItem(short const itemNumber) else { short linkNumber; - for (linkNumber = NextItemActive; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextActive) + for (linkNumber = NextItemActive; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextActive) { if (g_Level.Items[linkNumber].NextActive == itemNumber) { @@ -252,7 +252,7 @@ void KillItem(short const itemNumber) else { short linkNumber; - for (linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem) + for (linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) { if (g_Level.Items[linkNumber].NextItem == itemNumber) { @@ -290,7 +290,7 @@ void RemoveAllItemsInRoom(short roomNumber, short objectNumber) auto* room = &g_Level.Rooms[roomNumber]; short currentItemNumber = room->itemNumber; - while (currentItemNumber != NO_ITEM) + while (currentItemNumber != NO_VALUE) { auto* item = &g_Level.Items[currentItemNumber]; @@ -410,7 +410,7 @@ void KillEffect(short fxNumber) NextFxActive = fx->nextActive; else { - for (short linkNumber = NextFxActive; linkNumber != NO_ITEM; linkNumber = EffectList[linkNumber].nextActive) + for (short linkNumber = NextFxActive; linkNumber != NO_VALUE; linkNumber = EffectList[linkNumber].nextActive) { if (EffectList[linkNumber].nextActive == fxNumber) { @@ -424,7 +424,7 @@ void KillEffect(short fxNumber) g_Level.Rooms[fx->roomNumber].fxNumber = fx->nextFx; else { - for (short linkNumber = g_Level.Rooms[fx->roomNumber].fxNumber; linkNumber != NO_ITEM; linkNumber = EffectList[linkNumber].nextFx) + for (short linkNumber = g_Level.Rooms[fx->roomNumber].fxNumber; linkNumber != NO_VALUE; linkNumber = EffectList[linkNumber].nextFx) { if (EffectList[linkNumber].nextFx == fxNumber) { @@ -441,7 +441,7 @@ void KillEffect(short fxNumber) // HACK: Garbage collect nextFx if no active effects were detected. // This fixes random crashes after spawining multiple FXs (like body part). - if (NextFxActive == NO_ITEM) + if (NextFxActive == NO_VALUE) InitializeFXArray(); } @@ -449,7 +449,7 @@ short CreateNewEffect(short roomNumber) { short fxNumber = NextFxFree; - if (NextFxFree != NO_ITEM) + if (NextFxFree != NO_VALUE) { auto* fx = &EffectList[NextFxFree]; NextFxFree = fx->nextFx; @@ -469,7 +469,7 @@ short CreateNewEffect(short roomNumber) void InitializeFXArray() { - NextFxActive = NO_ITEM; + NextFxActive = NO_VALUE; NextFxFree = 0; for (int i = 0; i < NUM_EFFECTS; i++) @@ -478,7 +478,7 @@ void InitializeFXArray() fx->nextFx = i + 1; } - EffectList[NUM_EFFECTS - 1].nextFx = NO_ITEM; + EffectList[NUM_EFFECTS - 1].nextFx = NO_VALUE; } void RemoveDrawnItem(short itemNumber) @@ -489,7 +489,7 @@ void RemoveDrawnItem(short itemNumber) g_Level.Rooms[item->RoomNumber].itemNumber = item->NextItem; else { - for (short linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem) + for (short linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) { if (g_Level.Items[linkNumber].NextItem == itemNumber) { @@ -512,7 +512,7 @@ void RemoveActiveItem(short itemNumber, bool killed) } else { - for (short linkNumber = NextItemActive; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextActive) + for (short linkNumber = NextItemActive; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextActive) { if (g_Level.Items[linkNumber].NextActive == itemNumber) { @@ -532,10 +532,10 @@ void InitializeItem(short itemNumber) auto* item = &g_Level.Items[itemNumber]; SetAnimation(item, 0); - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; item->Animation.Velocity = Vector3::Zero; - for (int i = 0; i < NUM_ITEM_FLAGS; i++) + for (int i = 0; i < ITEM_FLAG_COUNT; i++) item->ItemFlags[i] = 0; item->Active = false; @@ -596,8 +596,8 @@ void InitializeItem(short itemNumber) short CreateItem() { - if (NextItemFree == NO_ITEM) - return NO_ITEM; + if (NextItemFree == NO_VALUE) + return NO_VALUE; short itemNumber = NextItemFree; g_Level.Items[NextItemFree].Flags = 0; @@ -626,15 +626,15 @@ void InitializeItemArray(int totalItem) } } - item->NextItem = NO_ITEM; - NextItemActive = NO_ITEM; + item->NextItem = NO_VALUE; + NextItemActive = NO_VALUE; NextItemFree = g_Level.NumItems; } short SpawnItem(const ItemInfo& item, GAME_OBJECT_ID objectID) { int itemNumber = CreateItem(); - if (itemNumber != NO_ITEM) + if (itemNumber != NO_VALUE) { auto& newItem = g_Level.Items[itemNumber]; @@ -650,7 +650,7 @@ short SpawnItem(const ItemInfo& item, GAME_OBJECT_ID objectID) else { TENLog("Failed to create new item.", LogLevel::Warning); - itemNumber = NO_ITEM; + itemNumber = NO_VALUE; } return itemNumber; @@ -663,7 +663,7 @@ int GlobalItemReplace(short search, GAME_OBJECT_ID replace) { auto* room = &g_Level.Rooms[i]; - for (short itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].NextItem) + for (short itemNumber = room->itemNumber; itemNumber != NO_VALUE; itemNumber = g_Level.Items[itemNumber].NextItem) { if (g_Level.Items[itemNumber].ObjectNumber == search) { @@ -705,12 +705,12 @@ std::vector FindCreatedItems(GAME_OBJECT_ID objectID) { auto itemNumbers = std::vector{}; - if (NextItemActive == NO_ITEM) + if (NextItemActive == NO_VALUE) return itemNumbers; const auto* itemPtr = &g_Level.Items[NextItemActive]; - for (int nextActive = NextItemActive; nextActive != NO_ITEM; nextActive = itemPtr->NextActive) + for (int nextActive = NextItemActive; nextActive != NO_VALUE; nextActive = itemPtr->NextActive) { itemPtr = &g_Level.Items[nextActive]; @@ -751,7 +751,7 @@ void UpdateAllItems() InItemControlLoop = true; short itemNumber = NextItemActive; - while (itemNumber != NO_ITEM) + while (itemNumber != NO_VALUE) { auto* item = &g_Level.Items[itemNumber]; short nextItem = item->NextActive; @@ -787,7 +787,7 @@ void UpdateAllEffects() InItemControlLoop = true; short fxNumber = NextFxActive; - while (fxNumber != NO_ITEM) + while (fxNumber != NO_VALUE) { short nextFx = EffectList[fxNumber].nextActive; auto* fx = &EffectList[fxNumber]; diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index e64453681..cda9aafee 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -1,56 +1,20 @@ #pragma once -#include -#include -#include - #include "Game/animation.h" #include "Game/itemdata/itemdata.h" -#include "Objects/game_object_ids.h" #include "Math/Math.h" -#include "Specific/newtypes.h" #include "Specific/BitField.h" +#include "Objects/game_object_ids.h" +#include "Specific/newtypes.h" using namespace TEN::Utils; -constexpr auto NO_ITEM = -1; -constexpr auto NOT_TARGETABLE = -16384; +constexpr auto ITEM_COUNT_MAX = 1024; +constexpr auto ITEM_FLAG_COUNT = 8; -constexpr auto NUM_ITEMS = 1024; -constexpr auto NUM_ITEM_FLAGS = 8; +constexpr auto NOT_TARGETABLE = SHRT_MIN / 2; -constexpr unsigned int ALL_JOINT_BITS = UINT_MAX; -constexpr unsigned int NO_JOINT_BITS = 0; -constexpr int NO_JOINT = -1; - -enum AIObjectType -{ - NO_AI = 0, - GUARD = (1 << 0), - AMBUSH = (1 << 1), - PATROL1 = (1 << 2), - MODIFY = (1 << 3), - FOLLOW = (1 << 4), - PATROL2 = (1 << 5), - ALL_AIOBJ = (GUARD | AMBUSH | PATROL1 | MODIFY | FOLLOW | PATROL2) -}; - -enum ItemStatus -{ - ITEM_NOT_ACTIVE = 0, - ITEM_ACTIVE = 1, - ITEM_DEACTIVATED = 2, - ITEM_INVISIBLE = 3 -}; - -enum ItemFlags -{ - IFLAG_TRIGGERED = (1 << 5), - IFLAG_CLEAR_BODY = (1 << 7), - IFLAG_INVISIBLE = (1 << 8), - IFLAG_ACTIVATION_MASK = (0x1F << 9), // Bits 9-13 (IFLAG_CODEBITS) - IFLAG_REVERSE = (1 << 14), - IFLAG_KILLED = (1 << 15) -}; +constexpr auto ALL_JOINT_BITS = UINT_MAX; +constexpr auto NO_JOINT_BITS = 0u; enum class EffectType { @@ -63,6 +27,36 @@ enum class EffectType Custom }; +enum ItemStatus +{ + ITEM_NOT_ACTIVE = 0, + ITEM_ACTIVE = 1, + ITEM_DEACTIVATED = 2, + ITEM_INVISIBLE = 3 +}; + +enum ItemFlags +{ + IFLAG_TRIGGERED = 1 << 5, + IFLAG_CLEAR_BODY = 1 << 7, + IFLAG_INVISIBLE = 1 << 8, + IFLAG_ACTIVATION_MASK = 0x1F << 9, // Bits 9-13 (IFLAG_CODEBITS) + IFLAG_REVERSE = 1 << 14, + IFLAG_KILLED = 1 << 15 +}; + +enum AIObjectType +{ + NO_AI = 0, + GUARD = 1 << 0, + AMBUSH = 1 << 1, + PATROL1 = 1 << 2, + MODIFY = 1 << 3, + FOLLOW = 1 << 4, + PATROL2 = 1 << 5, + ALL_AIOBJ = GUARD | AMBUSH | PATROL1 | MODIFY | FOLLOW | PATROL2 +}; + struct EntityAnimationData { GAME_OBJECT_ID AnimObjectID = ID_NO_OBJECT; @@ -71,28 +65,23 @@ struct EntityAnimationData int FrameNumber = 0; // g_Level.Frames index. int ActiveState = 0; int TargetState = 0; - int RequiredState = NO_STATE; + int RequiredState = NO_VALUE; - bool IsAirborne = false; - Vector3 Velocity = Vector3::Zero; // CONVENTION: +X = Right, +Y = Down, +Z = Forward -}; + // TODO: Have 3 velocity members: + // ControlVelocity: relative velocity derived from animation. + // ExtraControlVelocity: relative velocity set by code (used to control swimming, falling). + // ExternalVelocity: absolute velocity set by environment (slippery ice, offset blending). + Vector3 Velocity = Vector3::Zero; // CONVENTION: +X = Right, +Y = Down, +Z = Forward. -struct EntityModelData -{ - int BaseMesh = 0; - - Vector4 Color = Vector4::Zero; - - std::vector MeshIndex = {}; - std::vector Mutators = {}; + bool IsAirborne = false; }; struct EntityCallbackData { - std::string OnKilled; - std::string OnHit; - std::string OnObjectCollided; - std::string OnRoomCollided; + std::string OnKilled = {}; + std::string OnHit = {}; + std::string OnObjectCollided = {}; + std::string OnRoomCollided = {}; }; struct EntityEffectData @@ -101,75 +90,88 @@ struct EntityEffectData Vector3 LightColor = Vector3::Zero; Vector3 PrimaryEffectColor = Vector3::Zero; Vector3 SecondaryEffectColor = Vector3::Zero; - int Count = -1; + int Count = NO_VALUE; +}; + +struct EntityModelData +{ + int BaseMesh = 0; + + std::vector MeshIndex = {}; + std::vector Mutators = {}; + + Vector4 Color = Vector4::Zero; }; -// TODO: We need to find good "default states" for a lot of these. -- squidshire 25/05/2022 struct ItemInfo { - GAME_OBJECT_ID ObjectNumber = ID_NO_OBJECT; // ObjectID std::string Name = {}; + int Index = 0; // ItemNumber // TODO: Make int. + GAME_OBJECT_ID ObjectNumber = ID_NO_OBJECT; // ObjectID - int Status; // ItemStatus enum. - bool Active; + /*ItemStatus*/int Status = ITEM_NOT_ACTIVE; + bool Active = false; - short Index; - short NextItem; - short NextActive; + // TODO: Refactor linked list. + int NextItem = 0; + int NextActive = 0; - ItemData Data; - EntityAnimationData Animation; - EntityCallbackData Callbacks; - EntityModelData Model; - EntityEffectData Effect; - - Pose StartPose; - Pose Pose; - RoomVector Location; - short RoomNumber; - int Floor; + ItemData Data = {}; + EntityAnimationData Animation = {}; + EntityCallbackData Callbacks = {}; + EntityEffectData Effect = {}; + EntityModelData Model = {}; - int HitPoints; - bool HitStatus; - bool LookedAt; - bool Collidable; - bool InDrawRoom; + Pose StartPose = Pose::Zero; + Pose Pose = Pose::Zero; + RoomVector Location = {}; // NOTE: Describes vertical position in room. + short RoomNumber = 0; // TODO: Make int. + int Floor = 0; - int BoxNumber; - int Timer; + int HitPoints = 0; + bool HitStatus = false; + bool LookedAt = false; + bool Collidable = false; + bool InDrawRoom = false; - BitField TouchBits = BitField::Default; - BitField MeshBits = BitField::Default; + int BoxNumber = 0; + int Timer = 0; - unsigned short Flags; // ItemFlags enum - short ItemFlags[NUM_ITEM_FLAGS]; - short TriggerFlags; + BitField TouchBits = BitField::Default; // TouchFlags + BitField MeshBits = BitField::Default; // MeshFlags + + std::array ItemFlags = {}; + unsigned short Flags = 0; // ItemFlags enum + short TriggerFlags = 0; // TODO: Move to CreatureInfo? - unsigned char AIBits; // AIObjectType enum. - short AfterDeath; - short CarriedItem; + unsigned char AIBits = 0; // AIObjectFlags enum. + short AfterDeath = 0; + short CarriedItem = 0; + // OCB utilities bool TestOcb(short ocbFlags) const; void RemoveOcb(short ocbFlags); void ClearAllOcb(); - + + // ItemFlags utilities bool TestFlags(int id, short flags) const; // ItemFlags[id] & flags bool TestFlagField(int id, short flags) const; // ItemFlags[id] == flags short GetFlagField(int id) const; // ItemFlags[id] void SetFlagField(int id, short flags); // ItemFlags[id] = flags void ClearFlags(int id, short flags); // ItemFlags[id] &= ~flags + // Model utilities bool TestMeshSwapFlags(unsigned int flags); bool TestMeshSwapFlags(const std::vector& flags); void SetMeshSwapFlags(unsigned int flags, bool clear = false); void SetMeshSwapFlags(const std::vector& flags, bool clear = false); + void ResetModelToDefault(); + // Inquirers bool IsLara() const; bool IsCreature() const; bool IsBridge() const; - - void ResetModelToDefault(); }; bool TestState(int refState, const std::vector& stateList); diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 1160bbbec..3f5af7186 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -2,13 +2,14 @@ #include "Game/misc.h" #include "Game/animation.h" +#include "Game/collision/Point.h" #include "Game/Lara/lara.h" #include "Game/itemdata/creature_info.h" #include "Game/items.h" #include "Game/Setup.h" #include "Specific/level.h" -using std::vector; +using namespace TEN::Collision::Point; CreatureInfo* GetCreatureInfo(ItemInfo* item) { @@ -39,3 +40,91 @@ void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature) } } } + +bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist) +{ + auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, dist); + auto pointColl = GetPointCollision(item.Pose.Position, item.RoomNumber, dir, dist); + int height = GameBoundingBox(&item).GetHeight(); + + // TODO: Use floor normal directly. + auto floorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true); + + // Test for wall. + if (pointColl.GetSector().IsWall(projectedPos.x, projectedPos.z)) + return false; + + // Test for slippery slope. + if (pointColl.IsIllegalFloor()) + return false; + + // Flat floor. + if ((abs(floorTilt.x) == 0 && abs(floorTilt.y) == 0)) + { + // Test for step. + int relFloorHeight = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); + if (relFloorHeight >= CLICK(1) && item.Pose.Position.y >= pointColl.GetFloorHeight()) + return false; + } + // Sloped floor. + else + { + // Half block. + int relFloorHeight = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); + if (relFloorHeight > CLICK(1)) + return false; + + short slopeAngle = ANGLE(0.0f); + if (floorTilt.x > 0) + { + slopeAngle = ANGLE(-90.0f); + } + else if (floorTilt.x < 0) + { + slopeAngle = ANGLE(90.0f); + } + + if (floorTilt.y > 0 && floorTilt.y > abs(floorTilt.x)) + { + slopeAngle = ANGLE(180.0f); + } + else if (floorTilt.y < 0 && -floorTilt.y > abs(floorTilt.x)) + { + slopeAngle = ANGLE(0.0f); + } + + short dirAngle = phd_atan(dir.z, dir.x); + short alignAngle = Geometry::GetShortestAngle(slopeAngle, dirAngle); + + // Test if slope aspect is aligned with direction. + if (alignAngle != 0 && alignAngle != ANGLE(180.0f)) + return false; + } + + // Check for diagonal split. + if (pointColl.IsDiagonalFloorStep()) + return false; + + // Test ceiling height. + int relCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); + + if (relCeilHeight <= height) + return false; + + // Check for blocked grey box. + if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKABLE) + { + if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKED) + return false; + } + + // Check for inaccessible sector. + if (pointColl.GetSector().Box == NO_VALUE) + return false; + + // Check for stopper flag. + if (pointColl.GetSector().Stopper) + return false; + + return true; +} \ No newline at end of file diff --git a/TombEngine/Game/misc.h b/TombEngine/Game/misc.h index 7c99542e9..ef00bf1fd 100644 --- a/TombEngine/Game/misc.h +++ b/TombEngine/Game/misc.h @@ -19,3 +19,4 @@ enum LaraMeshMask CreatureInfo* GetCreatureInfo(ItemInfo* item); void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature); +bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist); diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index bf171f0be..29739935a 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -154,7 +154,7 @@ void ControlNatlaGun(short fxNumber) } fxNumber = CreateNewEffect(pointColl.GetRoomNumber()); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { auto& fxNew = EffectList[fxNumber]; @@ -171,7 +171,7 @@ void ControlNatlaGun(short fxNumber) short ShardGun(int x, int y, int z, short velocity, short yRot, short roomNumber) { int fxNumber = CreateNewEffect(roomNumber); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { auto& fx = EffectList[fxNumber]; @@ -191,7 +191,7 @@ short ShardGun(int x, int y, int z, short velocity, short yRot, short roomNumber short BombGun(int x, int y, int z, short velocity, short yRot, short roomNumber) { int fxNumber = CreateNewEffect(roomNumber); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { auto& fx = EffectList[fxNumber]; diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index c20a0a2e3..86d2fee4b 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -201,7 +201,7 @@ void RemoveObjectFromInventory(GAME_OBJECT_ID objectID, std::optional count void CollectCarriedItems(ItemInfo* item) { short pickupNumber = item->CarriedItem; - while (pickupNumber != NO_ITEM) + while (pickupNumber != NO_VALUE) { auto* pickupItem = &g_Level.Items[pickupNumber]; @@ -212,7 +212,7 @@ void CollectCarriedItems(ItemInfo* item) pickupNumber = pickupItem->CarriedItem; } - item->CarriedItem = NO_ITEM; + item->CarriedItem = NO_VALUE; } static void HideOrDisablePickup(ItemInfo& pickupItem) @@ -231,42 +231,35 @@ static void HideOrDisablePickup(ItemInfo& pickupItem) void CollectMultiplePickups(int itemNumber) { - auto* firstItem = &g_Level.Items[itemNumber]; - GetCollidedObjects(firstItem, LARA_RADIUS, true, CollidedItems, CollidedMeshes, true); - - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + auto& firstItem = g_Level.Items[itemNumber]; + + auto collObjects = GetCollidedObjects(firstItem, true, true, LARA_RADIUS, ObjectCollectionMode::Items); + collObjects.ItemPtrs.push_back(&firstItem); + for (auto* itemPtr : collObjects.ItemPtrs) { - auto* currentItem = CollidedItems[i]; - - if (currentItem == nullptr) - currentItem = firstItem; - - if (!Objects[currentItem->ObjectNumber].isPickup) + if (!Objects[itemPtr->ObjectNumber].isPickup) continue; // HACK: Exclude flares and torches from pickup batches. - if ((currentItem->ObjectNumber == ID_FLARE_ITEM && currentItem->Active) || - currentItem->ObjectNumber == ID_BURNING_TORCH_ITEM) + if ((itemPtr->ObjectNumber == ID_FLARE_ITEM && itemPtr->Active) || + itemPtr->ObjectNumber == ID_BURNING_TORCH_ITEM) { - continue; + continue; } - PickedUpObject(currentItem->ObjectNumber); - g_Hud.PickupSummary.AddDisplayPickup(currentItem->ObjectNumber, currentItem->Pose.Position.ToVector3()); + PickedUpObject(itemPtr->ObjectNumber); + g_Hud.PickupSummary.AddDisplayPickup(itemPtr->ObjectNumber, itemPtr->Pose.Position.ToVector3()); - if (currentItem->TriggerFlags & (1 << 8)) + if (itemPtr->TriggerFlags & (1 << 8)) { for (int i = 0; i < g_Level.NumItems; i++) { - if (g_Level.Items[i].ObjectNumber == currentItem->ObjectNumber) + if (g_Level.Items[i].ObjectNumber == itemPtr->ObjectNumber) KillItem(i); } } - HideOrDisablePickup(*currentItem); - - if (currentItem == firstItem) - break; + HideOrDisablePickup(*itemPtr); } } @@ -274,7 +267,7 @@ void DoPickup(ItemInfo* laraItem) { auto* lara = GetLaraInfo(laraItem); - if (lara->Context.InteractedItem == NO_ITEM) + if (lara->Context.InteractedItem == NO_VALUE) return; short pickupItemNumber = lara->Context.InteractedItem; @@ -295,7 +288,7 @@ void DoPickup(ItemInfo* laraItem) KillItem(pickupItemNumber); pickupItem->Pose.Orientation = prevOrient; - lara->Context.InteractedItem = NO_ITEM; + lara->Context.InteractedItem = NO_VALUE; return; } else if (pickupItem->ObjectNumber == ID_FLARE_ITEM && pickupItem->Active) @@ -321,7 +314,7 @@ void DoPickup(ItemInfo* laraItem) if (g_GameFlow->IsMassPickupEnabled()) { CollectMultiplePickups(lara->Context.InteractedItem); - lara->Context.InteractedItem = NO_ITEM; + lara->Context.InteractedItem = NO_VALUE; return; } @@ -330,7 +323,7 @@ void DoPickup(ItemInfo* laraItem) HideOrDisablePickup(*pickupItem); pickupItem->Pose.Orientation = prevOrient; - lara->Context.InteractedItem = NO_ITEM; + lara->Context.InteractedItem = NO_VALUE; return; } else @@ -350,7 +343,7 @@ void DoPickup(ItemInfo* laraItem) if (g_GameFlow->IsMassPickupEnabled()) { CollectMultiplePickups(lara->Context.InteractedItem); - lara->Context.InteractedItem = NO_ITEM; + lara->Context.InteractedItem = NO_VALUE; return; } @@ -369,13 +362,13 @@ void DoPickup(ItemInfo* laraItem) HideOrDisablePickup(*pickupItem); pickupItem->Pose.Orientation = prevOrient; - lara->Context.InteractedItem = NO_ITEM; + lara->Context.InteractedItem = NO_VALUE; return; } } } - lara->Context.InteractedItem = NO_ITEM; + lara->Context.InteractedItem = NO_VALUE; } void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) @@ -457,7 +450,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) return; } - if (!IsHeld(In::Action) && (g_Gui.GetInventoryItemChosen() == NO_ITEM || triggerFlags != 2) || + if (!IsHeld(In::Action) && (g_Gui.GetInventoryItemChosen() == NO_VALUE || triggerFlags != 2) || lara->Control.Look.IsUsingLasersight || (laraItem->Animation.ActiveState != LS_IDLE || laraItem->Animation.AnimNumber != LA_STAND_IDLE || lara->Control.HandStatus != HandStatus::Free) && (laraItem->Animation.ActiveState != LS_CROUCH_IDLE || laraItem->Animation.AnimNumber != LA_CROUCH_IDLE || lara->Control.HandStatus != HandStatus::Free) && @@ -542,7 +535,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) } if (!lara->Control.IsMoving) { - if (g_Gui.GetInventoryItemChosen() == NO_ITEM) + if (g_Gui.GetInventoryItemChosen() == NO_VALUE) { if (g_Gui.IsObjectInInventory(ID_CROWBAR_ITEM)) g_Gui.SetEnterInventory(ID_CROWBAR_ITEM); @@ -557,7 +550,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) return; } - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); } if (MoveLaraPosition(CrowbarPickUpPosition, item, laraItem)) @@ -848,8 +841,7 @@ void DropPickups(ItemInfo* item) origin.y = yPos; // Initialize drop origin Y point as floor height at centerpoint, in case all corner tests fail. - // Also collect objects which are around. - bool collidedWithObjects = GetCollidedObjects(item, extents.Length(), true, CollidedItems, CollidedMeshes, true); + auto collObjects = GetCollidedObjects(*item, true, true); short startAngle = ANGLE(Random::GenerateInt(0, 3) * 90.0f); // Randomize start corner. @@ -894,26 +886,22 @@ void DropPickups(ItemInfo* item) // Iterate through all found items and statics around, and determine if dummy sphere // intersects any of those. If so, try other corner. - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + for (const auto* itemPtr : collObjects.ItemPtrs) { - auto* currentItem = CollidedItems[i]; - if (!currentItem) - break; - - if (GameBoundingBox(currentItem).ToBoundingOrientedBox(currentItem->Pose).Intersects(sphere)) + auto box = GameBoundingBox(itemPtr).ToBoundingOrientedBox(itemPtr->Pose); + if (box.Intersects(sphere)) { collidedWithObject = true; break; } } - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + for (auto* staticPtr : collObjects.StaticPtrs) { - auto* currentMesh = CollidedMeshes[i]; - if (!currentMesh) - break; + auto& object = StaticObjects[staticPtr->staticNumber]; - if (StaticObjects[currentMesh->staticNumber].collisionBox.ToBoundingOrientedBox(currentMesh->pos).Intersects(sphere)) + auto box = object.collisionBox.ToBoundingOrientedBox(staticPtr->pos); + if (box.Intersects(sphere)) { collidedWithObject = true; break; @@ -938,7 +926,7 @@ void DropPickups(ItemInfo* item) break; } - for (short pickupNumber = item->CarriedItem; pickupNumber != NO_ITEM; pickupNumber = pickup->CarriedItem) + for (short pickupNumber = item->CarriedItem; pickupNumber != NO_VALUE; pickupNumber = pickup->CarriedItem) { pickup = &g_Level.Items[pickupNumber]; pickup->Pose.Position = origin; @@ -1029,11 +1017,11 @@ const GameBoundingBox* FindPlinth(ItemInfo* item) } } - if (room->itemNumber == NO_ITEM) + if (room->itemNumber == NO_VALUE) return nullptr; short itemNumber = room->itemNumber; - for (itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].NextItem) + for (itemNumber = room->itemNumber; itemNumber != NO_VALUE; itemNumber = g_Level.Items[itemNumber].NextItem) { auto* currentItem = &g_Level.Items[itemNumber]; auto* object = &Objects[currentItem->ObjectNumber]; @@ -1048,7 +1036,7 @@ const GameBoundingBox* FindPlinth(ItemInfo* item) } } - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) { return nullptr; } @@ -1091,7 +1079,7 @@ void InitializePickup(short itemNumber) auto pointColl = GetPointCollision(*item); int bridgeItemNumber = pointColl.GetSector().GetInsideBridgeItemNumber(item->Pose.Position, true, true); - if (bridgeItemNumber != NO_ITEM) + if (bridgeItemNumber != NO_VALUE) { // If pickup is within bridge item, most likely it means it is // below pushable or raising block, so ignore its collision. @@ -1314,7 +1302,7 @@ bool UseSpecialItem(ItemInfo* laraItem) int flag = 0; int itemIDToUse = g_Gui.GetInventoryItemChosen(); - if (itemIDToUse != NO_ITEM && + if (itemIDToUse != NO_VALUE && laraItem->Animation.AnimNumber == LA_STAND_IDLE && lara->Control.HandStatus == HandStatus::Free) { @@ -1368,7 +1356,7 @@ bool UseSpecialItem(ItemInfo* laraItem) SetAnimation(laraItem, LA_WATERSKIN_POUR_LOW); lara->Control.HandStatus = HandStatus::Busy; - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); return true; } } diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index 3d2d36ac9..58c76bd49 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -39,7 +39,7 @@ bool ROOM_INFO::Active() const static void AddRoomFlipItems(const ROOM_INFO& room) { // Run through linked items. - for (int itemNumber = room.itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].NextItem) + for (int itemNumber = room.itemNumber; itemNumber != NO_VALUE; itemNumber = g_Level.Items[itemNumber].NextItem) { const auto& item = g_Level.Items[itemNumber]; const auto& object = Objects[item.ObjectNumber]; @@ -53,7 +53,7 @@ static void AddRoomFlipItems(const ROOM_INFO& room) static void RemoveRoomFlipItems(const ROOM_INFO& room) { // Run through linked items. - for (int itemNumber = room.itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].NextItem) + for (int itemNumber = room.itemNumber; itemNumber != NO_VALUE; itemNumber = g_Level.Items[itemNumber].NextItem) { const auto& item = g_Level.Items[itemNumber]; const auto& object = Objects[item.ObjectNumber]; @@ -75,6 +75,12 @@ static void RemoveRoomFlipItems(const ROOM_INFO& room) void DoFlipMap(int group) { + if (group >= MAX_FLIPMAP) + { + TENLog("Maximum flipmap group number is " + std::to_string(MAX_FLIPMAP) + ".", LogLevel::Warning); + return; + } + // Run through rooms. for (int roomNumber = 0; roomNumber < g_Level.Rooms.size(); roomNumber++) { @@ -112,13 +118,13 @@ void DoFlipMap(int group) FlipStats[group] = !FlipStats[group]; for (auto& creature : ActiveCreatures) - creature->LOT.TargetBox = NO_BOX; + creature->LOT.TargetBox = NO_VALUE; } bool IsObjectInRoom(int roomNumber, GAME_OBJECT_ID objectID) { int itemNumber = g_Level.Rooms[roomNumber].itemNumber; - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return false; while (true) @@ -129,7 +135,7 @@ bool IsObjectInRoom(int roomNumber, GAME_OBJECT_ID objectID) break; itemNumber = item.NextItem; - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return false; } diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index a8df10abf..98100796f 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -23,10 +23,12 @@ #include "Objects/Generic/Switches/fullblock_switch.h" #include "Objects/Generic/puzzles_keys.h" #include "Objects/Sink.h" +#include "Objects/TR3/Entity/FishSwarm.h" #include "Objects/TR4/Entity/tr4_beetle_swarm.h" #include "Objects/TR5/Emitter/tr5_rats_emitter.h" #include "Objects/TR5/Emitter/tr5_bats_emitter.h" #include "Objects/TR5/Emitter/tr5_spider_emitter.h" +#include "Renderer/Renderer.h" #include "Scripting/Include/ScriptInterfaceGame.h" #include "Scripting/Include/ScriptInterfaceLevel.h" #include "Scripting/Include/Objects/ScriptInterfaceObjectsHandler.h" @@ -34,13 +36,13 @@ #include "Specific/clock.h" #include "Specific/level.h" #include "Specific/savegame/flatbuffers/ten_savegame_generated.h" -#include "Renderer/Renderer.h" using namespace flatbuffers; using namespace TEN::Collision::Floordata; using namespace TEN::Control::Volumes; -using namespace TEN::Entities::Generic; using namespace TEN::Effects::Items; +using namespace TEN::Entities::Creatures::TR3; +using namespace TEN::Entities::Generic; using namespace TEN::Entities::Switches; using namespace TEN::Entities::TR4; using namespace TEN::Gui; @@ -849,6 +851,28 @@ const std::vector SaveGame::Build() } auto serializedItemsOffset = fbb.CreateVector(serializedItems); + std::vector> fishSwarm; + for (const auto& fish : FishSwarm) + { + Save::FishDataBuilder fishSave{ fbb }; + fishSave.add_is_lethal(fish.IsLethal); + fishSave.add_is_patrolling(fish.IsPatrolling); + fishSave.add_leader_item_number((fish.LeaderItemPtr == nullptr) ? -1 : fish.LeaderItemPtr->Index); + fishSave.add_life(fish.Life); + fishSave.add_mesh_index(fish.MeshIndex); + fishSave.add_orientation(&FromEulerAngles(fish.Orientation)); + fishSave.add_position(&FromVector3(fish.Position)); + fishSave.add_position_target(&FromVector3(fish.PositionTarget)); + fishSave.add_room_number(fish.RoomNumber); + fishSave.add_target_item_number((fish.TargetItemPtr == nullptr) ? -1 : fish.TargetItemPtr->Index); + fishSave.add_undulation(fish.Undulation); + fishSave.add_velocity(fish.Velocity); + + auto fishSaveOffset = fishSave.Finish(); + fishSwarm.push_back(fishSaveOffset); + } + auto fishSwarmOffset = fbb.CreateVector(fishSwarm); + // TODO: In future, we should save only active FX, not whole array. // This may come together with Monty's branch merge -- Lwmte, 10.07.22 @@ -981,7 +1005,7 @@ const std::vector SaveGame::Build() { auto& entry = currVolume.StateQueue[k]; - int activator = NO_ITEM; + int activator = NO_VALUE; if (std::holds_alternative(entry.Activator)) activator = std::get(entry.Activator); else @@ -1384,6 +1408,7 @@ const std::vector SaveGame::Build() sgb.add_next_item_free(NextItemFree); sgb.add_next_item_active(NextItemActive); sgb.add_items(serializedItemsOffset); + sgb.add_fish_swarm(fishSwarmOffset); sgb.add_fxinfos(serializedEffectsOffset); sgb.add_next_fx_free(NextFxFree); sgb.add_next_fx_active(NextFxActive); @@ -1991,6 +2016,29 @@ static void ParseEffects(const Save::SaveGame* s) PlaySoundTrack(track->name()->str(), (SoundTrackType)i, track->position()); } + // Load fish swarm. + for (int i = 0; i < s->fish_swarm()->size(); i++) + { + const auto& fishSave = s->fish_swarm()->Get(i); + auto fish = FishData{}; + + fish.IsLethal = fishSave->is_lethal(); + fish.IsPatrolling = fishSave->is_patrolling(); + fish.LeaderItemPtr = (fishSave->leader_item_number() == -1) ? nullptr : &g_Level.Items[fishSave->leader_item_number()]; + fish.Life = fishSave->life(); + fish.MeshIndex = fishSave->mesh_index(); + fish.Orientation = ToEulerAngles(fishSave->orientation()); + fish.Position = ToVector3(fishSave->position()); + fish.PositionTarget = ToVector3(fishSave->position_target()); + fish.RoomNumber = fishSave->room_number(); + fish.TargetItemPtr = (fishSave->target_item_number() == -1) ? nullptr : &g_Level.Items[fishSave->target_item_number()]; + fish.Undulation = fishSave->undulation(); + fish.Velocity = fishSave->velocity(); + + FishSwarm.push_back(fish); + } + + // Load particles. for (int i = 0; i < s->particles()->size(); i++) { auto* particleInfo = s->particles()->Get(i); @@ -2297,7 +2345,7 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) item->Active = savedItem->active(); item->HitStatus = savedItem->hit_stauts(); - item->Status = savedItem->status(); + item->Status = (ItemStatus)savedItem->status(); item->AIBits = savedItem->ai_bits(); item->Animation.IsAirborne = savedItem->is_airborne(); item->Collidable = savedItem->collidable(); diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index 49f67c4e3..36fb46751 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -9,17 +9,14 @@ #include "Game/items.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" -#include "Math/Math.h" #include "Specific/Input/Input.h" -using namespace TEN::Control::Volumes; using namespace TEN::Input; -using namespace TEN::Math; using namespace TEN::Renderer; +using namespace TEN::Control::Volumes; constexpr auto MAX_CAMERA = 18; -// Globals bool TrackCameraInit; int SpotcamTimer; bool SpotcamPaused; @@ -34,8 +31,12 @@ int SplineToCamera; int FirstCamera; int LastCamera; int CurrentCameraCnt; -Vector3i CameraPosition[MAX_CAMERA]; -Vector3i CameraPositionTarget[MAX_CAMERA]; +int CameraXposition[MAX_CAMERA]; +int CameraYposition[MAX_CAMERA]; +int CameraZposition[MAX_CAMERA]; +int CameraXtarget[MAX_CAMERA]; +int CameraYtarget[MAX_CAMERA]; +int CameraZtarget[MAX_CAMERA]; int CameraRoll[MAX_CAMERA]; int CameraFOV[MAX_CAMERA]; int CameraSpeed[MAX_CAMERA]; @@ -62,6 +63,7 @@ void ClearSpotCamSequences() SpotcamDontDrawLara = false; SpotcamOverlay = false; + for (int i = 0; i < MAX_SPOTCAMS; i++) SpotCam[i] = {}; } @@ -70,37 +72,35 @@ void InitializeSpotCamSequences(bool startFirstSequence) { TrackCameraInit = false; - int spotCamCount = NumberSpotcams; + int n = NumberSpotcams; int cc = 1; - if (spotCamCount != 0) + if (n != 0) { int ce = 0; - int sequenceID = SpotCam[0].sequence; + int s = SpotCam[0].sequence; - if (cc < spotCamCount) + if (cc < n) { - for (spotCamCount = 1; spotCamCount < NumberSpotcams; spotCamCount++) + for (n = 1; n < NumberSpotcams; n++) { // Same sequence. - if (SpotCam[spotCamCount].sequence == sequenceID) - { + if (SpotCam[n].sequence == s) cc++; - } // New sequence. else { CameraCnt[ce] = cc; cc = 1; - SpotCamRemap[sequenceID] = ce; + SpotCamRemap[s] = ce; ce++; - sequenceID = SpotCam[spotCamCount].sequence; + s = SpotCam[n].sequence; } } } CameraCnt[ce] = cc; - SpotCamRemap[sequenceID] = ce; + SpotCamRemap[s] = ce; } if (startFirstSequence) @@ -110,9 +110,9 @@ void InitializeSpotCamSequences(bool startFirstSequence) } } -void InitializeSpotCam(short sequenceID) +void InitializeSpotCam(short Sequence) { - if (TrackCameraInit != 0 && LastSpotCamSequence == sequenceID) + if (TrackCameraInit != 0 && LastSpotCamSequence == Sequence) { TrackCameraInit = false; return; @@ -131,8 +131,8 @@ void InitializeSpotCam(short sequenceID) Lara.Inventory.IsBusy = 0; - CameraFade = NO_VALUE; - LastSpotCamSequence = sequenceID; + CameraFade = -1; + LastSpotCamSequence = Sequence; TrackCameraInit = false; SpotcamTimer = 0; SpotcamPaused = false; @@ -156,10 +156,10 @@ void InitializeSpotCam(short sequenceID) LaraFixedPosition.y = LaraItem->Pose.Position.y; LaraFixedPosition.z = LaraItem->Pose.Position.z; - CurrentSpotcamSequence = sequenceID; + CurrentSpotcamSequence = Sequence; CurrentSplineCamera = 0; - for (int i = 0; i < SpotCamRemap[sequenceID]; i++) + for (int i = 0; i < SpotCamRemap[Sequence]; i++) CurrentSplineCamera += CameraCnt[i]; CurrentSplinePosition = 0; @@ -167,21 +167,25 @@ void InitializeSpotCam(short sequenceID) FirstCamera = CurrentSplineCamera; - const auto* spotCamPtr = &SpotCam[CurrentSplineCamera]; + auto* spotcam = &SpotCam[CurrentSplineCamera]; - LastCamera = CurrentSplineCamera + (CameraCnt[SpotCamRemap[sequenceID]] - 1); - CurrentCameraCnt = CameraCnt[SpotCamRemap[sequenceID]]; + LastCamera = CurrentSplineCamera + (CameraCnt[SpotCamRemap[Sequence]] - 1); + CurrentCameraCnt = CameraCnt[SpotCamRemap[Sequence]]; - if ((spotCamPtr->flags & SCF_DISABLE_LARA_CONTROLS)) + if ((spotcam->flags & SCF_DISABLE_LARA_CONTROLS)) { Lara.Control.IsLocked = true; SetCinematicBars(1.0f, SPOTCAM_CINEMATIC_BARS_SPEED); } - if (spotCamPtr->flags & SCF_TRACKING_CAM) + if (spotcam->flags & SCF_TRACKING_CAM) { - CameraPosition[1] = SpotCam[FirstCamera].Position; - CameraPositionTarget[1] = SpotCam[FirstCamera].PositionTarget; + CameraXposition[1] = SpotCam[FirstCamera].x; + CameraYposition[1] = SpotCam[FirstCamera].y; + CameraZposition[1] = SpotCam[FirstCamera].z; + CameraXtarget[1] = SpotCam[FirstCamera].tx; + CameraYtarget[1] = SpotCam[FirstCamera].ty; + CameraZtarget[1] = SpotCam[FirstCamera].tz; CameraRoll[1] = SpotCam[FirstCamera].roll; CameraFOV[1] = SpotCam[FirstCamera].fov; CameraSpeed[1] = SpotCam[FirstCamera].speed; @@ -190,20 +194,28 @@ void InitializeSpotCam(short sequenceID) if (CurrentCameraCnt > 0) { - spotCamPtr = &SpotCam[FirstCamera]; + spotcam = &SpotCam[FirstCamera]; - for (int i = 0; i < CurrentCameraCnt; i++, spotCamPtr++) + for (int i = 0; i < CurrentCameraCnt; i++, spotcam++) { - CameraPosition[i + 2] = spotCamPtr->Position; - CameraPositionTarget[i + 2] = spotCamPtr->PositionTarget; - CameraRoll[i + 2] = spotCamPtr->roll; - CameraFOV[i + 2] = spotCamPtr->fov; - CameraSpeed[i + 2] = spotCamPtr->speed; + CameraXposition[i + 2] = spotcam->x; + CameraYposition[i + 2] = spotcam->y; + CameraZposition[i + 2] = spotcam->z; + CameraXtarget[i + 2] = spotcam->tx; + CameraYtarget[i + 2] = spotcam->ty; + CameraZtarget[i + 2] = spotcam->tz; + CameraRoll[i + 2] = spotcam->roll; + CameraFOV[i + 2] = spotcam->fov; + CameraSpeed[i + 2] = spotcam->speed; } } - CameraPosition[CurrentCameraCnt + 2] = SpotCam[LastCamera].Position; - CameraPositionTarget[CurrentCameraCnt + 2] = SpotCam[LastCamera].PositionTarget; + CameraXposition[CurrentCameraCnt + 2] = SpotCam[LastCamera].x; + CameraYposition[CurrentCameraCnt + 2] = SpotCam[LastCamera].y; + CameraZposition[CurrentCameraCnt + 2] = SpotCam[LastCamera].z; + CameraXtarget[CurrentCameraCnt + 2] = SpotCam[LastCamera].tx; + CameraYtarget[CurrentCameraCnt + 2] = SpotCam[LastCamera].ty; + CameraZtarget[CurrentCameraCnt + 2] = SpotCam[LastCamera].tz; CameraFOV[CurrentCameraCnt + 2] = SpotCam[LastCamera].fov; CameraRoll[CurrentCameraCnt + 2] = SpotCam[LastCamera].roll; CameraSpeed[CurrentCameraCnt + 2] = SpotCam[LastCamera].speed; @@ -211,10 +223,14 @@ void InitializeSpotCam(short sequenceID) else { int sp = 0; - if ((spotCamPtr->flags & SCF_CUT_PAN)) + if ((spotcam->flags & SCF_CUT_PAN)) { - CameraPosition[1] = SpotCam[CurrentSplineCamera].Position; - CameraPositionTarget[1] = SpotCam[CurrentSplineCamera].PositionTarget; + CameraXposition[1] = SpotCam[CurrentSplineCamera].x; + CameraYposition[1] = SpotCam[CurrentSplineCamera].y; + CameraZposition[1] = SpotCam[CurrentSplineCamera].z; + CameraXtarget[1] = SpotCam[CurrentSplineCamera].tx; + CameraYtarget[1] = SpotCam[CurrentSplineCamera].ty; + CameraZtarget[1] = SpotCam[CurrentSplineCamera].tz; CameraRoll[1] = SpotCam[CurrentSplineCamera].roll; CameraFOV[1] = SpotCam[CurrentSplineCamera].fov; CameraSpeed[1] = SpotCam[CurrentSplineCamera].speed; @@ -227,8 +243,12 @@ void InitializeSpotCam(short sequenceID) if (LastCamera < CurrentSplineCamera) cn = FirstCamera; - CameraPosition[sp + 2] = SpotCam[cn].Position; - CameraPositionTarget[sp + 2] = SpotCam[cn].PositionTarget; + CameraXposition[sp + 2] = SpotCam[cn].x; + CameraYposition[sp + 2] = SpotCam[cn].y; + CameraZposition[sp + 2] = SpotCam[cn].z; + CameraXtarget[sp + 2] = SpotCam[cn].tx; + CameraYtarget[sp + 2] = SpotCam[cn].ty; + CameraZtarget[sp + 2] = SpotCam[cn].tz; CameraRoll[sp + 2] = SpotCam[cn].roll; CameraFOV[sp + 2] = SpotCam[cn].fov; CameraSpeed[sp + 2] = SpotCam[cn].speed; @@ -241,30 +261,42 @@ void InitializeSpotCam(short sequenceID) if (CurrentSplineCamera > LastCamera) CurrentSplineCamera = FirstCamera; - if (spotCamPtr->flags & SCF_ACTIVATE_HEAVY_TRIGGERS) + if (spotcam->flags & SCF_ACTIVATE_HEAVY_TRIGGERS) CheckTrigger = true; - if (spotCamPtr->flags & SCF_HIDE_LARA) + if (spotcam->flags & SCF_HIDE_LARA) SpotcamDontDrawLara = true; } else { int cn = CurrentSplineCamera; - CameraPosition[1] = InitialCameraPosition; - CameraPositionTarget[1] = InitialCameraTarget; + CameraXposition[1] = InitialCameraPosition.x; + CameraYposition[1] = InitialCameraPosition.y; + CameraZposition[1] = InitialCameraPosition.z; + CameraXtarget[1] = InitialCameraTarget.x; + CameraYtarget[1] = InitialCameraTarget.y; + CameraZtarget[1] = InitialCameraTarget.z; CameraFOV[1] = CurrentFOV; CameraRoll[1] = 0; - CameraSpeed[1] = spotCamPtr->speed; + CameraSpeed[1] = spotcam->speed; - CameraPosition[2] = InitialCameraPosition; - CameraPositionTarget[2] = InitialCameraTarget; + CameraXposition[2] = InitialCameraPosition.x; + CameraYposition[2] = InitialCameraPosition.y; + CameraZposition[2] = InitialCameraPosition.z; + CameraXtarget[2] = InitialCameraTarget.x; + CameraYtarget[2] = InitialCameraTarget.y; + CameraZtarget[2] = InitialCameraTarget.z; CameraFOV[2] = CurrentFOV; CameraRoll[2] = 0; - CameraSpeed[2] = spotCamPtr->speed; + CameraSpeed[2] = spotcam->speed; - CameraPosition[3] = SpotCam[CurrentSplineCamera].Position; - CameraPositionTarget[3] = SpotCam[CurrentSplineCamera].PositionTarget; + CameraXposition[3] = SpotCam[CurrentSplineCamera].x; + CameraYposition[3] = SpotCam[CurrentSplineCamera].y; + CameraZposition[3] = SpotCam[CurrentSplineCamera].z; + CameraXtarget[3] = SpotCam[CurrentSplineCamera].tx; + CameraYtarget[3] = SpotCam[CurrentSplineCamera].ty; + CameraZtarget[3] = SpotCam[CurrentSplineCamera].tz; CameraRoll[3] = SpotCam[CurrentSplineCamera].roll; CameraFOV[3] = SpotCam[CurrentSplineCamera].fov; CameraSpeed[3] = SpotCam[CurrentSplineCamera].speed; @@ -276,8 +308,13 @@ void InitializeSpotCam(short sequenceID) if (LastCamera < cn) cn = FirstCamera; - CameraPosition[4] = SpotCam[cn].Position; - CameraPositionTarget[4] = SpotCam[cn].PositionTarget; + CameraXposition[4] = SpotCam[cn].x; + CameraYposition[4] = SpotCam[cn].y; + CameraZposition[4] = SpotCam[cn].z; + + CameraXtarget[4] = SpotCam[cn].tx; + CameraYtarget[4] = SpotCam[cn].ty; + CameraZtarget[4] = SpotCam[cn].tz; CameraRoll[4] = SpotCam[cn].roll; CameraFOV[4] = SpotCam[cn].fov; @@ -285,13 +322,42 @@ void InitializeSpotCam(short sequenceID) } } - if (spotCamPtr->flags & SCF_HIDE_LARA) + if (spotcam->flags & SCF_HIDE_LARA) SpotcamDontDrawLara = true; } void CalculateSpotCameras() { - auto backup = CAMERA_INFO{}; + int cpx; // stack offset -96 + int cpy; // stack offset -92 + int cpz; // stack offset -88 + int ctx; // stack offset -84 + int cty; // stack offset -80 + int ctz; // stack offset -76 + int cspeed; // stack offset -72 + int cfov; // stack offset -68 + int croll; // stack offset -64 + SPOTCAM* s; // stack offset -60 + short spline_cnt; // $s3 + int dx; // $v1 + int dy; // $s0 + int dz; // $s1 + + //{ // line 76, offset 0x38114 + int sp; // $s2 + int cp; // $fp + int clen; // $s4 + int tlen; // $v1 + int cx; // $s1 + int cy; // $s0 + int cz; // $v0 + int lx; // stack offset -56 + int lz; // stack offset -52 + int ly; // stack offset -48 + int cn; // $s0 + + + CAMERA_INFO backup; if (Lara.Control.IsLocked) { @@ -299,21 +365,22 @@ void CalculateSpotCameras() Lara.Status.Air = LaraAir; } - auto* s = &SpotCam[FirstCamera]; - int splineCount = 4; + s = &SpotCam[FirstCamera]; + spline_cnt = 4; if (s->flags & SCF_TRACKING_CAM) - splineCount = CurrentCameraCnt + 2; + spline_cnt = CurrentCameraCnt + 2; - int cpx = Spline(CurrentSplinePosition, &CameraPosition[1].x, splineCount); - int cpy = Spline(CurrentSplinePosition, &CameraPosition[1].y, splineCount); - int cpz = Spline(CurrentSplinePosition, &CameraPosition[1].z, splineCount); - int ctx = Spline(CurrentSplinePosition, &CameraPositionTarget[1].x, splineCount); - int cty = Spline(CurrentSplinePosition, &CameraPositionTarget[1].y, splineCount); - int ctz = Spline(CurrentSplinePosition, &CameraPositionTarget[1].z, splineCount); - int cspeed = Spline(CurrentSplinePosition, &CameraSpeed[1], splineCount); - int croll = Spline(CurrentSplinePosition, &CameraRoll[1], splineCount); - int cfov = Spline(CurrentSplinePosition, &CameraFOV[1], splineCount); + //loc_37F64 + cpx = Spline(CurrentSplinePosition, &CameraXposition[1], spline_cnt); + cpy = Spline(CurrentSplinePosition, &CameraYposition[1], spline_cnt); + cpz = Spline(CurrentSplinePosition, &CameraZposition[1], spline_cnt); + ctx = Spline(CurrentSplinePosition, &CameraXtarget[1], spline_cnt); + cty = Spline(CurrentSplinePosition, &CameraYtarget[1], spline_cnt); + ctz = Spline(CurrentSplinePosition, &CameraZtarget[1], spline_cnt); + cspeed = Spline(CurrentSplinePosition, &CameraSpeed[1], spline_cnt); + croll = Spline(CurrentSplinePosition, &CameraRoll[1], spline_cnt); + cfov = Spline(CurrentSplinePosition, &CameraFOV[1], spline_cnt); if ((SpotCam[CurrentSplineCamera].flags & SCF_SCREEN_FADE_IN) && CameraFade != CurrentSplineCamera) @@ -329,17 +396,17 @@ void CalculateSpotCameras() CameraFade = CurrentSplineCamera; } - int sp = 0; - int tlen = 0; - int clen = 0; - int cp = 0; + sp = 0; + tlen = 0; + clen = 0; + cp = 0; int temp = 0x2000; if (s->flags & SCF_TRACKING_CAM) { - int lx = LaraItem->Pose.Position.x; - int ly = LaraItem->Pose.Position.y; - int lz = LaraItem->Pose.Position.z; + lx = LaraItem->Pose.Position.x; + ly = LaraItem->Pose.Position.y; + lz = LaraItem->Pose.Position.z; for (int i = 0; i < 8; i++) { @@ -347,13 +414,13 @@ void CalculateSpotCameras() for (int j = 0; j < 8; j++) { - int cx = Spline(sp, &CameraPosition[1].x, splineCount); - int cy = Spline(sp, &CameraPosition[1].y, splineCount); - int cz = Spline(sp, &CameraPosition[1].z, splineCount); + cx = Spline(sp, &CameraXposition[1], spline_cnt); + cy = Spline(sp, &CameraYposition[1], spline_cnt); + cz = Spline(sp, &CameraZposition[1], spline_cnt); - int dx = SQUARE(cx - lx); - int dy = SQUARE(cy - ly); - int dz = SQUARE(cz - lz); + dx = SQUARE(cx - lx); + dy = SQUARE(cy - ly); + dz = SQUARE(cz - lz); tlen = sqrt(dx + dy + dz); @@ -385,23 +452,19 @@ void CalculateSpotCameras() } if (CurrentSplinePosition > 0x10000) - { CurrentSplinePosition = 0x10000; - } else if (CurrentSplinePosition < 0) - { CurrentSplinePosition = 0; - } } else if (!SpotcamTimer) - { CurrentSplinePosition += cspeed; - } - if (!IsHeld(In::Look)) + bool lookPressed = (IsHeld(In::Look)) != 0; + + if (!lookPressed) SpotCamFirstLook = false; - if ((s->flags & SCF_DISABLE_BREAKOUT) || !IsHeld(In::Look)) + if ((s->flags & SCF_DISABLE_BREAKOUT) || !lookPressed) { Camera.pos.x = cpx; Camera.pos.y = cpy; @@ -427,9 +490,7 @@ void CalculateSpotCameras() GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.RoomNumber); } else - { Camera.pos.RoomNumber = outsideRoom; - } AlterFOV(cfov, false); @@ -482,15 +543,10 @@ void CalculateSpotCameras() { CurrentSplinePosition = 0; - int cn = 0; if (CurrentSplineCamera != FirstCamera) - { cn = CurrentSplineCamera - 1; - } else - { cn = LastCamera; - } sp = 1; @@ -517,8 +573,12 @@ void CalculateSpotCameras() { cn = FirstCamera + SpotCam[CurrentSplineCamera].timer; - CameraPosition[1] = SpotCam[cn].Position; - CameraPositionTarget[1] = SpotCam[cn].PositionTarget; + CameraXposition[1] = SpotCam[cn].x; + CameraYposition[1] = SpotCam[cn].y; + CameraZposition[1] = SpotCam[cn].z; + CameraXtarget[1] = SpotCam[cn].tx; + CameraYtarget[1] = SpotCam[cn].ty; + CameraZtarget[1] = SpotCam[cn].tz; CameraRoll[1] = SpotCam[cn].roll; CameraFOV[1] = SpotCam[cn].fov; CameraSpeed[1] = SpotCam[cn].speed; @@ -528,8 +588,12 @@ void CalculateSpotCameras() sp = sp2 + 1; - CameraPosition[sp] = SpotCam[cn].Position; - CameraPositionTarget[sp] = SpotCam[cn].PositionTarget; + CameraXposition[sp] = SpotCam[cn].x; + CameraYposition[sp] = SpotCam[cn].y; + CameraZposition[sp] = SpotCam[cn].z; + CameraXtarget[sp] = SpotCam[cn].tx; + CameraYtarget[sp] = SpotCam[cn].ty; + CameraZtarget[sp] = SpotCam[cn].tz; CameraRoll[sp] = SpotCam[cn].roll; CameraFOV[sp] = SpotCam[cn].fov; CameraSpeed[sp] = SpotCam[cn].speed; @@ -551,8 +615,12 @@ void CalculateSpotCameras() cn = LastCamera; } - CameraPosition[sp + 1] = SpotCam[cn].Position; - CameraPositionTarget[sp + 1] = SpotCam[cn].PositionTarget; + CameraXposition[sp + 1] = SpotCam[cn].x; + CameraYposition[sp + 1] = SpotCam[cn].y; + CameraZposition[sp + 1] = SpotCam[cn].z; + CameraXtarget[sp + 1] = SpotCam[cn].tx; + CameraYtarget[sp + 1] = SpotCam[cn].ty; + CameraZtarget[sp + 1] = SpotCam[cn].tz; CameraRoll[sp + 1] = SpotCam[cn].roll; CameraFOV[sp + 1] = SpotCam[cn].fov; CameraSpeed[sp + 1] = SpotCam[cn].speed; @@ -620,14 +688,22 @@ void CalculateSpotCameras() } else { - CameraPosition[1] = SpotCam[CurrentSplineCamera - 1].Position; - CameraPositionTarget[1] = SpotCam[CurrentSplineCamera - 1].PositionTarget; + CameraXposition[1] = SpotCam[CurrentSplineCamera - 1].x; + CameraYposition[1] = SpotCam[CurrentSplineCamera - 1].y; + CameraZposition[1] = SpotCam[CurrentSplineCamera - 1].z; + CameraXtarget[1] = SpotCam[CurrentSplineCamera - 1].tx; + CameraYtarget[1] = SpotCam[CurrentSplineCamera - 1].ty; + CameraZtarget[1] = SpotCam[CurrentSplineCamera - 1].tz; CameraRoll[1] = SpotCam[CurrentSplineCamera - 1].roll; CameraFOV[1] = SpotCam[CurrentSplineCamera - 1].fov; CameraSpeed[1] = SpotCam[CurrentSplineCamera - 1].speed; - CameraPosition[2] = SpotCam[CurrentSplineCamera - 1].Position; - CameraPositionTarget[2] = SpotCam[CurrentSplineCamera - 1].PositionTarget; + CameraXposition[2] = SpotCam[CurrentSplineCamera - 1].x; + CameraYposition[2] = SpotCam[CurrentSplineCamera - 1].y; + CameraZposition[2] = SpotCam[CurrentSplineCamera - 1].z; + CameraXtarget[2] = SpotCam[CurrentSplineCamera - 1].tx; + CameraYtarget[2] = SpotCam[CurrentSplineCamera - 1].ty; + CameraZtarget[2] = SpotCam[CurrentSplineCamera - 1].tz; CameraRoll[2] = SpotCam[CurrentSplineCamera - 1].roll; CameraFOV[2] = SpotCam[CurrentSplineCamera - 1].fov; CameraSpeed[2] = SpotCam[CurrentSplineCamera - 1].speed; @@ -645,17 +721,30 @@ void CalculateSpotCameras() CameraRoll[3] = 0; CameraSpeed[2] = CameraSpeed[1]; - InitialCameraPosition = Camera.pos.ToVector3i(); - InitialCameraTarget = Camera.target.ToVector3i(); + InitialCameraPosition.x = Camera.pos.x; + InitialCameraPosition.y = Camera.pos.y; + InitialCameraPosition.z = Camera.pos.z; - CameraPosition[3] = Camera.pos.ToVector3i(); - CameraPositionTarget[3] = Camera.target.ToVector3i(); + InitialCameraTarget.x = Camera.target.x; + InitialCameraTarget.y = Camera.target.y; + InitialCameraTarget.z = Camera.target.z; + + CameraXposition[3] = Camera.pos.x; + CameraYposition[3] = Camera.pos.y; + CameraZposition[3] = Camera.pos.z; + CameraXtarget[3] = Camera.target.x; + CameraYtarget[3] = Camera.target.y; + CameraZtarget[3] = Camera.target.z; CameraFOV[3] = LastFOV; CameraSpeed[3] = CameraSpeed[2]; CameraRoll[3] = 0; - CameraPosition[4] = Camera.pos.ToVector3i(); - CameraPositionTarget[4] = Camera.target.ToVector3i(); + CameraXposition[4] = Camera.pos.x; + CameraYposition[4] = Camera.pos.y; + CameraZposition[4] = Camera.pos.z; + CameraXtarget[4] = Camera.target.x; + CameraYtarget[4] = Camera.target.y; + CameraZtarget[4] = Camera.target.z; CameraFOV[4] = LastFOV; CameraSpeed[4] = CameraSpeed[2] >> 1; CameraRoll[4] = 0; diff --git a/TombEngine/Game/spotcam.h b/TombEngine/Game/spotcam.h index 2efeaf9ae..24820b1aa 100644 --- a/TombEngine/Game/spotcam.h +++ b/TombEngine/Game/spotcam.h @@ -1,25 +1,28 @@ #pragma once +#include "Math/Math.h" #include "Specific/clock.h" -struct Vector3i; - constexpr auto MAX_SPOTCAMS = 256; constexpr auto SPOTCAM_CINEMATIC_BARS_HEIGHT = 1.0f / 16; constexpr auto SPOTCAM_CINEMATIC_BARS_SPEED = 1.0f / FPS; struct SPOTCAM { - Vector3i Position = Vector3i::Zero; - Vector3i PositionTarget = Vector3i::Zero; - - int roomNumber; - int sequence; - int camera; + int x; + int y; + int z; + int tx; + int ty; + int tz; + unsigned char sequence; + unsigned char camera; short fov; short roll; - int timer; - int speed; - int flags; + short timer; + short speed; + short flags; + short roomNumber; + short pad; }; enum SPOTCAM_FLAGS diff --git a/TombEngine/Math/Geometry.cpp b/TombEngine/Math/Geometry.cpp index d283a4185..22235dc26 100644 --- a/TombEngine/Math/Geometry.cpp +++ b/TombEngine/Math/Geometry.cpp @@ -384,4 +384,9 @@ namespace TEN::Math::Geometry return (distSqr <= radiusSqr); } + + bool CircleIntersects(const Vector3& circle0, const Vector3& circle1) + { + return (sqrt(SQUARE(circle1.x - circle0.x) + SQUARE(circle1.y - circle0.y)) <= (circle0.z + circle1.z)); + } } diff --git a/TombEngine/Math/Geometry.h b/TombEngine/Math/Geometry.h index 53f53fa8e..25a00ed9a 100644 --- a/TombEngine/Math/Geometry.h +++ b/TombEngine/Math/Geometry.h @@ -54,4 +54,7 @@ namespace TEN::Math::Geometry bool IsPointInBox(const Vector3& point, const BoundingBox& box); bool IsPointInBox(const Vector3& point, const BoundingOrientedBox& box); bool IsPointInSphere(const Vector3& point, const BoundingSphere& sphere); + + // Intersection inquirers + bool CircleIntersects(const Vector3& circle0, const Vector3& circle1); } diff --git a/TombEngine/Math/Math.cpp b/TombEngine/Math/Math.cpp index 6564b0178..3ede4ffd8 100644 --- a/TombEngine/Math/Math.cpp +++ b/TombEngine/Math/Math.cpp @@ -1,4 +1,6 @@ #include "framework.h" + +#include #include "Math/Math.h" namespace TEN::Math diff --git a/TombEngine/Math/Random.cpp b/TombEngine/Math/Random.cpp index 2546cb21f..0131624dc 100644 --- a/TombEngine/Math/Random.cpp +++ b/TombEngine/Math/Random.cpp @@ -4,6 +4,7 @@ #include #include "Math/Constants.h" +#include "Math/Objects/EulerAngles.h" namespace TEN::Math::Random { @@ -49,7 +50,8 @@ namespace TEN::Math::Random relPoint = Vector2( GenerateFloat(-1.0f, 1.0f), GenerateFloat(-1.0f, 1.0f)); - } while (relPoint.LengthSquared() > 1.0f); + } + while (relPoint.LengthSquared() > 1.0f); return (pos + (relPoint * radius)); } @@ -100,7 +102,8 @@ namespace TEN::Math::Random GenerateFloat(-1.0f, 1.0f), GenerateFloat(-1.0f, 1.0f), GenerateFloat(-1.0f, 1.0f)); - } while (relPoint.LengthSquared() > 1.0f); + } + while (relPoint.LengthSquared() > 1.0f); return (sphere.Center + (relPoint * sphere.Radius)); } @@ -120,6 +123,28 @@ namespace TEN::Math::Random return (sphere.Center + (relPoint * sphere.Radius)); } + Vector3 GeneratePointInSpheroid(const Vector3& center, const EulerAngles& orient, const Vector3& semiMajorAxis) + { + // Use rejection sampling method. + auto relPoint = Vector3::Zero; + do + { + relPoint = Vector3( + Random::GenerateFloat(-semiMajorAxis.x, semiMajorAxis.x), + Random::GenerateFloat(-semiMajorAxis.y, semiMajorAxis.y), + Random::GenerateFloat(-semiMajorAxis.z, semiMajorAxis.z)); + } + while ((SQUARE(relPoint.x) / SQUARE(semiMajorAxis.x) + + SQUARE(relPoint.y) / SQUARE(semiMajorAxis.y) + + SQUARE(relPoint.z) / SQUARE(semiMajorAxis.z)) > 1.0f); + + // Rotate relative point. + auto rotMatrix = orient.ToRotationMatrix(); + relPoint = Vector3::Transform(relPoint, rotMatrix); + + return (center + relPoint); + } + bool TestProbability(float prob) { if (prob <= 0.0f) diff --git a/TombEngine/Math/Random.h b/TombEngine/Math/Random.h index 8b4e988ac..fd7508d35 100644 --- a/TombEngine/Math/Random.h +++ b/TombEngine/Math/Random.h @@ -1,5 +1,7 @@ #pragma once +class EulerAngles; + namespace TEN::Math::Random { // Value generation @@ -18,6 +20,7 @@ namespace TEN::Math::Random Vector3 GeneratePointInBox(const BoundingOrientedBox& box); Vector3 GeneratePointInSphere(const BoundingSphere& sphere); Vector3 GeneratePointOnSphere(const BoundingSphere& sphere); + Vector3 GeneratePointInSpheroid(const Vector3& center, const EulerAngles& orient, const Vector3& semiMajorAxis); bool TestProbability(float prob); } diff --git a/TombEngine/Objects/Effects/Boss.cpp b/TombEngine/Objects/Effects/Boss.cpp index 17a8c6162..ed7cf2af4 100644 --- a/TombEngine/Objects/Effects/Boss.cpp +++ b/TombEngine/Objects/Effects/Boss.cpp @@ -21,7 +21,7 @@ namespace TEN::Effects::Boss return; int itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto& shieldItem = g_Level.Items[itemNumber]; @@ -50,7 +50,7 @@ namespace TEN::Effects::Boss return; int itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto& shockwaveItem = g_Level.Items[itemNumber]; diff --git a/TombEngine/Objects/Effects/flame_emitters.cpp b/TombEngine/Objects/Effects/flame_emitters.cpp index d790a652f..80fea9e67 100644 --- a/TombEngine/Objects/Effects/flame_emitters.cpp +++ b/TombEngine/Objects/Effects/flame_emitters.cpp @@ -64,24 +64,19 @@ namespace TEN::Entities::Effects void BurnNearbyItems(ItemInfo* item, int radius) { - GetCollidedObjects(item, radius, true, &CollidedItems[0], &CollidedMeshes[0], false); - - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + auto collObjects = GetCollidedObjects(*item, true, false, radius, ObjectCollectionMode::Items); + for (auto* itemPtr : collObjects.ItemPtrs) { - auto* currentItem = CollidedItems[i]; - if (!currentItem) - break; - - if (TestEnvironment(ENV_FLAG_WATER, currentItem->RoomNumber)) + if (TestEnvironment(ENV_FLAG_WATER, itemPtr->RoomNumber)) continue; - if ((!currentItem->IsCreature() && !currentItem->IsLara()) || currentItem->HitPoints <= 0) + if ((!itemPtr->IsCreature() && !itemPtr->IsLara()) || itemPtr->HitPoints <= 0) continue; - if (currentItem->IsLara() && GetLaraInfo(item)->Control.WaterStatus == WaterStatus::FlyCheat) + if (itemPtr->IsLara() && GetLaraInfo(item)->Control.WaterStatus == WaterStatus::FlyCheat) continue; - ItemBurn(currentItem, currentItem->IsLara() ? -1 : FLAME_ITEM_BURN_TIMEOUT); + ItemBurn(itemPtr, itemPtr->IsLara() ? -1 : FLAME_ITEM_BURN_TIMEOUT); } } diff --git a/TombEngine/Objects/Effects/tr4_locusts.cpp b/TombEngine/Objects/Effects/tr4_locusts.cpp index 28a6a71e7..e828ce78b 100644 --- a/TombEngine/Objects/Effects/tr4_locusts.cpp +++ b/TombEngine/Objects/Effects/tr4_locusts.cpp @@ -26,7 +26,7 @@ namespace TEN::Entities::TR4 return i; } - return NO_ITEM; + return NO_VALUE; } void SpawnLocust(ItemInfo* item) @@ -34,7 +34,7 @@ namespace TEN::Entities::TR4 Vector3i origin, target; short locustNumber = CreateLocust(); EulerAngles orient; - if (locustNumber != NO_ITEM) + if (locustNumber != NO_VALUE) { auto* locust = &Locusts[locustNumber]; diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index 3bd02ec50..abfd748a3 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -144,8 +144,6 @@ void ElectricityWiresControl(short itemNumber) SoundEffect(SFX_TR5_ELECTRIC_WIRES, &item->Pose); - GetCollidedObjects(item, BLOCK(4), true, CollidedItems, nullptr, 0) && CollidedItems[0]; - auto* object = &Objects[item->ObjectNumber]; auto cableBox = GameBoundingBox(item).ToBoundingOrientedBox(item->Pose); @@ -181,21 +179,18 @@ void ElectricityWiresControl(short itemNumber) if (GetRandomControl() & 1) return; - int k = 0; - while (CollidedItems[k] != nullptr) + auto collObjects = GetCollidedObjects(*item, true, false, BLOCK(2), ObjectCollectionMode::Items); + for (auto* itemPtr : collObjects.ItemPtrs) { - auto* collItem = CollidedItems[k]; - auto* collObj = &Objects[collItem->ObjectNumber]; + const auto& object = Objects[itemPtr->ObjectNumber]; - k++; - - if (collItem->ObjectNumber != ID_LARA && !collObj->intelligent) + if (itemPtr->ObjectNumber != ID_LARA && !object.intelligent) continue; bool isWaterNearby = false; - auto npcBox = GameBoundingBox(collItem).ToBoundingOrientedBox(collItem->Pose); + auto npcBox = GameBoundingBox(itemPtr).ToBoundingOrientedBox(itemPtr->Pose); - for (int i = 0; i < object->nmeshes; i++) + for (int i = 0; i < object.nmeshes; i++) { auto pos = GetJointPosition(item, i, Vector3i(0, 0, CLICK(1))); short roomNumber = item->RoomNumber; @@ -219,10 +214,10 @@ void ElectricityWiresControl(short itemNumber) if (pos.y < cableBottomPlane) continue; - for (int j = 0; j < collObj->nmeshes; j++) + for (int j = 0; j < object.nmeshes; j++) { - auto collPos = GetJointPosition(collItem, j); - auto pointCollJointRoom = GetPointCollision(collPos, collItem->RoomNumber).GetRoomNumber(); + auto collPos = GetJointPosition(itemPtr, j); + auto pointCollJointRoom = GetPointCollision(collPos, itemPtr->RoomNumber).GetRoomNumber(); if (!isWaterNearby && isTouchingWater && roomNumber == pointCollJointRoom) isWaterNearby = true; @@ -234,29 +229,35 @@ void ElectricityWiresControl(short itemNumber) { if (!isWaterNearby) { - if (collItem->Effect.Type != EffectType::Smoke) + if (itemPtr->Effect.Type != EffectType::Smoke) { - ItemBlueElectricBurn(collItem, 2 *FPS); + ItemBlueElectricBurn(itemPtr, 2 *FPS); } else - ItemSmoke(collItem, -1); + { + ItemSmoke(itemPtr, -1); + } } if (instantKill) - DoDamage(collItem, INT_MAX); + { + DoDamage(itemPtr, INT_MAX); + } else - DoDamage(collItem, 8); + { + DoDamage(itemPtr, 8); + } - for (int j = 0; j < collObj->nmeshes; j++) + for (int j = 0; j < object.nmeshes; j++) { if ((GetRandomControl() & 127) < 16) - TriggerElectricitySparks(collItem, j, false); + TriggerElectricitySparks(itemPtr, j, false); } TriggerDynamicLight( - collItem->Pose.Position.x, - collItem->Pose.Position.y, - collItem->Pose.Position.z, + itemPtr->Pose.Position.x, + itemPtr->Pose.Position.y, + itemPtr->Pose.Position.z, 5, 0, (GetRandomControl() & 0x3F) + 0x2F, diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index 945df867a..9db8cd967 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -88,7 +88,7 @@ namespace TEN::Entities::Doors boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->Box; } - doorData->d1.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX; + doorData->d1.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d1.data = *doorData->d1.floor; if (r->flippedRoom != -1) @@ -105,7 +105,7 @@ namespace TEN::Entities::Doors boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->Box; } - doorData->d1flip.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX; + doorData->d1flip.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d1flip.data = *doorData->d1flip.floor; } else @@ -135,7 +135,7 @@ namespace TEN::Entities::Doors boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->Box; } - doorData->d2.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX; + doorData->d2.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d2.data = *doorData->d2.floor; if (r->flippedRoom != -1) @@ -152,7 +152,7 @@ namespace TEN::Entities::Doors boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->Box; } - doorData->d2flip.block = (boxNumber != NO_BOX && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_BOX; + doorData->d2flip.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d2flip.data = *doorData->d2flip.floor; } else @@ -187,7 +187,7 @@ namespace TEN::Entities::Doors { if (!laraInfo->Control.IsMoving) { - if (g_Gui.GetInventoryItemChosen() == NO_ITEM) + if (g_Gui.GetInventoryItemChosen() == NO_VALUE) { if (g_Gui.IsObjectInInventory(ID_CROWBAR_ITEM)) { @@ -217,7 +217,7 @@ namespace TEN::Entities::Doors } } - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); if (MoveLaraPosition(CrowbarDoorPos, doorItem, laraItem)) { @@ -399,11 +399,11 @@ namespace TEN::Entities::Doors *doorPos->floor = doorPos->data; short boxIndex = doorPos->block; - if (boxIndex != NO_BOX) + if (boxIndex != NO_VALUE) { g_Level.Boxes[boxIndex].flags &= ~BLOCKED; for (auto& currentCreature : ActiveCreatures) - currentCreature->LOT.TargetBox = NO_BOX; + currentCreature->LOT.TargetBox = NO_VALUE; } } } @@ -416,7 +416,7 @@ namespace TEN::Entities::Doors if (floor) { - floor->Box = NO_BOX; + floor->Box = NO_VALUE; floor->TriggerIndex = 0; // FIXME: HACK!!!!!!! @@ -433,12 +433,12 @@ namespace TEN::Entities::Doors floor->CeilingSurface.Triangles[1].Plane = WALL_PLANE; short boxIndex = doorPos->block; - if (boxIndex != NO_BOX) + if (boxIndex != NO_VALUE) { g_Level.Boxes[boxIndex].flags |= BLOCKED; for (auto& currentCreature : ActiveCreatures) - currentCreature->LOT.TargetBox = NO_BOX; + currentCreature->LOT.TargetBox = NO_VALUE; } } } diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableBridge.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableBridge.cpp index dc910c8f6..9753906a4 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableBridge.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableBridge.cpp @@ -75,7 +75,7 @@ namespace TEN::Entities::Generic if (pushablePtr->UseBridgeCollision) addBridge ? AddBridge(pushableItem.Index) : RemoveBridge(pushableItem.Index); - while (pushablePtr->Stack.ItemNumberAbove != NO_ITEM) + while (pushablePtr->Stack.ItemNumberAbove != NO_VALUE) { pushableItemPtr = &g_Level.Items[pushablePtr->Stack.ItemNumberAbove]; pushablePtr = &GetPushableInfo(*pushableItemPtr); diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 1c5b33210..52c681f52 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -84,7 +84,7 @@ namespace TEN::Entities::Generic else { pushable.IsOnEdge = true; - if (!pushable.CanFall || pushable.Stack.ItemNumberAbove != NO_ITEM) + if (!pushable.CanFall || pushable.Stack.ItemNumberAbove != NO_VALUE) return false; } } @@ -118,28 +118,24 @@ namespace TEN::Entities::Generic // Test object collision. auto prevPos = pushableItem.Pose.Position; pushableItem.Pose.Position = targetPos; - GetCollidedObjects(&pushableItem, BLOCK(0.25f), true, &CollidedItems[0], &CollidedMeshes[0], true); + auto collObjects = GetCollidedObjects(pushableItem, true, true); pushableItem.Pose.Position = prevPos; - if (CollidedMeshes[0]) + if (!collObjects.StaticPtrs.empty()) return false; - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + for (const auto* itemPtr : collObjects.ItemPtrs) { - if (CollidedItems[i] == nullptr) - break; - - const auto& item = *CollidedItems[i]; - const auto& object = Objects[item.ObjectNumber]; + const auto& object = Objects[itemPtr->ObjectNumber]; if (object.isPickup) continue; - if (!item.IsBridge()) + if (!itemPtr->IsBridge()) return false; - const auto& bridge = GetBridgeObject(item); - if (!bridge.GetFloorHeight(item, item.Pose.Position).has_value()) + const auto& bridge = GetBridgeObject(*itemPtr); + if (!bridge.GetFloorHeight(*itemPtr, itemPtr->Pose.Position).has_value()) return false; } @@ -193,34 +189,30 @@ namespace TEN::Entities::Generic // Collide with objects. auto prevPos = LaraItem->Pose.Position; LaraItem->Pose.Position = pointColl.GetPosition(); - GetCollidedObjects(LaraItem, LARA_RADIUS, true, &CollidedItems[0], &CollidedMeshes[0], true); + auto collObjects = GetCollidedObjects(*LaraItem, true, true); LaraItem->Pose.Position = prevPos; - if (CollidedMeshes[0]) + if (!collObjects.StaticPtrs.empty()) return false; - for (int i = 0; i < MAX_COLLIDED_OBJECTS; i++) + for (const auto* itemPtr : collObjects.ItemPtrs) { - if (CollidedItems[i] == nullptr) - break; + const auto& object = Objects[itemPtr->ObjectNumber]; - const auto& item = *CollidedItems[i]; - const auto& object = Objects[item.ObjectNumber]; - - if (&item == &pushableItem) + if (itemPtr->Index == pushableItem.Index) continue; if (object.isPickup) continue; - if (!item.IsBridge()) + if (!itemPtr->IsBridge()) { return false; } else { - const auto& bridge = GetBridgeObject(item); - if (!bridge.GetFloorHeight(item, item.Pose.Position).has_value()) + const auto& bridge = GetBridgeObject(*itemPtr); + if (!bridge.GetFloorHeight(*itemPtr, itemPtr->Pose.Position).has_value()) return false; } } diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableInfo.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableInfo.cpp index 7c6a69792..a83ac1f69 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableInfo.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableInfo.cpp @@ -42,8 +42,8 @@ namespace TEN::Entities::Generic Oscillation = DEFAULT_OSC; Stack.Limit = DEFAULT_STACK_LIMIT; - Stack.ItemNumberAbove = NO_ITEM; - Stack.ItemNumberBelow = NO_ITEM; + Stack.ItemNumberAbove = NO_VALUE; + Stack.ItemNumberBelow = NO_VALUE; CanFall = false; DoCenterAlign = true; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp index 9f56c8b8f..4c1fa4072 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableStack.cpp @@ -107,7 +107,7 @@ namespace TEN::Entities::Generic void StackPushable(int itemNumber, int targetItemNumber) { - if (targetItemNumber == NO_ITEM) + if (targetItemNumber == NO_VALUE) return; auto& pushableItem = g_Level.Items[itemNumber]; @@ -126,14 +126,14 @@ namespace TEN::Entities::Generic auto& pushableItem = g_Level.Items[itemNumber]; auto& pushable = GetPushableInfo(pushableItem); - if (pushable.Stack.ItemNumberBelow == NO_ITEM) + if (pushable.Stack.ItemNumberBelow == NO_VALUE) return; auto& lowerPushableItem = g_Level.Items[pushable.Stack.ItemNumberBelow]; auto& lowerPushable = GetPushableInfo(lowerPushableItem); - pushable.Stack.ItemNumberBelow = NO_ITEM; - lowerPushable.Stack.ItemNumberAbove = NO_ITEM; + pushable.Stack.ItemNumberBelow = NO_VALUE; + lowerPushable.Stack.ItemNumberAbove = NO_VALUE; } int SearchNearPushablesStack(int itemNumber) @@ -142,7 +142,7 @@ namespace TEN::Entities::Generic int pushabelStackFound = FindPushableStackInRoom(itemNumber, pushableItem.RoomNumber); - if (pushabelStackFound != NO_ITEM) + if (pushabelStackFound != NO_VALUE) return pushabelStackFound; // Otherwise, check room below. @@ -150,7 +150,7 @@ namespace TEN::Entities::Generic //auto roomNumberBelow = collisionResult.Block->GetRoomNumberBelow(pushableItem.Pose.Position.x, pushableItem.Pose.Position.y, pushableItem.Pose.Position.z).value(); //pushabelStackFound = FindPushableStackInRoom(itemNumber, roomNumberBelow); - return NO_ITEM; + return NO_VALUE; } int FindPushableStackInRoom(int itemNumber, int roomNumber) @@ -161,7 +161,7 @@ namespace TEN::Entities::Generic if (roomNumber != NO_ROOM) { short currentItemNumber = g_Level.Rooms[roomNumber].itemNumber; - while (currentItemNumber != NO_ITEM) + while (currentItemNumber != NO_VALUE) { auto& currentItem = g_Level.Items[currentItemNumber]; @@ -171,19 +171,19 @@ namespace TEN::Entities::Generic (currentItem.Pose.Position.y > pushableItem.Pose.Position.y)) { // Find top item. - if (pushable.Stack.ItemNumberAbove == NO_ITEM) + if (pushable.Stack.ItemNumberAbove == NO_VALUE) { return currentItemNumber; } else { int topItemNumber = pushable.Stack.ItemNumberAbove; - while (topItemNumber != NO_ITEM) + while (topItemNumber != NO_VALUE) { auto& topItem = g_Level.Items[topItemNumber]; auto& topPushable = GetPushableInfo(topItem); - if (topPushable.Stack.ItemNumberAbove == NO_ITEM) + if (topPushable.Stack.ItemNumberAbove == NO_VALUE) { return topItemNumber; } @@ -201,7 +201,7 @@ namespace TEN::Entities::Generic } } - return NO_ITEM; + return NO_VALUE; } int GetPushableCountInStack(int itemNumber) @@ -210,7 +210,7 @@ namespace TEN::Entities::Generic auto& pushableCopy = GetPushableInfo(pushableItemCopy); int count = 1; - while (pushableCopy.Stack.ItemNumberAbove != NO_ITEM) + while (pushableCopy.Stack.ItemNumberAbove != NO_VALUE) { // Filter out current pushable item. if (pushableCopy.Stack.ItemNumberAbove == itemNumber) @@ -241,7 +241,7 @@ namespace TEN::Entities::Generic int totalHeight = pushableCopy.Height; - while (pushableCopy.Stack.ItemNumberAbove != NO_ITEM) + while (pushableCopy.Stack.ItemNumberAbove != NO_VALUE) { pushableItemCopy = g_Level.Items[pushableCopy.Stack.ItemNumberAbove]; pushableCopy = GetPushableInfo(pushableItemCopy); @@ -258,7 +258,7 @@ namespace TEN::Entities::Generic auto& pushable = GetPushableInfo(pushableItem); int currentItemNumber = pushable.Stack.ItemNumberAbove; - while (currentItemNumber != NO_ITEM) + while (currentItemNumber != NO_VALUE) { auto& currentPushableItem = g_Level.Items[currentItemNumber]; auto& currentPushable = GetPushableInfo(currentPushableItem); @@ -279,7 +279,7 @@ namespace TEN::Entities::Generic auto& pushable = GetPushableInfo(pushableItem); int currentItemNumber = pushable.Stack.ItemNumberAbove; - while (currentItemNumber != NO_ITEM) + while (currentItemNumber != NO_VALUE) { auto& currentPushableItem = g_Level.Items[currentItemNumber]; auto& currentPushable = GetPushableInfo(currentPushableItem); @@ -312,7 +312,7 @@ namespace TEN::Entities::Generic auto* pushableItemPtr = &g_Level.Items[pushableItem.Index]; const auto* pushablePtr = &GetPushableInfo(*pushableItemPtr); - while (pushablePtr->Stack.ItemNumberAbove != NO_ITEM) + while (pushablePtr->Stack.ItemNumberAbove != NO_VALUE) { if (pushablePtr->Stack.ItemNumberAbove == pushableItem.Index) break; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp index 265d4ed78..7e9e45f21 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp @@ -73,7 +73,7 @@ namespace TEN::Entities::Generic playerItem.Animation.ActiveState != LS_PUSHABLE_PUSH && playerItem.Animation.ActiveState != LS_PUSHABLE_EDGE_SLIP) { - player.Context.InteractedItem = NO_ITEM; + player.Context.InteractedItem = NO_VALUE; } } @@ -106,7 +106,7 @@ namespace TEN::Entities::Generic int waterheight = abs(pushableColl.FloorHeight - pushable.WaterSurfaceHeight); if (waterheight > GetPushableHeight(pushableItem)) { - if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_ITEM) + if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_VALUE) { pushable.BehaviorState = PushableBehaviourState::Float; pushable.Gravity = 0.0f; @@ -146,7 +146,7 @@ namespace TEN::Entities::Generic RemovePushableBridge(pushableItem); SetPushableStopperFlag(false, pushableItem.Pose.Position, pushableItem.RoomNumber); - if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_ITEM) + if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_VALUE) { pushable.BehaviorState = PushableBehaviourState::Float; pushable.Gravity = 0.0f; @@ -340,7 +340,7 @@ namespace TEN::Entities::Generic pushable.BehaviorState = PushableBehaviourState::Fall; pushable.SoundState = PushableSoundState::None; playerItem.Animation.TargetState = LS_IDLE; - player.Context.InteractedItem = NO_ITEM; + player.Context.InteractedItem = NO_VALUE; return; case PushableEnvironmentType::SlopedFloor: @@ -351,7 +351,7 @@ namespace TEN::Entities::Generic pushable.BehaviorState = PushableBehaviourState::Sink; pushable.SoundState = PushableSoundState::None; playerItem.Animation.TargetState = LS_IDLE; - player.Context.InteractedItem = NO_ITEM; + player.Context.InteractedItem = NO_VALUE; break; default: @@ -490,7 +490,7 @@ namespace TEN::Entities::Generic // Get pushable collision. auto pushableColl = GetPushableCollision(pushableItem); - int foundStack = NO_ITEM; + int foundStack = NO_VALUE; switch (pushableColl.EnvType) { @@ -509,7 +509,7 @@ namespace TEN::Entities::Generic pushableItem.Pose.Orientation = EulerAngles(0, pushableItem.Pose.Orientation.y, 0); // Set stopper flag. - if (pushable.Stack.ItemNumberBelow == NO_ITEM) + if (pushable.Stack.ItemNumberBelow == NO_VALUE) SetPushableStopperFlag(true, pushableItem.Pose.Position, pushableItem.RoomNumber); // Activate trigger. @@ -554,7 +554,7 @@ namespace TEN::Entities::Generic // Get pushable collision. auto pushableColl = GetPushableCollision(pushableItem); - int foundStack = NO_ITEM; + int foundStack = NO_VALUE; switch (pushableColl.EnvType) { @@ -562,7 +562,7 @@ namespace TEN::Entities::Generic case PushableEnvironmentType::FlatFloor: case PushableEnvironmentType::SlopedFloor: // Set stopper flag. - if (pushable.Stack.ItemNumberBelow == NO_ITEM) + if (pushable.Stack.ItemNumberBelow == NO_VALUE) SetPushableStopperFlag(true, pushableItem.Pose.Position, pushableItem.RoomNumber); pushable.BehaviorState = PushableBehaviourState::Fall; @@ -572,7 +572,7 @@ namespace TEN::Entities::Generic case PushableEnvironmentType::Water: { // Manage influence of gravity. - if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_ITEM) + if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_VALUE) { pushable.Gravity = pushable.Gravity - PUSHABLE_GRAVITY_ACCEL; if (pushable.Gravity <= 0.0f) @@ -606,7 +606,7 @@ namespace TEN::Entities::Generic break; case PushableEnvironmentType::WaterFloor: - if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_ITEM) + if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_VALUE) { pushableItem.Pose.Position.y = pushableColl.FloorHeight; pushable.BehaviorState = PushableBehaviourState::Float; @@ -649,7 +649,7 @@ namespace TEN::Entities::Generic case PushableEnvironmentType::SlopedFloor: // Set stopper flag. - if (pushable.Stack.ItemNumberBelow == NO_ITEM) + if (pushable.Stack.ItemNumberBelow == NO_VALUE) SetPushableStopperFlag(true, pushableItem.Pose.Position, pushableItem.RoomNumber); pushable.BehaviorState = PushableBehaviourState::Fall; @@ -719,7 +719,7 @@ namespace TEN::Entities::Generic case PushableEnvironmentType::SlopedFloor: case PushableEnvironmentType::Air: // Set stopper flag. - if (pushable.Stack.ItemNumberBelow == NO_ITEM) + if (pushable.Stack.ItemNumberBelow == NO_VALUE) SetPushableStopperFlag(true, pushableItem.Pose.Position, pushableItem.RoomNumber); pushableItem.Animation.Velocity.y = 0.0f; @@ -742,7 +742,7 @@ namespace TEN::Entities::Generic pushable.Gravity = PUSHABLE_GRAVITY_AIR; } } - else if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_ITEM) + else if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_VALUE) { pushableItem.Animation.Velocity.y = 0.0f; pushable.BehaviorState = PushableBehaviourState::Float; @@ -757,7 +757,7 @@ namespace TEN::Entities::Generic break; case PushableEnvironmentType::Water: - if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_ITEM) + if (pushable.IsBuoyant && pushable.Stack.ItemNumberAbove == NO_VALUE) { pushableItem.Animation.Velocity.y = 0.0f; pushable.BehaviorState = PushableBehaviourState::Float; @@ -769,7 +769,7 @@ namespace TEN::Entities::Generic if (abs(pushableColl.FloorHeight - pushableItem.Pose.Position.y) > CLICK(0.75f)) { //Reset Stopper Flag - if (pushable.Stack.ItemNumberBelow == NO_ITEM) + if (pushable.Stack.ItemNumberBelow == NO_VALUE) SetPushableStopperFlag(false, pushableItem.Pose.Position, pushableItem.RoomNumber); pushableItem.Animation.Velocity.y = 0.0f; diff --git a/TombEngine/Objects/Generic/Object/burning_torch.cpp b/TombEngine/Objects/Generic/Object/burning_torch.cpp index ec7882c0b..7d271b08d 100644 --- a/TombEngine/Objects/Generic/Object/burning_torch.cpp +++ b/TombEngine/Objects/Generic/Object/burning_torch.cpp @@ -231,14 +231,13 @@ namespace TEN::Entities::Generic item->Pose.Orientation.z = 0; } - auto velocity = Vector3i( + auto vel = Vector3i( item->Animation.Velocity.z * phd_sin(item->Pose.Orientation.y), item->Animation.Velocity.y, - item->Animation.Velocity.z * phd_cos(item->Pose.Orientation.y) - ); + item->Animation.Velocity.z * phd_cos(item->Pose.Orientation.y)); auto prevPos = item->Pose.Position; - item->Pose.Position += Vector3i(velocity.x, 0, velocity.z); + item->Pose.Position += Vector3i(vel.x, 0, vel.z); if (TestEnvironment(ENV_FLAG_WATER, item) || TestEnvironment(ENV_FLAG_SWAMP, item)) @@ -250,26 +249,31 @@ namespace TEN::Entities::Generic item->ItemFlags[3] = 0; } else + { item->Animation.Velocity.y += 6; + } item->Pose.Position.y += item->Animation.Velocity.y; - DoProjectileDynamics(itemNumber, prevPos.x, prevPos.y, prevPos.z, velocity.x, velocity.y, velocity.z); + DoProjectileDynamics(itemNumber, prevPos.x, prevPos.y, prevPos.z, vel.x, vel.y, vel.z); // Collide with entities. - if (GetCollidedObjects(item, 0, true, CollidedItems, CollidedMeshes, true)) + auto collObjects = GetCollidedObjects(*item, true, true); + if (!collObjects.IsEmpty()) { LaraCollision.Setup.EnableObjectPush = true; - if (CollidedItems[0]) + if (!collObjects.ItemPtrs.empty()) { - if (!Objects[CollidedItems[0]->ObjectNumber].intelligent && - CollidedItems[0]->ObjectNumber != ID_LARA) + const auto& object = Objects[collObjects.ItemPtrs.front()->ObjectNumber]; + + if (!object.intelligent && + !collObjects.ItemPtrs.front()->IsLara()) { - ObjectCollision(CollidedItems[0]->Index, item, &LaraCollision); + ObjectCollision(collObjects.ItemPtrs.front()->Index, item, &LaraCollision); } } - else if (CollidedMeshes[0]) + else if (!collObjects.StaticPtrs.empty()) { - ItemPushStatic(item, *CollidedMeshes[0], &LaraCollision); + ItemPushStatic(item, *collObjects.StaticPtrs.front(), &LaraCollision); } item->Animation.Velocity.z = -int(item->Animation.Velocity.z / 1.5f); diff --git a/TombEngine/Objects/Generic/Switches/crowbar_switch.cpp b/TombEngine/Objects/Generic/Switches/crowbar_switch.cpp index f3aa638b9..92fbe361b 100644 --- a/TombEngine/Objects/Generic/Switches/crowbar_switch.cpp +++ b/TombEngine/Objects/Generic/Switches/crowbar_switch.cpp @@ -77,7 +77,7 @@ namespace TEN::Entities::Switches else laraInfo->Context.InteractedItem = itemNumber; - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); } else doSwitch = -1; @@ -106,7 +106,7 @@ namespace TEN::Entities::Switches else laraInfo->Context.InteractedItem = itemNumber; - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); } else doSwitch = -1; diff --git a/TombEngine/Objects/Generic/Traps/dart_emitter.cpp b/TombEngine/Objects/Generic/Traps/dart_emitter.cpp index ee746b015..eb7fa126e 100644 --- a/TombEngine/Objects/Generic/Traps/dart_emitter.cpp +++ b/TombEngine/Objects/Generic/Traps/dart_emitter.cpp @@ -74,7 +74,7 @@ namespace TEN::Entities::Traps } int dartItemNumber = CreateItem(); - if (dartItemNumber == NO_ITEM) + if (dartItemNumber == NO_VALUE) return; ItemInfo* dartItem = &g_Level.Items[dartItemNumber]; diff --git a/TombEngine/Objects/Generic/puzzles_keys.cpp b/TombEngine/Objects/Generic/puzzles_keys.cpp index d8cadab16..811896ad1 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.cpp +++ b/TombEngine/Objects/Generic/puzzles_keys.cpp @@ -67,7 +67,7 @@ void InitializePuzzleDone(short itemNumber) auto& receptacleItem = g_Level.Items[itemNumber]; const auto& anim = GetAnimData(receptacleItem); - receptacleItem.Animation.RequiredState = NO_STATE; + receptacleItem.Animation.RequiredState = NO_VALUE; receptacleItem.Animation.FrameNumber = anim.frameBase + anim.frameEnd; } @@ -108,7 +108,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co puzzleType = PuzzleType::Specfic; } - if (((IsHeld(In::Action) || g_Gui.GetInventoryItemChosen() != NO_ITEM) && + if (((IsHeld(In::Action) || g_Gui.GetInventoryItemChosen() != NO_VALUE) && laraItem->Animation.ActiveState == LS_IDLE && laraItem->Animation.AnimNumber == LA_STAND_IDLE && player.Control.HandStatus == HandStatus::Free && @@ -128,7 +128,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co { if (!player.Control.IsMoving) { - if (g_Gui.GetInventoryItemChosen() == NO_ITEM) + if (g_Gui.GetInventoryItemChosen() == NO_VALUE) { if (g_Gui.IsObjectInInventory(receptacleItem.ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1))) g_Gui.SetEnterInventory(receptacleItem.ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)); @@ -150,7 +150,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co if (!MoveLaraPosition(pos, &receptacleItem, laraItem)) { player.Context.InteractedItem = itemNumber; - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); receptacleItem.Pose.Orientation.y = prevYOrient; return; } @@ -173,7 +173,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co receptacleItem.ItemFlags[0] = 1; } - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); ResetPlayerFlex(laraItem); laraItem->Animation.FrameNumber = GetAnimData(laraItem).frameBase; player.Control.IsMoving = false; @@ -281,7 +281,7 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co if (!MoveLaraPosition(pos, &receptacleItem, laraItem)) { player.Context.InteractedItem = itemNumber; - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); receptacleItem.Pose.Orientation.y = prevYOrient; return; } @@ -348,7 +348,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber) item->Animation.FrameNumber = GetAnimData(item).frameBase; item->Animation.ActiveState = GetAnimData(item).ActiveState; item->Animation.TargetState = GetAnimData(item).ActiveState; - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; item->ResetModelToDefault(); AddActiveItem(itemNumber); @@ -447,7 +447,7 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) short triggerType = (*(triggerIndexPtr++) >> 8) & TRIGGER_BITS; - bool isActionReady = (IsHeld(In::Action) || g_Gui.GetInventoryItemChosen() != NO_ITEM); + bool isActionReady = (IsHeld(In::Action) || g_Gui.GetInventoryItemChosen() != NO_VALUE); bool isPlayerAvailable = (player->Control.Look.OpticRange == 0 && laraItem->Animation.ActiveState == LS_IDLE && @@ -464,7 +464,7 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) if (keyHoleItem->Status != ITEM_NOT_ACTIVE && triggerType != TRIGGER_TYPES::SWITCH) return; - if (g_Gui.GetInventoryItemChosen() == NO_ITEM) + if (g_Gui.GetInventoryItemChosen() == NO_VALUE) { if (g_Gui.IsObjectInInventory(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1))) g_Gui.SetEnterInventory(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)); @@ -511,7 +511,7 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) keyHoleItem->Status = ITEM_ACTIVE; } - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); return; } diff --git a/TombEngine/Objects/TR1/Entity/Cowboy.cpp b/TombEngine/Objects/TR1/Entity/Cowboy.cpp index d001f3d62..befd4d1f3 100644 --- a/TombEngine/Objects/TR1/Entity/Cowboy.cpp +++ b/TombEngine/Objects/TR1/Entity/Cowboy.cpp @@ -102,7 +102,7 @@ namespace TEN::Entities::Creatures::TR1 case COWBOY_STATE_IDLE: creature.MaxTurn = 0; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -167,7 +167,7 @@ namespace TEN::Entities::Creatures::TR1 extraTorsoRot.y = ai.angle / 2; } - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = COWBOY_STATE_IDLE; } diff --git a/TombEngine/Objects/TR1/Entity/Kold.cpp b/TombEngine/Objects/TR1/Entity/Kold.cpp index 546bb6278..dfdfaf044 100644 --- a/TombEngine/Objects/TR1/Entity/Kold.cpp +++ b/TombEngine/Objects/TR1/Entity/Kold.cpp @@ -98,7 +98,7 @@ namespace TEN::Entities::Creatures::TR1 case KOLD_STATE_IDLE: creature.MaxTurn = 0; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -162,7 +162,7 @@ namespace TEN::Entities::Creatures::TR1 creature.MaxTurn = 0; creature.Flags = 0; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = KOLD_STATE_IDLE; } diff --git a/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp b/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp index c751fd541..7e9160975 100644 --- a/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp +++ b/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp @@ -61,7 +61,7 @@ namespace TEN::Entities::Creatures::TR1 static void SpawnSkateboard(ItemInfo& item) { int skateItemNumber = CreateItem(); - if (skateItemNumber == NO_ITEM) + if (skateItemNumber == NO_VALUE) return; auto& skate = g_Level.Items[skateItemNumber]; @@ -112,22 +112,25 @@ namespace TEN::Entities::Creatures::TR1 { if (!CreatureActive(itemNumber)) return; + auto& item = g_Level.Items[itemNumber]; - if (item.ItemFlags[0] == NO_ITEM) + + if (item.ItemFlags[0] == NO_VALUE) { TENLog("Failed to do the skateboard kid control (itemNumber: " + std::to_string(itemNumber) + "), the skateboard itemNumber is missing, probably failed to be created !"); return; } + auto& creature = *GetCreatureInfo(&item); auto& skateItem = g_Level.Items[item.ItemFlags[0]]; short headingAngle = 0; auto extraHeadRot = EulerAngles::Identity; auto extraTorsoRot = EulerAngles::Identity; - if (skateItem.Status & ITEM_INVISIBLE) + if (skateItem.Status == ITEM_INVISIBLE) { skateItem.Active = true; - skateItem.Status &= ~(ITEM_INVISIBLE); + skateItem.Status = ITEM_ACTIVE; } for (auto& flash : creature.MuzzleFlash) @@ -164,7 +167,7 @@ namespace TEN::Entities::Creatures::TR1 creature.MaxTurn = KID_TURN_RATE_MAX; creature.Flags = 0; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } diff --git a/TombEngine/Objects/TR1/Entity/tr1_ape.cpp b/TombEngine/Objects/TR1/Entity/tr1_ape.cpp index 9eb9876fd..2c6df8a84 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_ape.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_ape.cpp @@ -201,7 +201,7 @@ namespace TEN::Entities::Creatures::TR1 creatureInfo->Flags -= APE_FLAG_TURN_RIGHT; } - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.bite && AI.distance < APE_ATTACK_RANGE) item->Animation.TargetState = APE_STATE_ATTACK; @@ -286,7 +286,7 @@ namespace TEN::Entities::Creatures::TR1 break; case APE_STATE_ATTACK: - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && item->TouchBits.Test(ApeAttackJoints)) { item->Animation.RequiredState = APE_STATE_IDLE; diff --git a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp index 8d219f369..6ce1bc0c7 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_bear.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_bear.cpp @@ -187,7 +187,7 @@ namespace TEN::Entities::Creatures::TR1 item.Animation.TargetState = BEAR_STATE_LOW_WALK; } } - else if (item.Animation.RequiredState != NO_STATE) + else if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -210,7 +210,7 @@ namespace TEN::Entities::Creatures::TR1 if (creature.Mood == MoodType::Bored || isPlayerDead || - item.Animation.RequiredState != NO_STATE) + item.Animation.RequiredState != NO_VALUE) { // Go to WALK, EAT, or RequiredState state. item.Animation.TargetState = BEAR_STATE_LOW_IDLE; @@ -234,7 +234,7 @@ namespace TEN::Entities::Creatures::TR1 break; case BEAR_STATE_LOW_CHARGE_ATTACK: - if (item.Animation.RequiredState == NO_STATE && + if (item.Animation.RequiredState == NO_VALUE && item.TouchBits.Test(BearAttackJoints)) { DoDamage(creature.Enemy, BEAR_LOW_CHARGE_ATTACK_DAMAGE); @@ -284,7 +284,7 @@ namespace TEN::Entities::Creatures::TR1 item.Animation.RequiredState = BEAR_STATE_LOW_WALK; item.Animation.TargetState = BEAR_STATE_LOW_IDLE; } - else if (item.Animation.RequiredState != NO_STATE) + else if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -308,7 +308,7 @@ namespace TEN::Entities::Creatures::TR1 break; case BEAR_STATE_HIGH_CLAW_ATTACK: - if (item.Animation.RequiredState == NO_STATE && + if (item.Animation.RequiredState == NO_VALUE && item.TouchBits.Test(BearAttackJoints)) { DoDamage(creature.Enemy, BEAR_HIGH_CLAW_ATTACK_DAMAGE); diff --git a/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp b/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp index c29232faf..cfd63dc11 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp @@ -145,7 +145,7 @@ namespace TEN::Entities::Creatures::TR1 switch (item->Animation.ActiveState) { case BIG_RAT_STATE_IDLE: - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (ai.bite && ai.distance < BIG_RAT_LAND_BITE_ATTACK_RANGE) item->Animation.TargetState = BIG_RAT_STATE_LAND_BITE_ATTACK; @@ -180,7 +180,7 @@ namespace TEN::Entities::Creatures::TR1 break; case BIG_RAT_STATE_LAND_BITE_ATTACK: - if (item->Animation.RequiredState == NO_STATE && ai.ahead && + if (item->Animation.RequiredState == NO_VALUE && ai.ahead && item->TouchBits.Test(BigRatBite.BoneID)) { DoDamage(creature->Enemy, BIG_RAT_BITE_ATTACK_DAMAGE); @@ -191,7 +191,7 @@ namespace TEN::Entities::Creatures::TR1 break; case BIG_RAT_STATE_POUNCE_ATTACK: - if (item->Animation.RequiredState == NO_STATE && ai.ahead && + if (item->Animation.RequiredState == NO_VALUE && ai.ahead && item->TouchBits.Test(BigRatBite.BoneID)) { DoDamage(creature->Enemy, BIG_RAT_POUNCE_ATTACK_DAMAGE); @@ -222,7 +222,7 @@ namespace TEN::Entities::Creatures::TR1 break; case BIG_RAT_STATE_SWIM_BITE_ATTACK: - if (item->Animation.RequiredState == NO_STATE && ai.ahead && + if (item->Animation.RequiredState == NO_VALUE && ai.ahead && item->TouchBits.Test(BigRatBite.BoneID)) { DoDamage(creature->Enemy, BIG_RAT_BITE_ATTACK_DAMAGE); diff --git a/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp b/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp index 85b10484f..4e0904cdb 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp @@ -82,7 +82,7 @@ namespace TEN::Entities::Creatures::TR1 { case CENTAUR_STATE_IDLE: CreatureJoint(item, 17, 0); - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.bite && AI.distance < pow(CENTAUR_REAR_RANGE, 2)) item->Animation.TargetState = CENTAUR_STATE_RUN_FORWARD; @@ -113,7 +113,7 @@ namespace TEN::Entities::Creatures::TR1 break; case CENTAUR_STATE_AIM: - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Targetable(item, &AI)) item->Animation.TargetState = CENTAUR_PROJECTILE_ATTACK; @@ -123,7 +123,7 @@ namespace TEN::Entities::Creatures::TR1 break; case CENTAUR_PROJECTILE_ATTACK: - if (item->Animation.RequiredState == NO_STATE) + if (item->Animation.RequiredState == NO_VALUE) { item->Animation.RequiredState = CENTAUR_STATE_AIM; CreatureEffect2(item, CentaurRocketBite, CENTAUR_BOMB_VELOCITY, head, BombGun); @@ -132,7 +132,7 @@ namespace TEN::Entities::Creatures::TR1 break; case CENTAUR_STATE_WARNING: - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && item->TouchBits.Test(CentaurAttackJoints)) { DoDamage(creature->Enemy, CENTAUR_REAR_DAMAGE); diff --git a/TombEngine/Objects/TR1/Entity/tr1_natla.cpp b/TombEngine/Objects/TR1/Entity/tr1_natla.cpp index b3ab6f951..2fd77fcda 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_natla.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_natla.cpp @@ -301,7 +301,7 @@ namespace TEN::Entities::Creatures::TR1 case NATLA_STATE_AIM: creature->MaxTurn = NATLA_FLY_ANGLE_SPEED; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = item->Animation.RequiredState; } @@ -319,7 +319,7 @@ namespace TEN::Entities::Creatures::TR1 case NATLA_STATE_SHOOT: creature->MaxTurn = NATLA_FLY_ANGLE_SPEED; - if (item->Animation.RequiredState == NO_STATE && ai.ahead) + if (item->Animation.RequiredState == NO_VALUE && ai.ahead) { CreatureEffect2(item, NatlaGunBite, NATLA_GUN_VELOCITY, ai.angle, BombGun); CreatureEffect2(item, NatlaGunBite, NATLA_GUN_VELOCITY, ai.angle + (GetRandomControl() - ANGLE(45.0f)) / 4, BombGun); diff --git a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp b/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp index 469ee2f20..d0f36cd62 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp @@ -450,7 +450,7 @@ namespace TEN::Entities::Creatures::TR1 break; case WMUTANT_STATE_IDLE_JUMP_ATTACK: - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && (item->TouchBits.Test(WingedMutantHandsJoints) || item->TouchBits.Test(WingedMutantHeadJoints)) && creature->Flags == 0) { DoDamage(creature->Enemy, WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE / 2); @@ -466,7 +466,7 @@ namespace TEN::Entities::Creatures::TR1 break; case WMUTANT_STATE_RUN_JUMP_ATTACK: - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && (item->TouchBits.Test(WingedMutantHandsJoints) || item->TouchBits.Test(WingedMutantHeadJoints)) && creature->Flags == 0) { DoDamage(creature->Enemy, WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE / 2); @@ -482,7 +482,7 @@ namespace TEN::Entities::Creatures::TR1 break; case WMUTANT_STATE_SWIPE_ATTACK: - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && item->TouchBits.Test(WingedMutantHandsJoints) && creature->Flags == 0) { DoDamage(creature->Enemy, WINGED_MUTANT_SWIPE_ATTACK_DAMAGE / 2); diff --git a/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp b/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp index 39af75005..316ad01a4 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_wolf.cpp @@ -152,7 +152,7 @@ namespace TEN::Entities::Creatures::TR1 break; case WOLF_STATE_IDLE: - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -169,7 +169,7 @@ namespace TEN::Entities::Creatures::TR1 if (creature.Mood != MoodType::Bored) { item.Animation.TargetState = WOLF_STATE_STALK; - item.Animation.RequiredState = NO_STATE; + item.Animation.RequiredState = NO_VALUE; } else if (Random::TestProbability(WOLF_SLEEP_CHANCE)) { @@ -180,7 +180,7 @@ namespace TEN::Entities::Creatures::TR1 break; case WOLF_STATE_CROUCH: - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -257,7 +257,7 @@ namespace TEN::Entities::Creatures::TR1 else { item.Animation.TargetState = WOLF_STATE_JUMP_ATTACK; - item.Animation.RequiredState = NO_STATE; + item.Animation.RequiredState = NO_VALUE; } } else if (creature.Mood == MoodType::Stalk && @@ -276,7 +276,7 @@ namespace TEN::Entities::Creatures::TR1 case WOLF_STATE_JUMP_ATTACK: tiltAngle = headingAngle; - if (item.Animation.RequiredState == NO_STATE && + if (item.Animation.RequiredState == NO_VALUE && item.TouchBits.Test(WolfAttackJoints)) { item.Animation.RequiredState = WOLF_STATE_RUN; @@ -288,7 +288,7 @@ namespace TEN::Entities::Creatures::TR1 break; case WOLF_STATE_BITE_ATTACK: - if (ai.ahead && item.Animation.RequiredState == NO_STATE && + if (ai.ahead && item.Animation.RequiredState == NO_VALUE && item.TouchBits.Test(WolfAttackJoints)) { item.Animation.RequiredState = WOLF_STATE_CROUCH; diff --git a/TombEngine/Objects/TR2/Entity/Dragon.cpp b/TombEngine/Objects/TR2/Entity/Dragon.cpp index 6cab05dbf..e4dc52f49 100644 --- a/TombEngine/Objects/TR2/Entity/Dragon.cpp +++ b/TombEngine/Objects/TR2/Entity/Dragon.cpp @@ -118,7 +118,7 @@ namespace TEN::Entities::Creatures::TR2 int frontBoneItemNumber = SpawnItem(item, ID_DRAGON_BONE_FRONT); int backBoneItemNumber = SpawnItem(item, ID_DRAGON_BONE_BACK); - if (backBoneItemNumber == NO_ITEM || frontBoneItemNumber == NO_ITEM) + if (backBoneItemNumber == NO_VALUE || frontBoneItemNumber == NO_VALUE) { TENLog("Failed to create dragon skeleton objects.", LogLevel::Warning); return; @@ -129,7 +129,7 @@ namespace TEN::Entities::Creatures::TR2 { int backItemNumber = SpawnItem(frontItem, ID_DRAGON_BACK); - if (backItemNumber == NO_ITEM) + if (backItemNumber == NO_VALUE) { TENLog("Failed to create dragon back body segment.", LogLevel::Warning); return; @@ -143,7 +143,7 @@ namespace TEN::Entities::Creatures::TR2 // Store back body segment item number. frontItem.ItemFlags[0] = backItemNumber; - backItem.ItemFlags[0] = NO_ITEM; + backItem.ItemFlags[0] = NO_VALUE; } void InitializeDragon(short itemNumber) @@ -168,7 +168,7 @@ namespace TEN::Entities::Creatures::TR2 if (backItem.Status == ITEM_DEACTIVATED) { KillItem(backItem.Index); - backItemNumber = NO_ITEM; + backItemNumber = NO_VALUE; return; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp b/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp index 4dba5a129..d7f089c78 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_eagle_or_crow.cpp @@ -130,7 +130,7 @@ namespace TEN::Entities::Creatures::TR2 case 1: creature->Flags = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; if (creature->Mood == MoodType::Bored) item->Animation.TargetState = 2; diff --git a/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp b/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp index 5388d56ad..e528fac37 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_knife_thrower.cpp @@ -74,7 +74,7 @@ namespace TEN::Entities::Creatures::TR2 short ThrowKnife(int x, int y, int z, float vel, short yRot, int roomNumber) { int fxNumber = CreateNewEffect(roomNumber); - if (fxNumber == NO_ITEM) + if (fxNumber == NO_VALUE) return fxNumber; auto& fx = EffectList[fxNumber]; diff --git a/TombEngine/Objects/TR2/Entity/tr2_rat.cpp b/TombEngine/Objects/TR2/Entity/tr2_rat.cpp index 398a74d3c..365ec4eb5 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_rat.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_rat.cpp @@ -97,7 +97,7 @@ namespace TEN::Entities::Creatures::TR2 else item->Animation.RequiredState = RAT_STATE_WALK_FORWARD; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = RAT_STATE_IDLE; break; @@ -105,7 +105,7 @@ namespace TEN::Entities::Creatures::TR2 case RAT_STATE_IDLE: creature->MaxTurn = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; break; @@ -130,7 +130,7 @@ namespace TEN::Entities::Creatures::TR2 break; case RAT_STATE_POUNCE_ATTACK: - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && item->TouchBits.Test(RatBite.BoneID)) { item->Animation.RequiredState = RAT_STATE_IDLE; diff --git a/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp b/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp index d5093d5a6..cdbb893a8 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_silencer.cpp @@ -116,7 +116,7 @@ namespace TEN::Entities::Creatures::TR2 if (ai.ahead) extraHeadRot.y = ai.angle; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; break; @@ -321,7 +321,7 @@ namespace TEN::Entities::Creatures::TR2 extraHeadRot.y = ai.angle; } - if (item->Animation.RequiredState == NO_STATE && + if (item->Animation.RequiredState == NO_VALUE && (item->Animation.AnimNumber == GetAnimIndex(*item, SILENCER_ANIM_RUN_FORWARD_SHOOT_LEFT) && item->Animation.FrameNumber == GetFrameIndex(item, 1) || item->Animation.AnimNumber == GetAnimIndex(*item, SILENCER_ANIM_RUN_FORWARD_SHOOT_RIGHT) && diff --git a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp index 6f3a2f029..4b573f7b5 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp @@ -54,7 +54,7 @@ namespace TEN::Entities::Creatures::TR2 static void CreateSkidooGun(ItemInfo& riderItem) { int skidooItemNumber = CreateItem(); - if (skidooItemNumber == NO_ITEM) + if (skidooItemNumber == NO_VALUE) { TENLog("Failed to create ID_SNOWMOBILE_GUN from ID_SNOWMOBILE_DRIVER.", LogLevel::Warning); return; @@ -111,7 +111,7 @@ namespace TEN::Entities::Creatures::TR2 } } - if (Lara.Context.Vehicle == NO_ITEM && item.Animation.Velocity.z > 0.0f) + if (Lara.Context.Vehicle == NO_VALUE && item.Animation.Velocity.z > 0.0f) DoDamage(laraItem, 100); } @@ -250,7 +250,7 @@ namespace TEN::Entities::Creatures::TR2 { if (creature->Flags == 0 && abs(ai.angle) < SKIDOO_MAN_TARGET_ANGLE && creature->Enemy->HitPoints > 0) { - int damage = (creature->Enemy->IsLara() && GetLaraInfo(creature->Enemy)->Context.Vehicle != NO_ITEM) ? 10 : 50; + int damage = (creature->Enemy->IsLara() && GetLaraInfo(creature->Enemy)->Context.Vehicle != NO_VALUE) ? 10 : 50; ShotLara(skidooItem, &ai, SkidooBiteLeft, 0, damage); diff --git a/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp b/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp index 26b39a5bd..14b8e5f0c 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_yeti.cpp @@ -96,7 +96,7 @@ namespace TEN::Entities::Creatures::TR2 if (creature->Mood == MoodType::Escape) item->Animation.TargetState = 1; - else if (item->Animation.RequiredState != NO_STATE) + else if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (creature->Mood == MoodType::Bored) { diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index cff60fb15..47ec2fa3c 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -139,7 +139,7 @@ namespace TEN::Entities::Vehicles auto* skidooItem = &g_Level.Items[itemNumber]; auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(skidooItem, laraItem, coll, SkidooMountTypes, SKIDOO_MOUNT_DISTANCE); @@ -205,7 +205,7 @@ namespace TEN::Entities::Vehicles auto* lara = GetLaraInfo(laraItem); auto* skidoo = GetSkidooInfo(skidooItem); - if (lara->Context.Vehicle != NO_ITEM) + if (lara->Context.Vehicle != NO_VALUE) { if ((laraItem->Animation.ActiveState == SKIDOO_STATE_DISMOUNT_RIGHT || laraItem->Animation.ActiveState == SKIDOO_STATE_DISMOUNT_LEFT) && TestLastFrame(laraItem)) diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index 5f85dba8e..037c06ab8 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -167,7 +167,7 @@ namespace TEN::Entities::Vehicles auto* speedboatItem = &g_Level.Items[itemNumber]; auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(speedboatItem, laraItem, coll, SpeedboatMountTypes, SPEEDBOAT_MOUNT_DISTANCE, LARA_HEIGHT); @@ -278,7 +278,7 @@ namespace TEN::Entities::Vehicles laraItem->Animation.Velocity.y = -50; laraItem->Pose.Orientation.x = 0; laraItem->Pose.Orientation.z = 0; - lara->Context.Vehicle = NO_ITEM; // Leave vehicle itself active for inertia. + lara->Context.Vehicle = NO_VALUE; // Leave vehicle itself active for inertia. int x = laraItem->Pose.Position.x + 360 * phd_sin(laraItem->Pose.Orientation.y); int y = laraItem->Pose.Position.y - 90; @@ -302,7 +302,7 @@ namespace TEN::Entities::Vehicles void SpeedboatDoBoatShift(ItemInfo* speedboatItem, int itemNumber) { short itemNumber2 = g_Level.Rooms[speedboatItem->RoomNumber].itemNumber; - while (itemNumber2 != NO_ITEM) + while (itemNumber2 != NO_VALUE) { auto* item = &g_Level.Items[itemNumber2]; diff --git a/TombEngine/Objects/TR3/Entity/Compsognathus.cpp b/TombEngine/Objects/TR3/Entity/Compsognathus.cpp index 0f418aadc..6c891f5da 100644 --- a/TombEngine/Objects/TR3/Entity/Compsognathus.cpp +++ b/TombEngine/Objects/TR3/Entity/Compsognathus.cpp @@ -15,8 +15,8 @@ #include "Objects/TR3/Object/Corpse.h" #include "Specific/level.h" -using namespace TEN::Math; using namespace TEN::Entities::TR3; +using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 { @@ -117,7 +117,7 @@ namespace TEN::Entities::Creatures::TR3 if (cadaverPos == INVALID_CADAVER_POSITION) { - float shortestDistance = INFINITY; + float shortestDist = INFINITY; for (auto& targetItem : g_Level.Items) { if (!Objects.CheckID(targetItem.ObjectNumber) || targetItem.Index == itemNumber || targetItem.RoomNumber == NO_ROOM) @@ -125,11 +125,12 @@ namespace TEN::Entities::Creatures::TR3 if (SameZone(creature, &targetItem)) { - float distance = Vector3i::Distance(item->Pose.Position, targetItem.Pose.Position); - if (distance < shortestDistance && targetItem.ObjectNumber == ID_CORPSE && targetItem.Active && TriggerActive(&targetItem) && targetItem.ItemFlags[1] == (int)CorpseFlags::Lying) + float dist = Vector3i::Distance(item->Pose.Position, targetItem.Pose.Position); + if (dist < shortestDist && targetItem.ObjectNumber == ID_CORPSE && targetItem.Active && + TriggerActive(&targetItem) && targetItem.ItemFlags[1] == (int)CorpseFlag::Grounded) { cadaverPos = targetItem.Pose.Position.ToVector3(); - shortestDistance = distance; + shortestDist = dist; item->ItemFlags[1] = ATTACK_CADAVER; } } @@ -163,7 +164,7 @@ namespace TEN::Entities::Creatures::TR3 { item->ItemFlags[0] = (random + 0x700) >> 7; - // Scared for less time the more compys there are - adjust this when we've got lots of them. + // Spooked for less time the more compys there are. Adjust when there are many of them. item->ItemFlags[3] = LaraItem->Animation.Velocity.z * 2; } } @@ -260,9 +261,13 @@ namespace TEN::Entities::Creatures::TR3 if (item->ItemFlags[1] == ATTACK_PLAYER) { if (Random::TestProbability(1 / 2.0f)) + { item->Animation.TargetState = COMPY_STATE_ATTACK; + } else + { item->Animation.TargetState = COMPY_STATE_JUMP_ATTACK; + } } else { @@ -279,9 +284,13 @@ namespace TEN::Entities::Creatures::TR3 if (ai.ahead && ai.distance < (COMPY_ATTACK_RANGE * 3) && item->ItemFlags[1] == ATTACK_CADAVER) { if (Random::TestProbability(1 / 2.0f)) + { item->Animation.TargetState = COMPY_STATE_ATTACK; + } else + { item->Animation.TargetState = COMPY_STATE_JUMP_ATTACK; + } } else if (ai.distance > (COMPY_ATTACK_RANGE * 3)) { @@ -291,9 +300,13 @@ namespace TEN::Entities::Creatures::TR3 else { if (Random::TestProbability(COMPY_JUMP_ATTACK_CHANCE)) + { item->Animation.TargetState = COMPY_STATE_JUMP_ATTACK; + } else + { item->Animation.TargetState = COMPY_STATE_RUN_FORWARD; + } } break; diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp new file mode 100644 index 000000000..4701ee348 --- /dev/null +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp @@ -0,0 +1,427 @@ +#include "framework.h" +#include "Objects/TR3/Entity/FishSwarm.h" + +#include "Game/collision/collide_item.h" +#include "Game/collision/collide_room.h" +#include "Game/collision/Point.h" +#include "Game/control/box.h" +#include "Game/control/flipeffect.h" +#include "Game/effects/effects.h" +#include "Game/effects/tomb4fx.h" +#include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Game/Lara/lara_helpers.h" +#include "Game/misc.h" +#include "Game/Setup.h" +#include "Math/Math.h" +#include "Objects/TR3/Object/Corpse.h" +#include "Renderer/Renderer.h" +#include "Specific/clock.h" +#include "Specific/level.h" + +using namespace TEN::Collision::Point; +using namespace TEN::Entities::TR3; +using namespace TEN::Math; +using namespace TEN::Renderer; + +// NOTES: +// HitPoints = Fish count on spawn. +// ItemFlags[0] = leader item number. +// ItemFlags[1] = target item number. +// ItemFlags[2] = OCB orientation when in patrol mode. +// ItemFlags[3] = Start OCB of AI_FOLLOW. NOTE: Cannot change. +// ItemFlags[4] = Check if target is a corpse. +// ItemFlags[5] = Fish count. +// ItemFlags[6] = Is patrolling. +// ItemFlags[7] = Distance to player. + +namespace TEN::Entities::Creatures::TR3 +{ + constexpr auto FISH_HARM_DAMAGE = 3; + constexpr auto FISH_VELOCITY_MAX = 10.0f; + constexpr auto FISH_COHESION_FACTOR = 100.1f; + constexpr auto FISH_SPACING_FACTOR = 600.0f; + constexpr auto FISH_CATCH_UP_FACTOR = 0.2f; + constexpr auto FISH_TARGET_DISTANCE_MAX = SQUARE(BLOCK(0.01f)); + constexpr auto FISH_BASE_SEPARATION_DISTANCE = 210.0f; + constexpr auto FISH_UPDATE_INTERVAL_TIME = 0.2f; + + std::vector FishSwarm = {}; + + void InitializeFishSwarm(short itemNumber) + { + constexpr auto DEFAULT_FISH_COUNT = 24; + + auto& item = g_Level.Items[itemNumber]; + + item.StartPose.Position = item.Pose.Position; + item.Animation.Velocity.z = Random::GenerateFloat(32.0f, 160.0f); + item.HitPoints = DEFAULT_FISH_COUNT; + item.ItemFlags[0] = item.Index; + item.ItemFlags[1] = item.Index; + item.ItemFlags[5] = 0; + + if (item.AIBits) + item.ItemFlags[6] = true; + } + + static void SpawnFishSwarm(ItemInfo& item) + { + constexpr auto VEL_MAX = 48.0f; + constexpr auto VEL_MIN = 16.0f; + constexpr auto START_ORIENT_CONSTRAINT = std::pair( + EulerAngles(ANGLE(-3.0f), ANGLE(-6.0f), 0), + EulerAngles(ANGLE(3.0f), ANGLE(6.0f), 0)); + + // Create new fish. + auto& fish = GetNewEffect(FishSwarm, FISH_COUNT_MAX); + + fish.MeshIndex = abs(item.TriggerFlags); + fish.IsLethal = (item.TriggerFlags < 0) ? true : false; + fish.IsPatrolling = item.ItemFlags[6]; + + fish.Position = item.Pose.Position.ToVector3(); + fish.RoomNumber = item.RoomNumber; + fish.Orientation.x = Random::GenerateAngle(START_ORIENT_CONSTRAINT.first.x, START_ORIENT_CONSTRAINT.second.x); + fish.Orientation.y = (item.Pose.Orientation.y + ANGLE(180.0f)) + Random::GenerateAngle(START_ORIENT_CONSTRAINT.first.y, START_ORIENT_CONSTRAINT.second.y); + fish.Velocity = Random::GenerateFloat(VEL_MIN, VEL_MAX); + + fish.Life = 1.0f; + fish.Undulation = Random::GenerateFloat(0.0f, PI_MUL_2); + + fish.LeaderItemPtr = &g_Level.Items[item.ItemFlags[0]]; + } + + void ControlFishSwarm(short itemNumber) + { + if (!CreatureActive(itemNumber)) + return; + + auto& item = g_Level.Items[itemNumber]; + auto& creature = *GetCreatureInfo(&item); + const auto& playerItem = *LaraItem; + + AI_INFO ai; + CreatureAIInfo(&item, &ai); + + if (item.HitPoints != NOT_TARGETABLE) + { + int fishCount = item.HitPoints - item.ItemFlags[5]; + + if (fishCount < 0) + { + int fishToTurnOff = -fishCount; + for (auto& fish : FishSwarm) + { + if (fish.LeaderItemPtr == &item && fish.Life > 0.0f) + { + fish.Life = 0.0f; + fishToTurnOff--; + if (fishToTurnOff == 0) + break; + } + } + } + else if (fishCount > 0) + { + for (int i = 0; i < fishCount; i++) + SpawnFishSwarm(item); + } + + item.ItemFlags[5] = item.HitPoints; + item.HitPoints = NOT_TARGETABLE; + } + + int dx = creature.Target.x - item.Pose.Position.x; + int dz = creature.Target.z - item.Pose.Position.z; + ai.distance = SQUARE(dx) + SQUARE(dz); + + item.Animation.Velocity.z = FISH_VELOCITY_MAX; + + auto& playerRoom = g_Level.Rooms[playerItem.RoomNumber]; + + // Check if corpse is near. + // TODO: In future also check for other enemies like sharks or crocodile. + if (!item.ItemFlags[4] && TestGlobalTimeInterval(FISH_UPDATE_INTERVAL_TIME)) + { + float closestDist = INFINITY; + for (auto& targetItem : g_Level.Items) + { + if (!Objects.CheckID(targetItem.ObjectNumber) || targetItem.Index == itemNumber || targetItem.RoomNumber == NO_ROOM) + continue; + + if (SameZone(&creature, &targetItem) && item.TriggerFlags < 0) + { + float dist = Vector3i::Distance(item.Pose.Position, targetItem.Pose.Position); + if (dist < closestDist && + targetItem.ObjectNumber == ID_CORPSE && + targetItem.Active && TriggerActive(&targetItem) && + targetItem.ItemFlags[1] == (int)CorpseFlag::Grounded && + TestEnvironment(ENV_FLAG_WATER, targetItem.RoomNumber)) + { + item.ItemFlags[4] = 1; + closestDist = dist; + item.ItemFlags[1] = targetItem.Index; // Target corpse. + } + } + } + } + + if (item.ItemFlags[7] < BLOCK(7) && TestEnvironment(ENV_FLAG_WATER, &playerRoom) && + item.TriggerFlags < 0 && !item.ItemFlags[4]) + { + item.ItemFlags[1] = playerItem.Index; + item.ItemFlags[4] = 0; + item.ItemFlags[2] = 0; + } + // Circle around leader item. + else if (!item.ItemFlags[4]) + { + item.ItemFlags[1] = item.ItemFlags[0]; + item.ItemFlags[4] = 0; + } + + // Follow path. + if (item.AIBits && !item.ItemFlags[4]) + { + FindAITargetObject(&creature, ID_AI_FOLLOW, item.ItemFlags[3] + item.ItemFlags[2], false); + + if (creature.AITarget->TriggerFlags == (item.ItemFlags[3] + item.ItemFlags[2]) && + creature.AITarget->ObjectNumber == ID_AI_FOLLOW) + { + item.ItemFlags[1] = creature.AITarget->Index; + } + else + { + item.ItemFlags[2] = 0; + } + + item.ItemFlags[4] = 0; + } + + for (auto& fish : FishSwarm) + { + if (fish.LeaderItemPtr == &item) + { + if (fish.Life <= 0.0f) + continue; + + fish.RoomNumber = item.RoomNumber; + fish.TargetItemPtr = &g_Level.Items[item.ItemFlags[1]]; + } + } + } + + static Vector3 GetFishStartPosition(const ItemInfo& item) + { + constexpr auto BUFFER = BLOCK(0.1f); + constexpr auto SPHEROID_SEMI_MAJOR_AXIS = Vector3(BLOCK(2), BLOCK(1), BLOCK(5)); + + auto pos = Random::GeneratePointInSpheroid(item.StartPose.Position.ToVector3(), EulerAngles::Identity, SPHEROID_SEMI_MAJOR_AXIS); + + // Get point collision. + auto pointColl = GetPointCollision(pos, item.RoomNumber); + int waterHeight = GetWaterHeight(pointColl.GetPosition().x, pointColl.GetPosition().y, pointColl.GetPosition().z, pointColl.GetRoomNumber()); + + // 1) Test for water room. + if (!TestEnvironment(ENV_FLAG_WATER, pointColl.GetRoomNumber())) + return Vector3::Zero; + + // 2) Assess point collision. + if (pos.y >= (pointColl.GetFloorHeight() - BUFFER) || + pos.y <= (waterHeight + BUFFER) || + pointColl.GetSector().IsWall(item.Pose.Position.x + BUFFER, item.Pose.Position.z + BUFFER) || + pointColl.GetSector().IsWall(item.Pose.Position.x - BUFFER, item.Pose.Position.z - BUFFER)) + { + return Vector3::Zero; + } + + return pos; + } + + void UpdateFishSwarm() + { + constexpr auto WATER_SURFACE_OFFSET = CLICK(0.5f); + constexpr auto FLEE_VEL = 20.0f; + + static const auto SPHERE = BoundingSphere(Vector3::Zero, BLOCK(1 / 8.0f)); + + if (FishSwarm.empty()) + return; + + const auto& playerItem = *LaraItem; + const auto& player = GetLaraInfo(playerItem); + + const FishData* closestFishPtr = nullptr; + float minDistToTarget = INFINITY; + int minDist = INT_MAX; + + int fishID = 0; + for (auto& fish : FishSwarm) + { + if (fish.Life <= 0.0f) + continue; + + // Increase separation distance for each fish. + float separationDist = FISH_BASE_SEPARATION_DISTANCE + (fishID * 3); + fishID += 1; + + auto& leaderItem = *fish.LeaderItemPtr; + if (!leaderItem.ItemFlags[2] && fish.TargetItemPtr == fish.LeaderItemPtr) + { + if (!fish.IsPatrolling) + { + fish.TargetItemPtr->Pose.Position = GetFishStartPosition(leaderItem); + + if (fish.TargetItemPtr->Pose.Position != Vector3::Zero) + leaderItem.ItemFlags[2] = 1; + } + } + + int enemyVel = (fish.TargetItemPtr != fish.LeaderItemPtr) ? 16.0f : 26.0f; + + fish.PositionTarget = Random::GeneratePointInSphere(SPHERE); + + // Calculate desired position based on target object and random offsets. + auto desiredPos = fish.TargetItemPtr->Pose.Position + fish.PositionTarget; + auto dir = desiredPos - fish.Position; + + auto dirs = dir.ToVector3(); + dirs.Normalize(); + auto dirNorm = dirs; + + // Define cohesion factor to keep fish close together. + float distToTarget = dirs.Length(); + + float targetVel = (distToTarget * FISH_COHESION_FACTOR) + Random::GenerateFloat(3.0f, 5.0f); + fish.Velocity = std::min(targetVel, fish.TargetItemPtr->Animation.Velocity.z - 21.0f); + + // If fish is too far from target, increase velocity to catch up. + if (distToTarget > FISH_TARGET_DISTANCE_MAX) + fish.Velocity += FISH_CATCH_UP_FACTOR; + + // Translate. + auto moveDir = fish.Orientation.ToDirection(); + moveDir.Normalize(); + fish.Position += (moveDir * fish.Velocity) / enemyVel; + fish.Position += (moveDir * FISH_SPACING_FACTOR) / enemyVel; + + auto orientTo = Geometry::GetOrientToPoint(fish.Position, desiredPos.ToVector3()); + fish.Orientation.Lerp(orientTo, 0.1f); + + for (const auto& otherFish : FishSwarm) + { + if (&fish == &otherFish) + continue; + + float distToOtherFish = Vector3i::Distance(fish.Position, otherFish.Position); + float distToPlayer = Vector3i::Distance(fish.Position, playerItem.Pose.Position); + float distToTarget = Vector3i::Distance(fish.Position, otherFish.PositionTarget); + + leaderItem.ItemFlags[7] = distToPlayer; + + // Update the index of the nearest fish to the target + if (distToTarget < minDistToTarget && + (fish.TargetItemPtr == fish.LeaderItemPtr || fish.TargetItemPtr->ObjectNumber == ID_AI_FOLLOW)) + { + minDistToTarget = distToTarget; + closestFishPtr = &otherFish; + } + + if (fish.TargetItemPtr != fish.LeaderItemPtr && fish.TargetItemPtr->ObjectNumber != ID_AI_FOLLOW) + separationDist = 80.0f; + + if (distToOtherFish < separationDist) + { + auto separationDir = fish.Position - otherFish.Position; + separationDir.Normalize(); + + fish.Position += separationDir * (separationDist - distToOtherFish); + } + else + { + fish.Velocity += FISH_CATCH_UP_FACTOR; + } + + // Orient to fish nearest to target. Prevents other fish from swimming forward but oriented elsewhere. + if (closestFishPtr != nullptr && + fish.Orientation.x != closestFishPtr->Orientation.x && separationDist > 30.0f && + (fish.TargetItemPtr == fish.LeaderItemPtr || fish.TargetItemPtr->ObjectNumber == ID_AI_FOLLOW)) + { + separationDist--; + auto orientTo = Geometry::GetOrientToPoint(fish.Position, closestFishPtr->Position); + fish.Velocity += FISH_CATCH_UP_FACTOR; + } + + // If player is too close and fish are not lethal, flee. + if ((distToPlayer < separationDist * 3) && fish.IsLethal == false) + { + auto separationDir = fish.Position - playerItem.Pose.Position.ToVector3(); + separationDir.Normalize(); + + fish.Position += separationDir * FLEE_VEL; + + auto orientTo = Geometry::GetOrientToPoint(fish.Position, separationDir); + fish.Orientation.Lerp(orientTo, 0.05f); + + fish.Velocity -= std::min(FLEE_VEL, fish.TargetItemPtr->Animation.Velocity.z - 1.0f); + } + } + + auto pointColl = GetPointCollision(fish.Position, fish.RoomNumber); + const auto& room = g_Level.Rooms[fish.RoomNumber]; + + // Update fish room number. + if (pointColl.GetRoomNumber() != fish.RoomNumber && + pointColl.GetRoomNumber() != NO_VALUE && + TestEnvironment(ENV_FLAG_WATER, pointColl.GetRoomNumber())) + { + fish.RoomNumber = pointColl.GetRoomNumber(); + } + + // Clamp position to slightly below water surface. + int waterHeight = GetWaterHeight(fish.Position.x, fish.Position.y, fish.Position.z, fish.RoomNumber); + if (fish.Position.y < (waterHeight + WATER_SURFACE_OFFSET)) + fish.Position.y = waterHeight + WATER_SURFACE_OFFSET; + + if (ItemNearTarget(fish.Position, fish.TargetItemPtr, CLICK(0.5f)) && + fish.LeaderItemPtr != fish.TargetItemPtr) + { + if (fish.TargetItemPtr->ObjectNumber != ID_AI_FOLLOW) + { + DoBloodSplat( + fish.Position.x, fish.Position.y, fish.Position.z, + Random::GenerateFloat(4.0f, 8.0f), + fish.TargetItemPtr->Pose.Orientation.y, fish.TargetItemPtr->RoomNumber); + DoDamage(fish.TargetItemPtr, FISH_HARM_DAMAGE); + } + else + { + leaderItem.ItemFlags[2]++; + } + } + else if (ItemNearTarget(fish.Position, fish.TargetItemPtr, BLOCK(2)) && + fish.LeaderItemPtr == fish.TargetItemPtr) + { + leaderItem.ItemFlags[2] = 0; + } + + // Calculate undulation angle based on sine wave and fish velocity. + float movementValue = abs(moveDir.z); + float undulationAngle = sin(fish.Undulation) * ANGLE(std::clamp(movementValue * 7.0f, 4.0f, 7.0f)); + + // Apply undulation. + fish.Orientation.y += undulationAngle; + + // Update undulation. + fish.Undulation += std::clamp(movementValue / 2, 0.3f, 1.0f); + if (fish.Undulation > PI_MUL_2) + fish.Undulation -= PI_MUL_2; + } + } + + void ClearFishSwarm() + { + FishSwarm.clear(); + } +} diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.h b/TombEngine/Objects/TR3/Entity/FishSwarm.h new file mode 100644 index 000000000..1a1dfe471 --- /dev/null +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.h @@ -0,0 +1,37 @@ +#pragma once +#include "Game/items.h" +#include "Math/Math.h" + +using namespace TEN::Math; + +namespace TEN::Entities::Creatures::TR3 +{ + constexpr auto FISH_COUNT_MAX = 512; + + struct FishData + { + int MeshIndex = 0; + bool IsPatrolling = false; + bool IsLethal = false; + + Vector3 Position = Vector3::Zero; + int RoomNumber = 0; + Vector3 PositionTarget = Vector3::Zero; + EulerAngles Orientation = EulerAngles::Identity; + float Velocity = 0.0f; + + float Life = 0.0f; + float Undulation = 0.0f; + + ItemInfo* TargetItemPtr = nullptr; + ItemInfo* LeaderItemPtr = nullptr; + }; + + extern std::vector FishSwarm; + + void InitializeFishSwarm(short itemNumber); + void ControlFishSwarm(short itemNumber); + + void UpdateFishSwarm(); + void ClearFishSwarm(); +} diff --git a/TombEngine/Objects/TR3/Entity/Lizard.cpp b/TombEngine/Objects/TR3/Entity/Lizard.cpp index da395f0d3..d5a10e72b 100644 --- a/TombEngine/Objects/TR3/Entity/Lizard.cpp +++ b/TombEngine/Objects/TR3/Entity/Lizard.cpp @@ -68,7 +68,7 @@ namespace TEN::Entities::Creatures::TR3 { auto& creature = *GetCreatureInfo(&item); - return (creature.Enemy && creature.Enemy->BoxNumber != NO_BOX && + return (creature.Enemy && creature.Enemy->BoxNumber != NO_VALUE && (g_Level.Boxes[creature.Enemy->BoxNumber].flags & BLOCKABLE)); } @@ -140,7 +140,7 @@ namespace TEN::Entities::Creatures::TR3 } else if (creature.Mood == MoodType::Bored) { - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } diff --git a/TombEngine/Objects/TR3/Entity/PunaBoss.cpp b/TombEngine/Objects/TR3/Entity/PunaBoss.cpp index 9fe54f0a2..0597ede22 100644 --- a/TombEngine/Objects/TR3/Entity/PunaBoss.cpp +++ b/TombEngine/Objects/TR3/Entity/PunaBoss.cpp @@ -66,7 +66,7 @@ namespace TEN::Entities::Creatures::TR3 static short GetPunaHeadOrientToTarget(ItemInfo& item, const Vector3& target) { if (!item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard)) - return NO_ITEM; + return NO_VALUE; auto pos = GetJointPosition(&item, PunaBossHeadBite).ToVector3(); auto orient = Geometry::GetOrientToPoint(pos, target); @@ -94,7 +94,7 @@ namespace TEN::Entities::Creatures::TR3 static Vector3 GetLizardTargetPosition(ItemInfo& item) { - if (!item.TestFlagField((int)BossItemFlags::ItemNumber, NO_ITEM)) + if (!item.TestFlagField((int)BossItemFlags::ItemNumber, NO_VALUE)) { const auto& targetEntity = g_Level.Items[item.GetFlagField((int)BossItemFlags::ItemNumber)]; return targetEntity.Pose.Position.ToVector3(); @@ -108,11 +108,11 @@ namespace TEN::Entities::Creatures::TR3 static int GetLizardItemNumber(const ItemInfo& item) { if (!item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard)) - return NO_ITEM; + return NO_VALUE; auto lizardList = GetLizardEntityList(item); if (lizardList.empty()) - return NO_ITEM; + return NO_VALUE; if (lizardList.size() == 1) return lizardList[0]; @@ -199,7 +199,7 @@ namespace TEN::Entities::Creatures::TR3 static void SpawnLizard(ItemInfo& item) { - if (!item.TestFlagField((int)BossItemFlags::ItemNumber, NO_ITEM)) + if (!item.TestFlagField((int)BossItemFlags::ItemNumber, NO_VALUE)) { auto itemNumber = item.GetFlagField((int)BossItemFlags::ItemNumber); auto& currentItem = g_Level.Items[itemNumber]; @@ -289,7 +289,7 @@ namespace TEN::Entities::Creatures::TR3 item.SetFlagField((int)BossItemFlags::ShieldIsEnabled, 1); // Activated at start. item.SetFlagField((int)BossItemFlags::AttackCount, 0); item.SetFlagField((int)BossItemFlags::DeathCount, 0); - item.SetFlagField((int)BossItemFlags::ItemNumber, NO_ITEM); + item.SetFlagField((int)BossItemFlags::ItemNumber, NO_VALUE); item.SetFlagField((int)BossItemFlags::ExplodeCount, 0); // If there is no lizard nearby, remove the lizard flag. @@ -379,7 +379,7 @@ namespace TEN::Entities::Creatures::TR3 } else if (item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard) && item.TestFlagField((int)BossItemFlags::AttackType, (int)PunaAttackType::SummonLightning) && - item.TestFlagField((int)BossItemFlags::ItemNumber, NO_ITEM) && + item.TestFlagField((int)BossItemFlags::ItemNumber, NO_VALUE) && !item.TestFlagField((int)BossItemFlags::AttackType, (int)PunaAttackType::Wait) && isLizardActiveNearby) { // Get random lizard item number. @@ -388,7 +388,7 @@ namespace TEN::Entities::Creatures::TR3 } else if (item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard) && item.TestFlagField((int)BossItemFlags::AttackType, (int)PunaAttackType::Wait) && - !item.TestFlagField((int)BossItemFlags::ItemNumber, NO_ITEM)) + !item.TestFlagField((int)BossItemFlags::ItemNumber, NO_VALUE)) { // Rotate to idle position while player fights lizard. auto targetOrient = EulerAngles(item.Pose.Orientation.x, item.GetFlagField((int)BossItemFlags::Rotation), item.Pose.Orientation.z); @@ -402,7 +402,7 @@ namespace TEN::Entities::Creatures::TR3 // Reset the attack type, attack count, itemNumber, and restart the sequence. item.SetFlagField((int)BossItemFlags::AttackType, (int)PunaAttackType::DeathLightning); item.SetFlagField((int)BossItemFlags::AttackCount, 0); - item.SetFlagField((int)BossItemFlags::ItemNumber, NO_ITEM); + item.SetFlagField((int)BossItemFlags::ItemNumber, NO_VALUE); } } @@ -440,7 +440,7 @@ namespace TEN::Entities::Creatures::TR3 { item.SetFlagField((int)BossItemFlags::AttackType, (int)PunaAttackType::SummonLightning); - if (!item.TestFlagField((int)BossItemFlags::ItemNumber, NO_ITEM)) + if (!item.TestFlagField((int)BossItemFlags::ItemNumber, NO_VALUE)) { if (headYOrient > ANGLE(-1.0f) && headYOrient < ANGLE(1.0f)) { @@ -470,7 +470,7 @@ namespace TEN::Entities::Creatures::TR3 { if (item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard) && item.TestFlagField((int)BossItemFlags::AttackType, (int)PunaAttackType::SummonLightning) && - !item.TestFlagField((int)BossItemFlags::ItemNumber, NO_ITEM) && isLizardActiveNearby) + !item.TestFlagField((int)BossItemFlags::ItemNumber, NO_VALUE) && isLizardActiveNearby) { SpawnPunaLightning(item, targetPos.ToVector3(), PunaBossHandBite, true); } diff --git a/TombEngine/Objects/TR3/Entity/Shiva.cpp b/TombEngine/Objects/TR3/Entity/Shiva.cpp index 3d74ab035..21ccd1586 100644 --- a/TombEngine/Objects/TR3/Entity/Shiva.cpp +++ b/TombEngine/Objects/TR3/Entity/Shiva.cpp @@ -343,7 +343,7 @@ namespace TEN::Entities::Creatures::TR3 int z = item->Pose.Position.z + BLOCK(1) * phd_cos(item->Pose.Orientation.y + ANGLE(180.0f)); auto box = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetBottomSector().Box; - if (box != NO_BOX && !(g_Level.Boxes[box].flags & BLOCKABLE) && !creature.Flags) + if (box != NO_VALUE && !(g_Level.Boxes[box].flags & BLOCKABLE) && !creature.Flags) item->Animation.TargetState = SHIVA_STATE_WALK_BACK; else item->Animation.TargetState = SHIVA_STATE_GUARD_IDLE; diff --git a/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp b/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp index b358d0fd4..ea752dae8 100644 --- a/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp +++ b/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp @@ -246,7 +246,7 @@ namespace TEN::Entities::Creatures::TR3 static void SpawnSophiaLeighProjectileBolt(ItemInfo& item, ItemInfo* enemy, const CreatureBiteInfo& bite, SophiaData* data, bool isBoltLarge, short angleAdd) { int fxNumber = CreateNewEffect(item.RoomNumber); - if (fxNumber == NO_ITEM) + if (fxNumber == NO_VALUE) return; auto& fx = EffectList[fxNumber]; diff --git a/TombEngine/Objects/TR3/Entity/WaspMutant.cpp b/TombEngine/Objects/TR3/Entity/WaspMutant.cpp index dab4f691a..1e858ae6f 100644 --- a/TombEngine/Objects/TR3/Entity/WaspMutant.cpp +++ b/TombEngine/Objects/TR3/Entity/WaspMutant.cpp @@ -219,7 +219,7 @@ namespace TEN::Entities::Creatures::TR3 creature.MaxTurn = WASP_AIR_TURN_RATE_MAX; creature.Flags = 0; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } @@ -243,7 +243,7 @@ namespace TEN::Entities::Creatures::TR3 creature.MaxTurn = WASP_AIR_TURN_RATE_MAX; creature.Flags = 0; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } diff --git a/TombEngine/Objects/TR3/Entity/Winston.cpp b/TombEngine/Objects/TR3/Entity/Winston.cpp index 8c794bf7e..484d99524 100644 --- a/TombEngine/Objects/TR3/Entity/Winston.cpp +++ b/TombEngine/Objects/TR3/Entity/Winston.cpp @@ -231,7 +231,7 @@ namespace TEN::Entities::Creatures::TR3 case WINSTON_STATE_GUARD_MID: creature.MaxTurn = WINSTON_TURN_RATE_MAX; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) item.Animation.TargetState = item.Animation.RequiredState; if (!item.TriggerFlags) @@ -251,7 +251,7 @@ namespace TEN::Entities::Creatures::TR3 case WINSTON_STATE_GUARD_LOW: creature.MaxTurn = WINSTON_TURN_RATE_MAX; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) item.Animation.TargetState = item.Animation.RequiredState; if (item.HitStatus) @@ -262,7 +262,7 @@ namespace TEN::Entities::Creatures::TR3 case WINSTON_STATE_GUARD_HIGH: creature.MaxTurn = WINSTON_TURN_RATE_MAX; - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) item.Animation.TargetState = item.Animation.RequiredState; if (item.HitStatus) diff --git a/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp b/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp index ff2153d80..7a86c5c01 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp @@ -124,7 +124,7 @@ namespace TEN::Entities::Creatures::TR3 for (auto& targetCreature : ActiveCreatures) { // Ignore itself and invalid entities. - if (targetCreature->ItemNumber == NO_ITEM || targetCreature->ItemNumber == item.Index) + if (targetCreature->ItemNumber == NO_VALUE || targetCreature->ItemNumber == item.Index) continue; auto& currentItem = g_Level.Items[targetCreature->ItemNumber]; @@ -182,7 +182,7 @@ namespace TEN::Entities::Creatures::TR3 auto jointHeadRot = EulerAngles::Identity; auto jointTorsoRot = EulerAngles::Identity; - if (item.BoxNumber != NO_BOX && (g_Level.Boxes[item.BoxNumber].flags & BLOCKED) && item.HitPoints > 0) + if (item.BoxNumber != NO_VALUE && (g_Level.Boxes[item.BoxNumber].flags & BLOCKED) && item.HitPoints > 0) { DoDamage(&item, INT_MAX); DoLotsOfBlood(item.Pose.Position.x, item.Pose.Position.y - (GetRandomControl() & 255) - 32, item.Pose.Position.z, (GetRandomControl() & 127) + 128, GetRandomControl() << 1, item.RoomNumber, 3); diff --git a/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp b/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp index a3f368987..a92765cf8 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_claw_mutant.cpp @@ -149,7 +149,7 @@ namespace TEN::Entities::Creatures::TR3 const auto& creature = *GetCreatureInfo(&item); int plasmaBall = CreateNewEffect(item.RoomNumber); - if (plasmaBall == NO_ITEM) + if (plasmaBall == NO_VALUE) return; auto enemyPos = creature.Enemy->Pose.Position; @@ -378,7 +378,7 @@ namespace TEN::Entities::Creatures::TR3 if (Random::TestProbability(CLAW_MUTANT_WALK_CHANCE)) item.Animation.TargetState = CLAW_MUTANT_STATE_WALK; } - else if (item.Animation.RequiredState != NO_STATE) + else if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } diff --git a/TombEngine/Objects/TR3/Entity/tr3_fish_emitter.cpp b/TombEngine/Objects/TR3/Entity/tr3_fish_emitter.cpp deleted file mode 100644 index b1e1107a4..000000000 --- a/TombEngine/Objects/TR3/Entity/tr3_fish_emitter.cpp +++ /dev/null @@ -1,424 +0,0 @@ -#include "framework.h" -#include "Objects/TR3/Entity/tr3_fish_emitter.h" - -#include "Game/animation.h" -#include "Game/control/control.h" -#include "Game/effects/effects.h" -#include "Game/items.h" -#include "Game/Lara/lara.h" -#include "Math/Math.h" -#include "Objects/TR3/fish.h" -#include "Specific/level.h" - -using namespace TEN::Math; - -namespace TEN::Entities::Creatures::TR3 -{ - int PirahnaHitWait = false; - int CarcassItem = NO_ITEM; - - #define PIRAHNA_DAMAGE 4 - #define X 0 - #define Y 1 - #define Z 2 - #define XYZ 3 - #define MAX_FISH 8 - #define OCB_FISH_LETAL 0x1000 - #define OCB_FISH_EAT_CARCASS 0x2000 - - FishLeaderInfo LeaderInfo[MAX_FISH]; - FishInfo Fishes[MAX_FISH + (MAX_FISH * 24)]; - - unsigned char FishRanges[1][3] = - { - { - 8, - 20, - 3 - } - }; - - void SetupShoal(int shoalNumber) - { - LeaderInfo[shoalNumber].xRange = (FishRanges[shoalNumber][0] + 2) << 8; - LeaderInfo[shoalNumber].zRange = (FishRanges[shoalNumber][1] + 2) << 8; - LeaderInfo[shoalNumber].yRange = (FishRanges[shoalNumber][2]) << 8; - } - - void SetupFish(int leader, ItemInfo* item) - { - int fishXRange = LeaderInfo[leader].xRange; - int fishYRange = LeaderInfo[leader].yRange; - int fishZRange = LeaderInfo[leader].zRange; - - Fishes[leader].x = 0; - Fishes[leader].y = 0; - Fishes[leader].z = 0; - Fishes[leader].angle = 0; - Fishes[leader].speed = (Random::GenerateInt() & 63) + 8; - Fishes[leader].swim = Random::GenerateInt() & 63; - - for (int i = 0; i < 24; i++) - { - Fishes[MAX_FISH + (leader * 24) + i].x = (Random::GenerateInt() % (fishXRange * 2)) - fishXRange; - Fishes[MAX_FISH + (leader * 24) + i].y = (Random::GenerateInt() % fishYRange); - Fishes[MAX_FISH + (leader * 24) + i].destY = (Random::GenerateInt() % fishYRange); - Fishes[MAX_FISH + (leader * 24) + i].z = (Random::GenerateInt() % (fishZRange * 2)) - fishZRange; - Fishes[MAX_FISH + (leader * 24) + i].angle = Random::GenerateInt() & 4095; - Fishes[MAX_FISH + (leader * 24) + i].speed = (Random::GenerateInt() & 31) + 32; - Fishes[MAX_FISH + (leader * 24) + i].swim = Random::GenerateInt() & 63; - } - - LeaderInfo[leader].on = 1; - LeaderInfo[leader].angle = 0; - LeaderInfo[leader].speed = (Random::GenerateInt() & 127) + 32; - LeaderInfo[leader].angleTime = 0; - LeaderInfo[leader].speedTime = 0; - } - - void ControlFish(short itemNumber) - { - auto* item = &g_Level.Items[itemNumber]; - auto* enemy = item; - - if (!TriggerActive(item)) - return; - - int pirahnaAttack = 0; - int angle = 0; - - int leader = item->HitPoints; - if (!LeaderInfo[leader].on) - SetupFish(leader, item); - - if (item->TriggerFlags & OCB_FISH_LETAL) - { - if ((item->TriggerFlags == OCB_FISH_EAT_CARCASS) == 0) - pirahnaAttack = (LaraItem->RoomNumber == item->RoomNumber); - else - { - if (CarcassItem != -1) - pirahnaAttack = 2; - else - pirahnaAttack = (LaraItem->RoomNumber == item->RoomNumber); - } - } - else - pirahnaAttack = 0; - - if (PirahnaHitWait) - PirahnaHitWait--; - - auto* fish = &Fishes[leader]; - - if (pirahnaAttack) - { - if (pirahnaAttack == 1) - enemy = LaraItem; - else - enemy = &g_Level.Items[CarcassItem]; - - LeaderInfo[leader].angle = fish->angle = ((-(Geometry::GetOrientToPoint(Vector3(fish->x + item->Pose.Position.x, 0.0f, fish->z + item->Pose.Position.z), enemy->Pose.Position.ToVector3()).y + ANGLE(90.0f))) / 16) & ANGLE(22.5f); - LeaderInfo[leader].speed = (Random::GenerateInt() & 63) + 192; - } - - int deltaAngle = fish->angle - LeaderInfo[leader].angle; - - if (deltaAngle > 2048) - deltaAngle -= 4096; - else if (deltaAngle < -2048) - deltaAngle += 4096; - - if (deltaAngle > 128) - { - fish->angAdd -= 4; - if (fish->angAdd < -120) - fish->angAdd = -120; - } - else if (deltaAngle < -128) - { - fish->angAdd += 4; - if (fish->angAdd > 120) - fish->angAdd = 120; - } - else - { - fish->angAdd -= fish->angAdd / 4; - if (abs(fish->angAdd) < 4) - fish->angAdd = 0; - } - - fish->angle += fish->angAdd; - - if (deltaAngle > 1024) - fish->angle += fish->angAdd / 4; - fish->angle &= 4095; - - deltaAngle = fish->speed - LeaderInfo[leader].speed; - - if (deltaAngle < -4) - { - deltaAngle = fish->speed + (Random::GenerateInt() & 3) + 1; - if (deltaAngle < 0) - deltaAngle = 0; - - fish->speed = deltaAngle; - } - else if (deltaAngle > 4) - { - deltaAngle = fish->speed - (Random::GenerateInt() & 3) - 1; - if (deltaAngle > 255) - deltaAngle = 255; - - fish->speed = deltaAngle; - } - - fish->swim += fish->speed / 16; - fish->swim &= 63; - - int x = fish->x; - int z = fish->z; - - x -= fish->speed * phd_sin(fish->angle * 16) / 2; - z += fish->speed * phd_cos(fish->angle * 16) / 2; - - if (pirahnaAttack == 0) - { - int fishXRange = LeaderInfo[leader].xRange; - int fishZRange = LeaderInfo[leader].zRange; - - if (z < -fishZRange) - { - z = -fishZRange; - - if (fish->angle < 2048) - LeaderInfo[leader].angle = fish->angle - ((Random::GenerateInt() & 127) + 128); - else - LeaderInfo[leader].angle = fish->angle + ((Random::GenerateInt() & 127) + 128); - - LeaderInfo[leader].angleTime = (Random::GenerateInt() & 15) + 8; - LeaderInfo[leader].speedTime = 0; - } - else if (z > fishZRange) - { - z = fishZRange; - - if (fish->angle > 3072) - LeaderInfo[leader].angle = fish->angle - ((Random::GenerateInt() & 127) + 128); - else - LeaderInfo[leader].angle = fish->angle + ((Random::GenerateInt() & 127) + 128); - - LeaderInfo[leader].angleTime = (Random::GenerateInt() & 15) + 8; - LeaderInfo[leader].speedTime = 0; - } - - if (x < -fishXRange) - { - x = -fishXRange; - - if (fish->angle < 1024) - LeaderInfo[leader].angle = fish->angle - ((Random::GenerateInt() & 127) + 128); - else - LeaderInfo[leader].angle = fish->angle + ((Random::GenerateInt() & 127) + 128); - - LeaderInfo[leader].angleTime = (Random::GenerateInt() & 15) + 8; - LeaderInfo[leader].speedTime = 0; - } - else if (x > fishXRange) - { - x = fishXRange; - - if (fish->angle < 3072) - LeaderInfo[leader].angle = fish->angle - ((Random::GenerateInt() & 127) + 128); - else - LeaderInfo[leader].angle = fish->angle + ((Random::GenerateInt() & 127) + 128); - - LeaderInfo[leader].angleTime = (Random::GenerateInt() & 15) + 8; - LeaderInfo[leader].speedTime = 0; - } - - if ((Random::GenerateInt() & 15) == 0) - LeaderInfo[leader].angleTime = 0; - - if (LeaderInfo[leader].angleTime) - LeaderInfo[leader].angleTime--; - else - { - LeaderInfo[leader].angleTime = (Random::GenerateInt() & 15) + 8; - int angAdd = ((Random::GenerateInt() & 63) + 16) - 8 - 32; - - if ((Random::GenerateInt() & 3) == 0) - LeaderInfo[leader].angle += angAdd * 32; - else - LeaderInfo[leader].angle += angAdd; - - LeaderInfo[leader].angle &= 4095; - } - - if (LeaderInfo[leader].speedTime) - LeaderInfo[leader].speedTime--; - else - { - LeaderInfo[leader].speedTime = (Random::GenerateInt() & 31) + 32; - - if ((Random::GenerateInt() & 7) == 0) - LeaderInfo[leader].speed = (Random::GenerateInt() & 127) + 128; - else if ((Random::GenerateInt() & 3) == 0) - LeaderInfo[leader].speed += (Random::GenerateInt() & 127) + 32; - else if (LeaderInfo[leader].speed > 140) - LeaderInfo[leader].speed -= (Random::GenerateInt() & 31) + 48; - else - { - LeaderInfo[leader].speedTime = (Random::GenerateInt() & 3) + 4; - LeaderInfo[leader].speed += (Random::GenerateInt() & 31) - 15; - } - } - - } - - int ftx = x; - int ftz = z; - - fish->x = x; - fish->z = z; - - fish = (FishInfo*)&Fishes[MAX_FISH + (leader * 24)]; - - for (int i = 0; i < 24; i++) - { - if (item->Flags & OCB_FISH_LETAL) - { - Pose pos; - pos.Position.x = item->Pose.Position.x + fish->x; - pos.Position.y = item->Pose.Position.y + fish->y; - pos.Position.z = item->Pose.Position.z + fish->z; - - if (FishNearLara(&pos, 256, (pirahnaAttack < 2) ? LaraItem : enemy)) - { - if (PirahnaHitWait == 0) - { - DoBloodSplat(item->Pose.Position.x + fish->x, item->Pose.Position.y + fish->y, item->Pose.Position.z + fish->z, 0, 0, (pirahnaAttack < 2) ? LaraItem->RoomNumber : enemy->RoomNumber); - PirahnaHitWait = 8; - } - - if (pirahnaAttack != 2) - DoDamage(LaraItem, PIRAHNA_DAMAGE); - } - } - - angle = ((-(Geometry::GetOrientToPoint(Vector3(fish->x, 0.0f, fish->z), Vector3(ftx, 0.0f, ftz)).y + ANGLE(90.0f))) / 16) & ANGLE(22.5f); - int dx = fish->x - ftx + ((24 - i) * 128); - int dz = fish->z - ftz - ((24 - i) * 128); - - dx *= dx; - dz *= dz; - - deltaAngle = fish->angle - angle; - - if (deltaAngle > 2048) - deltaAngle -= 4096; - else if (deltaAngle < -2048) - deltaAngle += 4096; - - if (deltaAngle > 128) - { - fish->angAdd -= 4; - if (fish->angAdd < -92 - (i / 2)) - fish->angAdd = -92 - (i / 2); - } - else if (deltaAngle < -128) - { - fish->angAdd += 4; - if (fish->angAdd > 92 + (i / 2)) - fish->angAdd = 92 + (i / 2); - } - else - { - fish->angAdd -= fish->angAdd / 4; - if (abs(fish->angAdd) < 4) - fish->angAdd = 0; - } - - fish->angle += fish->angAdd; - - if (deltaAngle > 1024) - fish->angle += fish->angAdd / 4; - fish->angle &= 4095; - - if ((dx + dz) < (0x100000 + ((i * 128) * (i * 128)))) - { - if (fish->speed > 32 + (i * 2)) - fish->speed -= fish->speed / 32; - } - else - { - if (fish->speed < 160 + (i / 2)) - fish->speed += (Random::GenerateInt() & 3) + 1 + (i / 2); - - if (fish->speed > 160 + (i / 2) - (i * 4)) - fish->speed = 160 + (i / 2) - (i * 4); - } - - if (Random::GenerateInt() & 1) - fish->speed -= Random::GenerateInt() & 1; - else - fish->speed += Random::GenerateInt() & 1; - - if (fish->speed < 32) - fish->speed = 32; - else if (fish->speed > 200) - fish->speed = 200; - - fish->swim += (fish->speed / 16) + (fish->speed / 32); - fish->swim &= 63; - - x = fish->x - fish->speed * phd_sin(fish->angle * 16) / 2; - z = fish->z + fish->speed * phd_cos(fish->angle * 16) / 2; - - if (z < -32000) - z = -32000; - else if (z > 32000) - z = 32000; - if (x < -32000) - x = -32000; - else if (x > 32000) - x = 32000; - - fish->x = x; - fish->z = z; - - if (pirahnaAttack == 0) - { - if (abs(fish->y - fish->destY) < 16) - fish->destY = Random::GenerateInt() % LeaderInfo[leader].yRange; - } - else - { - int y = enemy->Pose.Position.y - item->Pose.Position.y; - if (abs(fish->y - fish->destY) < 16) - fish->destY = y + (Random::GenerateInt() & 255); - } - - fish->y += (fish->destY - fish->y) / 16; - fish++; - } - } - - bool FishNearLara(Pose* pos, int distance, ItemInfo* item) - { - int x = pos->Position.x - item->Pose.Position.x; - int y = abs(pos->Position.y - item->Pose.Position.y); - int z = pos->Position.z - item->Pose.Position.z; - - if (x < -distance || x > distance || z < -distance || z > distance || y < -BLOCK(3) || y > BLOCK(3)) - return false; - - if ((pow(x, 2) + pow(z, 2)) > pow(distance, 2)) - return false; - - if (y > distance) - return false; - - return true; - } -} diff --git a/TombEngine/Objects/TR3/Entity/tr3_fish_emitter.h b/TombEngine/Objects/TR3/Entity/tr3_fish_emitter.h deleted file mode 100644 index 0e067fccc..000000000 --- a/TombEngine/Objects/TR3/Entity/tr3_fish_emitter.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "Game/items.h" - -namespace TEN::Entities::Creatures::TR3 -{ - void SetupShoal(int shoalNumber); - void ControlFish(short itemNumber); - bool FishNearLara(Pose* pos, int distance, ItemInfo* item); -} diff --git a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp index a8d867df7..57d37d488 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp @@ -101,7 +101,7 @@ namespace TEN::Entities::Creatures::TR3 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; target = &g_Level.Items[currentCreature->ItemNumber]; diff --git a/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp b/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp index 8da52b5ef..2e5f81b20 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_monkey.cpp @@ -127,7 +127,7 @@ namespace TEN::Entities::Creatures::TR3 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; auto* target = &g_Level.Items[currentCreature->ItemNumber]; @@ -151,14 +151,14 @@ namespace TEN::Entities::Creatures::TR3 if (item->AIBits != MODIFY) { - if (item->CarriedItem != NO_ITEM) + if (item->CarriedItem != NO_VALUE) item->MeshBits = 0xFFFFFEFF; else item->MeshBits = ALL_JOINT_BITS; } else { - if (item->CarriedItem != NO_ITEM) + if (item->CarriedItem != NO_VALUE) item->MeshBits = 0xFFFF6E6F; else item->MeshBits = 0xFFFF6F6F; @@ -190,7 +190,7 @@ namespace TEN::Entities::Creatures::TR3 GetCreatureMood(item, &AI, true); - if (Lara.Context.Vehicle != NO_ITEM) + if (Lara.Context.Vehicle != NO_VALUE) creature->Mood = MoodType::Escape; CreatureMood(item, &AI, true); @@ -231,7 +231,7 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.TargetState = MONKEY_STATE_IDLE; else if (creature->Mood == MoodType::Bored) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(0.06f)) item->Animation.TargetState = MONKEY_STATE_WALK_FORWARD; @@ -246,7 +246,7 @@ namespace TEN::Entities::Creatures::TR3 else if ((item->AIBits & FOLLOW) && (creature->ReachedGoal || laraAI.distance > pow(BLOCK(2), 2))) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.ahead) item->Animation.TargetState = MONKEY_STATE_SIT; @@ -292,7 +292,7 @@ namespace TEN::Entities::Creatures::TR3 } else if (creature->Mood == MoodType::Bored) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(0.06f)) item->Animation.TargetState = MONKEY_STATE_WALK_FORWARD; @@ -307,7 +307,7 @@ namespace TEN::Entities::Creatures::TR3 else if (item->AIBits & FOLLOW && (creature->ReachedGoal || laraAI.distance > pow(BLOCK(2), 2))) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.ahead) item->Animation.TargetState = MONKEY_STATE_SIT; @@ -360,11 +360,11 @@ namespace TEN::Entities::Creatures::TR3 item->CarriedItem = creature->Enemy->Index; RemoveDrawnItem(creature->Enemy->Index); creature->Enemy->RoomNumber = NO_ROOM; - creature->Enemy->CarriedItem = NO_ITEM; + creature->Enemy->CarriedItem = NO_VALUE; for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; auto* target = &g_Level.Items[currentCreature->ItemNumber]; @@ -391,7 +391,7 @@ namespace TEN::Entities::Creatures::TR3 carriedItem->Pose.Position = item->Pose.Position; ItemNewRoom(item->CarriedItem, item->RoomNumber); - item->CarriedItem = NO_ITEM; + item->CarriedItem = NO_VALUE; carriedItem->AIBits = GUARD; creature->Enemy = nullptr; diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp index 96f4b2a76..7383b8925 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp @@ -72,7 +72,7 @@ namespace TEN::Entities::Creatures::TR3 if (creature->MuzzleFlash[0].Delay != 0) creature->MuzzleFlash[0].Delay--; - if (item->BoxNumber != NO_BOX && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) + if (item->BoxNumber != NO_VALUE && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) { DoDamage(item, 20); DoLotsOfBlood(item->Pose.Position.x, item->Pose.Position.y - (GetRandomControl() & 255) - 32, item->Pose.Position.z, (GetRandomControl() & 127) + 128, GetRandomControl() * 2, item->RoomNumber, 3); @@ -125,7 +125,7 @@ namespace TEN::Entities::Creatures::TR3 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; auto* target = &g_Level.Items[currentCreature->ItemNumber]; diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp index 56c5182f3..643f4d6c6 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp @@ -77,7 +77,7 @@ namespace TEN::Entities::Creatures::TR3 short head = 0; auto extraTorsoRot = EulerAngles::Identity; - if (item->BoxNumber != NO_BOX && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) + if (item->BoxNumber != NO_VALUE && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) { DoDamage(item, 20); DoLotsOfBlood(item->Pose.Position.x, item->Pose.Position.y - (GetRandomControl() & 255) - 32, item->Pose.Position.z, (GetRandomControl() & 127) + 128, GetRandomControl() * 2, item->RoomNumber, 3); @@ -107,7 +107,7 @@ namespace TEN::Entities::Creatures::TR3 int bestDistance = INT_MAX; for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; auto* target = &g_Level.Items[currentCreature->ItemNumber]; @@ -207,7 +207,7 @@ namespace TEN::Entities::Creatures::TR3 else if (creature->Mood == MoodType::Bored || (item->AIBits & FOLLOW && (creature->ReachedGoal || laraAI.distance > pow(BLOCK(2), 2)))) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.ahead) item->Animation.TargetState = MPSTICK_STATE_STOP; diff --git a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp index 7387baab4..77d4c0558 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp @@ -99,7 +99,7 @@ namespace TEN::Entities::Creatures::TR3 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; auto* targetItem = &g_Level.Items[currentCreature->ItemNumber]; @@ -148,7 +148,7 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = 0; creature->Flags &= ~1; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (creature->Flags & 2) { diff --git a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp index 2b7f9bf0d..92b5c5a95 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp @@ -62,7 +62,7 @@ namespace TEN::Entities::Creatures::TR3 static void ShootHarpoon(ItemInfo* item, Vector3i pos, short velocity, short yRot, short roomNumber) { short harpoonItemNumber = CreateItem(); - if (harpoonItemNumber == NO_ITEM) + if (harpoonItemNumber == NO_VALUE) return; auto* harpoonItem = &g_Level.Items[harpoonItemNumber]; diff --git a/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp b/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp index db8e7320c..2977c9c87 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tiger.cpp @@ -109,7 +109,7 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = 0; creature->Flags = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = item->Animation.RequiredState; } diff --git a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp index 27728f2a3..9a4ed5ac5 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tony.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tony.cpp @@ -87,7 +87,7 @@ namespace TEN::Entities::Creatures::TR3 static void TriggerTonyEffect(const TonyFlame& flame) { int fxNumber = CreateNewEffect(flame.RoomNumber); - if (fxNumber == NO_ITEM) + if (fxNumber == NO_VALUE) return; auto& fx = EffectList[fxNumber]; diff --git a/TombEngine/Objects/TR3/Entity/tr3_trex.cpp b/TombEngine/Objects/TR3/Entity/tr3_trex.cpp index 015516bb7..d530196a0 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_trex.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_trex.cpp @@ -124,7 +124,7 @@ namespace TEN::Entities::Creatures::TR3 switch (item->Animation.ActiveState) { case TREX_STATE_IDLE: - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (ai.distance < pow(1500, 2) && ai.bite) item->Animation.TargetState = TREX_STATE_ATTACK; diff --git a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp index 3ead12fa9..f97c28937 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp @@ -363,7 +363,7 @@ namespace TEN::Entities::Creatures::TR3 void TribesmanShotDart(ItemInfo* item) { int dartItemNumber = CreateItem(); - if (dartItemNumber == NO_ITEM) + if (dartItemNumber == NO_VALUE) return; auto* dartItem = &g_Level.Items[dartItemNumber]; diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp index 54df7cbfa..c646f49f4 100644 --- a/TombEngine/Objects/TR3/Object/corpse.cpp +++ b/TombEngine/Objects/TR3/Object/corpse.cpp @@ -16,60 +16,63 @@ #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" #include "Game/Setup.h" +#include "Math/Math.h" #include "Sound/sound.h" #include "Specific/level.h" using namespace TEN::Collision::Point; using namespace TEN::Effects::Ripple; -using namespace TEN::Math::Random; +using namespace TEN::Math; namespace TEN::Entities::TR3 { enum CorpseState { - CORPSE_STATE_LYING = 0, - CORPSE_STATE_HANGING = 1, - CORPSE_STATE_FALLING = 2, - CORPSE_STATE_LANDING = 3 + CORPSE_STATE_GROUNDED = 0, + CORPSE_STATE_HANG = 1, + CORPSE_STATE_FALL = 2, + CORPSE_STATE_LAND = 3 }; enum CorpseAnim { - CORPSE_ANIM_LYING = 0, - CORPSE_ANIM_HANGING = 1, - CORPSE_ANIM_FALLING = 2, - CORPSE_ANIM_LANDING = 3 + CORPSE_ANIM_GROUNDED = 0, + CORPSE_ANIM_HANG = 1, + CORPSE_ANIM_FALL = 2, + CORPSE_ANIM_LAND = 3 }; void InitializeCorpse(short itemNumber) { auto& item = g_Level.Items[itemNumber]; + const auto& object = Objects[item.ObjectNumber]; if (item.TriggerFlags == 1) { - item.ItemFlags[1] = (int)CorpseFlags::Hanging; - item.Animation.AnimNumber = Objects[item.ObjectNumber].animIndex + CORPSE_ANIM_HANGING; - item.Animation.ActiveState = CORPSE_STATE_HANGING; + item.ItemFlags[1] = (int)CorpseFlag::Hang; + item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_HANG; + item.Animation.ActiveState = CORPSE_STATE_HANG; } else { - item.ItemFlags[1] = (int)CorpseFlags::Lying; - item.Animation.AnimNumber = Objects[item.ObjectNumber].animIndex + CORPSE_ANIM_LYING; - item.Animation.ActiveState = CORPSE_STATE_LYING; + item.ItemFlags[1] = (int)CorpseFlag::Grounded; + item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_GROUNDED; + item.Animation.ActiveState = CORPSE_STATE_GROUNDED; } AddActiveItem(itemNumber); item.Status = ITEM_ACTIVE; } - void CorpseControl(short itemNumber) + void ControlCorpse(short itemNumber) { auto& item = g_Level.Items[itemNumber]; - - if (item.ItemFlags[1] == (int)CorpseFlags::Falling) + const auto& object = Objects[item.ObjectNumber]; + + if (item.ItemFlags[1] == (int)CorpseFlag::Fall) { bool isWater = TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber); - int VerticalVelCoeff = isWater ? 81.0f : 1.0f; + float verticalVelCoeff = isWater ? 81.0f : 1.0f; int roomNumber = GetPointCollision(item).GetRoomNumber(); if (item.RoomNumber != roomNumber) @@ -108,19 +111,18 @@ namespace TEN::Entities::TR3 item.Animation.IsAirborne = false; item.Animation.Velocity = Vector3::Zero; - item.Animation.TargetState = CORPSE_STATE_LANDING; - item.Animation.AnimNumber = Objects[item.ObjectNumber].animIndex + CORPSE_ANIM_LANDING; - AlignEntityToSurface(&item, Vector2(Objects[item.ObjectNumber].radius)); + item.Animation.TargetState = CORPSE_STATE_LAND; + item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_LAND; + AlignEntityToSurface(&item, Vector2(object.radius)); - item.ItemFlags[1] = (int)CorpseFlags::Lying; + item.ItemFlags[1] = (int)CorpseFlag::Grounded; return; } else { if (isWater) - { - item.Animation.Velocity.y += 0.1f / VerticalVelCoeff; + item.Animation.Velocity.y += 0.1f / verticalVelCoeff; } else { @@ -134,18 +136,20 @@ namespace TEN::Entities::TR3 if (!TriggerActive(&item)) return; - int numMeshes = Objects[item.ObjectNumber].nmeshes; - for (int i = 0; i < numMeshes; i++) + int meshCount = object.nmeshes; + for (int i = 0; i < meshCount; i++) { - auto pos = GetJointPosition(&item, i); - - if (TestProbability(1 / 72.0f)) - SpawnCorpseEffect(pos.ToVector3()); + if (Random::TestProbability(1 / 72.0f)) + { + auto pos = GetJointPosition(&item, i).ToVector3(); + SpawnCorpseEffect(pos); + } } } - void CorpseHit(ItemInfo& target, ItemInfo& source, std::optional pos, int damage, bool isExplosive, int jointIndex) + void HitCorpse(ItemInfo& target, ItemInfo& source, std::optional pos, int damage, bool isExplosive, int jointIndex) { + const auto& object = Objects[target.ObjectNumber]; const auto& player = *GetLaraInfo(&source); if (pos.has_value() && (player.Control.Weapon.GunType == LaraWeaponType::Pistol || @@ -156,13 +160,12 @@ namespace TEN::Entities::TR3 { DoBloodSplat(pos->x, pos->y, pos->z, Random::GenerateInt(4, 8), source.Pose.Orientation.y, pos->RoomNumber); - if (target.ItemFlags[1] == (int)CorpseFlags::Hanging) + if (target.ItemFlags[1] == (int)CorpseFlag::Hang) { - target.ItemFlags[1] = (int)CorpseFlags::Falling; - target.Animation.AnimNumber = Objects[target.ObjectNumber].animIndex + CORPSE_ANIM_FALLING; - target.Animation.ActiveState = CORPSE_STATE_FALLING; + target.ItemFlags[1] = (int)CorpseFlag::Fall; + target.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_FALL; + target.Animation.ActiveState = CORPSE_STATE_FALL; } - } else if (player.Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo == WeaponAmmoType::Ammo2) { diff --git a/TombEngine/Objects/TR3/Object/corpse.h b/TombEngine/Objects/TR3/Object/corpse.h index b2a146a25..1500faf4c 100644 --- a/TombEngine/Objects/TR3/Object/corpse.h +++ b/TombEngine/Objects/TR3/Object/corpse.h @@ -5,15 +5,15 @@ struct ItemInfo; namespace TEN::Entities::TR3 { - - enum class CorpseFlags + enum class CorpseFlag { - Lying = (1 << 0), - Hanging = (1 << 1), - Falling = (1 << 2) + None = 0, + Grounded = 1, + Hang = 2, + Fall = 3 }; void InitializeCorpse(short itemNumber); - void CorpseControl(short itemNumber); - void CorpseHit(ItemInfo& target, ItemInfo& source, std::optional pos, int damage, bool isExplosive, int jointIndex); + void ControlCorpse(short itemNumber); + void HitCorpse(ItemInfo& target, ItemInfo& source, std::optional pos, int damage, bool isExplosive, int jointIndex); } diff --git a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp index 13404cbae..3289a1196 100644 --- a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp +++ b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp @@ -9,6 +9,7 @@ #include "Game/effects/spark.h" #include "Game/effects/tomb4fx.h" #include "Game/Lara/lara_helpers.h" +#include "Game/misc.h" #include "Game/Setup.h" using namespace TEN::Collision::Point; @@ -73,102 +74,15 @@ namespace TEN::Entities::Traps } } - static bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir) - { - auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, BLOCK(1)); - auto pointColl = GetPointCollision(item.Pose.Position, item.RoomNumber, dir, BLOCK(1)); - - // TODO: Use floor normal directly. - auto floorTilt = GetSurfaceTilt(pointColl.GetFloorNormal(), true); - - // Test for wall. - if (pointColl.GetSector().IsWall(projectedPos.x, projectedPos.z)) - return false; - - // Test for slippery slope. - if (pointColl.IsIllegalFloor()) - return false; - - // Flat floor. - if (abs(floorTilt.x) == 0 && abs(floorTilt.y) == 0) - { - // Test for step. - int relFloorHeight = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); - if (relFloorHeight >= CLICK(1)) - return false; - } - // Sloped floor. - else - { - // Half block. - int relFloorHeight = abs(pointColl.GetFloorHeight() - item.Pose.Position.y); - if (relFloorHeight > CLICK(2)) - return false; - - short slopeAngle = ANGLE(0.0f); - if (floorTilt.x > 0) - { - slopeAngle = ANGLE(-90.0f); - } - else if (floorTilt.x < 0) - { - slopeAngle = ANGLE(90.0f); - } - - if (floorTilt.y > 0 && floorTilt.y > abs(floorTilt.x)) - { - slopeAngle = ANGLE(180.0f); - } - else if (floorTilt.y < 0 && -floorTilt.y > abs(floorTilt.x)) - { - slopeAngle = ANGLE(0.0f); - } - - short dirAngle = phd_atan(dir.z, dir.x); - short alignAngle = Geometry::GetShortestAngle(slopeAngle, dirAngle); - - // Test if slope aspect is aligned with direction. - if (alignAngle != 0 && alignAngle != ANGLE(180.0f)) - return false; - } - - // Check for diagonal split. - if (pointColl.IsDiagonalFloorStep()) - return false; - - // Test ceiling height. - int relCeilHeight = abs(pointColl.GetCeilingHeight() - pointColl.GetFloorHeight()); - int cleanerHeight = BLOCK(1); - if (relCeilHeight < cleanerHeight) - return false; - - // Check for inaccessible sector. - if (pointColl.GetSector().Box == NO_BOX) - return false; - - // Check for blocked grey box. - if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKABLE) - { - if (g_Level.Boxes[pointColl.GetSector().Box].flags& BLOCKED) - return false; - } - - // Check for stopper flag. - if (pointColl.GetSector().Stopper) - return false; - - return true; - } - static Vector3 GetElectricCleanerMovementDirection(const ItemInfo& item, const Vector3& dir0, const Vector3& dir1, const Vector3& dir2) { - if (IsNextSectorValid(item, dir0)) + if (IsNextSectorValid(item, dir0, BLOCK(1))) return dir0; - if (IsNextSectorValid(item, dir1)) + if (IsNextSectorValid(item, dir1, BLOCK(1))) return dir1; - if (IsNextSectorValid(item, dir2)) + if (IsNextSectorValid(item, dir2, BLOCK(1))) return dir2; return Vector3::Zero; @@ -197,18 +111,18 @@ namespace TEN::Entities::Traps break; } - if (GetCollidedObjects(&item, CLICK(1), true, CollidedItems, CollidedMeshes, true)) + auto collObjects = GetCollidedObjects(item, true, true); + if (!collObjects.IsEmpty()) { - int lp = 0; - while (CollidedItems[lp] != nullptr) + for (auto* itemPtr : collObjects.ItemPtrs) { - if (Objects[CollidedItems[lp]->ObjectNumber].intelligent) - { - CollidedItems[lp]->HitPoints = 0; - ItemElectricBurn(CollidedItems[lp], 120); - } + const auto& object = Objects[itemPtr->ObjectNumber]; - lp++; + if (object.intelligent) + { + itemPtr->HitPoints = 0; + ItemElectricBurn(itemPtr, 120); + } } } diff --git a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp index 2e49fb8b9..3c94992a0 100644 --- a/TombEngine/Objects/TR3/Vehicles/big_gun.cpp +++ b/TombEngine/Objects/TR3/Vehicles/big_gun.cpp @@ -120,7 +120,7 @@ namespace TEN::Entities::Vehicles void BigGunFire(ItemInfo* bigGunItem, ItemInfo* laraItem) { short itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto* lara = GetLaraInfo(laraItem); auto* bigGun = GetBigGunInfo(bigGunItem); @@ -156,7 +156,7 @@ namespace TEN::Entities::Vehicles auto* bigGun = GetBigGunInfo(bigGunItem); auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints <= 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints <= 0 || lara->Context.Vehicle != NO_VALUE) return; if (BigGunTestMount(laraItem, bigGunItem)) diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index e3ae3d7a8..c0e9dfdb0 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -148,7 +148,7 @@ namespace TEN::Entities::Vehicles auto* kayak = GetKayakInfo(kayakItem); auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(kayakItem, laraItem, coll, KayakMountTypes, KAYAK_MOUNT_DISTANCE, LARA_HEIGHT); @@ -1005,12 +1005,14 @@ namespace TEN::Entities::Vehicles short itemNum = g_Level.Rooms[i].itemNumber; - while (itemNum != NO_ITEM) + while (itemNum != NO_VALUE) { auto* item = &g_Level.Items[itemNum]; short nextItem = item->NextItem; - if (item->Collidable && item->Status != ITEM_INVISIBLE) + if (item->Collidable && + item->Status != ITEM_INVISIBLE && + item != laraItem && item != kayakItem) { auto* object = &Objects[item->ObjectNumber]; @@ -1106,7 +1108,7 @@ namespace TEN::Entities::Vehicles DoDamage(laraItem, (damage - 160) * 8); } - if (lara->Context.Vehicle != NO_ITEM) + if (lara->Context.Vehicle != NO_VALUE) { if (kayakItem->RoomNumber != probe.GetRoomNumber()) { @@ -1158,6 +1160,6 @@ namespace TEN::Entities::Vehicles KayakToItemCollision(kayakItem, laraItem); - return (lara->Context.Vehicle != NO_ITEM) ? true : false; + return (lara->Context.Vehicle != NO_VALUE) ? true : false; } } diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index 888cc1ab6..21215c3f9 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -155,7 +155,7 @@ namespace TEN::Entities::Vehicles MINECART_FLAG_DISMOUNT_RIGHT = (1 << 3), MINECART_FLAG_CONTROL = (1 << 4), MINECART_FLAG_STOPPED = (1 << 5), - MINECART_FLAG_NO_ANIM = (1 << 6), + MINECART_FLAG_NO_VALUE = (1 << 6), MINECART_FLAG_DEAD = (1 << 7) }; @@ -175,7 +175,7 @@ namespace TEN::Entities::Vehicles auto* minecartItem = &g_Level.Items[itemNumber]; auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; // Don't get into minecart if there are two stop blocks in front. @@ -288,7 +288,7 @@ namespace TEN::Entities::Vehicles short itemNumber = g_Level.Rooms[i].itemNumber; - while (itemNumber != NO_ITEM) + while (itemNumber != NO_VALUE) { auto* item = &g_Level.Items[itemNumber]; @@ -832,7 +832,7 @@ namespace TEN::Entities::Vehicles { if (TestAnimNumber(*laraItem, MINECART_ANIM_FALL_DEATH)) { - minecart->Flags |= MINECART_FLAG_NO_ANIM; + minecart->Flags |= MINECART_FLAG_NO_VALUE; laraItem->HitPoints = -1; } } @@ -846,7 +846,7 @@ namespace TEN::Entities::Vehicles laraItem->Animation.FrameNumber = GetFrameIndex(minecartItem, 34) + 28; minecartItem->Animation.Velocity.z = 0.0f; minecart->Velocity = 0; - minecart->Flags = (minecart->Flags & ~MINECART_FLAG_CONTROL) | MINECART_FLAG_NO_ANIM; + minecart->Flags = (minecart->Flags & ~MINECART_FLAG_CONTROL) | MINECART_FLAG_NO_VALUE; } break; @@ -864,8 +864,8 @@ namespace TEN::Entities::Vehicles break; } - if (lara->Context.Vehicle != NO_ITEM && - !(minecart->Flags & MINECART_FLAG_NO_ANIM)) + if (lara->Context.Vehicle != NO_VALUE && + !(minecart->Flags & MINECART_FLAG_NO_VALUE)) { AnimateItem(laraItem); SyncVehicleAnimation(*minecartItem, *laraItem); @@ -968,7 +968,7 @@ namespace TEN::Entities::Vehicles if (minecart->Flags & MINECART_FLAG_CONTROL) MoveCart(minecartItem, laraItem); - if (lara->Context.Vehicle != NO_ITEM) + if (lara->Context.Vehicle != NO_VALUE) laraItem->Pose = minecartItem->Pose; short probedRoomNumber = GetPointCollision(*minecartItem).GetRoomNumber(); @@ -986,6 +986,6 @@ namespace TEN::Entities::Vehicles Camera.targetDistance = BLOCK(2); } - return (lara->Context.Vehicle == NO_ITEM) ? false : true; + return (lara->Context.Vehicle == NO_VALUE) ? false : true; } } diff --git a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp index 8711384ef..6dc3a4f5f 100644 --- a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp +++ b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp @@ -180,7 +180,7 @@ namespace TEN::Entities::Vehicles auto* quadBikeItem = &g_Level.Items[itemNumber]; auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(quadBikeItem, laraItem, coll, QuadBikeMountTypes, QBIKE_MOUNT_DISTANCE); @@ -263,7 +263,7 @@ namespace TEN::Entities::Vehicles auto* quadBike = GetQuadBikeInfo(quadBikeItem); auto* lara = GetLaraInfo(laraItem); - if (lara->Context.Vehicle == NO_ITEM) + if (lara->Context.Vehicle == NO_VALUE) return true; if ((laraItem->Animation.ActiveState == QBIKE_STATE_DISMOUNT_RIGHT || laraItem->Animation.ActiveState == QBIKE_STATE_DISMOUNT_LEFT) && diff --git a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp index 78f938ab2..4466ff811 100644 --- a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp +++ b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp @@ -116,7 +116,7 @@ namespace TEN::Entities::Vehicles auto* rBoatItem = &g_Level.Items[itemNumber]; auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(rBoatItem, laraItem, coll, RubberBoatMountTypes, RBOAT_MOUNT_DISTANCE, LARA_HEIGHT); @@ -194,7 +194,7 @@ namespace TEN::Entities::Vehicles auto* lara = GetLaraInfo(laraItem); int itemNumber2 = g_Level.Rooms[boatItem->RoomNumber].itemNumber; - while (itemNumber2 != NO_ITEM) + while (itemNumber2 != NO_VALUE) { auto* item = &g_Level.Items[itemNumber2]; @@ -782,7 +782,7 @@ namespace TEN::Entities::Vehicles laraItem->Animation.IsAirborne = true; laraItem->Animation.Velocity.z = 20; laraItem->Animation.Velocity.y = -40; - lara->Context.Vehicle = NO_ITEM; // Leave vehicle itself active for inertia. + lara->Context.Vehicle = NO_VALUE; // Leave vehicle itself active for inertia. int x = laraItem->Pose.Position.x + 360 * phd_sin(laraItem->Pose.Orientation.y); int y = laraItem->Pose.Position.y - 90; diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index bbd37ad60..2a5928033 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -178,7 +178,7 @@ namespace TEN::Entities::Vehicles auto* UPVItem = &g_Level.Items[itemNumber]; auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints <= 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints <= 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(UPVItem, laraItem, coll, UPVMountTypes, UPV_MOUNT_DISTANCE); @@ -290,7 +290,7 @@ namespace TEN::Entities::Vehicles void UPVEffects(short itemNumber) { - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto* UPVItem = &g_Level.Items[itemNumber]; @@ -948,7 +948,7 @@ namespace TEN::Entities::Vehicles } if (!(UPV->Flags & UPV_FLAG_DEAD) && - lara->Context.Vehicle != NO_ITEM) + lara->Context.Vehicle != NO_VALUE) { DoCurrent(UPVItem, laraItem); diff --git a/TombEngine/Objects/TR3/fish.h b/TombEngine/Objects/TR3/fish.h deleted file mode 100644 index cb497408c..000000000 --- a/TombEngine/Objects/TR3/fish.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -struct FishInfo -{ - short x; - short y; - short z; - int angle; - short destY; - short angAdd; - unsigned char speed; - unsigned char acc; - unsigned char swim; -}; - -struct FishLeaderInfo -{ - short angle; - unsigned char speed; - unsigned char on; - short angleTime; - short speedTime; - short xRange, yRange, zRange; -}; diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index fd9377b80..2b607a6ca 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -20,7 +20,7 @@ #include "Objects/TR3/Entity/tr3_civvy.h" // OK #include "Objects/TR3/Entity/tr3_claw_mutant.h" // OK #include "Objects/TR3/Entity/tr3_cobra.h" // OK -#include "Objects/TR3/Entity/tr3_fish_emitter.h" // OK +#include "Objects/TR3/Entity/FishSwarm.h" // OK #include "Objects/TR3/Entity/tr3_flamethrower.h" // OK #include "Objects/TR3/Entity/tr3_monkey.h" // OK #include "Objects/TR3/Entity/tr3_mp_gun.h" // OK @@ -425,6 +425,15 @@ static void StartEntity(ObjectInfo* obj) obj->intelligent = true; obj->SetHitEffect(); } + + obj = &Objects[ID_FISH_EMITTER]; + if (obj->loaded) + { + obj->Initialize = InitializeFishSwarm; + obj->control = ControlFishSwarm; + obj->intelligent = true; + obj->drawRoutine = NULL; + } } static void StartObject(ObjectInfo* obj) @@ -462,8 +471,8 @@ static void StartObject(ObjectInfo* obj) obj->Initialize = InitializeCorpse; obj->collision = CreatureCollision; obj->damageType = DamageMode::None; - obj->control = CorpseControl; - obj->HitRoutine = CorpseHit; + obj->control = ControlCorpse; + obj->HitRoutine = HitCorpse; obj->HitPoints = NOT_TARGETABLE; obj->shadowType = ShadowMode::None; obj->SetHitEffect(); diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index e3e536366..b03fefcb9 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -322,7 +322,7 @@ namespace TEN::Entities::TR4 if (pointColl.GetRoomNumber() != item.RoomNumber) ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); - for (int linkItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkItemNumber != NO_ITEM; linkItemNumber = g_Level.Items[linkItemNumber].NextItem) + for (int linkItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkItemNumber != NO_VALUE; linkItemNumber = g_Level.Items[linkItemNumber].NextItem) { auto& targetItem = g_Level.Items[linkItemNumber]; @@ -702,15 +702,15 @@ namespace TEN::Entities::TR4 { ItemInfo* item2 = nullptr; - if (NextItemActive != NO_ITEM) + if (NextItemActive != NO_VALUE) { - for (; NextItemActive != NO_ITEM;) + for (; NextItemActive != NO_VALUE;) { auto* item2 = &g_Level.Items[NextItemActive]; if (item2->ObjectNumber == ID_WRAITH3 && !item2->HitPoints) break; - if (item2->NextActive == NO_ITEM) + if (item2->NextActive == NO_VALUE) { FlipEffect = -1; return; diff --git a/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp b/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp index 5ae2b9394..a2754fb84 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp @@ -215,7 +215,7 @@ namespace TEN::Entities::TR4 else if ((AI.angle >= AHMET_VIEW_ANGLE || AI.angle <= -AHMET_VIEW_ANGLE) || AI.distance >= AHMET_IDLE_RANGE) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else { diff --git a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp index 262a36d62..c94ebd6a0 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baboon.cpp @@ -112,7 +112,7 @@ namespace TEN::Entities::TR4 static void TriggerBaboonShockwave(Pose pos, short xRot) { short shockwaveID = GetFreeShockwave(); - if (shockwaveID != NO_ITEM) + if (shockwaveID != NO_VALUE) { auto* deathEffect = &ShockWaves[shockwaveID]; @@ -363,12 +363,12 @@ namespace TEN::Entities::TR4 else item->Animation.TargetState = BABOON_STATE_RUN_FORWARD; } - else if (item->Animation.RequiredState != NO_STATE) + else if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(1 / 2.0f)) item->Animation.TargetState = BABOON_STATE_SIT_IDLE; } - else if (item->Animation.RequiredState != NO_STATE) + else if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(0.25f)) item->Animation.TargetState = BABOON_STATE_WALK_FORWARD; @@ -401,7 +401,7 @@ namespace TEN::Entities::TR4 // NOTE: It's not true to the original functionality, but to avoid repetitive actions, // the SIT_IDLE state was given a higher chance of occurring. The EAT state was also added here. -- TokyoSU - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(1 / 2.0f)) item->Animation.TargetState = BABOON_STATE_SIT_IDLE; @@ -417,7 +417,7 @@ namespace TEN::Entities::TR4 } else if ((item->AIBits & FOLLOW) && AI.distance > BABOON_IDLE_RANGE) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else item->Animation.TargetState = BABOON_STATE_WALK_FORWARD; diff --git a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp index 4490c0f0a..951b1305c 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp @@ -395,7 +395,7 @@ namespace TEN::Entities::TR4 auto* currentCreature = creature; if (item->ItemFlags[1] == item->RoomNumber || - g_Level.Rooms[item->RoomNumber].itemNumber == NO_ITEM) + g_Level.Rooms[item->RoomNumber].itemNumber == NO_VALUE) { currentCreature = creature; } @@ -404,7 +404,7 @@ namespace TEN::Entities::TR4 currentCreature = creature; creature->Enemy = LaraItem; ItemInfo* currentItem = nullptr; - for (short itemNum = g_Level.Rooms[item->RoomNumber].itemNumber; itemNum != NO_ITEM; itemNum = currentItem->NextItem) + for (short itemNum = g_Level.Rooms[item->RoomNumber].itemNumber; itemNum != NO_VALUE; itemNum = currentItem->NextItem) { currentItem = &g_Level.Items[itemNum]; if ((currentItem->ObjectNumber == ID_SMALLMEDI_ITEM || @@ -540,7 +540,7 @@ namespace TEN::Entities::TR4 GetCreatureMood(item, &AI, true); // Vehicle handling - if (Lara.Context.Vehicle != NO_ITEM && AI.bite) + if (Lara.Context.Vehicle != NO_VALUE && AI.bite) currentCreature->Mood = MoodType::Escape; CreatureMood(item, &AI, true); @@ -1112,7 +1112,7 @@ namespace TEN::Entities::TR4 // Cancel enemy pointer for other active baddys for (int i = 0; i < ActiveCreatures.size(); i++) { - if (ActiveCreatures[i]->ItemNumber != NO_ITEM && ActiveCreatures[i]->ItemNumber != itemNumber && ActiveCreatures[i]->Enemy == creature->Enemy) + if (ActiveCreatures[i]->ItemNumber != NO_VALUE && ActiveCreatures[i]->ItemNumber != itemNumber && ActiveCreatures[i]->Enemy == creature->Enemy) ActiveCreatures[i]->Enemy = nullptr; } diff --git a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp index c8e5b90ee..9951cd441 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp @@ -70,7 +70,7 @@ namespace TEN::Entities::TR4 } short beetleNumber = GetFreeBeetle(); - if (beetleNumber != NO_ITEM) + if (beetleNumber != NO_VALUE) { auto* beetle = &BeetleSwarm[beetleNumber]; @@ -128,7 +128,7 @@ namespace TEN::Entities::TR4 } if (++i >= NUM_BEETLES) - return NO_ITEM; + return NO_VALUE; } NextBeetle = (result + 1) & (NUM_BEETLES - 1); diff --git a/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp b/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp index 664eb4f62..a2cc1ed9d 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_big_beetle.cpp @@ -144,7 +144,7 @@ namespace TEN::Entities::TR4 case BBEETLE_STATE_FLY_FORWARD: creature->MaxTurn = ANGLE(7.0f); - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.ahead && AI.distance < BIG_BEETLE_ATTACK_RANGE) item->Animation.TargetState = BBEETLE_STATE_FLY_IDLE; @@ -194,7 +194,7 @@ namespace TEN::Entities::TR4 case BBEETLE_STATE_FLY_IDLE: creature->MaxTurn = ANGLE(7.0f); - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (!item->HitStatus && item->AIBits != MODIFY && Random::TestProbability(0.99f) && diff --git a/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp b/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp index 520548fd9..fe4ce6c80 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_big_scorpion.cpp @@ -95,9 +95,9 @@ namespace TEN::Entities::TR4 creature->MaxTurn = 0; short linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; - if (linkNumber != NO_ITEM) + if (linkNumber != NO_VALUE) { - for (linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem) + for (linkNumber = g_Level.Rooms[item->RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) { auto* currentItem = &g_Level.Items[linkNumber]; @@ -140,7 +140,7 @@ namespace TEN::Entities::TR4 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber != NO_ITEM && currentCreature->ItemNumber != itemNumber) + if (currentCreature->ItemNumber != NO_VALUE && currentCreature->ItemNumber != itemNumber) { auto* currentItem = &g_Level.Items[currentCreature->ItemNumber]; if (currentItem->ObjectNumber != ID_LARA) diff --git a/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp b/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp index 19ec0f631..22b35629a 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp @@ -219,7 +219,7 @@ namespace TEN::Entities::TR4 break; } - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (ai.bite && ai.distance < CROC_ATTACK_RANGE) item->Animation.TargetState = CROC_STATE_IDLE; @@ -239,7 +239,7 @@ namespace TEN::Entities::TR4 break; } - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (ai.bite && ai.distance < CROC_ATTACK_RANGE) item->Animation.TargetState = CROC_STATE_IDLE; @@ -250,12 +250,12 @@ namespace TEN::Entities::TR4 case CROC_STATE_BITE_ATTACK: if (item->Animation.FrameNumber == GetAnimData(item).frameBase) - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; if (ai.bite && item->TouchBits.Test(CrocodileBiteAttackJoints)) { - if (item->Animation.RequiredState == NO_STATE) + if (item->Animation.RequiredState == NO_VALUE) { CreatureEffect2(item, CrocodileBite, 10, -1, DoBloodSplat); DoDamage(creature->Enemy, CROC_ATTACK_DAMAGE); @@ -277,7 +277,7 @@ namespace TEN::Entities::TR4 break; } - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (ai.bite) { @@ -289,11 +289,11 @@ namespace TEN::Entities::TR4 case CROC_STATE_WATER_BITE_ATTACK: if (item->Animation.FrameNumber == GetAnimData(item).frameBase) - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; if (ai.bite && item->TouchBits.Test(CrocodileBiteAttackJoints)) { - if (item->Animation.RequiredState == NO_STATE) + if (item->Animation.RequiredState == NO_VALUE) { CreatureEffect2(item, CrocodileBite, 10, -1, DoBloodSplat); DoDamage(creature->Enemy, CROC_ATTACK_DAMAGE); diff --git a/TombEngine/Objects/TR4/Entity/tr4_dog.cpp b/TombEngine/Objects/TR4/Entity/tr4_dog.cpp index bc603df7d..734f4b192 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_dog.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_dog.cpp @@ -179,7 +179,7 @@ namespace TEN::Entities::TR4 creature->MaxTurn = 0; if (item->Animation.ActiveState == DOG_STATE_STALK_IDLE && - item->Animation.RequiredState != NO_STATE) + item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = item->Animation.RequiredState; break; diff --git a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp index c540afd27..404066b31 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp @@ -27,7 +27,7 @@ namespace TEN::Entities::TR4 { short grenadeItemNumber = CreateItem(); - if (grenadeItemNumber != NO_ITEM) + if (grenadeItemNumber != NO_VALUE) { auto* grenadeItem = &g_Level.Items[grenadeItemNumber]; @@ -55,7 +55,7 @@ namespace TEN::Entities::TR4 grenadeItem->Animation.ActiveState = grenadeItem->Pose.Orientation.x; grenadeItem->Animation.TargetState = grenadeItem->Pose.Orientation.y; - grenadeItem->Animation.RequiredState = NO_STATE; + grenadeItem->Animation.RequiredState = NO_VALUE; grenadeItem->Animation.Velocity.z = 32; grenadeItem->Animation.Velocity.y = -32 * phd_sin(grenadeItem->Pose.Orientation.x); grenadeItem->HitPoints = 120; @@ -164,7 +164,7 @@ namespace TEN::Entities::TR4 if (item->ItemFlags[0] < 0) item->ItemFlags[0] = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.distance > pow(BLOCK(1), 2) || Lara.Location >= item->ItemFlags[3]) item->Animation.TargetState = 1; diff --git a/TombEngine/Objects/TR4/Entity/tr4_guide.cpp b/TombEngine/Objects/TR4/Entity/tr4_guide.cpp index c5bca20b2..cd657f137 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_guide.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_guide.cpp @@ -191,7 +191,7 @@ namespace TEN::Entities::TR4 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) { continue; @@ -280,7 +280,7 @@ namespace TEN::Entities::TR4 joint2 = AI.angle / 2; } - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (goalNode >= item->ItemFlags[3] || item->ItemFlags[1] != 2) @@ -660,7 +660,7 @@ namespace TEN::Entities::TR4 ItemInfo* currentItem = nullptr; short currentitemNumber = room->itemNumber; - while (currentitemNumber != NO_ITEM) + while (currentitemNumber != NO_VALUE) { currentItem = &g_Level.Items[currentitemNumber]; diff --git a/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp b/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp index 0dbb0efd4..d0477e4db 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_harpy.cpp @@ -243,7 +243,7 @@ namespace TEN::Entities::TR4 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber == NO_ITEM || currentCreature->ItemNumber == itemNumber) + if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) continue; auto* target = &g_Level.Items[currentCreature->ItemNumber]; @@ -335,7 +335,7 @@ namespace TEN::Entities::TR4 creature->MaxTurn = ANGLE(7.0f); creature->Flags = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = item->Animation.RequiredState; if (item->Animation.RequiredState == HARPY_STATE_FLAME_ATTACK) diff --git a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp index ef35f9efb..c486535a6 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp @@ -136,7 +136,7 @@ namespace TEN::Entities::TR4 InitializeCreature(itemNumber); SetAnimation(item, HORSEMAN_ANIM_IDLE); - item->ItemFlags[0] = NO_ITEM; // No horse yet. + item->ItemFlags[0] = NO_VALUE; // No horse yet. } void HorsemanSparks(Vector3i* pos, int param1, int maxSparks) @@ -221,7 +221,7 @@ namespace TEN::Entities::TR4 auto* creature = GetCreatureInfo(item); // Try to find a horse. - if (item->ItemFlags[0] == NO_ITEM) + if (item->ItemFlags[0] == NO_VALUE) { for (int i = 0; i < g_Level.NumItems; i++) { @@ -237,7 +237,7 @@ namespace TEN::Entities::TR4 } // If no horse was found, set ItemFlags[0] to 0 so it isn't searched for again. - if (item->ItemFlags[0] == NO_ITEM) + if (item->ItemFlags[0] == NO_VALUE) item->ItemFlags[0] = 0; // Get horse. @@ -381,7 +381,7 @@ namespace TEN::Entities::TR4 case HORSEMAN_STATE_MOUNTED_RUN_FORWARD: creature->MaxTurn = ANGLE(3.0f); horseItem->Animation.TargetState = HORSEMAN_STATE_MOUNTED_WALK_FORWARD; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = HORSEMAN_STATE_MOUNTED_SPRINT; horseItem->Animation.TargetState = HORSEMAN_STATE_MOUNT_HORSE; @@ -491,7 +491,7 @@ namespace TEN::Entities::TR4 else creature->Flags = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = HORSEMAN_STATE_MOUNTED_RUN_FORWARD; horseItem->Animation.TargetState = HORSEMAN_STATE_MOUNTED_WALK_FORWARD; @@ -582,7 +582,7 @@ namespace TEN::Entities::TR4 if (!item->AIBits || item->ItemFlags[3]) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (AI.bite && AI.distance < pow(682,2)) item->Animation.TargetState = HORSEMAN_STATE_IDLE_ATTACK; diff --git a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp index 7194eb2fc..41cc2809d 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp @@ -64,10 +64,10 @@ namespace TEN::Entities::TR4 void TriggerCrocgodMissile(Pose* src, short roomNumber, short counter) { - short fxNumber = NO_ITEM; + short fxNumber = NO_VALUE; fxNumber = CreateNewEffect(roomNumber); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { auto* fx = &EffectList[fxNumber]; fx->pos.Position.x = src->Position.x; diff --git a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp index 7c94d44d5..d8be29188 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sas.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sas.cpp @@ -177,7 +177,7 @@ namespace TEN::Entities::TR4 GetCreatureMood(&item, &AI, !creature.Enemy->IsLara()); // Vehicle handling - if (Lara.Context.Vehicle != NO_ITEM && AI.bite) + if (Lara.Context.Vehicle != NO_VALUE && AI.bite) creature.Mood = MoodType::Escape; CreatureMood(&item, &AI, !creature.Enemy->IsLara()); @@ -205,7 +205,7 @@ namespace TEN::Entities::TR4 else item.Pose.Orientation.y += ANGLE(10.0f); } - else if (item.AIBits & MODIFY || Lara.Context.Vehicle != NO_ITEM) + else if (item.AIBits & MODIFY || Lara.Context.Vehicle != NO_VALUE) { if (abs(AI.angle) < ANGLE(2.0f)) item.Pose.Orientation.y += AI.angle; @@ -229,7 +229,7 @@ namespace TEN::Entities::TR4 } else if (item.AIBits & PATROL1 && item.AIBits != MODIFY && - Lara.Context.Vehicle == NO_ITEM) + Lara.Context.Vehicle == NO_VALUE) { item.Animation.TargetState = SAS_STATE_WALK; joint2 = 0; @@ -299,7 +299,7 @@ namespace TEN::Entities::TR4 creature.Mood == MoodType::Bored || !AI.ahead || item.AIBits & MODIFY || - Lara.Context.Vehicle != NO_ITEM) + Lara.Context.Vehicle != NO_VALUE) { item.Animation.TargetState = SAS_STATE_IDLE; } @@ -315,7 +315,7 @@ namespace TEN::Entities::TR4 { item.Animation.TargetState = SAS_STATE_WALK; } - else if (Lara.Context.Vehicle != NO_ITEM && + else if (Lara.Context.Vehicle != NO_VALUE && (item.AIBits == MODIFY || !item.AIBits)) { @@ -363,7 +363,7 @@ namespace TEN::Entities::TR4 if (AI.ahead) joint2 = AI.angle; - if (Lara.Context.Vehicle != NO_ITEM) + if (Lara.Context.Vehicle != NO_VALUE) { if (item.AIBits == MODIFY || !item.AIBits) { @@ -645,7 +645,7 @@ namespace TEN::Entities::TR4 void SasFireGrenade(ItemInfo& item, short angle1, short angle2) { short itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto grenadeItem = &g_Level.Items[itemNumber]; @@ -677,7 +677,7 @@ namespace TEN::Entities::TR4 grenadeItem->Animation.Velocity.z = 128; grenadeItem->Animation.ActiveState = grenadeItem->Pose.Orientation.x; grenadeItem->Animation.TargetState = grenadeItem->Pose.Orientation.y; - grenadeItem->Animation.RequiredState = NO_STATE; + grenadeItem->Animation.RequiredState = NO_VALUE; if (Random::TestProbability(3 / 4.0f)) grenadeItem->ItemFlags[0] = (int)ProjectileType::Grenade; diff --git a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp index 03c5963c4..45af4e5f1 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_setha.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_setha.cpp @@ -183,7 +183,7 @@ namespace TEN::Entities::TR4 creature.Flags = 0; creature.LOT.IsJumping = false; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = item->Animation.RequiredState; break; diff --git a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp index b2ddd7053..b530c99b2 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp @@ -144,7 +144,7 @@ namespace TEN::Entities::TR4 void TriggerRiseEffect(ItemInfo* item) { int fxNumber = CreateNewEffect(item->RoomNumber); - if (fxNumber == NO_ITEM) + if (fxNumber == NO_VALUE) return; auto* fx = &EffectList[fxNumber]; @@ -452,7 +452,7 @@ namespace TEN::Entities::TR4 item->AIBits & FOLLOW && (creature->ReachedGoal || laraAI.distance > SQUARE(BLOCK(2)))) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(1 / 64.0f)) item->Animation.TargetState = 15; @@ -477,7 +477,7 @@ namespace TEN::Entities::TR4 else item->Animation.TargetState = SKELETON_STATE_ATTACK_3; } - else if (item->HitStatus || item->Animation.RequiredState != NO_STATE) + else if (item->HitStatus || item->Animation.RequiredState != NO_VALUE) { if (Random::TestProbability(1 / 2.0f)) { diff --git a/TombEngine/Objects/TR4/Entity/tr4_troops.cpp b/TombEngine/Objects/TR4/Entity/tr4_troops.cpp index 3aba0aafd..46f9de8da 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_troops.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_troops.cpp @@ -145,7 +145,7 @@ namespace TEN::Entities::TR4 for (auto& currentCreature : ActiveCreatures) { - if (currentCreature->ItemNumber != NO_ITEM && currentCreature->ItemNumber != itemNumber) + if (currentCreature->ItemNumber != NO_VALUE && currentCreature->ItemNumber != itemNumber) { auto* currentItem = &g_Level.Items[currentCreature->ItemNumber]; if (currentItem->ObjectNumber != ID_LARA) @@ -192,7 +192,7 @@ namespace TEN::Entities::TR4 CreatureMood(item, &AI, false); // Vehicle handling - if (Lara.Context.Vehicle != NO_ITEM && AI.bite) + if (Lara.Context.Vehicle != NO_VALUE && AI.bite) creature->Mood = MoodType::Escape; angle = CreatureTurn(item, creature->MaxTurn); diff --git a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp index 6b4c44690..4f7f7b93e 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_von_croy.cpp @@ -233,7 +233,7 @@ namespace TEN::Entities::TR4 for (auto& currentCreature : ActiveCreatures) { targetCreature = currentCreature; - if (targetCreature->ItemNumber == NO_ITEM || + if (targetCreature->ItemNumber == NO_VALUE || targetCreature->ItemNumber == itemNumber || g_Level.Items[targetCreature->ItemNumber].ObjectNumber == ID_VON_CROY || g_Level.Items[targetCreature->ItemNumber].ObjectNumber == ID_GUIDE) diff --git a/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp b/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp index 3c820a632..69fbed225 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_wild_boar.cpp @@ -85,7 +85,7 @@ namespace TEN::Entities::TR4 for (auto& currentCreature : ActiveCreatures) { auto* currentItem = currentCreature; - if (currentItem->ItemNumber == NO_ITEM || currentItem->ItemNumber == itemNumber) + if (currentItem->ItemNumber == NO_VALUE || currentItem->ItemNumber == itemNumber) continue; auto* target = &g_Level.Items[currentItem->ItemNumber]; diff --git a/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp b/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp index 0535ae8d2..3fa9113f3 100644 --- a/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_clockwork_beetle.cpp @@ -169,7 +169,7 @@ void ClockworkBeetleControl(short itemNumber) beetle->ItemFlags[2] = 5; short itemRoom = g_Level.Rooms[beetle->RoomNumber].itemNumber; - if (itemRoom != NO_ITEM) + if (itemRoom != NO_VALUE) { ItemInfo* item; short nextItem; @@ -195,7 +195,7 @@ void ClockworkBeetleControl(short itemNumber) itemRoom = nextItem; - if (itemRoom == NO_ITEM) + if (itemRoom == NO_VALUE) return; } @@ -310,7 +310,7 @@ void UseClockworkBeetle(short flag) { short itemNumber = CreateItem(); - if (itemNumber != NO_ITEM) + if (itemNumber != NO_VALUE) { auto* item = &g_Level.Items[itemNumber]; @@ -338,7 +338,7 @@ void UseClockworkBeetle(short flag) ItemInfo* item2; short itemRoom = g_Level.Rooms[item->RoomNumber].itemNumber; - if (itemRoom != NO_ITEM) + if (itemRoom != NO_VALUE) { while (true) { @@ -361,7 +361,7 @@ void UseClockworkBeetle(short flag) itemRoom = nextItem; - if (itemRoom == NO_ITEM) + if (itemRoom == NO_VALUE) { if (!item->ItemFlags[0]) item->ItemFlags[3] = 150; diff --git a/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp b/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp index 1c24c690b..5bb0117ff 100644 --- a/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp @@ -106,10 +106,10 @@ namespace TEN::Entities::TR4 } short currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; - if (currentItemNumber == NO_ITEM) + if (currentItemNumber == NO_VALUE) return; - while (currentItemNumber != NO_ITEM) + while (currentItemNumber != NO_VALUE) { auto* currentItem = &g_Level.Items[currentItemNumber]; diff --git a/TombEngine/Objects/TR4/Object/tr4_obelisk.cpp b/TombEngine/Objects/TR4/Object/tr4_obelisk.cpp index 213e9ece0..aa21894f0 100644 --- a/TombEngine/Objects/TR4/Object/tr4_obelisk.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_obelisk.cpp @@ -123,7 +123,7 @@ void ObeliskControl(short itemNumber) abs(pos2.y - LaraItem->Pose.Position.y) < BLOCK(20) && abs(pos2.z - LaraItem->Pose.Position.z) < BLOCK(20)) { - if (item->ItemFlags[2] != NO_ITEM) + if (item->ItemFlags[2] != NO_VALUE) { auto* item2 = &g_Level.Items[item->ItemFlags[2]]; ExplodeItemNode(item2, 0, 0, 128); @@ -132,7 +132,7 @@ void ObeliskControl(short itemNumber) TriggerExplosionSparks(pos.x, pos.y, pos.z, 3, -2, 0, item2->RoomNumber); TriggerExplosionSparks(pos.x, pos.y, pos.z, 3, -1, 0, item2->RoomNumber); - item->ItemFlags[2] = NO_ITEM; + item->ItemFlags[2] = NO_VALUE; item2 = FindItem(ID_PUZZLE_ITEM1_COMBO1); item2->Status = ITEM_NOT_ACTIVE; diff --git a/TombEngine/Objects/TR4/Object/tr4_senet.cpp b/TombEngine/Objects/TR4/Object/tr4_senet.cpp index 0568a42c6..d8dde9c1f 100644 --- a/TombEngine/Objects/TR4/Object/tr4_senet.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_senet.cpp @@ -331,7 +331,7 @@ void SenetPieceExplosionEffect(ItemInfo* item, int color, int speed) void TriggerItemInRoom(short room_number, int object)//originally this is in deltapak { short num = g_Level.Rooms[room_number].itemNumber; - while (num != NO_ITEM) + while (num != NO_VALUE) { auto* item = &g_Level.Items[num]; short nex = item->NextItem; diff --git a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp index 0554f13c5..bd1f55d5e 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp @@ -52,18 +52,20 @@ namespace TEN::Entities::Traps auto pointColl0 = GetPointCollision(item, item.Pose.Orientation.y, (forwardVel >= 0) ? bounds.Z2 : bounds.Z1, bounds.Y2); auto pointColl1 = GetPointCollision(item, item.Pose.Orientation.y, (forwardVel >= 0) ? bounds.Z2 : bounds.Z1, bounds.Y2, (bounds.X2 - bounds.X1) / 2); - if (GetCollidedObjects(&item, CLICK(1), true, CollidedItems, CollidedMeshes, true)) + auto collObjects = GetCollidedObjects(item, true, true); + if (!collObjects.IsEmpty()) { - int collidedItemNumber = 0; - while (CollidedItems[collidedItemNumber] != nullptr) + for (auto* itemPtr : collObjects.ItemPtrs) { - if (Objects[CollidedItems[collidedItemNumber]->ObjectNumber].intelligent) + const auto& object = Objects[itemPtr->ObjectNumber]; + + if (object.intelligent) { - CollidedItems[collidedItemNumber]->HitPoints = 0; + itemPtr->HitPoints = 0; } - else if (CollidedItems[collidedItemNumber]->ObjectNumber == ID_SPIKY_WALL && !item.ItemFlags[1]) + else if (itemPtr->ObjectNumber == ID_SPIKY_WALL && !item.ItemFlags[1]) { - CollidedItems[collidedItemNumber]->TriggerFlags = 0; + itemPtr->TriggerFlags = 0; item.TriggerFlags = 0; item.Status = ITEM_DEACTIVATED; @@ -71,8 +73,6 @@ namespace TEN::Entities::Traps StopSoundEffect(SFX_TR4_ROLLING_BALL); } - - collidedItemNumber++; } } diff --git a/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp b/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp new file mode 100644 index 000000000..3a00504e1 --- /dev/null +++ b/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp @@ -0,0 +1,221 @@ +#include "framework.h" +#include "Objects/TR4/Trap/SquishyBlock.h" + +#include "Game/animation.h" +#include "Game/camera.h" +#include "Game/collision/collide_item.h" +#include "Game/collision/collide_room.h" +#include "Game/collision/Point.h" +#include "Game/collision/sphere.h" +#include "Game/control/control.h" +#include "Game/effects/effects.h" +#include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Game/misc.h" +#include "Game/Setup.h" +#include "Sound/sound.h" +#include "Specific/level.h" + +using namespace TEN::Collision::Point; + +// NOTES: +// item.ItemFlags[0]: use dynamic motion. +// item.ItemFlags[1]: ?? +// item.ItemFlags[4]: heading angle. +// TODO: In future add support for 4 directions. + +namespace TEN::Entities::Traps +{ + constexpr auto SQUISHY_BLOCK_LETHAL_FRAME = 33; + constexpr auto MAX_FALLING_VELOCITY = 60; + constexpr auto MAX_VELOCITY = 300; + constexpr auto FALLING_BLOCK_IMPACT_FRAME = 8; + constexpr auto FALLING_BLOCK_NEXT_FRAME = 2; + + enum SquishyBlockState + { + SQUISHY_BLOCK_STATE_MOVE = 0, + SQUISHY_BLOCK_STATE_COLLIDE_LEFT = 1, + SQUISHY_BLOCK_STATE_COLLIDE_RIGHT = 2, + SQUISHY_BLOCK_STATE_BAKED_MOTION = 3, + SQUISHY_BLOCK_STATE_COLLIDE_FRONT = 4, + SQUISHY_BLOCK_STATE_COLLIDE_BACK = 5 + }; + + enum SquishyBlockAnim + { + SQUISHY_BLOCK_ANIM_MOVE = 0, + SQUISHY_BLOCK_ANIM_IMPACT_BACK = 1, + SQUISHY_BLOCK_ANIM_IMPACT_FRONT = 2, + SQUISHY_BLOCK_ANIM_BAKED_MOTION = 3, + SQUISHY_BLOCK_ANIM_COLLIDE_FRONT = 4, + SQUISHY_BLOCK_ANIM_COLLIDE_BACK = 5 + }; + + void InitializeSquishyBlock(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (!item.TriggerFlags) + SetAnimation(item, SQUISHY_BLOCK_ANIM_BAKED_MOTION); + + item.HitPoints = NOT_TARGETABLE; + item.ItemFlags[0] = item.TriggerFlags; + item.ItemFlags[1] = 0; + item.ItemFlags[4] = 0; + } + + void ControlSquishyBlock(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (!TriggerActive(&item)) + return; + + const auto& object = Objects[item.ObjectNumber]; + + short& velocity = item.ItemFlags[0]; + short& someAngle = item.ItemFlags[1]; + short& headingAngle = item.ItemFlags[4]; + + if (!item.TriggerFlags) + { + if (item.Animation.ActiveState != SQUISHY_BLOCK_STATE_BAKED_MOTION) + SetAnimation(item, SQUISHY_BLOCK_ANIM_BAKED_MOTION); + } + else + { + if (item.Animation.ActiveState == SQUISHY_BLOCK_ANIM_BAKED_MOTION) + SetAnimation(item, SQUISHY_BLOCK_STATE_MOVE); + + velocity = item.TriggerFlags; + + if (velocity > MAX_VELOCITY) + velocity = MAX_VELOCITY; + + if (item.Animation.ActiveState == SQUISHY_BLOCK_STATE_MOVE) + { + auto forwardDir = EulerAngles(0, item.Pose.Orientation.y + headingAngle, 0).ToDirection(); + + auto pointColl = GetPointCollision(item.Pose.Position, item.RoomNumber, forwardDir, BLOCK(0.5f)); + + if (pointColl.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); + + if (!IsNextSectorValid(item, forwardDir, BLOCK(0.5f))) + { + switch (headingAngle) + { + default: + case ANGLE(0.0f): + SetAnimation(item, SQUISHY_BLOCK_ANIM_IMPACT_FRONT); + break; + + case ANGLE(-180.0f): + SetAnimation(item, SQUISHY_BLOCK_ANIM_IMPACT_BACK); + break; + } + } + else + { + float dist = Lerp(item.TriggerFlags / 4, item.TriggerFlags, velocity); + item.Pose.Position = Geometry::TranslatePoint(item.Pose.Position, forwardDir, dist); + } + } + else + { + if (item.Animation.FrameNumber == GetAnimData(item).frameEnd) + { + if (item.HitPoints != NOT_TARGETABLE && item.HitPoints) + { + someAngle = item.HitPoints; + item.HitPoints = NOT_TARGETABLE; + } + + headingAngle += ANGLE(180.0f); + item.Pose.Orientation.y += ANGLE(someAngle); + } + } + } + + AnimateItem(&item); + } + + void ControlFallingSquishyBlock(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (!TriggerActive(&item)) + return; + + short& velocity = item.ItemFlags[0]; + + if (velocity < MAX_FALLING_VELOCITY) + { + SoundEffect(SFX_TR4_EARTHQUAKE_LOOP, &item.Pose); + Camera.bounce = (velocity - 92) / 2; + velocity++; + } + else + { + if ((item.Animation.FrameNumber - GetAnimData(item).frameBase) == FALLING_BLOCK_IMPACT_FRAME) + Camera.bounce = -96; + + AnimateItem(&item); + } + } + + void CollideSquishyBlock(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) + { + if (playerItem->HitPoints <= 0) + return; + + auto& item = g_Level.Items[itemNumber]; + + if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) + return; + + if (!TestCollision(&item, playerItem)) + return; + + if (!ItemPushItem(&item, playerItem, coll, false, 1)) + return; + + if (item.Animation.ActiveState == SQUISHY_BLOCK_STATE_BAKED_MOTION) + { + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; + if (!frameNumber || frameNumber == SQUISHY_BLOCK_LETHAL_FRAME) + DoDamage(playerItem, INT_MAX); + } + else if (item.Animation.ActiveState == SQUISHY_BLOCK_STATE_COLLIDE_RIGHT || + item.Animation.ActiveState == SQUISHY_BLOCK_STATE_COLLIDE_LEFT) + { + DoDamage(playerItem, INT_MAX); + } + } + + void CollideFallingSquishyBlock(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) + { + auto& item = g_Level.Items[itemNumber]; + + if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) + return; + + if (!TestCollision(&item, playerItem)) + return; + + if ((item.Animation.FrameNumber - GetAnimData(item).frameBase) <= FALLING_BLOCK_IMPACT_FRAME) + { + item.Animation.FrameNumber += FALLING_BLOCK_NEXT_FRAME; + + DoDamage(playerItem, INT_MAX); + SetAnimation(playerItem, LA_BOULDER_DEATH); + playerItem->Animation.Velocity.y = 0.0f; + playerItem->Animation.Velocity.z = 0.0f; + } + else if (playerItem->HitPoints > 0) + { + ItemPushItem(&item, playerItem, coll, false, 1); + } + } +} diff --git a/TombEngine/Objects/TR4/Trap/SquishyBlock.h b/TombEngine/Objects/TR4/Trap/SquishyBlock.h new file mode 100644 index 000000000..42b13766e --- /dev/null +++ b/TombEngine/Objects/TR4/Trap/SquishyBlock.h @@ -0,0 +1,13 @@ +#pragma once + +struct CollisionInfo; +struct ItemInfo; + +namespace TEN::Entities::Traps +{ + void InitializeSquishyBlock(short itemNumber); + void ControlSquishyBlock(short itemNumber); + void ControlFallingSquishyBlock(short itemNumber); + void CollideSquishyBlock(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); + void CollideFallingSquishyBlock(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); +} diff --git a/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp b/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp index 890b234d1..8dcd9c655 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp @@ -100,10 +100,10 @@ namespace TEN::Entities::TR4 { short targetItem = g_Level.Rooms[item->RoomNumber].itemNumber; - if (targetItem != NO_ITEM) + if (targetItem != NO_VALUE) { auto* target = &g_Level.Items[targetItem]; - for (; targetItem != NO_ITEM; targetItem = target->NextItem) + for (; targetItem != NO_VALUE; targetItem = target->NextItem) { target = &g_Level.Items[targetItem]; @@ -126,10 +126,10 @@ namespace TEN::Entities::TR4 { short targetItem = g_Level.Rooms[item->RoomNumber].itemNumber; - if (targetItem != NO_ITEM) + if (targetItem != NO_VALUE) { auto* target = &g_Level.Items[targetItem]; - for (; targetItem != NO_ITEM; targetItem = target->NextItem) + for (; targetItem != NO_VALUE; targetItem = target->NextItem) { target = &g_Level.Items[targetItem]; @@ -151,10 +151,10 @@ namespace TEN::Entities::TR4 { targetItem = g_Level.Rooms[item->RoomNumber].itemNumber; - if (targetItem != NO_ITEM) + if (targetItem != NO_VALUE) { auto* target = &g_Level.Items[targetItem]; - for (; targetItem != NO_ITEM; targetItem = target->NextItem) + for (; targetItem != NO_VALUE; targetItem = target->NextItem) { target = &g_Level.Items[targetItem]; diff --git a/TombEngine/Objects/TR4/Trap/tr4_mine.cpp b/TombEngine/Objects/TR4/Trap/tr4_mine.cpp index d5b5558c2..41c38608d 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_mine.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_mine.cpp @@ -57,7 +57,7 @@ namespace TEN::Entities::TR4 short currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; // Make the sentry gun explode? - while (currentItemNumber != NO_ITEM) + while (currentItemNumber != NO_VALUE) { auto* currentItem = &g_Level.Items[currentItemNumber]; diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp index 28f043852..2983d3832 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp @@ -151,7 +151,7 @@ namespace TEN::Entities::TR4 TriggerBlood(dx, yBottom - (GetRandomControl() % dy), dz, GetRandomControl() << 1, 1); } - if (LaraItem->HitPoints <= 0 && Lara.Context.Vehicle == NO_ITEM) + if (LaraItem->HitPoints <= 0 && Lara.Context.Vehicle == NO_VALUE) { int heightFromFloor = GetPointCollision(*LaraItem).GetFloorHeight() - LaraItem->Pose.Position.y; diff --git a/TombEngine/Objects/TR4/Vehicles/jeep.cpp b/TombEngine/Objects/TR4/Vehicles/jeep.cpp index d06cdbd3d..169e254e6 100644 --- a/TombEngine/Objects/TR4/Vehicles/jeep.cpp +++ b/TombEngine/Objects/TR4/Vehicles/jeep.cpp @@ -157,7 +157,7 @@ namespace TEN::Entities::Vehicles auto* jeep = GetJeepInfo(jeepItem); auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints <= 0 && lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints <= 0 && lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(jeepItem, laraItem, coll, JeepMountTypes, JEEP_MOUNT_DISTANCE); @@ -178,7 +178,7 @@ namespace TEN::Entities::Vehicles // HACK: Hardcoded jeep keys check. /*if (g_Gui.GetInventoryItemChosen() == ID_PUZZLE_ITEM1) { - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); return true; } else diff --git a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp index 358878548..985ab5360 100644 --- a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp +++ b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp @@ -160,7 +160,7 @@ namespace TEN::Entities::Vehicles auto* motorbike = GetMotorbikeInfo(motorbikeItem); auto* lara = GetLaraInfo(laraItem); - if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_ITEM) + if (laraItem->HitPoints < 0 || lara->Context.Vehicle != NO_VALUE) return; auto mountType = GetVehicleMountType(motorbikeItem, laraItem, coll, MotorbikeMountTypes, MOTORBIKE_MOUNT_DISTANCE); @@ -190,7 +190,7 @@ namespace TEN::Entities::Vehicles /*if (g_Gui.GetInventoryItemChosen() == ID_PUZZLE_ITEM1) { SetAnimation(*laraItem, ID_MOTORBIKE_LARA_ANIMS, MOTORBIKE_ANIM_UNLOCK); - g_Gui.SetInventoryItemChosen(NO_ITEM); + g_Gui.SetInventoryItemChosen(NO_VALUE); motorbike->Flags |= MOTORBIKE_FLAG_NITRO; } else @@ -400,7 +400,7 @@ namespace TEN::Entities::Vehicles auto* motorbike = GetMotorbikeInfo(motorbikeItem); auto* lara = GetLaraInfo(laraItem); - if (lara->Context.Vehicle == NO_ITEM) + if (lara->Context.Vehicle == NO_VALUE) return; if (laraItem->Animation.ActiveState != MOTORBIKE_STATE_MOUNT && laraItem->Animation.ActiveState != MOTORBIKE_STATE_DISMOUNT) @@ -432,7 +432,7 @@ namespace TEN::Entities::Vehicles { auto* lara = GetLaraInfo(laraItem); - if (lara->Context.Vehicle != NO_ITEM) + if (lara->Context.Vehicle != NO_VALUE) { auto* item = &g_Level.Items[lara->Context.Vehicle]; diff --git a/TombEngine/Objects/TR4/tr4_objects.cpp b/TombEngine/Objects/TR4/tr4_objects.cpp index 87476a078..b54171260 100644 --- a/TombEngine/Objects/TR4/tr4_objects.cpp +++ b/TombEngine/Objects/TR4/tr4_objects.cpp @@ -70,6 +70,7 @@ #include "Objects/TR4/Trap/tr4_plough.h" #include "Objects/TR4/Trap/tr4_sethblade.h" #include "Objects/TR4/Trap/tr4_slicerdicer.h" +#include "Objects/TR4/Trap/SquishyBlock.h" #include "Objects/TR4/Trap/tr4_spikeball.h" #include "Objects/TR4/Trap/tr4_stargate.h" #include "Objects/TR4/Trap/tr4_cog.h" @@ -949,6 +950,23 @@ namespace TEN::Entities obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } + + obj = &Objects[ID_SQUISHY_BLOCK_HORIZONTAL]; + if (obj->loaded) + { + obj->Initialize = InitializeSquishyBlock; + obj->control = ControlSquishyBlock; + obj->collision = CollideSquishyBlock; + obj->SetHitEffect(true); + } + + obj = &Objects[ID_SQUISHY_BLOCK_VERTICAL]; + if (obj->loaded) + { + obj->control = ControlFallingSquishyBlock; + obj->collision = CollideFallingSquishyBlock; + obj->SetHitEffect(true); + } } static void StartVehicles(ObjectInfo* obj) diff --git a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp index cb870c0c8..a071909d9 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp @@ -74,7 +74,7 @@ short GetNextBat() index++; if (index >= NUM_BATS) - return NO_ITEM; + return NO_VALUE; } NextBat = (batNumber + 1) & (NUM_BATS - 1); @@ -86,7 +86,7 @@ void TriggerLittleBat(ItemInfo* item) { short batNumber = GetNextBat(); - if (batNumber != NO_ITEM) + if (batNumber != NO_VALUE) { auto* bat = &Bats[batNumber]; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp index 6d6848002..bb1a1403a 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp @@ -39,7 +39,7 @@ short GetNextRat() i++; if (i >= NUM_RATS) - return NO_ITEM; + return NO_VALUE; } NextRat = (ratNumber + 1) & 0x1F; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp index b4eb28d9c..8e201afe2 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp @@ -34,7 +34,7 @@ short GetNextSpider() } if (++i >= NUM_SPIDERS) - return NO_ITEM; + return NO_VALUE; } NextSpider = (spiderNumber + 1) & (NUM_SPIDERS - 1); @@ -96,7 +96,7 @@ void SpidersEmitterControl(short itemNumber) item->ItemFlags[2]--; short spiderNumber = GetNextSpider(); - if (spiderNumber != NO_ITEM) + if (spiderNumber != NO_VALUE) { auto* spider = &Spiders[spiderNumber]; diff --git a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp index f618f3145..65d0fdd13 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_cyborg.cpp @@ -319,7 +319,7 @@ namespace TEN::Entities::Creatures::TR5 joint1 = AI.xAngle; } - if (item.Animation.RequiredState != NO_STATE) + if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } diff --git a/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp b/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp index f8856cc55..3de10ca75 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_doberman.cpp @@ -166,7 +166,7 @@ namespace TEN::Entities::Creatures::TR5 } else { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else { diff --git a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp index 52d97af04..2e10b3cbc 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp @@ -176,7 +176,7 @@ namespace TEN::Entities::Creatures::TR5 if (creature->Mood == MoodType::Bored || (item->AIBits & FOLLOW && (creature->ReachedGoal || distance > pow(BLOCK(2), 2)))) { - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (Random::TestProbability(1 / 64.0f)) item->Animation.TargetState = GLADIATOR_STATE_IDLE; diff --git a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp index b4867f799..b405ab487 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_guard.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_guard.cpp @@ -229,7 +229,7 @@ namespace TEN::Entities::Creatures::TR5 item->SetMeshSwapFlags(9216); roomItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; - if (roomItemNumber != NO_ITEM) + if (roomItemNumber != NO_VALUE) { ItemInfo* item2 = nullptr; while (true) @@ -244,7 +244,7 @@ namespace TEN::Entities::Creatures::TR5 } roomItemNumber = item2->NextItem; - if (roomItemNumber == NO_ITEM) + if (roomItemNumber == NO_VALUE) { item->Animation.FrameNumber = GetAnimData(item).frameBase; item->Animation.ActiveState = item->Animation.TargetState; @@ -467,7 +467,7 @@ namespace TEN::Entities::Creatures::TR5 if (item->ObjectNumber == ID_SCIENTIST && item == Lara.TargetEntity) item->Animation.TargetState = GUARD_STATE_SURRENDER; - else if (item->Animation.RequiredState != NO_STATE) + else if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (item->AIBits & GUARD) { @@ -767,7 +767,7 @@ namespace TEN::Entities::Creatures::TR5 item->SetMeshSwapFlags(NO_JOINT_BITS); short currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; - if (currentItemNumber == NO_ITEM) + if (currentItemNumber == NO_VALUE) break; while (true) @@ -783,11 +783,11 @@ namespace TEN::Entities::Creatures::TR5 } currentItemNumber = currentItem->NextItem; - if (currentItemNumber == NO_ITEM) + if (currentItemNumber == NO_VALUE) break; } - if (currentItemNumber == NO_ITEM) + if (currentItemNumber == NO_VALUE) break; currentItem->MeshBits = -3; @@ -849,7 +849,7 @@ namespace TEN::Entities::Creatures::TR5 creature->MaxTurn = 0; currentItem = nullptr; - for (currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; currentItemNumber != NO_ITEM; currentItemNumber = currentItem->NextItem) + for (currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; currentItemNumber != NO_VALUE; currentItemNumber = currentItem->NextItem) { currentItem = &g_Level.Items[currentItemNumber]; if (item->ObjectNumber == ID_PUZZLE_HOLE8) // TODO: Avoid hardcoded object number. -- TokyoSU 24/12/2022 diff --git a/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp b/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp index f20b47a91..70e8a43e6 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_hydra.cpp @@ -59,7 +59,7 @@ namespace TEN::Entities::Creatures::TR5 static void HydraBubblesAttack(Pose* pos, short roomNumber, int count) { short fxNumber = CreateNewEffect(roomNumber); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { auto* fx = &EffectList[fxNumber]; diff --git a/TombEngine/Objects/TR5/Entity/tr5_imp.cpp b/TombEngine/Objects/TR5/Entity/tr5_imp.cpp index 79bf1e917..350254539 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_imp.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_imp.cpp @@ -110,7 +110,7 @@ namespace TEN::Entities::Creatures::TR5 orient.y += short(GetRandomControl() % (distance / 4) - (distance / 8)); int fxNumber = CreateNewEffect(item->RoomNumber); - if (fxNumber == NO_ITEM) + if (fxNumber == NO_VALUE) return; auto& fx = EffectList[fxNumber]; @@ -150,7 +150,7 @@ namespace TEN::Entities::Creatures::TR5 auto torchItemsNumbers = FindCreatedItems(ID_BURNING_TORCH_ITEM); for (auto& itemNumber : torchItemsNumbers) { - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) continue; const auto& torchItem = g_Level.Items[itemNumber]; diff --git a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp index 535fe9ee0..a9adcaf22 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp @@ -153,7 +153,7 @@ namespace TEN::Entities::Creatures::TR5 if (AI.ahead) joint1 = AI.xAngle; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (item->AIBits & AMBUSH) item->Animation.TargetState = STATE_TR5_LARSON_RUN; diff --git a/TombEngine/Objects/TR5/Entity/tr5_lion.cpp b/TombEngine/Objects/TR5/Entity/tr5_lion.cpp index ac6e20bf8..d7ec76a4f 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_lion.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_lion.cpp @@ -136,7 +136,7 @@ namespace TEN::Entities::Creatures::TR5 creature->MaxTurn = 0; creature->Flags = 0; - if (item->Animation.RequiredState != NO_STATE) + if (item->Animation.RequiredState != NO_VALUE) { item->Animation.TargetState = item->Animation.RequiredState; break; diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index e13dad101..2e041645b 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -82,7 +82,7 @@ namespace TEN::Entities::Creatures::TR5 if (!(GetRandomControl() & 0x1F)) { int fxNumber = CreateNewEffect(item->RoomNumber); - if (fxNumber != NO_ITEM) + if (fxNumber != NO_VALUE) { auto* fx = &EffectList[fxNumber]; @@ -206,7 +206,7 @@ namespace TEN::Entities::Creatures::TR5 static void RomanStatueAttack(Pose* pos, short roomNumber, short count) { int fxNumber = CreateNewEffect(roomNumber); - if (fxNumber == NO_ITEM) + if (fxNumber == NO_VALUE) return; auto* fx = &EffectList[fxNumber]; diff --git a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp index ee7bb7b9e..081e13aa8 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp @@ -137,7 +137,7 @@ namespace TEN::Entities::Creatures::TR5 void SubmarineAttack(ItemInfo* item) { short itemNumber = CreateItem(); - if (itemNumber == NO_ITEM) + if (itemNumber == NO_VALUE) return; auto* torpedoItem = &g_Level.Items[itemNumber]; @@ -398,7 +398,7 @@ namespace TEN::Entities::Creatures::TR5 Vector3i pos; - if (item->ItemFlags[0] == NO_ITEM) + if (item->ItemFlags[0] == NO_VALUE) { bool found = false; for (int i = g_Level.NumItems; i < 256; i++) @@ -432,7 +432,7 @@ namespace TEN::Entities::Creatures::TR5 { pos.x = 4 * item->Animation.ActiveState; pos.y = 4 * item->Animation.TargetState; - pos.z = 4 * (item->Animation.RequiredState == NO_STATE) ? 0 : item->Animation.RequiredState; + pos.z = 4 * (item->Animation.RequiredState == NO_VALUE) ? 0 : item->Animation.RequiredState; } } diff --git a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp index 31de65aeb..24835ed4d 100644 --- a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp @@ -74,7 +74,7 @@ namespace TEN::Entities::Generic short roomNumber = item->RoomNumber; auto* floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); - if (floor->Box != NO_BOX) + if (floor->Box != NO_VALUE) g_Level.Boxes[floor->Box].flags &= ~BLOCKED; // Set mutators to EulerAngles identity by default. diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index 4c92f76e1..5b46ad3b0 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -484,7 +484,7 @@ void ClassicRollingBallControl(short itemNum) item->Animation.FrameNumber = GetAnimData(item).frameBase; item->Animation.ActiveState = GetAnimData(item).ActiveState; item->Animation.TargetState = GetAnimData(item).ActiveState; - item->Animation.RequiredState = NO_STATE; + item->Animation.RequiredState = NO_VALUE; RemoveActiveItem(itemNum); } } diff --git a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp index bb75a6201..4125df0a4 100644 --- a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp +++ b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp @@ -16,9 +16,9 @@ void InitializeSmashObject(short itemNumber) auto* room = &g_Level.Rooms[item->RoomNumber]; - // NOTE: Avoids crash when attempting to access Boxes[] array while box is equal to NO_BOX. -- TokyoSU 2022.12.20 + // NOTE: Avoids crash when attempting to access Boxes[] array while box is equal to NO_VALUE. -- TokyoSU 2022.12.20 FloorInfo* floor = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z); - if (floor->Box == NO_BOX) + if (floor->Box == NO_VALUE) { TENLog("Smash object with ID " + std::to_string(itemNumber) + " may be inside a wall." , LogLevel::Warning); return; @@ -42,7 +42,7 @@ void SmashObject(short itemNumber) SoundEffect(SFX_TR5_SMASH_GLASS, &item->Pose); - item->Collidable = 0; + item->Collidable = false; item->MeshBits = 0xFFFE; ExplodingDeath(itemNumber, BODY_DO_EXPLOSION | BODY_NO_BOUNCE); diff --git a/TombEngine/Objects/TR5/Trap/LaserBeam.cpp b/TombEngine/Objects/TR5/Trap/LaserBeam.cpp index 24faab523..ae227bcbc 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBeam.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBeam.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/Point.h" #include "Game/control/los.h" #include "Game/effects/effects.h" #include "Game/effects/item_fx.h" @@ -14,6 +15,7 @@ #include "Renderer/Renderer.h" #include "Specific/level.h" +using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; using namespace TEN::Effects::Spark; using namespace TEN::Math; @@ -87,7 +89,7 @@ namespace TEN::Traps::TR5 auto origin = GameVector(item.Pose.Position, item.RoomNumber); auto target = GameVector( Geometry::TranslatePoint(origin.ToVector3(), dir, MAX_VISIBILITY_DISTANCE), - GetCollision(origin.ToVector3i(), origin.RoomNumber, dir, MAX_VISIBILITY_DISTANCE).RoomNumber); + GetPointCollision(origin.ToVector3i(), origin.RoomNumber, dir, MAX_VISIBILITY_DISTANCE).GetRoomNumber()); // Hit wall; spawn sparks and light. if (!LOS(&origin, &target)) @@ -177,9 +179,6 @@ namespace TEN::Traps::TR5 void CollideLaserBeam(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) { - constexpr auto LIGHT_INTENSITY = 1.0f; - constexpr auto LIGHT_AMPLITUDE_MAX = 0.4f; - if (!LaserBeams.count(itemNumber)) return; @@ -195,9 +194,9 @@ namespace TEN::Traps::TR5 auto rotMatrix = EulerAngles(item.Pose.Orientation.x + ANGLE(180.0f), item.Pose.Orientation.y, item.Pose.Orientation.z); auto target = GameVector(Geometry::TranslatePoint(origin.ToVector3(), rotMatrix, MAX_VISIBILITY_DISTANCE), 0); - auto pointColl = GetCollision(target.ToVector3i(),item.RoomNumber); - if (pointColl.RoomNumber != target.RoomNumber) - target.RoomNumber = pointColl.RoomNumber; + auto pointColl = GetPointCollision(target.ToVector3i(), item.RoomNumber); + if (pointColl.GetRoomNumber() != target.RoomNumber) + target.RoomNumber = pointColl.GetRoomNumber(); bool los2 = LOS(&origin, &target); @@ -216,7 +215,7 @@ namespace TEN::Traps::TR5 } beam.Color.w = Random::GenerateFloat(0.6f, 1.0f); - SpawnLaserBeamLight(item.Pose.Position.ToVector3(), item.RoomNumber, item.Model.Color, LIGHT_INTENSITY, LIGHT_AMPLITUDE_MAX); + SpawnLaserBeamLight(item.Pose.Position.ToVector3(), item.RoomNumber, item.Model.Color, LASER_BEAM_LIGHT_INTENSITY, LASER_BEAM_LIGHT_AMPLITUDE_MAX); } } diff --git a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp index bb5bb3654..8b33196a2 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp @@ -129,49 +129,43 @@ void ExplosionControl(short itemNumber) } } - GetCollidedObjects(item, 2048, true, CollidedItems, CollidedMeshes, 1); - if (CollidedItems[0] || CollidedMeshes[0]) + auto collObjects = GetCollidedObjects(*item, true, true, BLOCK(2), ObjectCollectionMode::All); + if (!collObjects.IsEmpty()) { - int i = 0; - while (CollidedItems[i]) + for (auto* itemPtr : collObjects.ItemPtrs) { - if (CollidedItems[i]->ObjectNumber >= ID_SMASH_OBJECT1 && CollidedItems[i]->ObjectNumber <= ID_SMASH_OBJECT16) + if (itemPtr->ObjectNumber >= ID_SMASH_OBJECT1 && itemPtr->ObjectNumber <= ID_SMASH_OBJECT16) { - TriggerExplosionSparks(CollidedItems[i]->Pose.Position.x, CollidedItems[i]->Pose.Position.y, CollidedItems[i]->Pose.Position.z, 3, -2, 0, CollidedItems[i]->RoomNumber); - CollidedItems[i]->Pose.Position.y -= 128; - TriggerShockwave(&CollidedItems[i]->Pose, 48, 304, 96, 128, 96, 0, 24, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); - CollidedItems[i]->Pose.Position.y += 128; - ExplodeItemNode(CollidedItems[i], 0, 0, 80); - SmashObject(CollidedItems[i]->Index); - KillItem(CollidedItems[i]->Index); + TriggerExplosionSparks(itemPtr->Pose.Position.x, itemPtr->Pose.Position.y, itemPtr->Pose.Position.z, 3, -2, 0, itemPtr->RoomNumber); + itemPtr->Pose.Position.y -= 128; + TriggerShockwave(&itemPtr->Pose, 48, 304, 96, 128, 96, 0, 24, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); + itemPtr->Pose.Position.y += 128; + ExplodeItemNode(itemPtr, 0, 0, 80); + SmashObject(itemPtr->Index); + KillItem(itemPtr->Index); } - else if (CollidedItems[i]->ObjectNumber != ID_SWITCH_TYPE7 && CollidedItems[i]->ObjectNumber != ID_SWITCH_TYPE8) + else if (itemPtr->ObjectNumber != ID_SWITCH_TYPE7 && itemPtr->ObjectNumber != ID_SWITCH_TYPE8) { - if (Objects[CollidedItems[i]->ObjectNumber].intelligent) - DoExplosiveDamage(*LaraItem, *CollidedItems[i], *item, Weapons[(int)LaraWeaponType::GrenadeLauncher].ExplosiveDamage); + if (Objects[itemPtr->ObjectNumber].intelligent) + DoExplosiveDamage(*LaraItem, *itemPtr, *item, Weapons[(int)LaraWeaponType::GrenadeLauncher].ExplosiveDamage); } else { - /* @FIXME This calls CrossbowHitSwitchType78() */ + // @FIXME: This calls CrossbowHitSwitchType78() } - - ++i; } - i = 0; - while (CollidedMeshes[i]) + for (auto* staticPtr : collObjects.StaticPtrs) { - if (StaticObjects[CollidedMeshes[i]->staticNumber].shatterType != ShatterType::None) + if (StaticObjects[staticPtr->staticNumber].shatterType != ShatterType::None) { - TriggerExplosionSparks(CollidedMeshes[i]->pos.Position.x, CollidedMeshes[i]->pos.Position.y, CollidedMeshes[i]->pos.Position.z, 3, -2, 0, item->RoomNumber); - CollidedMeshes[i]->pos.Position.y -= 128; - TriggerShockwave(&CollidedMeshes[i]->pos, 40, 176, 64, 128, 96, 0, 16, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); - CollidedMeshes[i]->pos.Position.y += 128; - SoundEffect(GetShatterSound(CollidedMeshes[i]->staticNumber), &CollidedMeshes[i]->pos); - ShatterObject(NULL, CollidedMeshes[i], -128, item->RoomNumber, 0); + TriggerExplosionSparks(staticPtr->pos.Position.x, staticPtr->pos.Position.y, staticPtr->pos.Position.z, 3, -2, 0, item->RoomNumber); + staticPtr->pos.Position.y -= 128; + TriggerShockwave(&staticPtr->pos, 40, 176, 64, 128, 96, 0, 16, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); + staticPtr->pos.Position.y += 128; + SoundEffect(GetShatterSound(staticPtr->staticNumber), &staticPtr->pos); + ShatterObject(nullptr, staticPtr, -128, item->RoomNumber, 0); } - - ++i; } AlertNearbyGuards(item); diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index 485951b01..f04d93296 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -341,8 +341,8 @@ enum GAME_OBJECT_ID : short ID_SARCOPHAGUS, ID_ENEMY_PIECE, ID_EXPANDING_PLATFORM, - ID_SQUISHY_BLOCK1, - ID_SQUISHY_BLOCK2, + ID_SQUISHY_BLOCK_HORIZONTAL, + ID_SQUISHY_BLOCK_VERTICAL, ID_LASER_BEAM, ID_MINE_DETECTOR, ID_MAP, diff --git a/TombEngine/Renderer/ConstantBuffers/InstancedStaticBuffer.h b/TombEngine/Renderer/ConstantBuffers/InstancedStaticBuffer.h index 6a9f54008..8b5fc8033 100644 --- a/TombEngine/Renderer/ConstantBuffers/InstancedStaticBuffer.h +++ b/TombEngine/Renderer/ConstantBuffers/InstancedStaticBuffer.h @@ -17,7 +17,7 @@ namespace TEN::Renderer::ConstantBuffers //-- Vector4 Ambient; //-- - ShaderLight Lights[8]; + ShaderLight Lights[MAX_LIGHTS_PER_ITEM]; //-- int NumLights; int LightMode; diff --git a/TombEngine/Renderer/Renderer.cpp b/TombEngine/Renderer/Renderer.cpp index e7bfe0859..42db9a9c6 100644 --- a/TombEngine/Renderer/Renderer.cpp +++ b/TombEngine/Renderer/Renderer.cpp @@ -52,7 +52,7 @@ namespace TEN::Renderer { item.PrevRoomNumber = NO_ROOM; item.RoomNumber = NO_ROOM; - item.ItemNumber = NO_ITEM; + item.ItemNumber = NO_VALUE; item.LightsToDraw.clear(); } } diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 037545d6b..d738ae413 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -258,8 +258,8 @@ namespace TEN::Renderer // Preallocated pools of objects for avoiding new/delete // Items and effects are safe (can't be more than 1024 items in TR), // lights should be oversized (eventually ignore lights more than MAX_LIGHTS) - RendererItem _items[NUM_ITEMS]; - RendererEffect _effects[NUM_ITEMS]; + RendererItem _items[ITEM_COUNT_MAX]; + RendererEffect _effects[ITEM_COUNT_MAX]; // Debug variables int _numDrawCalls = 0; @@ -447,6 +447,7 @@ namespace TEN::Renderer void DrawTriangles3D(RenderView& view); void DrawOverlays(RenderView& view); void PrepareRopes(RenderView& view); + void DrawFishSwarm(RenderView& view, RendererPass rendererPass); void DrawBats(RenderView& view, RendererPass rendererPass); void DrawRats(RenderView& view, RendererPass rendererPass); void DrawScarabs(RenderView& view, RendererPass rendererPass); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 8a96725ef..8093ca8d3 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -21,6 +21,7 @@ #include "Game/Setup.h" #include "Objects/Effects/tr4_locusts.h" #include "Objects/Generic/Object/rope.h" +#include "Objects/TR3/Entity/FishSwarm.h" #include "Objects/TR4/Entity/tr4_beetle_swarm.h" #include "Objects/TR5/Emitter/tr5_bats_emitter.h" #include "Objects/TR5/Emitter/tr5_rats_emitter.h" @@ -31,16 +32,17 @@ #include "Specific/winmain.h" #include "Renderer/Structures/RendererSortableObject.h" +using namespace std::chrono; +using namespace TEN::Effects::Hair; +using namespace TEN::Entities::Creatures::TR3; +using namespace TEN::Entities::Generic; +using namespace TEN::Hud; +using namespace TEN::Renderer::Structures; + extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; namespace TEN::Renderer { - using namespace std::chrono; - using namespace TEN::Effects::Hair; - using namespace TEN::Entities::Generic; - using namespace TEN::Hud; - using namespace TEN::Renderer::Structures; - void Renderer::RenderBlobShadows(RenderView& renderView) { auto nearestSpheres = std::vector{}; @@ -610,14 +612,126 @@ namespace TEN::Renderer } } + void Renderer::DrawFishSwarm(RenderView& view, RendererPass rendererPass) + { + if (!Objects[ID_FISH_EMITTER].loaded) + return; + + if (rendererPass == RendererPass::CollectTransparentFaces) + { + for (const auto& fish : FishSwarm) + { + if (fish.Life <= 0.0f) + continue; + + auto& mesh = *GetMesh(Objects[ID_FISH_EMITTER].meshIndex + fish.MeshIndex); + for (auto& bucket : mesh.Buckets) + { + if (!IsSortedBlendMode(bucket.BlendMode)) + continue; + + for (auto& poly : bucket.Polygons) + { + auto worldMatrix = fish.Orientation.ToRotationMatrix() * Matrix::CreateTranslation(fish.Position); + auto center = Vector3::Transform(poly.Centre, worldMatrix); + float dist = Vector3::Distance(center, view.Camera.WorldPosition); + + auto object = RendererSortableObject{}; + object.ObjectType = RendererObjectType::MoveableAsStatic; + object.Centre = center; + object.Distance = dist; + object.Bucket = &bucket; + object.Mesh = &mesh; + object.Polygon = &poly; + object.World = worldMatrix; + object.Room = &_rooms[fish.RoomNumber]; + + view.TransparentObjectsToDraw.push_back(object); + } + } + } + } + else + { + bool doesActiveFishExist = false; + for (const auto& fish : FishSwarm) + { + if (fish.Life > 0.0f) + { + doesActiveFishExist = true; + break; + } + } + + if (doesActiveFishExist) + { + if (rendererPass == RendererPass::GBuffer) + { + _context->VSSetShader(_vsGBufferStatics.Get(), nullptr, 0); + _context->PSSetShader(_psGBuffer.Get(), nullptr, 0); + } + else + { + _context->VSSetShader(_vsStatics.Get(), nullptr, 0); + _context->PSSetShader(_psStatics.Get(), nullptr, 0); + } + + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; + + _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); + _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); + + const auto& moveableObj = *_moveableObjects[ID_FISH_EMITTER]; + + _stStatic.LightMode = (int)moveableObj.ObjectMeshes[0]->LightMode; + + for (const auto& fish : FishSwarm) + { + if (fish.Life <= 0.0f) + continue; + + const auto& mesh = *GetMesh(Objects[ID_FISH_EMITTER].meshIndex + fish.MeshIndex); + + _stStatic.World = fish.Orientation.ToRotationMatrix() * Matrix::CreateTranslation(fish.Position); + _stStatic.Color = Vector4::One; + _stStatic.AmbientLight = _rooms[fish.RoomNumber].AmbientLight; + + if (rendererPass != RendererPass::GBuffer) + BindStaticLights(_rooms[fish.RoomNumber].LightsToDraw); + + _cbStatic.UpdateData(_stStatic, _context.Get()); + + for (const auto& bucket : mesh.Buckets) + { + if (bucket.NumVertices == 0) + continue; + + int passCount = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest) ? 2 : 1; + for (int p = 0; p < passCount; p++) + { + if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) + continue; + + BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + + DrawIndexedTriangles(bucket.NumIndices, bucket.StartIndex, 0); + + _numMoveablesDrawCalls++; + } + } + } + } + } + } + void Renderer::DrawBats(RenderView& view, RendererPass rendererPass) { if (!Objects[ID_BATS_EMITTER].loaded) - { return; - } - RendererMesh* mesh = GetMesh(Objects[ID_BATS_EMITTER].meshIndex + (GlobalCounter & 3)); + auto* mesh = GetMesh(Objects[ID_BATS_EMITTER].meshIndex + (GlobalCounter & 3)); if (rendererPass == RendererPass::CollectTransparentFaces) { @@ -680,52 +794,55 @@ namespace TEN::Renderer batsCount++; } - } - if (batsCount > 0) - { - if (rendererPass == RendererPass::GBuffer) + if (batsCount == INSTANCED_STATIC_MESH_BUCKET_SIZE || + (i == NUM_BATS - 1 && batsCount > 0)) { - _context->VSSetShader(_vsGBufferInstancedStatics.Get(), nullptr, 0); - _context->PSSetShader(_psGBuffer.Get(), nullptr, 0); - } - else - { - _context->VSSetShader(_vsInstancedStaticMeshes.Get(), nullptr, 0); - _context->PSSetShader(_psInstancedStaticMeshes.Get(), nullptr, 0); - } - - UINT stride = sizeof(Vertex); - UINT offset = 0; - - _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); - _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); - - _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); - - for (auto& bucket : mesh->Buckets) - { - if (bucket.NumVertices == 0) + if (rendererPass == RendererPass::GBuffer) { - continue; + _context->VSSetShader(_vsGBufferInstancedStatics.Get(), nullptr, 0); + _context->PSSetShader(_psGBuffer.Get(), nullptr, 0); + } + else + { + _context->VSSetShader(_vsInstancedStaticMeshes.Get(), nullptr, 0); + _context->PSSetShader(_psInstancedStaticMeshes.Get(), nullptr, 0); } - int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; + UINT stride = sizeof(Vertex); + UINT offset = 0; - for (int p = 0; p < passes; p++) + _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); + _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); + + _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get()); + + for (auto& bucket : mesh->Buckets) { - if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) + if (bucket.NumVertices == 0) { continue; } - BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; - DrawIndexedInstancedTriangles(bucket.NumIndices, batsCount, bucket.StartIndex, 0); + for (int p = 0; p < passes; p++) + { + if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) + { + continue; + } - _numMoveablesDrawCalls++; + BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + + DrawIndexedInstancedTriangles(bucket.NumIndices, batsCount, bucket.StartIndex, 0); + + _numMoveablesDrawCalls++; + } } + + batsCount = 0; } } } @@ -779,7 +896,10 @@ namespace TEN::Renderer } else { + std::vector> beetlesBuckets; + unsigned int beetleCount = 0; + for (int i = 0; i < TEN::Entities::TR4::NUM_BEETLES; i++) { const auto& beetle = TEN::Entities::TR4::BeetleSwarm[i]; @@ -795,57 +915,65 @@ namespace TEN::Renderer if (rendererPass != RendererPass::GBuffer) { - BindInstancedStaticLights(room.LightsToDraw, beetleCount); + std::vector lights; + for (int i = 0; i < std::min((int)room.LightsToDraw.size(), MAX_LIGHTS_PER_ITEM); i++) + { + lights.push_back(room.LightsToDraw[i]); + } + BindInstancedStaticLights(lights, beetleCount); } beetleCount++; } - } - if (beetleCount > 0) - { - if (rendererPass == RendererPass::GBuffer) + if (beetleCount == INSTANCED_STATIC_MESH_BUCKET_SIZE || + (i == TEN::Entities::TR4::NUM_BEETLES - 1 && beetleCount > 0)) { - _context->VSSetShader(_vsGBufferInstancedStatics.Get(), nullptr, 0); - _context->PSSetShader(_psGBuffer.Get(), nullptr, 0); - } - else - { - _context->VSSetShader(_vsInstancedStaticMeshes.Get(), nullptr, 0); - _context->PSSetShader(_psInstancedStaticMeshes.Get(), nullptr, 0); - } - - unsigned int stride = sizeof(Vertex); - unsigned int offset = 0; - - _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); - _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); - - _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); - - for (const auto& bucket : mesh->Buckets) - { - if (bucket.NumVertices == 0) + if (rendererPass == RendererPass::GBuffer) { - continue; + _context->VSSetShader(_vsGBufferInstancedStatics.Get(), nullptr, 0); + _context->PSSetShader(_psGBuffer.Get(), nullptr, 0); + } + else + { + _context->VSSetShader(_vsInstancedStaticMeshes.Get(), nullptr, 0); + _context->PSSetShader(_psInstancedStaticMeshes.Get(), nullptr, 0); } - int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; - for (int p = 0; p < passes; p++) + _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); + _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); + + _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get()); + + for (const auto& bucket : mesh->Buckets) { - if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) + if (bucket.NumVertices == 0) { continue; } - BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; - DrawIndexedInstancedTriangles(bucket.NumIndices, beetleCount, bucket.StartIndex, 0); + for (int p = 0; p < passes; p++) + { + if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) + { + continue; + } - _numInstancedStaticsDrawCalls++; + BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + + DrawIndexedInstancedTriangles(bucket.NumIndices, beetleCount, bucket.StartIndex, 0); + + _numInstancedStaticsDrawCalls++; + } } + + beetleCount = 0; } } } @@ -1710,6 +1838,7 @@ namespace TEN::Renderer DrawLocusts(view, RendererPass::Opaque); DrawDebris(view, RendererPass::Opaque); DrawSprites(view, RendererPass::Opaque); + DrawFishSwarm(view, RendererPass::Opaque); // Draw additive faces. DrawRooms(view, RendererPass::Additive); @@ -1723,6 +1852,7 @@ namespace TEN::Renderer DrawLocusts(view, RendererPass::Additive); DrawDebris(view, RendererPass::Additive); DrawSprites(view, RendererPass::Additive); + DrawFishSwarm(view, RendererPass::Additive); // Collect all non-commutative transparent faces. // NOTE: Sorted sprites are already collected at the beginning of the frame. @@ -1733,6 +1863,7 @@ namespace TEN::Renderer DrawEffects(view, RendererPass::CollectTransparentFaces); DrawRats(view, RendererPass::CollectTransparentFaces); DrawLocusts(view, RendererPass::CollectTransparentFaces); + DrawFishSwarm(view, RendererPass::CollectTransparentFaces); // Draw sorted faces. DrawSortedFaces(view); @@ -3120,7 +3251,7 @@ namespace TEN::Renderer } SetBlendMode(objectInfo->Bucket->BlendMode); - SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD); + SetAlphaTest(AlphaTestMode::None, ALPHA_TEST_THRESHOLD); // Draw geometry if (objectInfo->Bucket->Animated) @@ -3181,10 +3312,10 @@ namespace TEN::Renderer SetDepthState(DepthState::Read); SetCullMode(CullMode::CounterClockwise); SetBlendMode(objectInfo->Bucket->BlendMode); - SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD); + SetAlphaTest(AlphaTestMode::None, ALPHA_TEST_THRESHOLD); - _context->VSSetShader(_vsItems.Get(), nullptr, 0); - _context->PSSetShader(_psItems.Get(), nullptr, 0); + _context->VSSetShader(_vsItems.Get(), nullptr, 0); + _context->PSSetShader(_psItems.Get(), nullptr, 0); ItemInfo* nativeItem = &g_Level.Items[objectInfo->Item->ItemNumber]; RendererRoom* room = &_rooms[objectInfo->Item->RoomNumber]; @@ -3237,7 +3368,7 @@ namespace TEN::Renderer SetDepthState(DepthState::Read); SetCullMode(CullMode::CounterClockwise); SetBlendMode(objectInfo->Bucket->BlendMode); - SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD); + SetAlphaTest(AlphaTestMode::None, ALPHA_TEST_THRESHOLD); BindTexture(TextureRegister::ColorMap, &std::get<0>(_staticTextures[objectInfo->Bucket->Texture]), SamplerStateRegister::AnisotropicClamp); diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index f56578d0a..91b188a16 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -318,8 +318,8 @@ namespace TEN::Renderer RendererRoom& room = _rooms[roomNumber]; ROOM_INFO* r = &g_Level.Rooms[room.RoomNumber]; - short itemNum = NO_ITEM; - for (itemNum = r->itemNumber; itemNum != NO_ITEM; itemNum = g_Level.Items[itemNum].NextItem) + short itemNum = NO_VALUE; + for (itemNum = r->itemNumber; itemNum != NO_VALUE; itemNum = g_Level.Items[itemNum].NextItem) { ItemInfo* item = &g_Level.Items[itemNum]; @@ -798,8 +798,8 @@ namespace TEN::Renderer RendererRoom& room = _rooms[roomNumber]; ROOM_INFO* r = &g_Level.Rooms[room.RoomNumber]; - short fxNum = NO_ITEM; - for (fxNum = r->fxNumber; fxNum != NO_ITEM; fxNum = EffectList[fxNum].nextFx) + short fxNum = NO_VALUE; + for (fxNum = r->fxNumber; fxNum != NO_VALUE; fxNum = EffectList[fxNum].nextFx) { FX_INFO *fx = &EffectList[fxNum]; if (fx->objectNumber < 0 || fx->color.w <= 0) @@ -828,7 +828,7 @@ namespace TEN::Renderer void Renderer::ResetAnimations() { - for (int i = 0; i < NUM_ITEMS; i++) + for (int i = 0; i < ITEM_COUNT_MAX; i++) _items[i].DoneAnimations = false; } diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp index b94d8c92e..c6d339c5e 100644 --- a/TombEngine/Renderer/RendererInit.cpp +++ b/TombEngine/Renderer/RendererInit.cpp @@ -130,7 +130,7 @@ namespace TEN::Renderer _lines3DToDraw = createVector(MAX_LINES_3D); _triangles3DToDraw = createVector(MAX_TRIANGLES_3D); - for (int i = 0; i < NUM_ITEMS; i++) + for (int i = 0; i < ITEM_COUNT_MAX; i++) { _items[i].LightsToDraw = createVector(MAX_LIGHTS_PER_ITEM); _effects[i].LightsToDraw = createVector(MAX_LIGHTS_PER_ITEM); diff --git a/TombEngine/Renderer/RendererSprites.cpp b/TombEngine/Renderer/RendererSprites.cpp index 490a7b3d6..b969a0efe 100644 --- a/TombEngine/Renderer/RendererSprites.cpp +++ b/TombEngine/Renderer/RendererSprites.cpp @@ -540,9 +540,10 @@ namespace TEN::Renderer SetDepthState(DepthState::Read); SetCullMode(CullMode::None); SetBlendMode(objectInfo->Sprite->BlendMode); - SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD); + SetAlphaTest(AlphaTestMode::None, ALPHA_TEST_THRESHOLD); BindTexture(TextureRegister::ColorMap, objectInfo->Sprite->Sprite->Texture, SamplerStateRegister::LinearClamp); + BindRenderTargetAsTexture(TextureRegister::DepthMap, &_depthRenderTarget, SamplerStateRegister::PointWrap); DrawTriangles((int)_sortedPolygonsVertices.size(), 0); diff --git a/TombEngine/Resources.rc b/TombEngine/Resources.rc index 45ac7cd20..c475bfd5e 100644 --- a/TombEngine/Resources.rc +++ b/TombEngine/Resources.rc @@ -26,8 +26,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,0,0 - PRODUCTVERSION 1,7,0,0 + FILEVERSION 1,4,0,0 + PRODUCTVERSION 1,7,1,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BLOCK "000904b0" BEGIN VALUE "CompanyName", "Tomb Engine Development Community" - VALUE "FileVersion", "1.3.0.0" + VALUE "FileVersion", "1.4.0.0" VALUE "InternalName", "TombEngine.exe" VALUE "LegalCopyright", "Copyright (c) 2024" VALUE "OriginalFilename", "TombEngine.exe" VALUE "ProductName", "Tomb Engine" - VALUE "ProductVersion", "1.7.0.0" + VALUE "ProductVersion", "1.7.1.0" END END BLOCK "VarFileInfo" diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index bacae1d8f..e8821218c 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -315,6 +315,7 @@ static constexpr char ScriptReserved_KeyPush[] = "KeyPush"; static constexpr char ScriptReserved_KeyClear[] = "KeyClear"; static constexpr char ScriptReserved_FlipMap[] = "FlipMap"; +static constexpr char ScriptReserved_GetFlipMapStatus[] = "GetFlipMapStatus"; static constexpr char ScriptReserved_PlayFlyBy[] = "PlayFlyBy"; static constexpr char ScriptReserved_PlayCamera[] = "PlayCamera"; diff --git a/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp b/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp index 8e403a9d3..e76903b6b 100644 --- a/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp +++ b/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp @@ -167,7 +167,7 @@ namespace TEN::Scripting::Effects constexpr float secsPerFrame = 1.0f / (float)FPS; float life = USE_IF_HAVE(float, lifetime, 2.0f); - life = std::max(0.0f, life); + life = std::max(0.1f, life); int lifeInFrames = (int)round(life / secsPerFrame); s->life = s->sLife = lifeInFrames; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp index e2e99aef4..5240789f8 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp @@ -198,6 +198,19 @@ Must be an integer value (0 means no secrets). @tparam int total number of secrets */ tableFlow.set_function(ScriptReserved_SetTotalSecretCount, &FlowHandler::SetTotalSecretCount, this); + +/*** Do FlipMap with specific group ID. +@function FlipMap +@tparam int flipmap (ID of flipmap group to actuvate / deactivate) +*/ + tableFlow.set_function(ScriptReserved_FlipMap, &FlowHandler::FlipMap, this); + +/*** Get current FlipMap status for specific group ID. +@function GetFlipMapStatus +@int[opt] index Flipmap group ID to check. If no group specified or group is -1, function returns overall flipmap status (on or off). +@treturn int Status of the flipmap group (true means on, false means off). +*/ + tableFlow.set_function(ScriptReserved_GetFlipMapStatus, &FlowHandler::GetFlipMapStatus, this); /*** settings.lua. These functions are called in settings.lua, a file which holds your local settings. @@ -240,12 +253,6 @@ Specify which translations in the strings table correspond to which languages. */ tableFlow.set_function(ScriptReserved_SetLanguageNames, &FlowHandler::SetLanguageNames, this); -/*** Do FlipMap with specific ID. -//@function FlipMap -//@tparam int flipmap (ID of flipmap) -*/ - tableFlow.set_function(ScriptReserved_FlipMap, &FlowHandler::FlipMap, this); - ScriptColor::Register(parent); Rotation::Register(parent); Vec2::Register(parent); @@ -444,9 +451,25 @@ GameStatus FlowHandler::GetGameStatus() return this->LastGameStatus; } -void FlowHandler::FlipMap(int flipmap) +void FlowHandler::FlipMap(int group) { - DoFlipMap(flipmap); + DoFlipMap(group); +} + +bool FlowHandler::GetFlipMapStatus(std::optional group) +{ + if (!group.has_value() || group.value() == NO_VALUE) + { + return FlipStatus; + } + + if (group.value() < 0 || group.value() >= MAX_FLIPMAP) + { + TENLog("Maximum flipmap group number is " + std::to_string(MAX_FLIPMAP) + ". Please specify another index.", LogLevel::Warning); + return false; + } + + return FlipStatus && FlipStats[group.value()]; } void FlowHandler::SaveGame(int slot) diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h index b72d70f08..b6aa5a417 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h @@ -63,7 +63,8 @@ public: int GetNumLevels() const; void EndLevel(std::optional nextLevel, std::optional startPosIndex); GameStatus GetGameStatus(); - void FlipMap(int flipmap); + void FlipMap(int group); + bool GetFlipMapStatus(std::optional group); void SaveGame(int slot); void LoadGame(int slot); void DeleteSaveGame(int slot); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/AIObject/AIObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/AIObject/AIObject.cpp index 403d31ca9..49bfe900c 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/AIObject/AIObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/AIObject/AIObject.cpp @@ -13,8 +13,8 @@ AI object @pragma nostrip */ -static auto index_error = index_error_maker(AIObject, ScriptReserved_AIObject); -static auto newindex_error = newindex_error_maker(AIObject, ScriptReserved_AIObject); +static auto IndexError = index_error_maker(AIObject, ScriptReserved_AIObject); +static auto NewIndexError = newindex_error_maker(AIObject, ScriptReserved_AIObject); AIObject::AIObject(AI_OBJECT & ref) : m_aiObject{ref} {}; @@ -23,8 +23,8 @@ void AIObject::Register(sol::table& parent) { parent.new_usertype(ScriptReserved_AIObject, sol::no_constructor, // ability to spawn new ones could be added later - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, /// Get the object's position // @function AIObject:GetPosition diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp index 05547a72f..557d24bb8 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Camera/CameraObject.cpp @@ -16,8 +16,8 @@ Basic cameras that can point at Lara or at a CAMERA_TARGET. @pragma nostrip */ -static auto index_error = index_error_maker(CameraObject, ScriptReserved_Camera); -static auto newindex_error = newindex_error_maker(CameraObject, ScriptReserved_Camera); +static auto IndexError = index_error_maker(CameraObject, ScriptReserved_Camera); +static auto NewIndexError = newindex_error_maker(CameraObject, ScriptReserved_Camera); CameraObject::CameraObject(LevelCameraInfo & ref) : m_camera{ref} {}; @@ -26,8 +26,8 @@ void CameraObject::Register(sol::table& parent) { parent.new_usertype(ScriptReserved_Camera, sol::no_constructor, // ability to spawn new ones could be added later - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, /// Get the camera's position // @function Camera:GetPosition diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Lara/LaraObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Lara/LaraObject.cpp index 7bdbc18c8..c3e2cb273 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Lara/LaraObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Lara/LaraObject.cpp @@ -356,7 +356,7 @@ std::unique_ptr LaraObject::GetVehicle() const { auto* lara = GetLaraInfo(m_item); - if (lara->Context.Vehicle == NO_ITEM) + if (lara->Context.Vehicle == NO_VALUE) return nullptr; return std::make_unique(lara->Context.Vehicle); @@ -386,7 +386,7 @@ std::unique_ptr LaraObject::GetPlayerInteractedMoveable() const { const auto& player = GetLaraInfo(*m_item); - if (player.Context.InteractedItem == NO_ITEM) + if (player.Context.InteractedItem == NO_VALUE) return nullptr; return std::make_unique(player.Context.InteractedItem); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 05925ffcc..9df528d08 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -36,8 +36,8 @@ pickups, and Lara herself (see also @{Objects.LaraObject} for Lara-specific feat constexpr auto LUA_CLASS_NAME{ ScriptReserved_Moveable }; -static auto index_error = index_error_maker(Moveable, LUA_CLASS_NAME); -static auto newindex_error = newindex_error_maker(Moveable, LUA_CLASS_NAME); +static auto IndexError = index_error_maker(Moveable, LUA_CLASS_NAME); +static auto NewIndexError = newindex_error_maker(Moveable, LUA_CLASS_NAME); Moveable::Moveable(short num, bool alreadyInitialized) : m_item{ &g_Level.Items[num] }, m_num{ num }, m_initialized{ alreadyInitialized } @@ -48,7 +48,7 @@ Moveable::Moveable(short num, bool alreadyInitialized) : m_item{ &g_Level.Items[ Moveable::Moveable(Moveable&& other) noexcept : m_item{ std::exchange(other.m_item, nullptr) }, - m_num{ std::exchange(other.m_num, NO_ITEM) }, + m_num{ std::exchange(other.m_num, NO_VALUE) }, m_initialized{ std::exchange(other.m_initialized, false) } { if (GetValid()) @@ -69,26 +69,29 @@ bool operator ==(const Moveable& first, const Moveable& second) return first.m_item == second.m_item; } -/*** For more information on each parameter, see the +/*** Used to generate a new moveable dynamically at runtime. +For more information on each parameter, see the associated getters and setters. If you do not know what to set for these, most can just be ignored (see usage). + @function Moveable @tparam Objects.ObjID object ID @tparam string name Lua name of the item @tparam Vec3 position position in level - @tparam[opt] Rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) - @int[opt] roomID room ID item is in (default: calculated automatically) - @int[opt=0] animNumber anim number - @int[opt=0] frameNumber frame number - @int[opt=10] hp HP of item - @int[opt=0] OCB ocb of item - @tparam[opt] table AIBits table with AI bits (default { 0, 0, 0, 0, 0, 0 }) + @tparam Rotation rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) + @tparam int roomID room ID item is in (default: calculated automatically) + @tparam int animNumber animation number + @tparam int frameNumber frame number + @tparam int hp HP of item + @tparam int OCB ocb of item + @tparam table AIBits table with AI bits (default { 0, 0, 0, 0, 0, 0 }) @treturn Moveable A new Moveable object (a wrapper around the new object) + @usage local item = Moveable( TEN.Objects.ObjID.PISTOLS_ITEM, -- object id "test", -- name - Vec3(18907, 0, 21201)) + Vec3(18907, 0, 21201)) -- position */ static std::unique_ptr Create( GAME_OBJECT_ID objID, @@ -139,7 +142,7 @@ static std::unique_ptr Create( ptr->SetOCB(USE_IF_HAVE(short, ocb, 0)); ptr->SetAIBits(USE_IF_HAVE(aiBitsType, aiBits, aiBitsType{})); ptr->SetColor(ScriptColor(Vector4::One)); - item->CarriedItem = NO_ITEM; + item->CarriedItem = NO_VALUE; // call this when resetting name too? dynamic_cast(g_GameScriptEntities)->AddMoveableToMap(item, ptr.get()); @@ -153,8 +156,8 @@ void Moveable::Register(sol::state& state, sol::table& parent) { parent.new_usertype(LUA_CLASS_NAME, sol::call_constructor, Create, - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, sol::meta_function::equal_to, std::equal_to(), ScriptReserved_Enable, &Moveable::EnableItem, @@ -165,62 +168,42 @@ void Moveable::Register(sol::state& state, sol::table& parent) ScriptReserved_SetVisible, &Moveable::SetVisible, - /// Explode item. This also kills and disables item. - // @function Moveable:Explode +/// Explode item. This also kills and disables item. +// @function Moveable:Explode ScriptReserved_Explode, &Moveable::Explode, - /// Shatter item. This also kills and disables item. - // @function Moveable:Shatter +/// Shatter item. This also kills and disables item. +// @function Moveable:Shatter ScriptReserved_Shatter, &Moveable::Shatter, - /// Set effect to moveable - // @function Moveable:SetEffect - // @tparam Effects.EffectID effect Type of effect to assign. - // @tparam float timeout time (in seconds) after which effect turns off (optional). +/// Set effect to moveable +// @function Moveable:SetEffect +// @tparam Effects.EffectID effect Type of effect to assign. +// @tparam float timeout time (in seconds) after which effect turns off (optional). ScriptReserved_SetEffect, &Moveable::SetEffect, - /// Set custom colored burn effect to moveable - // @function Moveable:SetCustomEffect - // @tparam Color Color1 color the primary color of the effect (also used for lighting). - // @tparam Color Color2 color the secondary color of the effect. - // @tparam float timeout time (in seconds) after which effect turns off (optional). +/// Set custom colored burn effect to moveable +// @function Moveable:SetCustomEffect +// @tparam Color Color1 color the primary color of the effect (also used for lighting). +// @tparam Color Color2 color the secondary color of the effect. +// @tparam float timeout time (in seconds) after which effect turns off (optional). ScriptReserved_SetCustomEffect, &Moveable::SetCustomEffect, - /// Get current moveable effect - // @function Moveable:GetEffect - // @treturn Effects.EffectID effect type currently assigned to moveable. +/// Get current moveable effect +// @function Moveable:GetEffect +// @treturn Effects.EffectID effect type currently assigned to moveable. ScriptReserved_GetEffect, &Moveable::GetEffect, - /// Get the moveable's status. - // @function Moveable:GetStatus() - // @treturn Objects.MoveableStatus The moveable's status. +/// Get the moveable's status. +// @function Moveable:GetStatus() +// @treturn Objects.MoveableStatus The moveable's status. ScriptReserved_GetStatus, &Moveable::GetStatus, - /// Set the moveable's status. - // @function Moveable:SetStatus() - // @tparam Objects.MoveableStatus status The new status of the moveable. +/// Set the moveable's status. +// @function Moveable:SetStatus() +// @tparam Objects.MoveableStatus status The new status of the moveable. ScriptReserved_SetStatus, &Moveable::SetStatus, - /// Set the name of the function to be called when the moveable is shot by Lara. - // Note that this will be triggered twice when shot with both pistols at once. - // @function Moveable:SetOnHit - // @tparam function callback function in LevelFuncs hierarchy to call when moveable is shot - ScriptReserved_SetOnHit, &Moveable::SetOnHit, - - ScriptReserved_SetOnCollidedWithObject, &Moveable::SetOnCollidedWithObject, - - ScriptReserved_SetOnCollidedWithRoom, &Moveable::SetOnCollidedWithRoom, - -/// Set the name of the function to be called when the moveable is destroyed/killed -// Note that enemy death often occurs at the end of an animation, and not at the exact moment -// the enemy's HP becomes zero. -// @function Moveable:SetOnKilled -// @tparam function callback function in LevelFuncs hierarchy to call when enemy is killed -// @usage -// LevelFuncs.baddyKilled = function(theBaddy) print("You killed a baddy!") end -// baddy:SetOnKilled(LevelFuncs.baddyKilled) - ScriptReserved_SetOnKilled, &Moveable::SetOnKilled, - /// Retrieve the object ID // @function Moveable:GetObjectID // @treturn int a number representing the ID of the object @@ -433,7 +416,43 @@ ScriptReserved_GetSlotHP, & Moveable::GetSlotHP, // @tparam Objects.ObjID ObjectID to take animation and stateID from, // @tparam int animNumber animation from object // @tparam int stateID state from object - ScriptReserved_AnimFromObject, &Moveable::AnimFromObject); + ScriptReserved_AnimFromObject, &Moveable::AnimFromObject, + +/// Set the name of the function to be called when the moveable is shot by Lara. +// Note that this will be triggered twice when shot with both pistols at once. +// @function Moveable:SetOnHit +// @tparam function callback function in LevelFuncs hierarchy to call when moveable is shot + ScriptReserved_SetOnHit, &Moveable::SetOnHit, + +/// Set the function to be called when this moveable collides with another moveable +// @function Moveable:SetOnCollidedWithObject +// @tparam function func callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. +// @usage +// LevelFuncs.objCollided = function(obj1, obj2) +// print(obj1:GetName() .. " collided with " .. obj2:GetName()) +// end +// baddy:SetOnCollidedWithObject(LevelFuncs.objCollided) + ScriptReserved_SetOnCollidedWithObject, &Moveable::SetOnCollidedWithObject, + +/// Set the function called when this moveable collides with room geometry (e.g. a wall or floor). This function can take an argument that holds the @{Moveable} that collided with geometry. +// @function Moveable:SetOnCollidedWithRoom +// @tparam function func callback function to be called (must be in LevelFuncs hierarchy) +// @usage +// LevelFuncs.roomCollided = function(obj) +// print(obj:GetName() .. " collided with room geometry") +// end +// baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided) + ScriptReserved_SetOnCollidedWithRoom, &Moveable::SetOnCollidedWithRoom, + +/// Set the name of the function to be called when the moveable is destroyed/killed +// Note that enemy death often occurs at the end of an animation, and not at the exact moment +// the enemy's HP becomes zero. +// @function Moveable:SetOnKilled +// @tparam function callback function in LevelFuncs hierarchy to call when enemy is killed +// @usage +// LevelFuncs.baddyKilled = function(theBaddy) print("You killed a baddy!") end +// baddy:SetOnKilled(LevelFuncs.baddyKilled) + ScriptReserved_SetOnKilled, &Moveable::SetOnKilled); } void Moveable::Init() @@ -502,27 +521,11 @@ void Moveable::SetOnKilled(const TypeOrNil& cb) SetLevelFuncCallback(cb, ScriptReserved_SetOnKilled, *this, m_item->Callbacks.OnKilled); } -/// Set the function to be called when this moveable collides with another moveable -// @function Moveable:SetOnCollidedWithObject -// @tparam function func callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. -// @usage -// LevelFuncs.objCollided = function(obj1, obj2) -// print(obj1:GetName() .. " collided with " .. obj2:GetName()) -// end -// baddy:SetOnCollidedWithObject(LevelFuncs.objCollided) void Moveable::SetOnCollidedWithObject(const TypeOrNil& cb) { SetLevelFuncCallback(cb, ScriptReserved_SetOnCollidedWithObject, *this, m_item->Callbacks.OnObjectCollided); } -/// Set the function called when this moveable collides with room geometry (e.g. a wall or floor). This function can take an argument that holds the @{Moveable} that collided with geometry. -// @function Moveable:SetOnCollidedWithRoom -// @tparam function func callback function to be called (must be in LevelFuncs hierarchy) -// @usage -// LevelFuncs.roomCollided = function(obj) -// print(obj:GetName() .. " collided with room geometry") -// end -// baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided) void Moveable::SetOnCollidedWithRoom(const TypeOrNil& cb) { SetLevelFuncCallback(cb, ScriptReserved_SetOnCollidedWithRoom, *this, m_item->Callbacks.OnRoomCollided); @@ -1072,7 +1075,7 @@ void Moveable::UnswapMesh(int meshId) // @function Moveable:Enable void Moveable::EnableItem() { - if (m_num == NO_ITEM) + if (m_num == NO_VALUE) return; bool wasInvisible = false; @@ -1092,12 +1095,12 @@ void Moveable::EnableItem() // @function Moveable:Disable void Moveable::DisableItem() { - if (m_num == NO_ITEM) + if (m_num == NO_VALUE) return; Antitrigger(m_num); - if (m_num > NO_ITEM && (m_item->Status == ITEM_INVISIBLE)) + if (m_num > NO_VALUE && (m_item->Status == ITEM_INVISIBLE)) dynamic_cast(g_GameScriptEntities)->TryRemoveColliding(m_num); } @@ -1146,7 +1149,7 @@ void Moveable::SetVisible(bool isVisible) m_item->Status = ITEM_INVISIBLE; - if (m_num > NO_ITEM) + if (m_num > NO_VALUE) dynamic_cast(g_GameScriptEntities)->TryRemoveColliding(m_num); } else @@ -1168,7 +1171,7 @@ void Moveable::SetVisible(bool isVisible) m_item->Status = ITEM_ACTIVE; } - if (m_num > NO_ITEM) + if (m_num > NO_VALUE) dynamic_cast(g_GameScriptEntities)->TryAddColliding(m_num); } } @@ -1176,18 +1179,18 @@ void Moveable::SetVisible(bool isVisible) void Moveable::Invalidate() { // Keep m_item as-is so it can be properly removed from moveables set when destructor is called. - m_num = NO_ITEM; + m_num = NO_VALUE; m_initialized = false; } bool Moveable::GetValid() const { - return m_num > NO_ITEM; + return m_num > NO_VALUE; } void Moveable::Destroy() { - if (m_num > NO_ITEM) + if (m_num > NO_VALUE) { dynamic_cast(g_GameScriptEntities)->RemoveMoveableFromMap(m_item, this); s_callbackRemoveName(m_item->Name); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index 069908be0..351402296 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -344,8 +344,8 @@ The following constants are inside ObjID. SARCOPHAGUS ENEMY_PIECE EXPANDING_PLATFORM - SQUISHY_BLOCK1 - SQUISHY_BLOCK2 + SQUISHY_BLOCK_HORIZONTAL + SQUISHY_BLOCK_VERTICAL LASER_BEAM MINE_DETECTOR MAP @@ -1519,8 +1519,8 @@ static const std::unordered_map kObjIDs { { "SARCOPHAGUS", ID_SARCOPHAGUS }, { "ENEMY_PIECE", ID_ENEMY_PIECE }, { "EXPANDING_PLATFORM", ID_EXPANDING_PLATFORM }, - { "SQUISHY_BLOCK1", ID_SQUISHY_BLOCK1 }, - { "SQUISHY_BLOCK2", ID_SQUISHY_BLOCK2 }, + { "SQUISHY_BLOCK_HORIZONTAL", ID_SQUISHY_BLOCK_HORIZONTAL }, + { "SQUISHY_BLOCK_VERTICAL", ID_SQUISHY_BLOCK_VERTICAL }, { "LASER_BEAM", ID_LASER_BEAM }, { "MINE_DETECTOR", ID_MINE_DETECTOR }, { "MAP", ID_MAP }, diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp index 513123b29..64b74ca70 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp @@ -172,32 +172,27 @@ ObjectsHandler::ObjectsHandler(sol::state* lua, sol::table& parent) : void ObjectsHandler::TestCollidingObjects() { - // Remove any items which can't collide. - for (const auto id : m_collidingItemsToRemove) - m_collidingItems.erase(id); + // Remove items which can't collide. + for (int itemNumber : m_collidingItemsToRemove) + m_collidingItems.erase(itemNumber); m_collidingItemsToRemove.clear(); - for (const auto idOne : m_collidingItems) + for (int itemNumber0 : m_collidingItems) { - auto item = &g_Level.Items[idOne]; - if (!item->Callbacks.OnObjectCollided.empty()) + auto& item = g_Level.Items[itemNumber0]; + if (!item.Callbacks.OnObjectCollided.empty()) { // Test against other moveables. - GetCollidedObjects(item, 0, true, CollidedItems, nullptr, false); - size_t i = 0; - while (CollidedItems[i]) - { - short idTwo = CollidedItems[i] - &g_Level.Items[0]; - g_GameScript->ExecuteFunction(item->Callbacks.OnObjectCollided, idOne, idTwo); - ++i; - } + auto collObjects = GetCollidedObjects(item, true, false); + for (const auto& collidedItemPtr : collObjects.ItemPtrs) + g_GameScript->ExecuteFunction(item.Callbacks.OnObjectCollided, itemNumber0, collidedItemPtr->Index); } - if (!item->Callbacks.OnRoomCollided.empty()) + if (!item.Callbacks.OnRoomCollided.empty()) { // Test against room geometry. - if (TestItemRoomCollisionAABB(item)) - g_GameScript->ExecuteFunction(item->Callbacks.OnRoomCollided, idOne); + if (TestItemRoomCollisionAABB(&item)) + g_GameScript->ExecuteFunction(item.Callbacks.OnRoomCollided, itemNumber0); } } } @@ -210,10 +205,10 @@ void ObjectsHandler::AssignLara() bool ObjectsHandler::NotifyKilled(ItemInfo* key) { auto it = moveables.find(key); - if (std::end(moveables) != it) + if (it != std::end(moveables)) { - for (auto& m : moveables[key]) - m->Invalidate(); + for (auto* movPtr : moveables[key]) + movPtr->Invalidate(); return true; } diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp index 6e67e7fbc..3ca57da71 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp @@ -20,8 +20,8 @@ Rooms @pragma nostrip */ -static auto index_error = index_error_maker(Room, ScriptReserved_Volume); -static auto newindex_error = newindex_error_maker(Room, ScriptReserved_Volume); +static auto IndexError = index_error_maker(Room, ScriptReserved_Volume); +static auto NewIndexError = newindex_error_maker(Room, ScriptReserved_Volume); Room::Room(ROOM_INFO& room) : m_room{ room } {}; @@ -30,8 +30,8 @@ void Room::Register(sol::table& parent) { parent.new_usertype(ScriptReserved_Room, sol::no_constructor, - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, /// Determine whether the room is active or not // @function Room:GetActive diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp index 5bd864e04..2c0a57d00 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Sink/SinkObject.cpp @@ -14,8 +14,8 @@ Sink @pragma nostrip */ -static auto index_error = index_error_maker(Sink, ScriptReserved_Sink); -static auto newindex_error = newindex_error_maker(Sink, ScriptReserved_Sink); +static auto IndexError = index_error_maker(Sink, ScriptReserved_Sink); +static auto NewIndexError = newindex_error_maker(Sink, ScriptReserved_Sink); Sink::Sink(SinkInfo& ref) : m_sink{ref} {}; @@ -24,8 +24,8 @@ void Sink::Register(sol::table& parent) { parent.new_usertype(ScriptReserved_Sink, sol::no_constructor, // ability to spawn new ones could be added later - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, /// Get the sink's position // @function Sink:GetPosition diff --git a/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp index 1271f0bd1..84eba0177 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/SoundSource/SoundSourceObject.cpp @@ -13,8 +13,8 @@ Sound source @pragma nostrip */ -static auto index_error = index_error_maker(SoundSource, ScriptReserved_SoundSource); -static auto newindex_error = newindex_error_maker(SoundSource, ScriptReserved_SoundSource); +static auto IndexError = index_error_maker(SoundSource, ScriptReserved_SoundSource); +static auto NewIndexError = newindex_error_maker(SoundSource, ScriptReserved_SoundSource); SoundSource::SoundSource(SoundSourceInfo& ref) : m_soundSource{ref} {}; @@ -23,8 +23,8 @@ void SoundSource::Register(sol::table& parent) { parent.new_usertype(ScriptReserved_SoundSource, sol::no_constructor, // ability to spawn new ones could be added later - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, /// Get the sound source's position // @function SoundSource:GetPosition diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp index c07b93abe..2715fea57 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Static/StaticObject.cpp @@ -16,8 +16,8 @@ Statics @pragma nostrip */ -static auto index_error = index_error_maker(Static, ScriptReserved_Static); -static auto newindex_error = newindex_error_maker(Static, ScriptReserved_Static); +static auto IndexError = index_error_maker(Static, ScriptReserved_Static); +static auto NewIndexError = newindex_error_maker(Static, ScriptReserved_Static); Static::Static(MESH_INFO & ref) : m_mesh{ref} {}; @@ -26,8 +26,8 @@ void Static::Register(sol::table & parent) { parent.new_usertype(ScriptReserved_Static, sol::no_constructor, // ability to spawn new ones could be added later - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, /// Enable the static, for cases when it was shattered or manually disabled before. // @function Static:Enable diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp index 10b70d67c..4338ce52f 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp @@ -5,185 +5,178 @@ #include "Scripting/Internal/ReservedScriptNames.h" #include "Scripting/Internal/ScriptAssert.h" #include "Scripting/Internal/ScriptUtil.h" -#include "Scripting/Internal/TEN/Vec3/Vec3.h" #include "Scripting/Internal/TEN/Rotation/Rotation.h" +#include "Scripting/Internal/TEN/Vec3/Vec3.h" #include "Specific/level.h" /*** -Volumes +Activator volume. @tenclass Objects.Volume @pragma nostrip */ -static auto index_error = index_error_maker(Volume, ScriptReserved_Volume); -static auto newindex_error = newindex_error_maker(Volume, ScriptReserved_Volume); +static auto IndexError = index_error_maker(Volume, ScriptReserved_Volume); +static auto NewIndexError = newindex_error_maker(Volume, ScriptReserved_Volume); -Volume::Volume(TriggerVolume& volume) : m_volume{ volume } +Volume::Volume(TriggerVolume& volume) : + _volume(volume) {}; void Volume::Register(sol::table& parent) { parent.new_usertype(ScriptReserved_Volume, - sol::no_constructor, // TODO: Ability to spawn new ones could be added later. - sol::meta_function::index, index_error, - sol::meta_function::new_index, newindex_error, + sol::no_constructor, // TODO: Ability to spawn new volumes could be added later. + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, - /// Enable the volume. - // @function Volume:Enable - ScriptReserved_Enable, &Volume::Enable, - - /// Disable the volume. - // @function Volume:Disable - ScriptReserved_Disable, &Volume::Disable, - - /// Determine whether the volume is active or not - // @function Volume:GetActive - // @treturn bool true if the volume is active - ScriptReserved_GetName, &Volume::GetActive, - - /// Get the volume's position. - // @function Volume:GetPosition - // @treturn Vec3 a copy of the volume's position + ScriptReserved_GetName, &Volume::GetName, ScriptReserved_GetPosition, &Volume::GetPos, - - /// Set the volume's position. - // @function Volume:SetPosition - // @tparam Vec3 position the new position of the volume - ScriptReserved_SetPosition, &Volume::SetPos, - - /// Get the volume's rotation. - // @function Volume:GetRotation - // @treturn Rotation a copy of the volume's rotation ScriptReserved_GetRotation, &Volume::GetRot, - - /// Set the volume's rotation. - // @function Volume:SetRotation - // @tparam Rotation rotation the volume's new rotation - ScriptReserved_SetRotation, &Volume::SetRot, - - /// Get the volume's scale (separately on all 3 axes). - // @function Volume:GetScale - // @treturn Vec3 current volume scale ScriptReserved_GetScale, &Volume::GetScale, - /// Set the volume's scale (separately on all 3 axes). - // @function Volume:SetScale - // @tparam Vec3 scale the volume's new scale + ScriptReserved_SetName, &Volume::SetName, + ScriptReserved_SetPosition, &Volume::SetPos, + ScriptReserved_SetRotation, &Volume::SetRot, ScriptReserved_SetScale, &Volume::SetScale, - /// Get the volume's unique string identifier. - // @function Volume:GetName - // @treturn string the volume's name - ScriptReserved_GetName, &Volume::GetName, - - /// Set the volume's name (its unique string identifier). - // @function Volume:SetName - // @tparam string name The volume's new name - ScriptReserved_SetName, &Volume::SetName, - - /// Clear activator list for volumes (makes volume trigger everything again) - // @function Volume:ClearActivators + ScriptReserved_Enable, &Volume::Enable, + ScriptReserved_Disable, &Volume::Disable, ScriptReserved_ClearActivators, &Volume::ClearActivators, - /// Check if specified moveable is inside the volume - // @function Volume:IsMoveableInside - // @tparam Objects.Moveable Moveable which should be checked for containment - // @treturn bool state of the moveable, true if contained, false if not + ScriptReserved_GetName, &Volume::GetActive, ScriptReserved_IsMoveableInside, &Volume::IsMoveableInside); } -void Volume::Enable() +/// Get the unique string identifier of this volume. +// @function Volume:GetName() +// @treturn string Name. +std::string Volume::GetName() const { - m_volume.Enabled = true; -} - -void Volume::Disable() -{ - ClearActivators(); - m_volume.Enabled = false; -} - -bool Volume::GetActive() const -{ - return m_volume.Enabled; + return _volume.Name; } +/// Get the position of this volume. +// @function Volume:GetPosition() +// @treturn Vec3 Position. Vec3 Volume::GetPos() const { - return Vec3(m_volume.Box.Center.x, m_volume.Box.Center.y, m_volume.Box.Center.z); -} - -void Volume::SetPos(const Vec3& pos) -{ - m_volume.Box.Center = - m_volume.Sphere.Center = Vector3i(pos).ToVector3(); + return Vec3(_volume.Box.Center.x, _volume.Box.Center.y, _volume.Box.Center.z); } +/// Get the rotation of this volume. +// @function Volume:GetRotation() +// @treturn Rotation Rotation. Rotation Volume::GetRot() const { - auto eulers = EulerAngles(m_volume.Box.Orientation); + auto eulers = EulerAngles(_volume.Box.Orientation); return Rotation(TO_DEGREES(eulers.x), TO_DEGREES(eulers.y), TO_DEGREES(eulers.z)); } -void Volume::SetRot(const Rotation& rot) -{ - auto eulers = EulerAngles(ANGLE(rot.x), ANGLE(rot.y), ANGLE(rot.z)); - m_volume.Box.Orientation = eulers.ToQuaternion(); -} - +/// Get this scale of this volume. +// @function Volume:GetScale() +// @treturn Vec3 Scale. Vec3 Volume::GetScale() const { - return Vec3((Vector3)m_volume.Box.Extents); -} - -void Volume::SetScale(const Vec3& scale) -{ - m_volume.Box.Extents = Vector3(scale.x, scale.y, scale.z); - m_volume.Sphere.Radius = m_volume.Box.Extents.x; -} - -std::string Volume::GetName() const -{ - return m_volume.Name; + return Vec3((Vector3)_volume.Box.Extents); } +/// Set the unique string identifier of this volume. +// @function Volume:SetName() +// @tparam string name New name. void Volume::SetName(const std::string& name) { - if (!ScriptAssert(!name.empty(), "Name cannot be blank. Not setting name.")) + if (!ScriptAssert(!name.empty(), "Attempted to set name to blank string.")) return; - if (s_callbackSetName(name, m_volume)) + // Remove previous name if it exists. + if (s_callbackSetName(name, _volume)) { - // Remove the old name if we have one. - s_callbackRemoveName(m_volume.Name); - m_volume.Name = name; + s_callbackRemoveName(_volume.Name); + _volume.Name = name; } else { - ScriptAssertF(false, "Could not add name {} - does an object with this name already exist?", name); - TENLog("Name will not be set", LogLevel::Warning, LogConfig::All); + ScriptAssertF(false, "Could not add name {}. Object with this name may already exist.", name); + TENLog("Name not set.", LogLevel::Warning, LogConfig::All); } } -void Volume::ClearActivators() +/// Set the position of this volume. +// @function Volume:SetPosition() +// @tparam Vec3 pos New position. +void Volume::SetPos(const Vec3& pos) { - m_volume.StateQueue.clear(); + _volume.Box.Center = + _volume.Sphere.Center = pos.ToVector3(); } -bool Volume::IsMoveableInside(const Moveable& moveable) +/// Set the rotation of this volume. +// @function Volume:SetRotation() +// @tparam Rotation rot New rotation. +void Volume::SetRot(const Rotation& rot) { - for (auto& entry : m_volume.StateQueue) + auto eulers = EulerAngles(ANGLE(rot.x), ANGLE(rot.y), ANGLE(rot.z)); + _volume.Box.Orientation = eulers.ToQuaternion(); +} + +/// Set the scale of the volume. +// @function Volume:SetScale() +// @tparam Vec3 scale New scale. +void Volume::SetScale(const Vec3& scale) +{ + _volume.Box.Extents = scale.ToVector3(); + _volume.Sphere.Radius = _volume.Box.Extents.x; +} + +/// Determine if this volume is active. +// @function Volume:GetActive() +// @treturn bool Boolean representing active status. +bool Volume::GetActive() const +{ + return _volume.Enabled; +} + +/// Determine if a moveable is inside this volume. +// @function Volume:IsMoveableInside() +// @tparam Objects.Moveable Moveable to be checked for containment. +// @treturn bool Boolean representing containment status. +bool Volume::IsMoveableInside(const Moveable& mov) +{ + for (const auto& entry : _volume.StateQueue) { + // TODO: Use int, not short. if (std::holds_alternative(entry.Activator)) { - short id = std::get(entry.Activator); - auto& mov = std::make_unique(id); + int id = std::get(entry.Activator); + auto& mov2 = std::make_unique(id); - if (mov.get()->GetName() == moveable.GetName()) + if (mov2.get()->GetName() == mov.GetName()) return true; } } return false; } + +/// Enable this volume. +// @function Volume:Enable() +void Volume::Enable() +{ + _volume.Enabled = true; +} + +/// Disable this volume. +// @function Volume:Disable() +void Volume::Disable() +{ + ClearActivators(); + _volume.Enabled = false; +} + +/// Clear the activators for this volume, allowing it to trigger again. +// @function Volume:ClearActivators() +void Volume::ClearActivators() +{ + _volume.StateQueue.clear(); +} diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.h b/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.h index fba9bb0ec..12c463632 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.h @@ -9,31 +9,40 @@ class Vec3; class Volume : public NamedBase { +private: + TriggerVolume& _volume; + public: using IdentifierType = std::reference_wrapper; - Volume(TriggerVolume& volume); - ~Volume() = default; - - Volume& operator =(const Volume& other) = delete; - Volume(const Volume& other) = delete; static void Register(sol::table& parent); + // Cosntructors and destructors + Volume(TriggerVolume& volume); + Volume(const Volume& other) = delete; + ~Volume() = default; + + // Getters + std::string GetName() const; + Vec3 GetPos() const; + Rotation GetRot() const; + Vec3 GetScale() const; + + // Setters + void SetName(const std::string& name); + void SetRot(const Rotation& rot); + void SetPos(const Vec3& pos); + void SetScale(const Vec3& scale); + + // Inquirers + bool GetActive() const; + bool IsMoveableInside(const Moveable& mov); + + // Utilities void Enable(); void Disable(); - [[nodiscard]] bool GetActive() const; - [[nodiscard]] Rotation GetRot() const; - void SetRot(const Rotation& rot); - [[nodiscard]] Vec3 GetPos() const; - void SetPos(const Vec3& pos); - [[nodiscard]] Vec3 GetScale() const; - void SetScale(const Vec3& scale); - [[nodiscard]] std::string GetName() const; - void SetName(const std::string& name); - void ClearActivators(); - [[nodiscard]] bool IsMoveableInside(const Moveable& moveable); -private: - TriggerVolume& m_volume; + // Operators + Volume& operator =(const Volume& other) = delete; }; diff --git a/TombEngine/Specific/clock.cpp b/TombEngine/Specific/clock.cpp index 4812b9511..6f79c529c 100644 --- a/TombEngine/Specific/clock.cpp +++ b/TombEngine/Specific/clock.cpp @@ -1,52 +1,68 @@ #include "framework.h" #include "Specific/clock.h" -LARGE_INTEGER PerformanceCount; -double LdFreq; -double LdSync; +// Globals +LARGE_INTEGER PerformanceCount = {}; +double LdFreq = 0.0; +double LdSync = 0.0; + +int Sync() +{ + auto ct = LARGE_INTEGER{}; + QueryPerformanceCounter(&ct); + + double dCounter = (double)ct.LowPart + (double)ct.HighPart * (double)0xffffffff; + dCounter /= LdFreq; + + long gameFrames = (long)dCounter - (long)LdSync; + LdSync = dCounter; + return gameFrames; +} bool TimeReset() { - LARGE_INTEGER fq; + auto fq = LARGE_INTEGER{}; QueryPerformanceCounter(&fq); - LdSync = (double)fq.LowPart + (double)fq.HighPart * (double)0xffffffff; + + LdSync = (double)fq.LowPart + ((double)fq.HighPart * (double)0xffffffff); LdSync /= LdFreq; return true; } bool TimeInit() { - LARGE_INTEGER fq; + auto fq = LARGE_INTEGER{}; if (!QueryPerformanceFrequency(&fq)) return false; - LdFreq = (double)fq.LowPart + (double)fq.HighPart * (double)0xFFFFFFFF; + + LdFreq = (double)fq.LowPart + ((double)fq.HighPart * (double)0xffffffff); LdFreq /= 60.0; TimeReset(); return true; } -int Sync() +GameTime GetGameTime(int ticks) { - LARGE_INTEGER ct; - double dCounter; - QueryPerformanceCounter(&ct); - dCounter = (double)ct.LowPart + (double)ct.HighPart * (double)0xFFFFFFFF; - dCounter /= LdFreq; - long nFrames = long(dCounter) - long(LdSync); - LdSync = dCounter; - return nFrames; + auto gameTime = GameTime{}; + int seconds = ticks / FPS; + + gameTime.Days = (seconds / (DAY_UNIT * SQUARE(TIME_UNIT))); + gameTime.Hours = (seconds % (DAY_UNIT * SQUARE(TIME_UNIT))) / SQUARE(TIME_UNIT); + gameTime.Minutes = (seconds / TIME_UNIT) % TIME_UNIT; + gameTime.Seconds = seconds % TIME_UNIT; + return gameTime; } -GameTime GetGameTime(int frameCount) +bool TestGlobalTimeInterval(float intervalSecs, float offsetSecs) { - GameTime result = {}; + int intervalGameFrames = (int)round(intervalSecs * FPS); + int offsetGameFrames = (int)round(offsetSecs * FPS); - auto seconds = GameTimer / FPS; + if (offsetGameFrames >= intervalGameFrames) + { + TENLog("TestGlobalTimeInterval(): interval must be greater than offset.", LogLevel::Warning); + return false; + } - result.Days = (seconds / (DAY_UNIT * TIME_UNIT * TIME_UNIT)); - result.Hours = (seconds % (DAY_UNIT * TIME_UNIT * TIME_UNIT)) / (TIME_UNIT * TIME_UNIT); - result.Minutes = (seconds / TIME_UNIT) % TIME_UNIT; - result.Seconds = (seconds % TIME_UNIT); - - return result; -} \ No newline at end of file + return ((GlobalCounter % intervalGameFrames) == offsetGameFrames); +} diff --git a/TombEngine/Specific/clock.h b/TombEngine/Specific/clock.h index 2fd36373b..883b89085 100644 --- a/TombEngine/Specific/clock.h +++ b/TombEngine/Specific/clock.h @@ -11,14 +11,16 @@ constexpr auto DAY_UNIT = 24; struct GameTime { - int Days; - int Hours; - int Minutes; - int Seconds; + int Days = 0; + int Hours = 0; + int Minutes = 0; + int Seconds = 0; }; -int Sync(); +int Sync(); bool TimeInit(); bool TimeReset(); -GameTime GetGameTime(int frameCount); +GameTime GetGameTime(int ticks); + +bool TestGlobalTimeInterval(float intervalSecs, float offsetSecs = 0.0f); diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index d355ac0bc..3cccca52a 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -38,8 +38,8 @@ using namespace TEN::Utils; const std::vector BRIDGE_OBJECT_IDS = { ID_EXPANDING_PLATFORM, - ID_SQUISHY_BLOCK1, - ID_SQUISHY_BLOCK2, + ID_SQUISHY_BLOCK_HORIZONTAL, + ID_SQUISHY_BLOCK_VERTICAL, ID_FALLING_BLOCK, ID_FALLING_BLOCK2, @@ -205,7 +205,7 @@ void LoadItems() if (g_Level.NumItems == 0) return; - InitializeItemArray(NUM_ITEMS); + InitializeItemArray(ITEM_COUNT_MAX); if (g_Level.NumItems > 0) { @@ -499,6 +499,7 @@ void LoadCameras() NumberSpotcams = ReadInt32(); + // TODO: Read properly! if (NumberSpotcams != 0) ReadBytes(SpotCam, NumberSpotcams * sizeof(SPOTCAM)); @@ -907,8 +908,8 @@ void ReadRooms() room.reverbType = (ReverbType)ReadInt32(); room.flipNumber = ReadInt32(); - room.itemNumber = NO_ITEM; - room.fxNumber = NO_ITEM; + room.itemNumber = NO_VALUE; + room.fxNumber = NO_VALUE; room.index = i; g_GameScriptEntities->AddName(room.name, room); @@ -1463,7 +1464,7 @@ void LoadSprites() void GetCarriedItems() { for (int i = 0; i < g_Level.NumItems; ++i) - g_Level.Items[i].CarriedItem = NO_ITEM; + g_Level.Items[i].CarriedItem = NO_VALUE; for (int i = 0; i < g_Level.NumItems; ++i) { @@ -1473,7 +1474,7 @@ void GetCarriedItems() if (object.intelligent || (item.ObjectNumber >= ID_SEARCH_OBJECT1 && item.ObjectNumber <= ID_SEARCH_OBJECT3)) { - for (short linkNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem) + for (short linkNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) { auto& item2 = g_Level.Items[linkNumber]; diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index 2fa321185..de658eaa8 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -149,6 +149,10 @@ struct Volume; struct VolumeBuilder; struct VolumeT; +struct FishData; +struct FishDataBuilder; +struct FishDataT; + struct KeyValPair; struct ScriptTable; @@ -5877,6 +5881,185 @@ inline flatbuffers::Offset CreateVolumeDirect( flatbuffers::Offset CreateVolume(flatbuffers::FlatBufferBuilder &_fbb, const VolumeT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct FishDataT : public flatbuffers::NativeTable { + typedef FishData TableType; + bool is_patrolling = false; + bool is_lethal = false; + int32_t leader_item_number = 0; + float life = 0.0f; + int32_t mesh_index = 0; + std::unique_ptr orientation{}; + std::unique_ptr position{}; + std::unique_ptr position_target{}; + int32_t room_number = 0; + int32_t target_item_number = 0; + float undulation = 0.0f; + float velocity = 0.0f; +}; + +struct FishData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FishDataT NativeTableType; + typedef FishDataBuilder Builder; + struct Traits; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_IS_PATROLLING = 4, + VT_IS_LETHAL = 6, + VT_LEADER_ITEM_NUMBER = 8, + VT_LIFE = 10, + VT_MESH_INDEX = 12, + VT_ORIENTATION = 14, + VT_POSITION = 16, + VT_POSITION_TARGET = 18, + VT_ROOM_NUMBER = 20, + VT_TARGET_ITEM_NUMBER = 22, + VT_UNDULATION = 24, + VT_VELOCITY = 26 + }; + bool is_patrolling() const { + return GetField(VT_IS_PATROLLING, 0) != 0; + } + bool is_lethal() const { + return GetField(VT_IS_LETHAL, 0) != 0; + } + int32_t leader_item_number() const { + return GetField(VT_LEADER_ITEM_NUMBER, 0); + } + float life() const { + return GetField(VT_LIFE, 0.0f); + } + int32_t mesh_index() const { + return GetField(VT_MESH_INDEX, 0); + } + const TEN::Save::EulerAngles *orientation() const { + return GetStruct(VT_ORIENTATION); + } + const TEN::Save::Vector3 *position() const { + return GetStruct(VT_POSITION); + } + const TEN::Save::Vector3 *position_target() const { + return GetStruct(VT_POSITION_TARGET); + } + int32_t room_number() const { + return GetField(VT_ROOM_NUMBER, 0); + } + int32_t target_item_number() const { + return GetField(VT_TARGET_ITEM_NUMBER, 0); + } + float undulation() const { + return GetField(VT_UNDULATION, 0.0f); + } + float velocity() const { + return GetField(VT_VELOCITY, 0.0f); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_IS_PATROLLING) && + VerifyField(verifier, VT_IS_LETHAL) && + VerifyField(verifier, VT_LEADER_ITEM_NUMBER) && + VerifyField(verifier, VT_LIFE) && + VerifyField(verifier, VT_MESH_INDEX) && + VerifyField(verifier, VT_ORIENTATION) && + VerifyField(verifier, VT_POSITION) && + VerifyField(verifier, VT_POSITION_TARGET) && + VerifyField(verifier, VT_ROOM_NUMBER) && + VerifyField(verifier, VT_TARGET_ITEM_NUMBER) && + VerifyField(verifier, VT_UNDULATION) && + VerifyField(verifier, VT_VELOCITY) && + verifier.EndTable(); + } + FishDataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(FishDataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FishDataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct FishDataBuilder { + typedef FishData Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_is_patrolling(bool is_patrolling) { + fbb_.AddElement(FishData::VT_IS_PATROLLING, static_cast(is_patrolling), 0); + } + void add_is_lethal(bool is_lethal) { + fbb_.AddElement(FishData::VT_IS_LETHAL, static_cast(is_lethal), 0); + } + void add_leader_item_number(int32_t leader_item_number) { + fbb_.AddElement(FishData::VT_LEADER_ITEM_NUMBER, leader_item_number, 0); + } + void add_life(float life) { + fbb_.AddElement(FishData::VT_LIFE, life, 0.0f); + } + void add_mesh_index(int32_t mesh_index) { + fbb_.AddElement(FishData::VT_MESH_INDEX, mesh_index, 0); + } + void add_orientation(const TEN::Save::EulerAngles *orientation) { + fbb_.AddStruct(FishData::VT_ORIENTATION, orientation); + } + void add_position(const TEN::Save::Vector3 *position) { + fbb_.AddStruct(FishData::VT_POSITION, position); + } + void add_position_target(const TEN::Save::Vector3 *position_target) { + fbb_.AddStruct(FishData::VT_POSITION_TARGET, position_target); + } + void add_room_number(int32_t room_number) { + fbb_.AddElement(FishData::VT_ROOM_NUMBER, room_number, 0); + } + void add_target_item_number(int32_t target_item_number) { + fbb_.AddElement(FishData::VT_TARGET_ITEM_NUMBER, target_item_number, 0); + } + void add_undulation(float undulation) { + fbb_.AddElement(FishData::VT_UNDULATION, undulation, 0.0f); + } + void add_velocity(float velocity) { + fbb_.AddElement(FishData::VT_VELOCITY, velocity, 0.0f); + } + explicit FishDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateFishData( + flatbuffers::FlatBufferBuilder &_fbb, + bool is_patrolling = false, + bool is_lethal = false, + int32_t leader_item_number = 0, + float life = 0.0f, + int32_t mesh_index = 0, + const TEN::Save::EulerAngles *orientation = 0, + const TEN::Save::Vector3 *position = 0, + const TEN::Save::Vector3 *position_target = 0, + int32_t room_number = 0, + int32_t target_item_number = 0, + float undulation = 0.0f, + float velocity = 0.0f) { + FishDataBuilder builder_(_fbb); + builder_.add_velocity(velocity); + builder_.add_undulation(undulation); + builder_.add_target_item_number(target_item_number); + builder_.add_room_number(room_number); + builder_.add_position_target(position_target); + builder_.add_position(position); + builder_.add_orientation(orientation); + builder_.add_mesh_index(mesh_index); + builder_.add_life(life); + builder_.add_leader_item_number(leader_item_number); + builder_.add_is_lethal(is_lethal); + builder_.add_is_patrolling(is_patrolling); + return builder_.Finish(); +} + +struct FishData::Traits { + using type = FishData; + static auto constexpr Create = CreateFishData; +}; + +flatbuffers::Offset CreateFishData(flatbuffers::FlatBufferBuilder &_fbb, const FishDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct ScriptTableT : public flatbuffers::NativeTable { typedef ScriptTable TableType; std::vector keys_vals{}; @@ -6925,6 +7108,7 @@ struct SaveGameT : public flatbuffers::NativeTable { int32_t next_item_free = 0; int32_t next_item_active = 0; std::vector room_items{}; + std::vector> fish_swarm{}; std::vector> fxinfos{}; int32_t next_fx_free = 0; int32_t next_fx_active = 0; @@ -6983,48 +7167,49 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_NEXT_ITEM_FREE = 16, VT_NEXT_ITEM_ACTIVE = 18, VT_ROOM_ITEMS = 20, - VT_FXINFOS = 22, - VT_NEXT_FX_FREE = 24, - VT_NEXT_FX_ACTIVE = 26, - VT_FIXED_CAMERAS = 28, - VT_SINKS = 30, - VT_STATIC_MESHES = 32, - VT_FLYBY_CAMERAS = 34, - VT_PARTICLES = 36, - VT_RATS = 38, - VT_SPIDERS = 40, - VT_SCARABS = 42, - VT_BATS = 44, - VT_FLIP_MAPS = 46, - VT_FLIP_STATS = 48, - VT_FLIP_EFFECT = 50, - VT_FLIP_TIMER = 52, - VT_FLIP_STATUS = 54, - VT_CURRENT_FOV = 56, - VT_LAST_INV_ITEM = 58, - VT_ACTION_QUEUE = 60, - VT_SOUNDTRACKS = 62, - VT_CD_FLAGS = 64, - VT_POSTPROCESS_MODE = 66, - VT_POSTPROCESS_STRENGTH = 68, - VT_POSTPROCESS_TINT = 70, - VT_ROPE = 72, - VT_PENDULUM = 74, - VT_ALTERNATE_PENDULUM = 76, - VT_VOLUMES = 78, - VT_GLOBAL_EVENT_SETS = 80, - VT_VOLUME_EVENT_SETS = 82, - VT_SCRIPT_VARS = 84, - VT_CALLBACKS_PRE_START = 86, - VT_CALLBACKS_POST_START = 88, - VT_CALLBACKS_PRE_END = 90, - VT_CALLBACKS_POST_END = 92, - VT_CALLBACKS_PRE_SAVE = 94, - VT_CALLBACKS_POST_SAVE = 96, - VT_CALLBACKS_PRE_LOAD = 98, - VT_CALLBACKS_POST_LOAD = 100, - VT_CALLBACKS_PRE_LOOP = 102, - VT_CALLBACKS_POST_LOOP = 104 + VT_FISH_SWARM = 22, + VT_FXINFOS = 24, + VT_NEXT_FX_FREE = 26, + VT_NEXT_FX_ACTIVE = 28, + VT_FIXED_CAMERAS = 30, + VT_SINKS = 32, + VT_STATIC_MESHES = 34, + VT_FLYBY_CAMERAS = 36, + VT_PARTICLES = 38, + VT_RATS = 40, + VT_SPIDERS = 42, + VT_SCARABS = 44, + VT_BATS = 46, + VT_FLIP_MAPS = 48, + VT_FLIP_STATS = 50, + VT_FLIP_EFFECT = 52, + VT_FLIP_TIMER = 54, + VT_FLIP_STATUS = 56, + VT_CURRENT_FOV = 58, + VT_LAST_INV_ITEM = 60, + VT_ACTION_QUEUE = 62, + VT_SOUNDTRACKS = 64, + VT_CD_FLAGS = 66, + VT_POSTPROCESS_MODE = 68, + VT_POSTPROCESS_STRENGTH = 70, + VT_POSTPROCESS_TINT = 72, + VT_ROPE = 74, + VT_PENDULUM = 76, + VT_ALTERNATE_PENDULUM = 78, + VT_VOLUMES = 80, + VT_GLOBAL_EVENT_SETS = 82, + VT_VOLUME_EVENT_SETS = 84, + VT_SCRIPT_VARS = 86, + VT_CALLBACKS_PRE_START = 88, + VT_CALLBACKS_POST_START = 90, + VT_CALLBACKS_PRE_END = 92, + VT_CALLBACKS_POST_END = 94, + VT_CALLBACKS_PRE_SAVE = 96, + VT_CALLBACKS_POST_SAVE = 98, + VT_CALLBACKS_PRE_LOAD = 100, + VT_CALLBACKS_POST_LOAD = 102, + VT_CALLBACKS_PRE_LOOP = 104, + VT_CALLBACKS_POST_LOOP = 106 }; const TEN::Save::SaveGameHeader *header() const { return GetPointer(VT_HEADER); @@ -7053,6 +7238,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector *room_items() const { return GetPointer *>(VT_ROOM_ITEMS); } + const flatbuffers::Vector> *fish_swarm() const { + return GetPointer> *>(VT_FISH_SWARM); + } const flatbuffers::Vector> *fxinfos() const { return GetPointer> *>(VT_FXINFOS); } @@ -7199,6 +7387,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_NEXT_ITEM_ACTIVE) && VerifyOffset(verifier, VT_ROOM_ITEMS) && verifier.VerifyVector(room_items()) && + VerifyOffset(verifier, VT_FISH_SWARM) && + verifier.VerifyVector(fish_swarm()) && + verifier.VerifyVectorOfTables(fish_swarm()) && VerifyOffset(verifier, VT_FXINFOS) && verifier.VerifyVector(fxinfos()) && verifier.VerifyVectorOfTables(fxinfos()) && @@ -7335,6 +7526,9 @@ struct SaveGameBuilder { void add_room_items(flatbuffers::Offset> room_items) { fbb_.AddOffset(SaveGame::VT_ROOM_ITEMS, room_items); } + void add_fish_swarm(flatbuffers::Offset>> fish_swarm) { + fbb_.AddOffset(SaveGame::VT_FISH_SWARM, fish_swarm); + } void add_fxinfos(flatbuffers::Offset>> fxinfos) { fbb_.AddOffset(SaveGame::VT_FXINFOS, fxinfos); } @@ -7483,6 +7677,7 @@ inline flatbuffers::Offset CreateSaveGame( int32_t next_item_free = 0, int32_t next_item_active = 0, flatbuffers::Offset> room_items = 0, + flatbuffers::Offset>> fish_swarm = 0, flatbuffers::Offset>> fxinfos = 0, int32_t next_fx_free = 0, int32_t next_fx_active = 0, @@ -7567,6 +7762,7 @@ inline flatbuffers::Offset CreateSaveGame( builder_.add_next_fx_active(next_fx_active); builder_.add_next_fx_free(next_fx_free); builder_.add_fxinfos(fxinfos); + builder_.add_fish_swarm(fish_swarm); builder_.add_room_items(room_items); builder_.add_next_item_active(next_item_active); builder_.add_next_item_free(next_item_free); @@ -7596,6 +7792,7 @@ inline flatbuffers::Offset CreateSaveGameDirect( int32_t next_item_free = 0, int32_t next_item_active = 0, const std::vector *room_items = nullptr, + const std::vector> *fish_swarm = nullptr, const std::vector> *fxinfos = nullptr, int32_t next_fx_free = 0, int32_t next_fx_active = 0, @@ -7641,6 +7838,7 @@ inline flatbuffers::Offset CreateSaveGameDirect( auto rooms__ = rooms ? _fbb.CreateVector>(*rooms) : 0; auto items__ = items ? _fbb.CreateVector>(*items) : 0; auto room_items__ = room_items ? _fbb.CreateVector(*room_items) : 0; + auto fish_swarm__ = fish_swarm ? _fbb.CreateVector>(*fish_swarm) : 0; auto fxinfos__ = fxinfos ? _fbb.CreateVector>(*fxinfos) : 0; auto fixed_cameras__ = fixed_cameras ? _fbb.CreateVector>(*fixed_cameras) : 0; auto sinks__ = sinks ? _fbb.CreateVector>(*sinks) : 0; @@ -7680,6 +7878,7 @@ inline flatbuffers::Offset CreateSaveGameDirect( next_item_free, next_item_active, room_items__, + fish_swarm__, fxinfos__, next_fx_free, next_fx_active, @@ -9387,6 +9586,65 @@ inline flatbuffers::Offset CreateVolume(flatbuffers::FlatBufferBuilder & _queue); } +inline FishDataT *FishData::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void FishData::UnPackTo(FishDataT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = is_patrolling(); _o->is_patrolling = _e; } + { auto _e = is_lethal(); _o->is_lethal = _e; } + { auto _e = leader_item_number(); _o->leader_item_number = _e; } + { auto _e = life(); _o->life = _e; } + { auto _e = mesh_index(); _o->mesh_index = _e; } + { auto _e = orientation(); if (_e) _o->orientation = std::unique_ptr(new TEN::Save::EulerAngles(*_e)); } + { auto _e = position(); if (_e) _o->position = std::unique_ptr(new TEN::Save::Vector3(*_e)); } + { auto _e = position_target(); if (_e) _o->position_target = std::unique_ptr(new TEN::Save::Vector3(*_e)); } + { auto _e = room_number(); _o->room_number = _e; } + { auto _e = target_item_number(); _o->target_item_number = _e; } + { auto _e = undulation(); _o->undulation = _e; } + { auto _e = velocity(); _o->velocity = _e; } +} + +inline flatbuffers::Offset FishData::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FishDataT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateFishData(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateFishData(flatbuffers::FlatBufferBuilder &_fbb, const FishDataT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FishDataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _is_patrolling = _o->is_patrolling; + auto _is_lethal = _o->is_lethal; + auto _leader_item_number = _o->leader_item_number; + auto _life = _o->life; + auto _mesh_index = _o->mesh_index; + auto _orientation = _o->orientation ? _o->orientation.get() : 0; + auto _position = _o->position ? _o->position.get() : 0; + auto _position_target = _o->position_target ? _o->position_target.get() : 0; + auto _room_number = _o->room_number; + auto _target_item_number = _o->target_item_number; + auto _undulation = _o->undulation; + auto _velocity = _o->velocity; + return TEN::Save::CreateFishData( + _fbb, + _is_patrolling, + _is_lethal, + _leader_item_number, + _life, + _mesh_index, + _orientation, + _position, + _position_target, + _room_number, + _target_item_number, + _undulation, + _velocity); +} + inline ScriptTableT *ScriptTable::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); @@ -9785,6 +10043,7 @@ inline void SaveGame::UnPackTo(SaveGameT *_o, const flatbuffers::resolver_functi { auto _e = next_item_free(); _o->next_item_free = _e; } { auto _e = next_item_active(); _o->next_item_active = _e; } { auto _e = room_items(); if (_e) { _o->room_items.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->room_items[_i] = _e->Get(_i); } } } + { auto _e = fish_swarm(); if (_e) { _o->fish_swarm.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->fish_swarm[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = fxinfos(); if (_e) { _o->fxinfos.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->fxinfos[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = next_fx_free(); _o->next_fx_free = _e; } { auto _e = next_fx_active(); _o->next_fx_active = _e; } @@ -9846,6 +10105,7 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild auto _next_item_free = _o->next_item_free; auto _next_item_active = _o->next_item_active; auto _room_items = _fbb.CreateVector(_o->room_items); + auto _fish_swarm = _fbb.CreateVector> (_o->fish_swarm.size(), [](size_t i, _VectorArgs *__va) { return CreateFishData(*__va->__fbb, __va->__o->fish_swarm[i].get(), __va->__rehasher); }, &_va ); auto _fxinfos = _fbb.CreateVector> (_o->fxinfos.size(), [](size_t i, _VectorArgs *__va) { return CreateFXInfo(*__va->__fbb, __va->__o->fxinfos[i].get(), __va->__rehasher); }, &_va ); auto _next_fx_free = _o->next_fx_free; auto _next_fx_active = _o->next_fx_active; @@ -9899,6 +10159,7 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild _next_item_free, _next_item_active, _room_items, + _fish_swarm, _fxinfos, _next_fx_free, _next_fx_active, diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index 2d6a93de2..2c67b42ec 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -411,6 +411,21 @@ table Volume { queue: [VolumeState]; } +table FishData { + is_patrolling: bool; + is_lethal: bool; + leader_item_number: int32; + life: float; + mesh_index: int32; + orientation: EulerAngles; + position: Vector3; + position_target: Vector3; + room_number: int32; + target_item_number: int32; + undulation: float; + velocity: float; +} + struct KeyValPair { key: uint32; val: uint32; @@ -503,6 +518,7 @@ table SaveGame { next_item_free: int32; next_item_active: int32; room_items: [int32]; + fish_swarm: [FishData]; fxinfos: [FXInfo]; next_fx_free: int32; next_fx_active: int32; diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index e4612b226..94bbf469b 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -526,6 +526,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -535,7 +536,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -563,7 +563,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -607,6 +606,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -1033,6 +1033,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -1040,7 +1041,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -1107,6 +1107,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From 146c89b88866071630bb1b7c86b23dabb39f7651 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 16 Apr 2024 09:15:00 +0200 Subject: [PATCH 077/410] Added interpolation for. - splashed - ripples - blood - drips - underwater dust - rain - snow - shockwaves - all effects based on Particle class --- TombEngine/Game/Setup.cpp | 4 +- TombEngine/Game/effects/Blood.cpp | 2 + TombEngine/Game/effects/Blood.h | 10 ++ TombEngine/Game/effects/Ripple.cpp | 2 + TombEngine/Game/effects/Ripple.h | 11 ++ TombEngine/Game/effects/bubble.cpp | 2 + TombEngine/Game/effects/bubble.h | 13 ++ TombEngine/Game/effects/chaffFX.cpp | 2 +- TombEngine/Game/effects/drip.cpp | 2 + TombEngine/Game/effects/drip.h | 15 ++ TombEngine/Game/effects/effects.cpp | 4 + TombEngine/Game/effects/effects.h | 53 ++++++-- TombEngine/Game/effects/tomb4fx.cpp | 21 ++- TombEngine/Game/effects/tomb4fx.h | 54 +++++++- TombEngine/Game/effects/weather.cpp | 2 + TombEngine/Game/effects/weather.h | 13 ++ TombEngine/Renderer/RendererDraw.cpp | 2 +- TombEngine/Renderer/RendererDrawEffect.cpp | 151 ++++++++++++++++----- 18 files changed, 297 insertions(+), 66 deletions(-) diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp index 20eaa6b14..a427dfe71 100644 --- a/TombEngine/Game/Setup.cpp +++ b/TombEngine/Game/Setup.cpp @@ -135,8 +135,8 @@ void InitializeGameFlags() void InitializeSpecialEffects() { memset(&FireSparks, 0, MAX_SPARKS_FIRE * sizeof(FIRE_SPARKS)); - memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SmokeSparkInfo)); - memset(&Gunshells, 0, MAX_GUNSHELL * sizeof(GunshellInfo)); + memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SMOKE_SPARKS)); + memset(&Gunshells, 0, MAX_GUNSHELL * sizeof(GUNSHELL_STRUCT)); memset(&Blood, 0, MAX_SPARKS_BLOOD * sizeof(BLOOD_STRUCT)); memset(&Splashes, 0, MAX_SPLASHES * sizeof(SPLASH_STRUCT)); memset(&ShockWaves, 0, MAX_SHOCKWAVE * sizeof(SHOCKWAVE_STRUCT)); diff --git a/TombEngine/Game/effects/Blood.cpp b/TombEngine/Game/effects/Blood.cpp index 9c46f2653..1d215db83 100644 --- a/TombEngine/Game/effects/Blood.cpp +++ b/TombEngine/Game/effects/Blood.cpp @@ -58,6 +58,8 @@ namespace TEN::Effects::Blood if (uwBlood.Life <= 0.0f) continue; + uwBlood.StoreInterpolationData(); + // Update size. if (uwBlood.Size < UW_BLOOD_SIZE_MAX) uwBlood.Size += 4.0f; diff --git a/TombEngine/Game/effects/Blood.h b/TombEngine/Game/effects/Blood.h index 820f269d0..37939810b 100644 --- a/TombEngine/Game/effects/Blood.h +++ b/TombEngine/Game/effects/Blood.h @@ -19,6 +19,16 @@ namespace TEN::Effects::Blood Vector4 OldColor = Vector4::Zero; float OldSize = 0.0f; float OldOpacity = 0.0f; + float OldLife = 0.0f; + + void StoreInterpolationData() + { + OldPosition = Position; + OldColor = Color; + OldSize = Size; + OldOpacity = Opacity; + OldLife = Life; + } }; extern std::vector UnderwaterBloodParticles; diff --git a/TombEngine/Game/effects/Ripple.cpp b/TombEngine/Game/effects/Ripple.cpp index 982c15177..e266ef127 100644 --- a/TombEngine/Game/effects/Ripple.cpp +++ b/TombEngine/Game/effects/Ripple.cpp @@ -59,6 +59,8 @@ namespace TEN::Effects::Ripple if (ripple.Life <= 0.0f) continue; + ripple.StoreInterpolationData(); + // Update size. if (ripple.Size < RIPPLE_SIZE_MAX) ripple.Size += (ripple.Flags & ((int)RippleFlags::SlowFade | (int)RippleFlags::OnGround)) ? SIZE_STEP_SMALL : SIZE_STEP_LARGE; diff --git a/TombEngine/Game/effects/Ripple.h b/TombEngine/Game/effects/Ripple.h index ad1688c2b..031301911 100644 --- a/TombEngine/Game/effects/Ripple.h +++ b/TombEngine/Game/effects/Ripple.h @@ -23,6 +23,17 @@ namespace TEN::Effects::Ripple float Size = 0.0f; float FadeDuration = 0.0f; int Flags = 0; + + Vector3 OldPosition; + Vector4 OldColor; + float OldSize; + + void StoreInterpolationData() + { + OldPosition = Position; + OldColor = Color; + OldSize = Size; + } }; extern std::vector Ripples; diff --git a/TombEngine/Game/effects/bubble.cpp b/TombEngine/Game/effects/bubble.cpp index 58f10ccf4..9dedf6592 100644 --- a/TombEngine/Game/effects/bubble.cpp +++ b/TombEngine/Game/effects/bubble.cpp @@ -147,6 +147,8 @@ namespace TEN::Effects::Bubble if (bubble.Life <= 0.0f) continue; + bubble.StoreInterpolationData(); + // Update room number. TODO: Should use GetCollision(), but calling it for each bubble is very inefficient. auto roomVector = RoomVector(bubble.RoomNumber, int(bubble.Position.y - bubble.Gravity)); int roomNumber = GetRoomVector(roomVector, Vector3i(bubble.Position.x, bubble.Position.y - bubble.Gravity, bubble.Position.z)).RoomNumber; diff --git a/TombEngine/Game/effects/bubble.h b/TombEngine/Game/effects/bubble.h index 4825b89cf..e410842a9 100644 --- a/TombEngine/Game/effects/bubble.h +++ b/TombEngine/Game/effects/bubble.h @@ -30,6 +30,19 @@ namespace TEN::Effects::Bubble float Gravity = 0.0f; float OscillationPeriod = 0.0f; float OscillationVelocity = 0.0f; + + Vector3 OldPosition = Vector3::Zero; + Vector4 OldColor = Vector4::Zero; + Vector2 OldSize = Vector2::Zero; + float OldLife = 0.0f; + + void StoreInterpolationData() + { + OldPosition = Position; + OldColor = Color; + OldSize = Size; + OldLife = Life; + } }; extern std::vector Bubbles; diff --git a/TombEngine/Game/effects/chaffFX.cpp b/TombEngine/Game/effects/chaffFX.cpp index 4b4674204..f3e511a89 100644 --- a/TombEngine/Game/effects/chaffFX.cpp +++ b/TombEngine/Game/effects/chaffFX.cpp @@ -98,7 +98,7 @@ void TriggerChaffSparkles(const Vector3i& pos, const Vector3i& vel, const Color& void TriggerChaffSmoke(const Vector3i& pos, const Vector3i& vel, int speed, bool isMoving, bool wind) { - SmokeSparkInfo* smoke; + SMOKE_SPARKS* smoke; int rnd = 0; BYTE trans, size; diff --git a/TombEngine/Game/effects/drip.cpp b/TombEngine/Game/effects/drip.cpp index 01609b5f0..4c08fc73f 100644 --- a/TombEngine/Game/effects/drip.cpp +++ b/TombEngine/Game/effects/drip.cpp @@ -105,6 +105,8 @@ namespace TEN::Effects::Drip if (drip.Life <= 0.0f) continue; + drip.StoreInterpolationData(); + // Update velocity. drip.Velocity.y += drip.Gravity; if (TestEnvironment(ENV_FLAG_WIND, drip.RoomNumber)) diff --git a/TombEngine/Game/effects/drip.h b/TombEngine/Game/effects/drip.h index 52f13d39c..bb6946ab1 100644 --- a/TombEngine/Game/effects/drip.h +++ b/TombEngine/Game/effects/drip.h @@ -15,6 +15,21 @@ namespace TEN::Effects::Drip float Life = 0.0f; float LifeMax = 0.0f; float Gravity = 0.0f; + + Vector3 OldPosition = Vector3::Zero; + Vector4 OldColor = Vector4::Zero; + Vector2 OldSize = Vector2::Zero; + float OldLife = 0.0f; + Vector3 OldVelocity = Vector3::Zero; + + void StoreInterpolationData() + { + OldPosition = Position; + OldColor = Color; + OldSize = Size; + OldLife = Life; + OldVelocity = Velocity; + } }; extern std::vector Drips; diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index e1e04d1ab..8743543a6 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -195,6 +195,8 @@ void UpdateSparks() if (spark->on) { + spark->StoreInterpolationData(); + spark->life--; if (!spark->life) @@ -1046,6 +1048,8 @@ void UpdateSplashes() if (splash.isActive) { + splash.StoreInterpolationData(); + splash.life--; if (splash.life <= 0) splash.isActive = false; diff --git a/TombEngine/Game/effects/effects.h b/TombEngine/Game/effects/effects.h index 2b77640a0..ba45f28c4 100644 --- a/TombEngine/Game/effects/effects.h +++ b/TombEngine/Game/effects/effects.h @@ -110,17 +110,6 @@ struct SPLASH_SETUP int room; }; -struct RIPPLE_STRUCT -{ - int x; - int y; - int z; - char flags; - unsigned char life; - unsigned char size; - unsigned char init; -}; - struct Particle { int x; @@ -160,6 +149,27 @@ struct Particle int fxObj; int roomNumber; unsigned char nodeNumber; // ParticleNodeOffsetIDs enum. + + int oldX; + int oldY; + int oldZ; + short oldRotAng; + byte oldR; + byte oldG; + byte oldB; + byte oldScalar; + + void StoreInterpolationData() + { + oldX = x; + oldY = y; + oldZ = z; + oldRotAng = rotAng; + oldR = r; + oldG = g; + oldB = b; + oldScalar = scalar; + } }; struct SPLASH_STRUCT @@ -181,6 +191,27 @@ struct SPLASH_STRUCT unsigned short life; bool isRipple; bool isActive; + + float oldX; + float oldY; + float oldZ; + float oldInnerRad; + float oldOuterRad; + float oldHeight; + unsigned short oldLife; + float oldHeightSpeed; + + void StoreInterpolationData() + { + oldX = x; + oldY = y; + oldZ = z; + oldInnerRad = innerRad; + oldOuterRad = outerRad; + oldHeight = height; + oldLife = life; + oldHeightSpeed = heightSpeed; + } }; struct ParticleDynamic diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 886a240c4..daaf05c94 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -47,8 +47,8 @@ int NextBlood = 0; int NextGunShell = 0; FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -SmokeSparkInfo SmokeSparks[MAX_SPARKS_SMOKE]; -GunshellInfo Gunshells[MAX_GUNSHELL]; +SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; +GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; FIRE_LIST Fires[MAX_FIRE_LIST]; @@ -492,7 +492,7 @@ void UpdateFireSparks() int GetFreeSmokeSpark() { - SmokeSparkInfo* spark = &SmokeSparks[NextSmokeSpark]; + SMOKE_SPARKS* spark = &SmokeSparks[NextSmokeSpark]; int sparkNum = NextSmokeSpark; short minLife = 4095; short minIndex = 0; @@ -532,7 +532,7 @@ void UpdateSmoke() { for (int i = 0; i < MAX_SPARKS_SMOKE; i++) { - SmokeSparkInfo* spark = &SmokeSparks[i]; + SMOKE_SPARKS* spark = &SmokeSparks[i]; if (spark->on) { @@ -652,7 +652,7 @@ void TriggerGunSmoke(int x, int y, int z, short xv, short yv, short zv, byte ini void TriggerShatterSmoke(int x, int y, int z) { - SmokeSparkInfo* spark = &SmokeSparks[GetFreeSmokeSpark()]; + SMOKE_SPARKS* spark = &SmokeSparks[GetFreeSmokeSpark()]; spark->on = true; spark->sShade = 0; @@ -786,12 +786,7 @@ void UpdateBlood() continue; } - blood->oldX = blood->x; - blood->oldY = blood->y; - blood->oldZ = blood->z; - blood->oldRotAng = blood->rotAng; - blood->oldSize = blood->size; - blood->oldShade = blood->shade; + blood->StoreInterpolationData(); if (blood->sLife - blood->life >= blood->colFadeSpeed) { @@ -843,7 +838,7 @@ int GetFreeGunshell() while (true) { - GunshellInfo* gs = &Gunshells[NextGunShell]; + GUNSHELL_STRUCT* gs = &Gunshells[NextGunShell]; if (!gs->counter) break; @@ -1394,6 +1389,8 @@ void UpdateShockwaves() if (shockwave.life <= 0) continue; + shockwave.StoreInterpolationData(); + shockwave.life--; // Spawn light. diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index da63cb1cc..b75aad25d 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -25,7 +25,7 @@ enum BodyPartFlags BODY_NO_SHATTER_EFFECT = (1 << 13), // Remove shatter effect upon despawn. }; -struct SmokeSparkInfo +struct SMOKE_SPARKS { Vector3i position; Vector3i velocity; @@ -95,9 +95,24 @@ struct SHOCKWAVE_STRUCT bool fadeIn = false; bool HasLight = false; + + short oldInnerRad; + short oldOuterRad; + byte oldR; + byte oldG; + byte oldB; + + void StoreInterpolationData() + { + oldInnerRad = innerRad; + oldOuterRad = outerRad; + oldR = r; + oldG = g; + oldB = b; + } }; -struct GunshellInfo +struct GUNSHELL_STRUCT { Pose pos; short fallspeed; @@ -130,6 +145,23 @@ struct DRIP_STRUCT short roomNumber; byte outside; byte pad; + + int oldX; + int oldY; + int oldZ; + byte oldR; + byte oldG; + byte oldB; + + void StoreInterpolationData() + { + oldX = x; + oldY = y; + oldZ = z; + oldR = r; + oldG = g; + oldB = b; + } }; struct FIRE_LIST @@ -224,8 +256,18 @@ struct BLOOD_STRUCT int oldY; int oldZ; short oldRotAng; - unsigned char oldShade; - unsigned char oldSize; + byte oldShade; + byte oldSize; + + void StoreInterpolationData() + { + oldX = x; + oldY = y; + oldZ = z; + oldRotAng = rotAng; + oldShade = shade; + oldSize = size; + } }; enum class ShockwaveStyle @@ -260,8 +302,8 @@ constexpr auto MAX_GUNSHELL = 24; constexpr auto MAX_SHOCKWAVE = 16; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -extern SmokeSparkInfo SmokeSparks[MAX_SPARKS_SMOKE]; -extern GunshellInfo Gunshells[MAX_GUNSHELL]; +extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; +extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; extern FIRE_LIST Fires[MAX_FIRE_LIST]; diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index a532d3b00..b4d99a50c 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -225,6 +225,8 @@ namespace TEN::Effects::Environment { for (auto& p : Particles) { + p.StoreInterpolationData(); + p.Life -= 2; // Disable particle if it is dead. It will be cleaned on next call of diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index e96f27d76..214cd1ff5 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -22,6 +22,19 @@ namespace TEN::Effects::Environment bool Stopped = false; float Transparency() const; + + Vector3 OldPosition = Vector3::Zero; + Vector3 OldVelocity = Vector3::Zero; + float OldSize = 0.0f; + float OldLife = 0.0f; + + void StoreInterpolationData() + { + OldPosition = Position; + OldVelocity = Velocity; + OldSize = Size; + OldLife = Life; + } }; class EnvironmentController diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index b5f99e81c..17b9aea3f 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -39,7 +39,7 @@ using namespace TEN::Entities::Generic; using namespace TEN::Hud; using namespace TEN::Renderer::Structures; -extern GunshellInfo Gunshells[MAX_GUNSHELL]; +extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; namespace TEN::Renderer { diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 2e353c16d..f8e99036a 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -48,7 +48,7 @@ using namespace TEN::Traps::TR5; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; -extern SmokeSparkInfo SmokeSparks[MAX_SPARKS_SMOKE]; +extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; extern FIRE_LIST Fires[MAX_FIRE_LIST]; extern Particle Particles[MAX_PARTICLES]; @@ -277,7 +277,7 @@ namespace TEN::Renderer { for (int i = 0; i < 32; i++) { - SmokeSparkInfo* spark = &SmokeSparks[i]; + SMOKE_SPARKS* spark = &SmokeSparks[i]; if (spark->on) { @@ -495,8 +495,19 @@ namespace TEN::Renderer } } - float innerRadius = splash.innerRad; - float outerRadius = splash.outerRad; + byte oldColor = (splash.oldLife >= 32 ? 128 : (byte)((splash.oldLife / 32.0f) * 128)); + + if (!splash.isRipple) + { + if (splash.oldHeightSpeed < 0 && splash.oldHeight < 1024) + { + float multiplier = splash.oldHeight / 1024.0f; + oldColor = (float)oldColor * multiplier; + } + } + + color = (byte)Lerp(oldColor, color, _interpolationFactor); + float xInner; float zInner; float xOuter; @@ -508,6 +519,9 @@ namespace TEN::Renderer float yInner = splash.y; float yOuter = splash.y - splash.height; + float innerRadius = Lerp(splash.oldInnerRad, splash.innerRad, _interpolationFactor); + float outerRadius = Lerp(splash.oldOuterRad, splash.outerRad, _interpolationFactor); + for (int i = 0; i < NUM_POINTS; i++) { xInner = innerRadius * sin(alpha * i * PI / 180); @@ -527,12 +541,19 @@ namespace TEN::Renderer x2Outer += splash.x; z2Outer = outerRadius * cos(alpha * j * PI / 180); z2Outer += splash.z; + AddQuad(&_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + splash.spriteSequenceStart + (int)splash.animationPhase], - Vector3(xOuter, yOuter, zOuter), - Vector3(x2Outer, yOuter, z2Outer), - Vector3(x2Inner, yInner, z2Inner), - Vector3(xInner, yInner, zInner), Vector4(color / 255.0f, color / 255.0f, color / 255.0f, 1.0f), - 0, 1, { 0, 0 }, BlendMode::Additive, false, view); + Vector3(xOuter, yOuter, zOuter), + Vector3(x2Outer, yOuter, z2Outer), + Vector3(x2Inner, yInner, z2Inner), + Vector3(xInner, yInner, zInner), + Vector4(color / 255.0f, color / 255.0f, color / 255.0f, 1.0f), + 0, + 1, + { 0, 0 }, + BlendMode::Additive, + false, + view); } } } @@ -552,8 +573,14 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + bubble.SpriteIndex], - bubble.Position, - bubble.Color, 0.0f, 1.0f, bubble.Size / 2, BlendMode::Additive, true, view); + Vector3::Lerp(bubble.OldPosition, bubble.Position, _interpolationFactor), + Vector4::Lerp(bubble.OldColor, bubble.Color, _interpolationFactor), + 0.0f, + 1.0f, + Vector2::Lerp(bubble.OldSize, bubble.Size, _interpolationFactor) / 2, + BlendMode::Additive, + true, + view); } } @@ -573,10 +600,20 @@ namespace TEN::Renderer auto axis = drip.Velocity; drip.Velocity.Normalize(axis); + auto oldAxis = drip.OldVelocity; + drip.OldVelocity.Normalize(oldAxis); + AddSpriteBillboardConstrained( &_sprites[Objects[ID_DRIP_SPRITE].meshIndex], - drip.Position, - drip.Color, 0.0f, 1.0f, drip.Size, BlendMode::Additive, -axis, false, view); + Vector3::Lerp(drip.OldPosition, drip.Position, _interpolationFactor), + Vector4::Lerp(drip.OldColor, drip.Color, _interpolationFactor), + 0.0f, + 1.0f, + Vector2::Lerp(drip.OldSize, drip.Size, _interpolationFactor), + BlendMode::Additive, + -Vector3::Lerp(oldAxis, axis, _interpolationFactor), + false, + view); } } @@ -594,10 +631,21 @@ namespace TEN::Renderer auto color = ripple.Color; color.w = opacity; + float oldOpacity = ripple.OldColor.w * ((ripple.Flags & (int)RippleFlags::LowOpacity) ? 0.5f : 1.0f); + auto oldColor = ripple.OldColor; + oldColor.w = oldOpacity; + AddSpriteBillboardConstrainedLookAt( &_sprites[ripple.SpriteIndex], - ripple.Position, - color, 0.0f, 1.0f, Vector2(ripple.Size * 2), BlendMode::Additive, ripple.Normal, true, view); + Vector3::Lerp(ripple.OldPosition, ripple.Position, _interpolationFactor), + Vector4::Lerp(oldColor, color, _interpolationFactor), + 0.0f, + 1.0f, + Vector2(Lerp(ripple.OldSize, ripple.Size, _interpolationFactor) * 2), + BlendMode::Additive, + ripple.Normal, + true, + view); } } @@ -622,10 +670,30 @@ namespace TEN::Renderer color.z = (int)std::clamp((int)color.z, 0, UCHAR_MAX); color /= UCHAR_MAX; + auto oldColor = Vector4::Zero; + if (uwBlood.Init) + oldColor = Vector4(uwBlood.Init / 2, 0, uwBlood.Init / 16, UCHAR_MAX); + else + oldColor = Vector4(uwBlood.OldLife / 2, 0, uwBlood.OldLife / 16, UCHAR_MAX); + + oldColor.x = (int)std::clamp((int)oldColor.x, 0, UCHAR_MAX); + oldColor.y = (int)std::clamp((int)oldColor.y, 0, UCHAR_MAX); + oldColor.z = (int)std::clamp((int)oldColor.z, 0, UCHAR_MAX); + oldColor /= UCHAR_MAX; + AddSpriteBillboard( &_sprites[uwBlood.SpriteIndex], - uwBlood.Position, - color, 0.0f, 1.0f, Vector2(uwBlood.Size, uwBlood.Size) * 2, BlendMode::Additive, true, view); + Vector3::Lerp(uwBlood.OldPosition, uwBlood.Position, _interpolationFactor), + Vector4::Lerp(oldColor, color, _interpolationFactor), + 0.0f, + 1.0f, + Vector2( + Lerp(uwBlood.OldSize, uwBlood.Size, _interpolationFactor), + Lerp(uwBlood.OldSize, uwBlood.Size, _interpolationFactor) + ) * 2, + BlendMode::Additive, + true, + view); } } @@ -659,6 +727,9 @@ namespace TEN::Renderer auto pos = Vector3(shockwave->x, shockwave->y, shockwave->z); + float innerRadius = Lerp(shockwave->oldInnerRad, shockwave->innerRad, _interpolationFactor); + float outerRadius = Lerp(shockwave->oldOuterRad, shockwave->outerRad, _interpolationFactor); + // Inner circle if (shockwave->style == (int)ShockwaveStyle::Normal) { @@ -675,10 +746,10 @@ namespace TEN::Renderer angle -= PI / 4.0f; } - float x1 = (shockwave->innerRad * c); - float z1 = (shockwave->innerRad * s); - float x4 = (shockwave->outerRad * c); - float z4 = (shockwave->outerRad * s); + float x1 = (innerRadius * c); + float z1 = (innerRadius * s); + float x4 = (innerRadius * c); + float z4 = (innerRadius * s); auto p1 = Vector3(x1, 0, z1); auto p4 = Vector3(x4, 0, z4); @@ -736,11 +807,11 @@ namespace TEN::Renderer c = cos(angle); s = sin(angle); - float x2 = (shockwave->innerRad * c); - float z2 = (shockwave->innerRad * s); + float x2 = (innerRadius * c); + float z2 = (innerRadius * s); - float x3 = (shockwave->outerRad * c); - float z3 = (shockwave->outerRad * s); + float x3 = (outerRadius * c); + float z3 = (outerRadius * s); auto p2 = Vector3(x2, 0, z2); auto p3 = Vector3(x3, 0, z3); @@ -856,10 +927,14 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], - p.Position, + Vector3::Lerp(p.OldPosition, p.Position, _interpolationFactor), Vector4(1.0f, 1.0f, 1.0f, p.Transparency()), - 0.0f, 1.0f, Vector2(p.Size), - BlendMode::Additive, true, view); + 0.0f, + 1.0f, + Vector2(Lerp(p.OldSize, p.Size, _interpolationFactor)), + BlendMode::Additive, + true, + view); break; @@ -870,10 +945,14 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], - p.Position, + Vector3::Lerp(p.OldPosition, p.Position, _interpolationFactor), Vector4(1.0f, 1.0f, 1.0f, p.Transparency()), - 0.0f, 1.0f, Vector2(p.Size), - BlendMode::Additive, true, view); + 0.0f, + 1.0f, + Vector2(Lerp(p.OldSize, p.Size, _interpolationFactor)), + BlendMode::Additive, + true, + view); break; @@ -887,9 +966,15 @@ namespace TEN::Renderer AddSpriteBillboardConstrained( &_sprites[Objects[ID_DRIP_SPRITE].meshIndex], - p.Position, + Vector3::Lerp(p.OldPosition, p.Position, _interpolationFactor), Vector4(0.8f, 1.0f, 1.0f, p.Transparency()), - 0.0f, 1.0f, Vector2(RAIN_WIDTH, p.Size), BlendMode::Additive, -v, true, view); + 0.0f, + 1.0f, + Vector2(RAIN_WIDTH, Lerp(p.OldSize, p.Size, _interpolationFactor)), + BlendMode::Additive, + -v, + true, + view); break; } From d37eb6a69be8433069a474d21ec2ba9a488559f5 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 16 Apr 2024 09:18:56 +0200 Subject: [PATCH 078/410] Fixed bug with last merge --- TombEngine/Renderer/Structures/RendererItem.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Renderer/Structures/RendererItem.h b/TombEngine/Renderer/Structures/RendererItem.h index a913a9f94..31f2a4204 100644 --- a/TombEngine/Renderer/Structures/RendererItem.h +++ b/TombEngine/Renderer/Structures/RendererItem.h @@ -34,8 +34,8 @@ namespace TEN::Renderer::Structures Matrix InterpolatedScale; Matrix InterpolatedAnimationTransforms[MAX_BONES]; - int RoomNumber = NO_ROOM; - int PrevRoomNumber = NO_ROOM; + int RoomNumber = NO_VALUE; + int PrevRoomNumber = NO_VALUE; Vector4 Color; Vector4 AmbientLight; From c11eab5f587a06eda44ed8abe792972a5469eccf Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 17 Apr 2024 05:31:19 +0200 Subject: [PATCH 079/410] Hairs interpolation --- TombEngine/Game/effects/hair.cpp | 5 +++++ TombEngine/Game/effects/hair.h | 9 +++++++++ TombEngine/Renderer/RendererLara.cpp | 6 +++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 4a27ba83a..3ffc2215a 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -23,6 +23,11 @@ namespace TEN::Effects::Hair void HairUnit::Update(const ItemInfo& item, int hairUnitIndex) { + for (int i = 0; i < Segments.size(); i++) + { + Segments[i].StoreInterpolationData(); + } + const auto& player = GetLaraInfo(item); bool isYoung = (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); diff --git a/TombEngine/Game/effects/hair.h b/TombEngine/Game/effects/hair.h index 8e0a842b6..dde5d3b3c 100644 --- a/TombEngine/Game/effects/hair.h +++ b/TombEngine/Game/effects/hair.h @@ -15,6 +15,15 @@ namespace TEN::Effects::Hair Vector3 Position = Vector3::Zero; Vector3 Velocity = Vector3::Zero; Quaternion Orientation = Quaternion::Identity; + + Vector3 OldPosition = Vector3::Zero; + Quaternion OldOrientation = Quaternion::Identity; + + void StoreInterpolationData() + { + OldPosition = Position; + OldOrientation = Orientation; + } }; public: diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index b294e5735..b36f8113f 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -350,7 +350,11 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render for (int i = 0; i < unit.Segments.size(); i++) { const auto& segment = unit.Segments[i]; - auto worldMatrix = Matrix::CreateFromQuaternion(segment.Orientation) * Matrix::CreateTranslation(segment.Position); + auto worldMatrix = + Matrix::CreateFromQuaternion( + Quaternion::Lerp(segment.OldOrientation, segment.Orientation, _interpolationFactor)) * + Matrix::CreateTranslation( + Vector3::Lerp(segment.OldPosition, segment.Position, _interpolationFactor)); _stItem.BonesMatrices[i + 1] = worldMatrix; _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; From ff32cca745b02189fc5ff8e096b7e694b15d665d Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 18 Apr 2024 05:52:20 +0200 Subject: [PATCH 080/410] Shadow maps interpolation --- TombEngine/Game/effects/Electricity.cpp | 4 + TombEngine/Game/effects/Electricity.h | 58 +++++++++++-- TombEngine/Game/effects/explosion.cpp | 2 + TombEngine/Game/effects/explosion.h | 69 ++++++++------- TombEngine/Game/effects/simple_particle.cpp | 2 + TombEngine/Game/effects/simple_particle.h | 14 +++- TombEngine/Game/items.cpp | 5 ++ TombEngine/Game/items.h | 6 ++ TombEngine/Renderer/RendererDraw.cpp | 6 +- TombEngine/Renderer/RendererDrawEffect.cpp | 93 +++++++++++++++++---- 10 files changed, 201 insertions(+), 58 deletions(-) diff --git a/TombEngine/Game/effects/Electricity.cpp b/TombEngine/Game/effects/Electricity.cpp index 2c169717c..7e64d4cb4 100644 --- a/TombEngine/Game/effects/Electricity.cpp +++ b/TombEngine/Game/effects/Electricity.cpp @@ -175,6 +175,8 @@ namespace TEN::Effects::Electricity for (auto& laser : HelicalLasers) { + laser.StoreInterpolationData(); + // Set to despawn. laser.Life -= 1.0f; if (laser.Life <= 0.0f) @@ -213,6 +215,8 @@ namespace TEN::Effects::Electricity if (arc.life <= 0.0f) continue; + arc.StoreInterpolationData(); + // If/when this behaviour is changed, modify AddLightningArc accordingly. arc.life -= 2.0f; if (arc.life > 0.0f) diff --git a/TombEngine/Game/effects/Electricity.h b/TombEngine/Game/effects/Electricity.h index 45ea1ecbd..0aa4fa764 100644 --- a/TombEngine/Game/effects/Electricity.h +++ b/TombEngine/Game/effects/Electricity.h @@ -39,24 +39,66 @@ namespace TEN::Effects::Electricity int rotation; int type; int flags; + + Vector3 oldPos1; + Vector3 oldPos2; + Vector3 oldPos3; + Vector3 oldPos4; + byte oldR; + byte oldG; + byte oldB; + float oldLife; + + void StoreInterpolationData() + { + oldPos1 = pos1; + oldPos2 = pos2; + oldPos3 = pos3; + oldPos4 = pos4; + oldR = r; + oldG = g; + oldB = b; + oldLife = life; + } }; struct HelicalLaser { unsigned int NumSegments = 0; - Vector3 Origin = Vector3::Zero; - Vector3 Target = Vector3::Zero; + Vector3 Origin = Vector3::Zero; + Vector3 Target = Vector3::Zero; short Orientation2D = 0; Vector3 LightPosition = Vector3::Zero; // TODO: Use light cone instead? - Vector4 Color = Vector4::Zero; + Vector4 Color = Vector4::Zero; - float Life = 0.0f; - float Radius = 0.0f; - float Length = 0.0f; + float Life = 0.0f; + float Radius = 0.0f; + float Length = 0.0f; float LengthEnd = 0.0f; - float Opacity = 0.0f; - short Rotation = 0; + float Opacity = 0.0f; + short Rotation = 0; + + Vector3 OldOrigin = Vector3::Zero; + Vector3 OldTarget = Vector3::Zero; + float OldLife = 0.0f; + float OldRadius = 0.0f; + float OldLength = 0.0f; + float OldOpacity = 0.0f; + Vector4 OldColor = Vector4::Zero; + short OldOrientation2D = 0; + + void StoreInterpolationData() + { + OldOrigin = Origin; + OldTarget = Target; + OldLife = Life; + OldRadius = Radius; + OldLength = Length; + OldOpacity = Opacity; + OldColor = Color; + OldOrientation2D = Orientation2D; + } }; extern std::vector ElectricityArcs; diff --git a/TombEngine/Game/effects/explosion.cpp b/TombEngine/Game/effects/explosion.cpp index 592e21580..d64dd8e42 100644 --- a/TombEngine/Game/effects/explosion.cpp +++ b/TombEngine/Game/effects/explosion.cpp @@ -49,6 +49,8 @@ namespace TEN::Effects::Explosion if (!e.active) continue; + e.StoreInterpolationData(); + e.age++; if (e.age > e.life) { diff --git a/TombEngine/Game/effects/explosion.h b/TombEngine/Game/effects/explosion.h index 4c6ff9348..bc822573f 100644 --- a/TombEngine/Game/effects/explosion.h +++ b/TombEngine/Game/effects/explosion.h @@ -1,28 +1,41 @@ -#pragma once -#include -#include -#include - -namespace TEN::Effects::Explosion -{ - struct ExplosionParticle - { - Vector3 pos; - Vector3 vel; - Vector4 tint; - float size; - float rotation; - float angularVel; - float age; - float life; - int room; - int sprite; - bool active; - }; - extern std::array explosionParticles; - - void TriggerExplosion(const Vector3& pos, float size, bool triggerSparks, bool triggerSmoke, bool triggerShockwave, int room); - void UpdateExplosionParticles(); - ExplosionParticle& getFreeExplosionParticle(); - void SpawnExplosionParticle(const Vector3& pos); -} +#pragma once +#include +#include +#include + +namespace TEN::Effects::Explosion +{ + struct ExplosionParticle + { + Vector3 pos; + Vector3 vel; + Vector4 tint; + float size; + float rotation; + float angularVel; + float age; + float life; + int room; + int sprite; + bool active; + + Vector3 oldPos; + Vector4 oldTint; + float oldSize; + float oldRotation; + + void StoreInterpolationData() + { + oldPos = pos; + oldTint = tint; + oldSize = size; + oldRotation = rotation; + } + }; + extern std::array explosionParticles; + + void TriggerExplosion(const Vector3& pos, float size, bool triggerSparks, bool triggerSmoke, bool triggerShockwave, int room); + void UpdateExplosionParticles(); + ExplosionParticle& getFreeExplosionParticle(); + void SpawnExplosionParticle(const Vector3& pos); +} diff --git a/TombEngine/Game/effects/simple_particle.cpp b/TombEngine/Game/effects/simple_particle.cpp index 0165512ac..867f0da63 100644 --- a/TombEngine/Game/effects/simple_particle.cpp +++ b/TombEngine/Game/effects/simple_particle.cpp @@ -73,6 +73,8 @@ namespace TEN::Effects if (!p.active) continue; + p.StoreInterpolationData(); + p.age+= p.ageRate; if (p.life < p.age) p.active = false; diff --git a/TombEngine/Game/effects/simple_particle.h b/TombEngine/Game/effects/simple_particle.h index cd32afa42..592c23154 100644 --- a/TombEngine/Game/effects/simple_particle.h +++ b/TombEngine/Game/effects/simple_particle.h @@ -1,14 +1,17 @@ #pragma once #include "Objects\objectslist.h" +#include enum class BlendMode; struct ItemInfo; namespace TEN::Effects { + using namespace DirectX::SimpleMath; + struct SimpleParticle { - DirectX::SimpleMath::Vector3 worldPosition; + Vector3 worldPosition; float size; float age; float ageRate; @@ -18,6 +21,15 @@ namespace TEN::Effects GAME_OBJECT_ID sequence; bool active; BlendMode blendMode; + + Vector3 oldWorldPosition; + float oldSize; + + void StoreInterpolationData() + { + oldWorldPosition = worldPosition; + oldSize = size; + } }; extern std::array simpleParticles; diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 29a4cf9bc..590de6614 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -745,6 +745,11 @@ int FindItem(ItemInfo* item) void UpdateAllItems() { + for (int i = 0; i < g_Level.Items.size(); i++) + { + g_Level.Items[i].StoreInterpolationData(); + } + InItemControlLoop = true; short itemNumber = NextItemActive; diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index cda9aafee..9e0faed69 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -122,6 +122,7 @@ struct ItemInfo EntityEffectData Effect = {}; EntityModelData Model = {}; + Pose OldPose = Pose::Zero; Pose StartPose = Pose::Zero; Pose Pose = Pose::Zero; RoomVector Location = {}; // NOTE: Describes vertical position in room. @@ -172,6 +173,11 @@ struct ItemInfo bool IsLara() const; bool IsCreature() const; bool IsBridge() const; + + void StoreInterpolationData() + { + OldPose = Pose; + } }; bool TestState(int refState, const std::vector& stateList); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 979919fd7..5bd6c0abe 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -208,10 +208,10 @@ namespace TEN::Renderer RendererObject& obj = GetRendererObject((GAME_OBJECT_ID)item->ObjectNumber); - _stItem.World = item->World; + _stItem.World = item->InterpolatedWorld; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; - memcpy(_stItem.BonesMatrices, item->AnimationTransforms, sizeof(Matrix) * MAX_BONES); + memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); for (int k = 0; k < MAX_BONES; k++) _stItem.BoneLightModes[k] = (int)LightMode::Static; @@ -2308,7 +2308,7 @@ namespace TEN::Renderer RendererObject& moveableObj = *_moveableObjects[item->ObjectNumber]; // Bind item main properties - _stItem.World = item->InterpolatedWorld; // item->World; + _stItem.World = item->InterpolatedWorld; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index f8e99036a..1839a5875 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -169,14 +169,16 @@ namespace TEN::Renderer if (laser.Life <= 0.0f) continue; - auto color = laser.Color; - color.w = laser.Opacity; + auto color = Vector4::Lerp(laser.OldColor, laser.Color, _interpolationFactor); + color.w = Lerp(laser.OldOpacity, laser.Opacity, _interpolationFactor); - ElectricityKnots[0] = laser.Target; - ElectricityKnots[1] = laser.Origin; + Vector3 laserTarget = Vector3::Lerp(laser.OldTarget, laser.Target, _interpolationFactor); + + ElectricityKnots[0] = laserTarget; + ElectricityKnots[1] = Vector3::Lerp(laser.OldOrigin, laser.Origin, _interpolationFactor); for (int j = 0; j < 2; j++) - ElectricityKnots[j] -= laser.Target; + ElectricityKnots[j] -= laserTarget; CalculateHelixSpline(laser, ElectricityKnots, ElectricityBuffer); @@ -189,9 +191,9 @@ namespace TEN::Renderer auto& interpPosArray = ElectricityBuffer; for (int s = 0; s < laser.NumSegments ; s++) { - auto origin = laser.Target + interpPosArray[bufferIndex]; + auto origin = laserTarget + interpPosArray[bufferIndex]; bufferIndex++; - auto target = laser.Target + interpPosArray[bufferIndex]; + auto target = laserTarget + interpPosArray[bufferIndex]; auto center = (origin + target) / 2; auto direction = target - origin; @@ -201,7 +203,13 @@ namespace TEN::Renderer &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LIGHTHING], center, color, - PI_DIV_2, 1.0f, Vector2(5 * 8.0f, Vector3::Distance(origin, target)), BlendMode::Additive, direction, true, view); + PI_DIV_2, + 1.0f, + Vector2(5 * 8.0f, Vector3::Distance(origin, target)), + BlendMode::Additive, + direction, + true, + view); } } } @@ -220,12 +228,12 @@ namespace TEN::Renderer if (arc.life <= 0) continue; - ElectricityKnots[0] = arc.pos1; - ElectricityKnots[1] = arc.pos1; - ElectricityKnots[2] = arc.pos2; - ElectricityKnots[3] = arc.pos3; - ElectricityKnots[4] = arc.pos4; - ElectricityKnots[5] = arc.pos4; + ElectricityKnots[0] = Vector3::Lerp(arc.oldPos1, arc.pos1, _interpolationFactor); + ElectricityKnots[1] = Vector3::Lerp(arc.oldPos1, arc.pos1, _interpolationFactor); + ElectricityKnots[2] = Vector3::Lerp(arc.oldPos2, arc.pos2, _interpolationFactor); + ElectricityKnots[3] = Vector3::Lerp(arc.oldPos3, arc.pos3, _interpolationFactor); + ElectricityKnots[4] = Vector3::Lerp(arc.oldPos4, arc.pos4, _interpolationFactor); + ElectricityKnots[5] = Vector3::Lerp(arc.oldPos4, arc.pos4, _interpolationFactor); for (int j = 0; j < ElectricityKnots.size(); j++) ElectricityKnots[j] -= LaraItem->Pose.Position.ToVector3(); @@ -239,6 +247,7 @@ namespace TEN::Renderer int bufferIndex = 0; auto& interpPosArray = ElectricityBuffer; + for (int s = 0; s < ((arc.segments * 3) - 1); s++) { auto origin = (LaraItem->Pose.Position + interpPosArray[bufferIndex]).ToVector3(); @@ -263,11 +272,36 @@ namespace TEN::Renderer b = (arc.life * arc.b) / 16; } + + byte oldR, oldG, oldB; + if (arc.oldLife >= 16) + { + oldR = arc.oldR; + oldG = arc.oldG; + oldB = arc.oldB; + } + else + { + oldR = (arc.oldLife * arc.oldR) / 16; + oldG = (arc.oldLife * arc.oldG) / 16; + oldB = (arc.oldLife * arc.oldB) / 16; + } + + r = (byte)Lerp(oldR, r, _interpolationFactor); + g = (byte)Lerp(oldG, g, _interpolationFactor); + b = (byte)Lerp(oldB, b, _interpolationFactor); + AddSpriteBillboardConstrained( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LIGHTHING], center, Vector4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f), - PI_DIV_2, 1.0f, Vector2(arc.width * 8, Vector3::Distance(origin, target)), BlendMode::Additive, direction, true, view); + PI_DIV_2, + 1.0f, + Vector2(arc.width * 8, Vector3::Distance(origin, target)), + BlendMode::Additive, + direction, + true, + view); } } } @@ -1490,8 +1524,19 @@ namespace TEN::Renderer if (!CheckIfSlotExists(ID_EXPLOSION_SPRITES, "Explosion particles rendering")) return; - AddSpriteBillboard(&_sprites[Objects[ID_EXPLOSION_SPRITES].meshIndex + e.sprite], - e.pos, e.tint, e.rotation, 1.0f, { e.size, e.size }, BlendMode::Additive, true, view); + AddSpriteBillboard( + &_sprites[Objects[ID_EXPLOSION_SPRITES].meshIndex + e.sprite], + Vector3::Lerp(e.oldPos, e.pos, _interpolationFactor), + Vector4::Lerp(e.oldTint, e.tint, _interpolationFactor), + Lerp(e.oldRotation, e.rotation, _interpolationFactor), + 1.0f, + { + Lerp(e.oldSize, e.size, _interpolationFactor), + Lerp(e.oldSize, e.size, _interpolationFactor) + }, + BlendMode::Additive, + true, + view); } } @@ -1506,7 +1551,19 @@ namespace TEN::Renderer if (!CheckIfSlotExists(s.sequence, "Particle rendering")) continue; - AddSpriteBillboard(&_sprites[Objects[s.sequence].meshIndex + s.sprite], s.worldPosition, Vector4(1, 1, 1, 1), 0, 1.0f, { s.size, s.size / 2 }, BlendMode::AlphaBlend, true, view); + AddSpriteBillboard( + &_sprites[Objects[s.sequence].meshIndex + s.sprite], + Vector3::Lerp(s.oldWorldPosition, s.worldPosition, _interpolationFactor), + Vector4(1.0f), + 0, + 1.0f, + { + Lerp(s.oldSize, s.size, _interpolationFactor), + Lerp(s.oldSize, s.size, _interpolationFactor) / 2 + }, + BlendMode::AlphaBlend, + true, + view); } } } From ce403506b54b9eb4babf18841e803d0e347eb836 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 18 Apr 2024 09:38:15 +0200 Subject: [PATCH 081/410] Lens flares prototype --- TombEngine/Renderer/Renderer.h | 2 + TombEngine/Renderer/RendererInit.cpp | 3 +- TombEngine/Renderer/RendererPostProcess.cpp | 17 ++++- TombEngine/Shaders/PostProcess.fx | 74 +++++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 30c1386b0..9b0197193 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -355,6 +355,8 @@ namespace TEN::Renderer ComPtr _psPostProcessNegative; ComPtr _psPostProcessExclusion; ComPtr _psPostProcessFinalPass; + ComPtr _psPostProcessLensFlare; + bool _doingFullscreenPass = false; // SSAO diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp index c6d339c5e..b918d6a4d 100644 --- a/TombEngine/Renderer/RendererInit.cpp +++ b/TombEngine/Renderer/RendererInit.cpp @@ -297,12 +297,13 @@ namespace TEN::Renderer { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; Utils::throwIfFailed(_device->CreateInputLayout(postProcessInputLayoutItems, 3, blob->GetBufferPointer(), blob->GetBufferSize(), &_fullscreenTriangleInputLayout)); - + _psPostProcessCopy = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\PostProcess.fx"), "PSCopy", "ps_5_0", nullptr, blob); _psPostProcessMonochrome = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\PostProcess.fx"), "PSMonochrome", "ps_5_0", nullptr, blob); _psPostProcessNegative = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\PostProcess.fx"), "PSNegative", "ps_5_0", nullptr, blob); _psPostProcessExclusion = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\PostProcess.fx"), "PSExclusion", "ps_5_0", nullptr, blob); _psPostProcessFinalPass = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\PostProcess.fx"), "PSFinalPass", "ps_5_0", nullptr, blob); + _psPostProcessLensFlare = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\PostProcess.fx"), "PSLensFlare", "ps_5_0", nullptr, blob); } void Renderer::CreateSSAONoiseTexture() diff --git a/TombEngine/Renderer/RendererPostProcess.cpp b/TombEngine/Renderer/RendererPostProcess.cpp index 5742f01c6..300322794 100644 --- a/TombEngine/Renderer/RendererPostProcess.cpp +++ b/TombEngine/Renderer/RendererPostProcess.cpp @@ -72,9 +72,22 @@ namespace TEN::Renderer BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); DrawTriangles(3, 0); - destinationRenderTarget = 0; - currentRenderTarget = 1; + destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; + currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; } + + // Lens flare + { + _context->ClearRenderTargetView(_postProcessRenderTarget[destinationRenderTarget].RenderTargetView.Get(), clearColor); + _context->OMSetRenderTargets(1, _postProcessRenderTarget[destinationRenderTarget].RenderTargetView.GetAddressOf(), nullptr); + + _context->PSSetShader(_psPostProcessLensFlare.Get(), nullptr, 0); + BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); + DrawTriangles(3, 0); + + destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; + currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; + } // Do the final pass _context->PSSetShader(_psPostProcessFinalPass.Get(), nullptr, 0); diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx index bc17733d0..193e9eadd 100644 --- a/TombEngine/Shaders/PostProcess.fx +++ b/TombEngine/Shaders/PostProcess.fx @@ -89,4 +89,78 @@ float4 PSFinalPass(PixelShaderInput input) : SV_TARGET output.xyz = output.xyz * Tint; return output; +} + +float3 LensFlare(float2 uv, float2 pos) +{ + float intensity = 1.5; + float2 main = uv-pos; + float2 uvd = uv*(length(uv)); + + float dist=length(main); dist = pow(dist,.1); + + + float f1 = max(0.01-pow(length(uv+1.2*pos),1.9),.0)*7.0; + + float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),.0)*00.1; + float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),.0)*00.08; + float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),.0)*00.06; + + float2 uvx = lerp(uv,uvd,-0.5); + + float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),.0)*6.0; + float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),.0)*5.0; + float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),.0)*3.0; + + uvx = lerp(uv,uvd,-.4); + + float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),.0)*2.0; + float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),.0)*2.0; + float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),.0)*2.0; + + uvx = lerp(uv,uvd,-0.5); + + float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),.0)*6.0; + float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),.0)*3.0; + float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),.0)*5.0; + + float3 c = float3(0,0,0); + + c.r+=f2+f4+f5+f6; c.g+=f22+f42+f52+f62; c.b+=f23+f43+f53+f63; + c = c*1.3 - float3(length(uvd)*.05,length(uvd)*.05,length(uvd)*.05); + + return c * intensity; +} + +float3 LensFlareColorCorrection(float3 color, float factor,float factor2) // color modifier +{ + float w = color.x+color.y+color.z; + return lerp(color,float3(w,w,w)*factor,w*factor2); +} + +float4 PSLensFlare(PixelShaderInput input) : SV_Target +{ + float4 color = ColorTexture.Sample(ColorSampler, input.UV); + + float4 position = input.PositionCopy; + + position.xyz /= position.w; + position.xyz = position.xyz * 0.5f + 0.5f; + position.y = 1.0f - position.y; + + float4 offset = float4(0,-5000,0, 1.0); + offset = mul(mul(offset, View), Projection); + offset.xyz /= offset.w; + + //offset.xyz /= offset.w; + // offset.xyz = offset.xyz * 0.5f + 0.5f; + // offset.y = 1.0f - offset.y; + + position = input.PositionCopy; + + + color.xyz += max(float3(0,0,0), float3(1.5,1.2,1.2)*float3(3,3,3)*LensFlare(position.xy, offset.xy)); + //color.xyz = LensFlareColorCorrection(color,.5,.1); + + return color; // float4(output, color.a); } \ No newline at end of file From 4bbf52abf55d4388124cdd0b5d70b4d3a6fcfc48 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 18 Apr 2024 15:58:47 +0200 Subject: [PATCH 082/410] Polished the lens flare pixel shader --- TombEngine/Shaders/PostProcess.fx | 84 ++++++++++++++++--------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx index 193e9eadd..2c090a27d 100644 --- a/TombEngine/Shaders/PostProcess.fx +++ b/TombEngine/Shaders/PostProcess.fx @@ -93,49 +93,52 @@ float4 PSFinalPass(PixelShaderInput input) : SV_TARGET float3 LensFlare(float2 uv, float2 pos) { - float intensity = 1.5; - float2 main = uv-pos; - float2 uvd = uv*(length(uv)); - - float dist=length(main); dist = pow(dist,.1); - - - float f1 = max(0.01-pow(length(uv+1.2*pos),1.9),.0)*7.0; + float intensity = 1.5f; + float2 main = uv - pos; + float2 uvd = uv * (length(uv)); - float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),.0)*00.1; - float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),.0)*00.08; - float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),.0)*00.06; - - float2 uvx = lerp(uv,uvd,-0.5); - - float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),.0)*6.0; - float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),.0)*5.0; - float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),.0)*3.0; - - uvx = lerp(uv,uvd,-.4); - - float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),.0)*2.0; - float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),.0)*2.0; - float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),.0)*2.0; - - uvx = lerp(uv,uvd,-0.5); - - float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),.0)*6.0; - float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),.0)*3.0; - float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),.0)*5.0; - - float3 c = float3(0,0,0); - - c.r+=f2+f4+f5+f6; c.g+=f22+f42+f52+f62; c.b+=f23+f43+f53+f63; - c = c*1.3 - float3(length(uvd)*.05,length(uvd)*.05,length(uvd)*.05); + float dist = length(main); + dist = pow(dist, 0.1f); + + float f1 = max(0.01f - pow(length(uv + 1.2f * pos), 1.9f), 0.0f) * 7.0f; + + float f2 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.8f * pos), 2.0f)), 0.0f) * 00.1f; + float f22 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.85f * pos), 2.0f)), 0.0f) * 00.08f; + float f23 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.9f * pos), 2.0f)), 0.0f) * 00.06f; + + float2 uvx = lerp(uv, uvd, -0.5f); + + float f4 = max(0.01f - pow(length(uvx + 0.4f * pos), 2.4f), 0.0f) * 6.0f; + float f42 = max(0.01f - pow(length(uvx + 0.45f * pos), 2.4f), 0.0f) * 5.0f; + float f43 = max(0.01f - pow(length(uvx + 0.5f * pos), 2.4f), 0.0f) * 3.0f; + + uvx = lerp(uv, uvd, -0.4f); + + float f5 = max(0.01f - pow(length(uvx + 0.2f * pos), 5.5f), 0.0f) * 2.0f; + float f52 = max(0.01f - pow(length(uvx + 0.4f * pos), 5.5f), 0.0f) * 2.0f; + float f53 = max(0.01f - pow(length(uvx + 0.6f * pos), 5.5f), 0.0f) * 2.0f; + + uvx = lerp(uv, uvd, -0.5f); + + float f6 = max(0.01f - pow(length(uvx - 0.3f * pos), 1.6f), 0.0f) * 6.0f; + float f62 = max(0.01f - pow(length(uvx - 0.325f * pos), 1.6f), 0.0f) * 3.0f; + float f63 = max(0.01f - pow(length(uvx - 0.35f * pos), 1.6f), 0.0f) * 5.0f; + + float3 c = float3(0.0f, 0.0f, 0.0f); + + c.r += f2 + f4 + f5 + f6; + c.g += f22 + f42 + f52 + f62; + c.b += f23 + f43 + f53 + f63; + c = c * 1.3f - float3(length(uvd) * 0.05f, length(uvd) * 0.05f, length(uvd) * 0.05f); + return c * intensity; } -float3 LensFlareColorCorrection(float3 color, float factor,float factor2) // color modifier +float3 LensFlareColorCorrection(float3 color, float factor,float factor2) { - float w = color.x+color.y+color.z; - return lerp(color,float3(w,w,w)*factor,w*factor2); + float w = color.x + color.y + color.z; + return lerp(color, float3(w, w, w) * factor, w * factor2); } float4 PSLensFlare(PixelShaderInput input) : SV_Target @@ -159,8 +162,9 @@ float4 PSLensFlare(PixelShaderInput input) : SV_Target position = input.PositionCopy; - color.xyz += max(float3(0,0,0), float3(1.5,1.2,1.2)*float3(3,3,3)*LensFlare(position.xy, offset.xy)); - //color.xyz = LensFlareColorCorrection(color,.5,.1); + float3 lensFlareColor = max(float3(0.0f, 0.0f, 0.0f), float3(4.5f, 3.6f, 3.6f) * LensFlare(position.xy, offset.xy)); + lensFlareColor = LensFlareColorCorrection(lensFlareColor, 0.5f, 0.1f); + color.xyz += lensFlareColor; - return color; // float4(output, color.a); + return color; } \ No newline at end of file From 7d66d49742fc3bb1d5d5ae6142d22c2a6050224f Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 18 Apr 2024 16:58:07 +0200 Subject: [PATCH 083/410] Lens flares set by code and not hardcoded in shader --- .../ConstantBuffers/PostProcessBuffer.h | 10 +++++++ TombEngine/Renderer/RendererPostProcess.cpp | 7 ++++- .../Renderer/Structures/RendererLensFlare.h | 14 ++++++++++ TombEngine/Shaders/CBPostProcess.hlsli | 10 +++++++ TombEngine/Shaders/PostProcess.fx | 27 ++++++++----------- TombEngine/TombEngine.vcxproj | 1 + 6 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 TombEngine/Renderer/Structures/RendererLensFlare.h diff --git a/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h b/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h index e0fc6821f..bd86c56f4 100644 --- a/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h +++ b/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h @@ -4,6 +4,12 @@ namespace TEN::Renderer::ConstantBuffers { using namespace DirectX::SimpleMath; + struct alignas(16) ShaderLensFlare + { + Vector3 Position; + float Padding; + }; + struct alignas(16) CPostProcessBuffer { float CinematicBarsHeight; @@ -15,5 +21,9 @@ namespace TEN::Renderer::ConstantBuffers Vector3 Tint; //-- Vector4 SSAOKernel[64]; + //-- + ShaderLensFlare LensFlares[4]; + //-- + int NumLensFlares; }; } \ No newline at end of file diff --git a/TombEngine/Renderer/RendererPostProcess.cpp b/TombEngine/Renderer/RendererPostProcess.cpp index 300322794..99867f4b7 100644 --- a/TombEngine/Renderer/RendererPostProcess.cpp +++ b/TombEngine/Renderer/RendererPostProcess.cpp @@ -70,7 +70,7 @@ namespace TEN::Renderer } BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); - DrawTriangles(3, 0); + DrawTriangles(3, 0); destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; @@ -82,6 +82,11 @@ namespace TEN::Renderer _context->OMSetRenderTargets(1, _postProcessRenderTarget[destinationRenderTarget].RenderTargetView.GetAddressOf(), nullptr); _context->PSSetShader(_psPostProcessLensFlare.Get(), nullptr, 0); + + _stPostProcessBuffer.LensFlares[0].Position = Vector3(0, -10000, 0); + _stPostProcessBuffer.NumLensFlares = 1; + _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get()); + BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); DrawTriangles(3, 0); diff --git a/TombEngine/Renderer/Structures/RendererLensFlare.h b/TombEngine/Renderer/Structures/RendererLensFlare.h new file mode 100644 index 000000000..0385700bb --- /dev/null +++ b/TombEngine/Renderer/Structures/RendererLensFlare.h @@ -0,0 +1,14 @@ +#pragma once +#include +#include "Renderer/RendererEnums.h" + +namespace TEN::Renderer::Structures +{ + using namespace DirectX::SimpleMath; + + struct RendererLensFlare + { + Vector3 Position; + float Padding; + }; +} \ No newline at end of file diff --git a/TombEngine/Shaders/CBPostProcess.hlsli b/TombEngine/Shaders/CBPostProcess.hlsli index a4ab6cd8b..4d292c5aa 100644 --- a/TombEngine/Shaders/CBPostProcess.hlsli +++ b/TombEngine/Shaders/CBPostProcess.hlsli @@ -1,5 +1,11 @@ #include "./Math.hlsli" +struct ShaderLensFlare +{ + float3 Position; + float Padding; +}; + cbuffer CBPostProcess : register(b7) { float CinematicBarsHeight; @@ -11,4 +17,8 @@ cbuffer CBPostProcess : register(b7) float3 Tint; //-- float4 SSAOKernel[64]; + //-- + ShaderLensFlare LensFlares[4]; + //-- + int NumLensFlares; }; \ No newline at end of file diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx index 2c090a27d..1fa91fb39 100644 --- a/TombEngine/Shaders/PostProcess.fx +++ b/TombEngine/Shaders/PostProcess.fx @@ -146,25 +146,20 @@ float4 PSLensFlare(PixelShaderInput input) : SV_Target float4 color = ColorTexture.Sample(ColorSampler, input.UV); float4 position = input.PositionCopy; + float3 totalLensFlareColor = float3(0.0f, 0.0f, 0.0f); - position.xyz /= position.w; - position.xyz = position.xyz * 0.5f + 0.5f; - position.y = 1.0f - position.y; + for (int i = 0; i < NumLensFlares; i++) + { + float4 lensFlarePosition = float4(LensFlares[i].Position, 1.0f); + lensFlarePosition = mul(mul(lensFlarePosition, View), Projection); + lensFlarePosition.xyz /= lensFlarePosition.w; - float4 offset = float4(0,-5000,0, 1.0); - offset = mul(mul(offset, View), Projection); - offset.xyz /= offset.w; + float3 lensFlareColor = max(float3(0.0f, 0.0f, 0.0f), float3(4.5f, 3.6f, 3.6f) * LensFlare(position.xy, lensFlarePosition.xy)); + lensFlareColor = LensFlareColorCorrection(lensFlareColor, 0.5f, 0.1f); + totalLensFlareColor += lensFlareColor; + } - //offset.xyz /= offset.w; - // offset.xyz = offset.xyz * 0.5f + 0.5f; - // offset.y = 1.0f - offset.y; + color.xyz += totalLensFlareColor; - position = input.PositionCopy; - - - float3 lensFlareColor = max(float3(0.0f, 0.0f, 0.0f), float3(4.5f, 3.6f, 3.6f) * LensFlare(position.xy, offset.xy)); - lensFlareColor = LensFlareColorCorrection(lensFlareColor, 0.5f, 0.1f); - color.xyz += lensFlareColor; - return color; } \ No newline at end of file diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 32b5b12f6..2615d05d2 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -732,6 +732,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From 374697f38b5be933f3ee6da9a958bb225957cbea Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 20 Apr 2024 05:41:01 +0200 Subject: [PATCH 084/410] WIP ID_LENS_FLARE objects --- TombEngine/Objects/Effects/lens_flare.cpp | 28 +++++++++++++++++++++++ TombEngine/Objects/Effects/lens_flare.h | 20 ++++++++++++++++ TombEngine/TombEngine.vcxproj | 2 ++ 3 files changed, 50 insertions(+) create mode 100644 TombEngine/Objects/Effects/lens_flare.cpp create mode 100644 TombEngine/Objects/Effects/lens_flare.h diff --git a/TombEngine/Objects/Effects/lens_flare.cpp b/TombEngine/Objects/Effects/lens_flare.cpp new file mode 100644 index 000000000..e03d3c448 --- /dev/null +++ b/TombEngine/Objects/Effects/lens_flare.cpp @@ -0,0 +1,28 @@ +#include "framework.h" +#include "Objects/Effects/lens_flare.h" +#include "Specific/level.h" + +namespace TEN::Entities::Effects +{ + std::vector LensFlares; + + void LensFlareControl(short itemNumber) + { + auto* item = &g_Level.Items[itemNumber]; + + if (TriggerActive(item)) + { + LensFlare lensFlare; + + lensFlare.Position = item->Pose.Position.ToVector3(); + lensFlare.RoomNumber = item->RoomNumber; + + LensFlares.push_back(lensFlare); + } + } + + void ClearLensFlares() + { + LensFlare.clear(); + } +} \ No newline at end of file diff --git a/TombEngine/Objects/Effects/lens_flare.h b/TombEngine/Objects/Effects/lens_flare.h new file mode 100644 index 000000000..3acaab5b7 --- /dev/null +++ b/TombEngine/Objects/Effects/lens_flare.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace TEN::Entities::Effects +{ + using namespace DirectX::SimpleMath; + + struct LensFlare + { + Vector3 Position; + short RoomNumber; + }; + + extern std::vector LensFlares; + + void LensFlareControl(short itemNumber); + void ClearLensFlares(); +} \ No newline at end of file diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 2615d05d2..44ef99dbf 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -441,6 +441,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -950,6 +951,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From 994dc69ce0ce62059827a265fef5d5d21db9e4f1 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 20 Apr 2024 06:30:00 +0200 Subject: [PATCH 085/410] Implemented ID_LENS_FARE objects --- TombEngine/Game/control/control.cpp | 3 ++ TombEngine/Objects/Effects/effect_objects.cpp | 8 ++++ TombEngine/Objects/Effects/lens_flare.cpp | 2 +- TombEngine/Objects/TR5/tr5_objects.cpp | 7 ---- TombEngine/Renderer/RenderView.cpp | 1 + TombEngine/Renderer/RenderView.h | 2 + TombEngine/Renderer/RendererFrame.cpp | 40 ++++++++++++++----- TombEngine/Renderer/RendererPostProcess.cpp | 11 +++-- 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 0f86ed4b4..b0a419461 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -60,6 +60,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" #include "Specific/winmain.h" +#include "Objects/Effects/lens_flare.h" using namespace std::chrono; using namespace TEN::Effects; @@ -87,6 +88,7 @@ using namespace TEN::Math; using namespace TEN::Renderer; using namespace TEN::Traps::TR5; using namespace TEN::Entities::Creatures::TR3; +using namespace TEN::Entities::Effects; int GameTimer = 0; int GlobalCounter = 0; @@ -140,6 +142,7 @@ GameStatus ControlPhase(int numFrames) ClearFires(); g_Renderer.ClearDynamicLights(); RegeneratePickups(); + ClearLensFlares(); numFrames = std::clamp(numFrames, 0, 10); diff --git a/TombEngine/Objects/Effects/effect_objects.cpp b/TombEngine/Objects/Effects/effect_objects.cpp index 6014c7c5b..1449d8ed2 100644 --- a/TombEngine/Objects/Effects/effect_objects.cpp +++ b/TombEngine/Objects/Effects/effect_objects.cpp @@ -4,6 +4,7 @@ #include "Game/Setup.h" #include "Objects/Effects/flame_emitters.h" #include "Objects/Effects/enemy_missile.h" +#include "Objects/Effects/lens_flare.h" using namespace TEN::Entities::Effects; @@ -54,4 +55,11 @@ void InitializeEffectsObjects() obj->collision = nullptr; obj->control = ControlEnemyMissile; } + + obj = &Objects[ID_LENS_FLARE]; + if (obj->loaded) + { + obj->control = LensFlareControl; + } + } \ No newline at end of file diff --git a/TombEngine/Objects/Effects/lens_flare.cpp b/TombEngine/Objects/Effects/lens_flare.cpp index e03d3c448..fb60940b5 100644 --- a/TombEngine/Objects/Effects/lens_flare.cpp +++ b/TombEngine/Objects/Effects/lens_flare.cpp @@ -23,6 +23,6 @@ namespace TEN::Entities::Effects void ClearLensFlares() { - LensFlare.clear(); + LensFlares.clear(); } } \ No newline at end of file diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp index 686c9d28c..9a31f90c7 100644 --- a/TombEngine/Objects/TR5/tr5_objects.cpp +++ b/TombEngine/Objects/TR5/tr5_objects.cpp @@ -818,13 +818,6 @@ static void StartObject(ObjectInfo *obj) obj->usingDrawAnimatingItem = false; } - obj = &Objects[ID_LENS_FLARE]; - if (obj->loaded) - { - //obj->drawRoutine = DrawLensFlare; - - } - obj = &Objects[ID_WATERFALLSS1]; if (obj->loaded) { diff --git a/TombEngine/Renderer/RenderView.cpp b/TombEngine/Renderer/RenderView.cpp index 3c6d416b3..6558d062c 100644 --- a/TombEngine/Renderer/RenderView.cpp +++ b/TombEngine/Renderer/RenderView.cpp @@ -51,6 +51,7 @@ namespace TEN::Renderer DisplaySpritesToDraw.clear(); SortedStaticsToDraw.clear(); FogBulbsToDraw.clear(); + LensFlaresToDraw.clear(); } RenderViewCamera::RenderViewCamera(CAMERA_INFO* cam, float roll, float fov, float n, float f, int w, int h) diff --git a/TombEngine/Renderer/RenderView.h b/TombEngine/Renderer/RenderView.h index 5260b7626..b028b4788 100644 --- a/TombEngine/Renderer/RenderView.h +++ b/TombEngine/Renderer/RenderView.h @@ -14,6 +14,7 @@ #include "Renderer/Structures/RendererRoom.h" #include "Renderer/Structures/RendererSortableObject.h" #include "Renderer/Structures/RendererSpriteToDraw.h" +#include "Renderer/Structures/RendererLensFlare.h" namespace TEN::Renderer { @@ -51,6 +52,7 @@ namespace TEN::Renderer std::vector DisplaySpritesToDraw = {}; std::map> SortedStaticsToDraw = {}; std::vector TransparentObjectsToDraw = {}; + std::vector LensFlaresToDraw = {}; RenderView(CAMERA_INFO* cam, float roll, float fov, float nearPlane, float farPlane, int w, int h); RenderView(const Vector3& pos, const Vector3& dir, const Vector3& up, int w, int h, int room, float nearPlane, float farPlane, float fov); diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index e5389d24b..1b9956cc1 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -13,8 +13,10 @@ #include "Math/Math.h" #include "Specific/level.h" #include "Renderer/RenderView.h" +#include "Objects/Effects/lens_flare.h" using namespace TEN::Math; +using namespace TEN::Entities::Effects; namespace TEN::Renderer { @@ -27,10 +29,10 @@ namespace TEN::Renderer _visitedRoomsStack.clear(); for (int i = 0; i < g_Level.Rooms.size(); i++) - { + { auto& room = _rooms[i]; - - room.ItemsToDraw.clear(); + + room.ItemsToDraw.clear(); room.EffectsToDraw.clear(); room.StaticsToDraw.clear(); room.LightsToDraw.clear(); @@ -47,7 +49,7 @@ namespace TEN::Renderer GetVisibleRooms(NO_VALUE, renderView.Camera.RoomNumber, VIEW_PORT, false, 0, onlyRooms, renderView); - _invalidateCache = false; + _invalidateCache = false; // Prepare real DX scissor test rectangle. for (auto* roomPtr : renderView.RoomsToDraw) @@ -56,17 +58,17 @@ namespace TEN::Renderer roomPtr->ClipBounds.Bottom = (1.0f - roomPtr->ViewPort.y) * _screenHeight * 0.5f; roomPtr->ClipBounds.Right = (roomPtr->ViewPort.z + 1.0f) * _screenWidth * 0.5f; roomPtr->ClipBounds.Top = (1.0f - roomPtr->ViewPort.w) * _screenHeight * 0.5f; - } + } // Collect fog bulbs. std::vector tempFogBulbs; tempFogBulbs.reserve(MAX_FOG_BULBS_DRAW); - for (auto& room : _rooms) + for (auto& room : _rooms) { if (!g_Level.Rooms[room.RoomNumber].Active()) continue; - + for (const auto& light : room.Lights) { if (light.Type != LightType::FogBulb) @@ -76,7 +78,7 @@ namespace TEN::Renderer if (renderView.Camera.Frustum.SphereInFrustum(light.Position, light.Out * 1.2f)) { RendererFogBulb bulb; - + bulb.Position = light.Position; bulb.Density = light.Intensity; bulb.Color = light.Color; @@ -88,7 +90,7 @@ namespace TEN::Renderer } } } - + // Sort fog bulbs. std::sort( tempFogBulbs.begin(), @@ -100,6 +102,26 @@ namespace TEN::Renderer for (int i = 0; i < std::min(MAX_FOG_BULBS_DRAW, (int)tempFogBulbs.size()); i++) renderView.FogBulbsToDraw.push_back(tempFogBulbs[i]); + + // Collect lens flares + for (auto lensFlare : LensFlares) + { + if (Vector3::Distance(lensFlare.Position, renderView.Camera.WorldPosition) < BLOCK(32)) + { + Vector3 lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; + Vector3 cameraDirection = renderView.Camera.WorldDirection; + + lensFlareToCamera.Normalize(); + cameraDirection.Normalize(); + + if (lensFlareToCamera.Dot(cameraDirection) >= 0.0f) + { + RendererLensFlare lensFlareToDraw; + lensFlareToDraw.Position = lensFlare.Position; + renderView.LensFlaresToDraw.push_back(lensFlareToDraw); + } + } + } } bool Renderer::CheckPortal(short parentRoomNumber, RendererDoor* door, Vector4 viewPort, Vector4* clipPort, RenderView& renderView) diff --git a/TombEngine/Renderer/RendererPostProcess.cpp b/TombEngine/Renderer/RendererPostProcess.cpp index 99867f4b7..c53787082 100644 --- a/TombEngine/Renderer/RendererPostProcess.cpp +++ b/TombEngine/Renderer/RendererPostProcess.cpp @@ -83,16 +83,19 @@ namespace TEN::Renderer _context->PSSetShader(_psPostProcessLensFlare.Get(), nullptr, 0); - _stPostProcessBuffer.LensFlares[0].Position = Vector3(0, -10000, 0); - _stPostProcessBuffer.NumLensFlares = 1; - _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get()); + for (int i = 0; i < view.LensFlaresToDraw.size(); i++) + { + _stPostProcessBuffer.LensFlares[i].Position = view.LensFlaresToDraw[i].Position; + } + _stPostProcessBuffer.NumLensFlares = (int)view.LensFlaresToDraw.size(); + _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get()); BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); DrawTriangles(3, 0); destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; - } + } // Do the final pass _context->PSSetShader(_psPostProcessFinalPass.Get(), nullptr, 0); From e73bb7b92b7740e68af43b40b00712134540bece Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 20 Apr 2024 06:44:12 +0200 Subject: [PATCH 086/410] Increased max lens flares to 8; Choose the nearest 8 ones; Make the code in post process optional only if some lens flares are available; Max distance of lens flare 20 blocks and they must be in the same room of camera; --- .../ConstantBuffers/PostProcessBuffer.h | 3 ++- TombEngine/Renderer/RendererEnums.h | 1 + TombEngine/Renderer/RendererFrame.cpp | 22 ++++++++++++++++--- TombEngine/Renderer/RendererPostProcess.cpp | 13 ++++++----- .../Renderer/Structures/RendererLensFlare.h | 2 +- TombEngine/Shaders/CBPostProcess.hlsli | 2 +- 6 files changed, 31 insertions(+), 12 deletions(-) diff --git a/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h b/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h index bd86c56f4..130136463 100644 --- a/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h +++ b/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h @@ -1,4 +1,5 @@ #include +#include "Renderer/RendererEnums.h" namespace TEN::Renderer::ConstantBuffers { @@ -22,7 +23,7 @@ namespace TEN::Renderer::ConstantBuffers //-- Vector4 SSAOKernel[64]; //-- - ShaderLensFlare LensFlares[4]; + ShaderLensFlare LensFlares[MAX_LENS_FLARES_DRAW]; //-- int NumLensFlares; }; diff --git a/TombEngine/Renderer/RendererEnums.h b/TombEngine/Renderer/RendererEnums.h index 5d46489ce..69fa97d1e 100644 --- a/TombEngine/Renderer/RendererEnums.h +++ b/TombEngine/Renderer/RendererEnums.h @@ -64,6 +64,7 @@ constexpr auto MAX_ITEMS_DRAW = 128; constexpr auto MAX_LIGHTS_DRAW = 48; constexpr auto MAX_FOG_BULBS_DRAW = 32; constexpr auto MAX_SPRITES_DRAW = 512; +constexpr auto MAX_LENS_FLARES_DRAW = 8; constexpr auto ROOM_AMBIENT_MAP_SIZE = 32; constexpr auto MAX_ROOM_AMBIENT_MAPS = 10; diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 1b9956cc1..7169c1785 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -91,7 +91,6 @@ namespace TEN::Renderer } } - // Sort fog bulbs. std::sort( tempFogBulbs.begin(), tempFogBulbs.end(), @@ -104,9 +103,14 @@ namespace TEN::Renderer renderView.FogBulbsToDraw.push_back(tempFogBulbs[i]); // Collect lens flares + std::vector tempLensFlares; + tempLensFlares.reserve(MAX_LENS_FLARES_DRAW); + for (auto lensFlare : LensFlares) { - if (Vector3::Distance(lensFlare.Position, renderView.Camera.WorldPosition) < BLOCK(32)) + float distance = Vector3::Distance(lensFlare.Position, renderView.Camera.WorldPosition); + + if (lensFlare.RoomNumber == Camera.pos.RoomNumber && distance < BLOCK(20)) { Vector3 lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; Vector3 cameraDirection = renderView.Camera.WorldDirection; @@ -118,10 +122,22 @@ namespace TEN::Renderer { RendererLensFlare lensFlareToDraw; lensFlareToDraw.Position = lensFlare.Position; - renderView.LensFlaresToDraw.push_back(lensFlareToDraw); + lensFlareToDraw.Distance = distance; + tempLensFlares.push_back(lensFlareToDraw); } } } + + std::sort( + tempLensFlares.begin(), + tempLensFlares.end(), + [](const RendererLensFlare& lensFlare0, const RendererLensFlare& lensFlare1) + { + return lensFlare0.Distance < lensFlare1.Distance; + }); + + for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++) + renderView.LensFlaresToDraw.push_back(tempLensFlares[i]); } bool Renderer::CheckPortal(short parentRoomNumber, RendererDoor* door, Vector4 viewPort, Vector4* clipPort, RenderView& renderView) diff --git a/TombEngine/Renderer/RendererPostProcess.cpp b/TombEngine/Renderer/RendererPostProcess.cpp index c53787082..3393dfacc 100644 --- a/TombEngine/Renderer/RendererPostProcess.cpp +++ b/TombEngine/Renderer/RendererPostProcess.cpp @@ -50,7 +50,7 @@ namespace TEN::Renderer { _context->ClearRenderTargetView(_postProcessRenderTarget[destinationRenderTarget].RenderTargetView.Get(), clearColor); _context->OMSetRenderTargets(1, _postProcessRenderTarget[destinationRenderTarget].RenderTargetView.GetAddressOf(), nullptr); - + switch (_postProcessMode) { case PostProcessMode::Monochrome: @@ -64,19 +64,20 @@ namespace TEN::Renderer case PostProcessMode::Exclusion: _context->PSSetShader(_psPostProcessExclusion.Get(), nullptr, 0); break; - + default: return; } BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); - DrawTriangles(3, 0); + DrawTriangles(3, 0); destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; - } - - // Lens flare + } + + // Lens flares + if (view.LensFlaresToDraw.size() > 0) { _context->ClearRenderTargetView(_postProcessRenderTarget[destinationRenderTarget].RenderTargetView.Get(), clearColor); _context->OMSetRenderTargets(1, _postProcessRenderTarget[destinationRenderTarget].RenderTargetView.GetAddressOf(), nullptr); diff --git a/TombEngine/Renderer/Structures/RendererLensFlare.h b/TombEngine/Renderer/Structures/RendererLensFlare.h index 0385700bb..4acb56fcd 100644 --- a/TombEngine/Renderer/Structures/RendererLensFlare.h +++ b/TombEngine/Renderer/Structures/RendererLensFlare.h @@ -9,6 +9,6 @@ namespace TEN::Renderer::Structures struct RendererLensFlare { Vector3 Position; - float Padding; + float Distance; }; } \ No newline at end of file diff --git a/TombEngine/Shaders/CBPostProcess.hlsli b/TombEngine/Shaders/CBPostProcess.hlsli index 4d292c5aa..dfe6f2514 100644 --- a/TombEngine/Shaders/CBPostProcess.hlsli +++ b/TombEngine/Shaders/CBPostProcess.hlsli @@ -18,7 +18,7 @@ cbuffer CBPostProcess : register(b7) //-- float4 SSAOKernel[64]; //-- - ShaderLensFlare LensFlares[4]; + ShaderLensFlare LensFlares[8]; //-- int NumLensFlares; }; \ No newline at end of file From a7dcba12cefcd4a0e3fd800e1a8f9adf55aa403e Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 21 Apr 2024 19:39:05 +0200 Subject: [PATCH 087/410] Fix directional flame emitters --- TombEngine/Game/effects/effects.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index fd825b073..4cdc79ac4 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -939,14 +939,17 @@ void TriggerSuperJetFlame(ItemInfo* item, int yvel, int deadly) float xAngle = item->Pose.Orientation.x; float yAngle = item->Pose.Orientation.y; + + Vector3 dir; + dir.x = phd_cos(xAngle) * phd_sin(yAngle); + dir.y = phd_sin(xAngle); + dir.z = phd_cos(xAngle) * phd_cos(yAngle); - float xDir = phd_cos(yAngle) * phd_cos(xAngle); - float zDir = phd_sin(yAngle) * phd_cos(xAngle); - float yDir = phd_sin(xAngle); + dir.Normalize(); - sptr->xVel += xDir * (size - (size >> 2)); - sptr->yVel += yDir * (size - (size >> 2)); - sptr->zVel += zDir * (size - (size >> 2)); + sptr->xVel += dir.x * (size - (size >> 2)); + sptr->yVel -= dir.y * (size - (size >> 2)); + sptr->zVel += dir.z * (size - (size >> 2)); } } From 29ebdf452fa42d53add505e9b0d4ccf800f46ab2 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 22 Apr 2024 20:58:46 +0200 Subject: [PATCH 088/410] Update effects.cpp --- TombEngine/Game/effects/effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 4cdc79ac4..1a67640be 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -937,7 +937,7 @@ void TriggerSuperJetFlame(ItemInfo* item, int yvel, int deadly) sptr->xVel = (GetRandomControl() & 0xFF) - 128; sptr->zVel = (GetRandomControl() & 0xFF) - 128; - float xAngle = item->Pose.Orientation.x; + float xAngle = item->Pose.Orientation.x + ANGLE(180); // Nullmesh is rotated 180 degrees in editor float yAngle = item->Pose.Orientation.y; Vector3 dir; From c55b25239372709d18d14ce707b3f4f2eee391df Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 23 Apr 2024 20:40:51 +0200 Subject: [PATCH 089/410] Global lens flare; Starry night simulation; --- TombEngine/Game/control/control.cpp | 1 + TombEngine/Game/effects/weather.cpp | 124 ++++++++++++ TombEngine/Game/effects/weather.h | 37 ++++ TombEngine/Objects/Effects/lens_flare.cpp | 86 +++++++- TombEngine/Objects/Effects/lens_flare.h | 3 + TombEngine/Objects/objectslist.h | 6 +- TombEngine/Renderer/Renderer.h | 2 + TombEngine/Renderer/RendererDraw.cpp | 190 +++++++++++++++++- TombEngine/Renderer/RendererFrame.cpp | 41 ++-- .../Renderer/Structures/RendererLensFlare.h | 2 + TombEngine/Renderer/Structures/RendererStar.h | 17 ++ TombEngine/TombEngine.vcxproj | 1 + 12 files changed, 486 insertions(+), 24 deletions(-) create mode 100644 TombEngine/Renderer/Structures/RendererStar.h diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index b0a419461..d3fa54462 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -243,6 +243,7 @@ GameStatus ControlPhase(int numFrames) UpdateBeetleSwarm(); UpdateLocusts(); UpdateUnderwaterBloodParticles(); + SetupGlobalLensFlare(180.0f, 30.0f); // Update HUD. g_Hud.Update(*LaraItem); diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index 16f24c5b0..b5b4667ad 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -39,6 +39,12 @@ namespace TEN::Effects::Environment constexpr auto DUST_LIFE = 40; constexpr auto DUST_SPAWN_RADIUS = (10 * 1024); + constexpr auto METEOR_PARTICLES_MAX_COUNT = 10; + constexpr auto METEOR_PARTICLES_MAX_LIFE = 150; + constexpr auto METEOR_PARTICLES_SPEED = 32.0f; + constexpr auto METEOR_PARTICLES_SPAWN_DENSITY = 4; + constexpr auto METEOR_PARTICLES_FADE_TIME = 30; + EnvironmentController Weather; float WeatherParticle::Transparency() const @@ -72,8 +78,11 @@ namespace TEN::Effects::Environment UpdateWind(level); UpdateFlash(level); UpdateWeather(level); + UpdateStarfield(level); + SpawnWeatherParticles(level); SpawnDustParticles(level); + SpawnMeteorParticles(level); } void EnvironmentController::Clear() @@ -93,6 +102,10 @@ namespace TEN::Effects::Environment // Clear weather Particles.clear(); + + // Clear starfield + ResetStarField = true; + Meteors.clear(); } void EnvironmentController::Flash(int r, int g, int b, float speed) @@ -221,6 +234,74 @@ namespace TEN::Effects::Environment FlashColorBase = Vector3::Zero; } + void EnvironmentController::UpdateStarfield(ScriptInterfaceLevel* level) + { + if (ResetStarField) + { + Stars.clear(); + Stars.reserve(StarsCount); + + for (int i = 0; i < StarsCount; i++) + { + Vector3 starDirection = Random::GenerateDirectionInCone(-Vector3::UnitY, 70.0f); + starDirection.Normalize(); + + StarParticle star; + star.Direction = starDirection; + star.Color = Vector3( + Random::GenerateFloat(0.6f, 1.0f), + Random::GenerateFloat(0.6f, 1.0f), + Random::GenerateFloat(0.6f, 1.0f) + ); + star.Scale = Random::GenerateFloat(0.5f, 1.5f); + + float cosine = Vector3::UnitY.Dot(starDirection); + float maxCosine = cos(DEG_TO_RAD(50)); + float minCosine = cos(DEG_TO_RAD(70)); + + if (cosine >= minCosine && cosine <= maxCosine) + { + star.Extinction = (cosine - minCosine) / (maxCosine - minCosine); + } + else + { + star.Extinction = 1.0f; + } + + Stars.push_back(star); + } + + ResetStarField = false; + } + + for (auto& s : Stars) + { + s.Blinking = Random::GenerateFloat(0.5f, 1.0f); + } + + for (auto& m : Meteors) + { + //p.StoreInterpolationData(); + + m.Life--; + + if (m.Life <= 0) + { + m.Active = false; + continue; + } + + if (m.Life <= METEOR_PARTICLES_FADE_TIME) + m.Fade = m.Life / (float)METEOR_PARTICLES_FADE_TIME; + else if (m.Life >= METEOR_PARTICLES_MAX_LIFE - METEOR_PARTICLES_FADE_TIME) + m.Fade = (METEOR_PARTICLES_MAX_LIFE - m.Life) / (float)METEOR_PARTICLES_FADE_TIME; + else + m.Fade = 1.0f; + + m.Position += m.Direction * METEOR_PARTICLES_SPEED; + } + } + void EnvironmentController::UpdateWeather(ScriptInterfaceLevel* level) { for (auto& p : Particles) @@ -519,4 +600,47 @@ namespace TEN::Effects::Environment } } } + + void EnvironmentController::SpawnMeteorParticles(ScriptInterfaceLevel* level) + { + // Clean up dead particles + if (Meteors.size() > 0) + Meteors.erase(std::remove_if(Meteors.begin(), Meteors.end(), [](const MeteorParticle& part) { return !part.Active; }), Meteors.end()); + + //if (level->GetWeatherType() == WeatherType::None || level->GetWeatherStrength() == 0.0f) + // return; + + int newParticlesCount = 0; + int density = METEOR_PARTICLES_SPAWN_DENSITY; + + if (density > 0.0f /* && level->GetWeatherType() != WeatherType::None */) + { + while (Meteors.size() < METEOR_PARTICLES_MAX_COUNT) + { + if (newParticlesCount > density) + break; + + newParticlesCount++; + + auto part = MeteorParticle(); + + part.Active = true; + part.Life = METEOR_PARTICLES_MAX_LIFE; + part.StartPosition = part.Position = Random::GenerateDirectionInCone(-Vector3::UnitY, 40.0f) * BLOCK(1.5f); + part.Fade = 0.0f; + part.Color = Vector3( + Random::GenerateFloat(0.6f, 1.0f), + Random::GenerateFloat(0.6f, 1.0f), + Random::GenerateFloat(0.6f, 1.0f) + ); + + Vector2 horizontalDirection = Random::GenerateDirection2D(); + part.Direction = Random::GenerateDirectionInCone(Vector3(horizontalDirection.x, 0, horizontalDirection.y), 10.0f); + if (part.Direction.y < 0.0f) + part.Direction.y = -part.Direction.y; + + Meteors.push_back(part); + } + } + } } diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index 214cd1ff5..0efc267b7 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -2,9 +2,33 @@ #include #include "Scripting/Include/ScriptInterfaceLevel.h" #include "Math/Math.h" +#include "Objects/Effects/lens_flare.h" + +using namespace TEN::Entities::Effects; namespace TEN::Effects::Environment { + struct StarParticle + { + Vector3 Position = Vector3::Zero; + Vector3 Direction = Vector3::Zero; + Vector3 Color = Vector3::Zero; + float Extinction = 1.0f; + float Scale = 1.0f; + float Blinking = 1.0f; + }; + + struct MeteorParticle + { + Vector3 Position = Vector3::Zero; + Vector3 Direction = Vector3::Zero; + Vector3 StartPosition = Vector3::Zero; + Vector3 Color = Vector3::Zero; + float Life; + bool Active; + float Fade; + }; + struct WeatherParticle { WeatherType Type = WeatherType::None; @@ -52,6 +76,8 @@ namespace TEN::Effects::Environment void Clear(); const std::vector& GetParticles() const { return Particles; } + const std::vector& GetStars() const { return Stars; } + const std::vector& GetMeteors() { return Meteors; } private: // Weather @@ -80,6 +106,16 @@ namespace TEN::Effects::Environment byte StormSkyColor = 1; byte StormSkyColor2 = 1; + // Starfield + int StarsCount = 3000; + std::vector Stars; + std::vector Meteors; + bool ResetStarField = true; + + // Lens flare + LensFlare GlobalLensFlare; + + void UpdateStarfield(ScriptInterfaceLevel* level); void UpdateSky(ScriptInterfaceLevel* level); void UpdateStorm(ScriptInterfaceLevel* level); void UpdateWind(ScriptInterfaceLevel* level); @@ -89,6 +125,7 @@ namespace TEN::Effects::Environment void SpawnDustParticles(ScriptInterfaceLevel* level); void SpawnWeatherParticles(ScriptInterfaceLevel* level); + void SpawnMeteorParticles(ScriptInterfaceLevel* level); }; extern EnvironmentController Weather; diff --git a/TombEngine/Objects/Effects/lens_flare.cpp b/TombEngine/Objects/Effects/lens_flare.cpp index fb60940b5..fd06249b8 100644 --- a/TombEngine/Objects/Effects/lens_flare.cpp +++ b/TombEngine/Objects/Effects/lens_flare.cpp @@ -1,6 +1,8 @@ #include "framework.h" #include "Objects/Effects/lens_flare.h" #include "Specific/level.h" +#include "Game/camera.h" +#include "Game/control/los.h" namespace TEN::Entities::Effects { @@ -12,12 +14,7 @@ namespace TEN::Entities::Effects if (TriggerActive(item)) { - LensFlare lensFlare; - - lensFlare.Position = item->Pose.Position.ToVector3(); - lensFlare.RoomNumber = item->RoomNumber; - - LensFlares.push_back(lensFlare); + SetupLensFlare(item->Pose.Position.ToVector3(), item->RoomNumber, false); } } @@ -25,4 +22,81 @@ namespace TEN::Entities::Effects { LensFlares.clear(); } + + void SetupGlobalLensFlare(float yaw, float pitch) + { + Vector3 position = Camera.pos.ToVector3(); + Matrix rotation = Matrix::CreateFromYawPitchRoll(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), 0); + position += Vector3::Transform(Vector3(0, 0, BLOCK(256)), rotation); + SetupLensFlare(position, NO_VALUE, true); + } + + void SetupLensFlare(Vector3 position, short roomNumber, bool sun) + { + Vector3 lensFlarePosition; + + if (sun) + { + if (g_Level.Rooms[Camera.pos.RoomNumber].flags & ENV_FLAG_NO_LENSFLARE) + { + return; + } + + lensFlarePosition = position; + Vector3 delta = (lensFlarePosition - Camera.pos.ToVector3()) / 16.0f; + while (abs(delta.x) > BLOCK(200) || abs(delta.y) > BLOCK(200) || abs(delta.z) > BLOCK(200)) + { + lensFlarePosition -= delta; + } + + delta = (lensFlarePosition - Camera.pos.ToVector3()) / 16.0f; + while (abs(delta.x) > BLOCK(32) || abs(delta.y) > BLOCK(32) || abs(delta.z) > BLOCK(32)) + { + lensFlarePosition -= delta; + } + + delta = (lensFlarePosition - Camera.pos.ToVector3()) / 16.0f; + for (int i = 0; i < 16; i++) + { + short foundRoomNumber = IsRoomOutside(lensFlarePosition.x, lensFlarePosition.y, lensFlarePosition.z); + if (foundRoomNumber != NO_VALUE) + { + roomNumber = foundRoomNumber; + break; + } + lensFlarePosition -= delta; + } + } + else + { + if (Vector3::Distance(position, Camera.pos.ToVector3()) > BLOCK(32)) + { + return; + } + lensFlarePosition = position; + } + + bool flareVisible = false; + + if (roomNumber != NO_VALUE) + { + if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_NOT_NEAR_OUTSIDE || !sun) + { + GameVector source = { Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber }; + GameVector destination = { (int)lensFlarePosition.x, (int)lensFlarePosition.y, (int)lensFlarePosition.z, roomNumber }; + flareVisible = LOS(&source, &destination); + } + } + + if (!flareVisible && !sun) + { + return; + } + + LensFlare lensFlare; + lensFlare.Position = position; + lensFlare.RoomNumber = roomNumber; + lensFlare.Sun = sun; + LensFlares.push_back(lensFlare); + } } \ No newline at end of file diff --git a/TombEngine/Objects/Effects/lens_flare.h b/TombEngine/Objects/Effects/lens_flare.h index 3acaab5b7..0f0901338 100644 --- a/TombEngine/Objects/Effects/lens_flare.h +++ b/TombEngine/Objects/Effects/lens_flare.h @@ -11,10 +11,13 @@ namespace TEN::Entities::Effects { Vector3 Position; short RoomNumber; + bool Sun; }; extern std::vector LensFlares; void LensFlareControl(short itemNumber); void ClearLensFlares(); + void SetupLensFlare(Vector3 position, short roomNumber, bool global); + void SetupGlobalLensFlare(float yaw, float pitch); } \ No newline at end of file diff --git a/TombEngine/Objects/objectslist.h b/TombEngine/Objects/objectslist.h index f8f04a841..73f48b3b1 100644 --- a/TombEngine/Objects/objectslist.h +++ b/TombEngine/Objects/objectslist.h @@ -50,5 +50,9 @@ template std::enable_if_t _sortedPolygonsVertexBuffer; IndexBuffer _sortedPolygonsIndexBuffer; + // Used for variable framerate float _interpolationFactor = 0.0f; // Private functions diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 5bd6c0abe..2b04a3126 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -31,6 +31,7 @@ #include "Specific/level.h" #include "Specific/winmain.h" #include "Renderer/Structures/RendererSortableObject.h" +#include "Game/effects/weather.h" using namespace std::chrono; using namespace TEN::Effects::Hair; @@ -38,6 +39,7 @@ using namespace TEN::Entities::Creatures::TR3; using namespace TEN::Entities::Generic; using namespace TEN::Hud; using namespace TEN::Renderer::Structures; +using namespace TEN::Effects::Environment; extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; @@ -2819,19 +2821,151 @@ namespace TEN::Renderer _context->ClearDepthStencilView(depthTarget, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); + int starsCount = (int)Weather.GetStars().size(); + if (starsCount > 0) + { + SetDepthState(DepthState::Read); + SetBlendMode(BlendMode::Additive); + SetCullMode(CullMode::None); + + _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + _context->VSSetShader(_vsInstancedSprites.Get(), nullptr, 0); + _context->PSSetShader(_psInstancedSprites.Get(), nullptr, 0); + + // Set up vertex buffer and parameters. + UINT stride = sizeof(Vertex); + UINT offset = 0; + _context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); + + BindTexture(TextureRegister::ColorMap, _sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3].Texture, SamplerStateRegister::LinearClamp); + + int drawnStars = 0; + while (drawnStars < starsCount) + { + int starsToDraw = (starsCount - drawnStars) > 100 ? 100 : (starsCount - drawnStars); + int i = 0; + + for (int i = 0; i < starsToDraw; i++) + { + auto& s = Weather.GetStars()[drawnStars + i]; + + RendererSpriteToDraw rDrawSprite; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; + + constexpr auto STAR_SIZE = 2; + + rDrawSprite.Type = SpriteType::Billboard; + rDrawSprite.pos = renderView.Camera.WorldPosition + s.Direction * BLOCK(1); + rDrawSprite.Rotation = 0; + rDrawSprite.Scale = 1; + rDrawSprite.Width = STAR_SIZE * s.Scale; + rDrawSprite.Height = STAR_SIZE * s.Scale; + + _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); + _stInstancedSpriteBuffer.Sprites[i].Color = Vector4( + s.Color.x, + s.Color.y, + s.Color.z, + s.Blinking * s.Extinction); + _stInstancedSpriteBuffer.Sprites[i].IsBillboard = 1; + _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; + + // NOTE: Strange packing due to particular HLSL 16 byte alignment requirements. + _stInstancedSpriteBuffer.Sprites[i].UV[0].x = rDrawSprite.Sprite->UV[0].x; + _stInstancedSpriteBuffer.Sprites[i].UV[0].y = rDrawSprite.Sprite->UV[1].x; + _stInstancedSpriteBuffer.Sprites[i].UV[0].z = rDrawSprite.Sprite->UV[2].x; + _stInstancedSpriteBuffer.Sprites[i].UV[0].w = rDrawSprite.Sprite->UV[3].x; + _stInstancedSpriteBuffer.Sprites[i].UV[1].x = rDrawSprite.Sprite->UV[0].y; + _stInstancedSpriteBuffer.Sprites[i].UV[1].y = rDrawSprite.Sprite->UV[1].y; + _stInstancedSpriteBuffer.Sprites[i].UV[1].z = rDrawSprite.Sprite->UV[2].y; + _stInstancedSpriteBuffer.Sprites[i].UV[1].w = rDrawSprite.Sprite->UV[3].y; + } + + _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); + + // Draw sprites with instancing. + DrawInstancedTriangles(4, starsToDraw, 0); + + drawnStars += starsToDraw; + } + + // Draw meteor + if (Weather.GetMeteors().size() > 0) + { + RendererSpriteToDraw rDrawSprite; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; + BindTexture(TextureRegister::ColorMap, rDrawSprite.Sprite->Texture, SamplerStateRegister::LinearClamp); + + int meteorsCount = 0; + + for (int i = 0; i < Weather.GetMeteors().size(); i++) + { + MeteorParticle meteor = Weather.GetMeteors()[i]; + + if (meteor.Active == false) + continue; + + rDrawSprite.Type = SpriteType::CustomBillboard; + rDrawSprite.pos = renderView.Camera.WorldPosition + meteor.Position; + rDrawSprite.Rotation = 0; + rDrawSprite.Scale = 1; + rDrawSprite.Width = 2; + rDrawSprite.Height = 192; + rDrawSprite.ConstrainAxis = meteor.Direction; + + _stInstancedSpriteBuffer.Sprites[meteorsCount].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); + _stInstancedSpriteBuffer.Sprites[meteorsCount].Color = Vector4( + meteor.Color.x, + meteor.Color.y, + meteor.Color.z, + meteor.Fade + ); + _stInstancedSpriteBuffer.Sprites[meteorsCount].IsBillboard = 1; + _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; + + // NOTE: Strange packing due to particular HLSL 16 byte alignment requirements. + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].x = rDrawSprite.Sprite->UV[0].x; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].y = rDrawSprite.Sprite->UV[1].x; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].z = rDrawSprite.Sprite->UV[2].x; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].w = rDrawSprite.Sprite->UV[3].x; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].x = rDrawSprite.Sprite->UV[0].y; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].y = rDrawSprite.Sprite->UV[1].y; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].z = rDrawSprite.Sprite->UV[2].y; + _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].w = rDrawSprite.Sprite->UV[3].y; + + meteorsCount++; + } + + _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); + + // Draw sprites with instancing. + DrawInstancedTriangles(4, meteorsCount, 0); + } + + _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + } + // Draw horizon. if (_moveableObjects[ID_HORIZON].has_value()) { + SetDepthState(DepthState::None); + SetBlendMode(BlendMode::Opaque); + SetCullMode(CullMode::CounterClockwise); + _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); + _context->VSSetShader(_vsSky.Get(), nullptr, 0); + _context->PSSetShader(_psSky.Get(), nullptr, 0); + auto& moveableObj = *_moveableObjects[ID_HORIZON]; _stStatic.World = Matrix::CreateTranslation(renderView.Camera.WorldPosition); _stStatic.Color = Vector4::One; _stStatic.ApplyFogBulbs = 1; _cbStatic.UpdateData(_stStatic, _context.Get()); - + for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) { auto* meshPtr = moveableObj.ObjectMeshes[k]; @@ -2858,6 +2992,60 @@ namespace TEN::Renderer } } + // Eventually draw the sun sprite + if (renderView.LensFlaresToDraw.size() > 0 && renderView.LensFlaresToDraw[0].Sun) + { + SetDepthState(DepthState::Read); + SetBlendMode(BlendMode::Additive); + SetCullMode(CullMode::None); + + _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + _context->VSSetShader(_vsInstancedSprites.Get(), nullptr, 0); + _context->PSSetShader(_psInstancedSprites.Get(), nullptr, 0); + + // Set up vertex buffer and parameters. + UINT stride = sizeof(Vertex); + UINT offset = 0; + _context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); + + RendererSpriteToDraw rDrawSprite; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; + + constexpr auto SUN_SIZE = 64; + + rDrawSprite.Type = SpriteType::Billboard; + rDrawSprite.pos = renderView.Camera.WorldPosition + renderView.LensFlaresToDraw[0].Direction * BLOCK(1); + rDrawSprite.Rotation = 0; + rDrawSprite.Scale = 1; + rDrawSprite.Width = SUN_SIZE; + rDrawSprite.Height = SUN_SIZE; + + _stInstancedSpriteBuffer.Sprites[0].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); + _stInstancedSpriteBuffer.Sprites[0].Color = Vector4::One; + _stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1; + _stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = 0; + + // NOTE: Strange packing due to particular HLSL 16 byte alignment requirements. + _stInstancedSpriteBuffer.Sprites[0].UV[0].x = rDrawSprite.Sprite->UV[0].x; + _stInstancedSpriteBuffer.Sprites[0].UV[0].y = rDrawSprite.Sprite->UV[1].x; + _stInstancedSpriteBuffer.Sprites[0].UV[0].z = rDrawSprite.Sprite->UV[2].x; + _stInstancedSpriteBuffer.Sprites[0].UV[0].w = rDrawSprite.Sprite->UV[3].x; + _stInstancedSpriteBuffer.Sprites[0].UV[1].x = rDrawSprite.Sprite->UV[0].y; + _stInstancedSpriteBuffer.Sprites[0].UV[1].y = rDrawSprite.Sprite->UV[1].y; + _stInstancedSpriteBuffer.Sprites[0].UV[1].z = rDrawSprite.Sprite->UV[2].y; + _stInstancedSpriteBuffer.Sprites[0].UV[1].w = rDrawSprite.Sprite->UV[3].y; + + BindTexture(TextureRegister::ColorMap, rDrawSprite.Sprite->Texture, SamplerStateRegister::LinearClamp); + + _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); + + // Draw sprites with instancing. + DrawInstancedTriangles(4, 1, 0); + + _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + } + // Clear just the Z-buffer to start drawing on top of horizon. _context->ClearDepthStencilView(depthTarget, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 7169c1785..041d11aad 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -108,23 +108,25 @@ namespace TEN::Renderer for (auto lensFlare : LensFlares) { - float distance = Vector3::Distance(lensFlare.Position, renderView.Camera.WorldPosition); - - if (lensFlare.RoomNumber == Camera.pos.RoomNumber && distance < BLOCK(20)) + Vector3 lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; + float distance = 0.0f; + if (!lensFlare.Sun) { - Vector3 lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; - Vector3 cameraDirection = renderView.Camera.WorldDirection; + distance = lensFlareToCamera.Length(); + } + lensFlareToCamera.Normalize(); + + Vector3 cameraDirection = renderView.Camera.WorldDirection; + cameraDirection.Normalize(); - lensFlareToCamera.Normalize(); - cameraDirection.Normalize(); - - if (lensFlareToCamera.Dot(cameraDirection) >= 0.0f) - { - RendererLensFlare lensFlareToDraw; - lensFlareToDraw.Position = lensFlare.Position; - lensFlareToDraw.Distance = distance; - tempLensFlares.push_back(lensFlareToDraw); - } + if (lensFlareToCamera.Dot(cameraDirection) >= 0.0f) + { + RendererLensFlare lensFlareToDraw; + lensFlareToDraw.Position = lensFlare.Position; + lensFlareToDraw.Distance = distance; + lensFlareToDraw.Direction = lensFlareToCamera; + lensFlareToDraw.Sun = lensFlare.Sun; + tempLensFlares.push_back(lensFlareToDraw); } } @@ -133,11 +135,18 @@ namespace TEN::Renderer tempLensFlares.end(), [](const RendererLensFlare& lensFlare0, const RendererLensFlare& lensFlare1) { - return lensFlare0.Distance < lensFlare1.Distance; + if (lensFlare0.Sun && !lensFlare1.Sun) + return true; + else if (!lensFlare0.Sun && lensFlare1.Sun) + return false; + else + return lensFlare0.Distance < lensFlare1.Distance; }); for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++) + { renderView.LensFlaresToDraw.push_back(tempLensFlares[i]); + } } bool Renderer::CheckPortal(short parentRoomNumber, RendererDoor* door, Vector4 viewPort, Vector4* clipPort, RenderView& renderView) diff --git a/TombEngine/Renderer/Structures/RendererLensFlare.h b/TombEngine/Renderer/Structures/RendererLensFlare.h index 4acb56fcd..2fc8b74ae 100644 --- a/TombEngine/Renderer/Structures/RendererLensFlare.h +++ b/TombEngine/Renderer/Structures/RendererLensFlare.h @@ -9,6 +9,8 @@ namespace TEN::Renderer::Structures struct RendererLensFlare { Vector3 Position; + Vector3 Direction; float Distance; + bool Sun; }; } \ No newline at end of file diff --git a/TombEngine/Renderer/Structures/RendererStar.h b/TombEngine/Renderer/Structures/RendererStar.h new file mode 100644 index 000000000..d0bb916f9 --- /dev/null +++ b/TombEngine/Renderer/Structures/RendererStar.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include "Renderer/RendererEnums.h" + +namespace TEN::Renderer::Structures +{ + using namespace DirectX::SimpleMath; + + struct RendererStar + { + Vector3 Direction; + Vector3 Color; + float Blinking; + float Scale; + float Extinction; + }; +} \ No newline at end of file diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 44ef99dbf..6464b9af8 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -750,6 +750,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From c241af1c70b55ebc2a839efc8da731075b32ca5c Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 23 Apr 2024 20:59:43 +0200 Subject: [PATCH 090/410] Meteors interpolation --- TombEngine/Game/effects/weather.cpp | 2 ++ TombEngine/Game/effects/weather.h | 9 +++++++++ TombEngine/Renderer/RendererDraw.cpp | 6 ++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index b5b4667ad..f6269b983 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -291,6 +291,8 @@ namespace TEN::Effects::Environment continue; } + m.StoreInterpolationData(); + if (m.Life <= METEOR_PARTICLES_FADE_TIME) m.Fade = m.Life / (float)METEOR_PARTICLES_FADE_TIME; else if (m.Life >= METEOR_PARTICLES_MAX_LIFE - METEOR_PARTICLES_FADE_TIME) diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index 0efc267b7..43daf02d9 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -27,6 +27,15 @@ namespace TEN::Effects::Environment float Life; bool Active; float Fade; + + Vector3 OldPosition = Vector3::Zero; + float OldFade = 0.0f; + + void StoreInterpolationData() + { + OldPosition = Position; + OldFade = Fade; + } }; struct WeatherParticle diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 2b04a3126..30a4e11bb 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2907,7 +2907,9 @@ namespace TEN::Renderer continue; rDrawSprite.Type = SpriteType::CustomBillboard; - rDrawSprite.pos = renderView.Camera.WorldPosition + meteor.Position; + rDrawSprite.pos = + renderView.Camera.WorldPosition + + Vector3::Lerp(meteor.OldPosition, meteor.Position, _interpolationFactor); rDrawSprite.Rotation = 0; rDrawSprite.Scale = 1; rDrawSprite.Width = 2; @@ -2919,7 +2921,7 @@ namespace TEN::Renderer meteor.Color.x, meteor.Color.y, meteor.Color.z, - meteor.Fade + Lerp(meteor.OldFade, meteor.Fade, _interpolationFactor) ); _stInstancedSpriteBuffer.Sprites[meteorsCount].IsBillboard = 1; _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; From c13bd9ab19e90f173ddbd3a61a90c05b06d95220 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:21:00 +0200 Subject: [PATCH 091/410] Fixed original issue with classic switch off trigger wrongly activating some trigger actions --- Documentation/Changes.txt | 6 +++ TombEngine/Game/control/trigger.cpp | 74 ++++++++++++++++------------- TombEngine/Game/control/trigger.h | 2 +- 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 09efb1cbc..d15337e7d 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -1,3 +1,9 @@ +Version 1.5 +=========== + +* Fixed original issue with classic switch off trigger wrongly activating some trigger actions. + + Version 1.4 =========== diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 5b03b8f2a..fa24bc70f 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -114,7 +114,7 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitc return k; } -int SwitchTrigger(short itemNumber, short timer) +bool SwitchTrigger(short itemNumber, short timer) { auto& item = g_Level.Items[itemNumber]; const auto& player = Lara; @@ -127,7 +127,7 @@ int SwitchTrigger(short itemNumber, short timer) item.Status = ITEM_ACTIVE; item.ItemFlags[1] = false; - return 1; + return true; } if (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16 && @@ -137,13 +137,13 @@ int SwitchTrigger(short itemNumber, short timer) item.Status = ITEM_DEACTIVATED; item.ItemFlags[1] = false; - return 1; + return true; } if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) || (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16)) { - return 0; + return false; } // Handle reusable receptacles. @@ -156,7 +156,7 @@ int SwitchTrigger(short itemNumber, short timer) item.Status = ITEM_ACTIVE; item.ItemFlags[5] = (int)ReusableReceptacleState::Done; item.ItemFlags[1] = false; - return 1; + return true; } if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 && @@ -167,11 +167,11 @@ int SwitchTrigger(short itemNumber, short timer) item.Status = ITEM_DEACTIVATED; item.ItemFlags[5] = (int)ReusableReceptacleState::Empty; item.ItemFlags[1] = false; - return 1; + return true; } if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16) - return 0; + return false; // Handle switches. if (item.Status == ITEM_DEACTIVATED) @@ -186,7 +186,7 @@ int SwitchTrigger(short itemNumber, short timer) if (timer != 1) item.Timer = FPS * timer; - return 1; + return true; } if (item.TriggerFlags >= 0 || item.Animation.ActiveState != SWITCH_OFF) @@ -197,12 +197,12 @@ int SwitchTrigger(short itemNumber, short timer) if (!item.ItemFlags[0] == 0) item.Flags |= ONESHOT; - return 1; + return true; } else { item.Status = ITEM_ACTIVE; - return 1; + return true; } } else if (item.Status != ITEM_NOT_ACTIVE) @@ -211,13 +211,14 @@ int SwitchTrigger(short itemNumber, short timer) item.Animation.AnimNumber == GetAnimIndex(item, 2) && item.Animation.FrameNumber == GetFrameIndex(&item, 0)) { - return 1; + return true; } - return ((item.Flags & ONESHOT) >> 8); + if (item.Flags & ONESHOT) + return true; } - return 0; + return false; } int KeyTrigger(short itemNumber) @@ -398,15 +399,11 @@ void Trigger(short const value, short const flags) void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bool heavy, int heavyFlags) { - int flip = -1; - int flipAvailable = 0; - int newEffect = -1; - int switchOff = 0; - //int switchFlag = 0; - short objectNumber = 0; + bool switchOff = false; + bool flipAvailable = false; + int flip = NO_VALUE; + int newEffect = NO_VALUE; int keyResult = 0; - short cameraFlags = 0; - short cameraTimer = 0; int spotCamIndex = 0; auto data = GetTriggerIndex(floor, x, y, z); @@ -466,13 +463,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo if (!SwitchTrigger(value, timer)) return; - objectNumber = g_Level.Items[value].ObjectNumber; - //This disables the antitrigger of the Valve switch (ocb 5). I don't know the purpose of this in TR4. - //if (objectNumber >= ID_SWITCH_TYPE1 && objectNumber <= ID_SWITCH_TYPE6 && g_Level.Items[value].TriggerFlags == 5) - //switchFlag = 1; - - switchOff = (g_Level.Items[value].Animation.ActiveState == 1); - + switchOff = (triggerType == TRIGGER_TYPES::SWITCH && timer && g_Level.Items[value].Animation.ActiveState == 1); break; case TRIGGER_TYPES::MONKEY: @@ -571,8 +562,8 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo if (keyResult >= 2 || (triggerType == TRIGGER_TYPES::ANTIPAD || - triggerType == TRIGGER_TYPES::ANTITRIGGER || - triggerType == TRIGGER_TYPES::HEAVYANTITRIGGER) && + triggerType == TRIGGER_TYPES::ANTITRIGGER || + triggerType == TRIGGER_TYPES::HEAVYANTITRIGGER) && item->Flags & ATONESHOT) break; @@ -656,7 +647,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo if (triggerType == TRIGGER_TYPES::COMBAT) break; - if (triggerType == TRIGGER_TYPES::SWITCH && timer && switchOff) + if (switchOff) break; if (Camera.number != Camera.last || triggerType == TRIGGER_TYPES::SWITCH) @@ -674,6 +665,9 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo if (keyResult == 1) break; + if (switchOff) + break; + if (triggerType == TRIGGER_TYPES::ANTIPAD || triggerType == TRIGGER_TYPES::ANTITRIGGER || triggerType == TRIGGER_TYPES::HEAVYANTITRIGGER) @@ -748,16 +742,25 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo break; case TO_FLIPEFFECT: + if (switchOff) + break; + TriggerTimer = timer; newEffect = value; break; case TO_FINISH: + if (switchOff) + break; + NextLevel = value ? value : (CurrentLevel + 1); RequiredStartPos = timer; break; case TO_CD: + if (switchOff) + break; + PlaySoundTrack(value, flags); break; @@ -766,6 +769,9 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo break; case TO_SECRET: + if (switchOff) + break; + if (!(SaveGame::Statistics.Level.Secrets & (1 << value))) { PlaySecretTrack(); @@ -777,6 +783,8 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo case TO_VOLUMEEVENT: case TO_GLOBALEVENT: trigger = *(data++); + + if (!switchOff) { auto& list = targetType == TO_VOLUMEEVENT ? g_Level.VolumeEventSets : g_Level.GlobalEventSets; @@ -815,10 +823,10 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo if (cameraItem && (Camera.type == CameraType::Fixed || Camera.type == CameraType::Heavy)) Camera.item = cameraItem; - if (flip != -1) + if (flip != NO_VALUE) DoFlipMap(flip); - if (newEffect != -1 && (flip || !flipAvailable)) + if (newEffect != NO_VALUE && (flip || !flipAvailable)) FlipEffect = newEffect; } diff --git a/TombEngine/Game/control/trigger.h b/TombEngine/Game/control/trigger.h index fb60974fa..f1b3e2668 100644 --- a/TombEngine/Game/control/trigger.h +++ b/TombEngine/Game/control/trigger.h @@ -63,7 +63,7 @@ extern int KeyTriggerActive; bool GetKeyTrigger(ItemInfo* item); int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch); -int SwitchTrigger(short itemNumber, short timer); +bool SwitchTrigger(short itemNumber, short timer); int KeyTrigger(short itemNumber); bool PickupTrigger(short itemNumber); void RefreshCamera(short type, short* data); From 46d19878165fb598bbb8529b4637ce2adfa97711 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:30:02 +0200 Subject: [PATCH 092/410] Implement lua API functions to get last chosen inventory item --- TombEngine/Game/Lara/lara.cpp | 6 ---- TombEngine/Game/control/control.cpp | 3 ++ TombEngine/Game/gui.cpp | 9 +++++ TombEngine/Game/gui.h | 1 + .../Scripting/Internal/ReservedScriptNames.h | 3 ++ .../TEN/Inventory/InventoryHandler.cpp | 35 +++++++++++++++++++ 6 files changed, 51 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 447f10052..07a251277 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -634,12 +634,6 @@ void UpdateLara(ItemInfo* item, bool isTitle) if (isTitle) ActionMap = actionMap; - if (g_Gui.GetInventoryItemChosen() != NO_VALUE) - { - g_Gui.SetInventoryItemChosen(NO_VALUE); - SayNo(); - } - // Update player animations. g_Renderer.UpdateLaraAnimations(true); diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 4b71e240b..4502e5a59 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -162,6 +162,9 @@ GameStatus ControlPhase(int numFrames) g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index); + // Clear last selected item in inventory (need to be after on loop event handling, so they can detect that). + g_Gui.CancelInventorySelection(); + // Control lock is processed after handling scripts, because builder may want to // process input externally, while still locking Lara from input. if (!isTitle && Lara.Control.IsLocked) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 06635e097..e1e74e083 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3427,6 +3427,15 @@ namespace TEN::Gui } } + void GuiController::CancelInventorySelection() + { + if (GetInventoryItemChosen() != NO_VALUE) + { + SetInventoryItemChosen(NO_VALUE); + SayNo(); + } + } + void GuiController::DrawCompass(ItemInfo* item) { constexpr auto POS_2D = Vector2(130.0f, 450.0f); diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h index 2bdf145bb..f456889bd 100644 --- a/TombEngine/Game/gui.h +++ b/TombEngine/Game/gui.h @@ -180,6 +180,7 @@ namespace TEN::Gui void DrawAmmoSelector(); bool PerformWaterskinCombine(ItemInfo* item, bool flag); void DrawCompass(ItemInfo* item); + void CancelInventorySelection(); // Getters const InventoryRing& GetRing(RingTypes ringType); diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index e8821218c..181e94953 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -259,6 +259,9 @@ static constexpr char ScriptReserved_GiveInvItem[] = "GiveItem"; static constexpr char ScriptReserved_TakeInvItem[] = "TakeItem"; static constexpr char ScriptReserved_GetInvItemCount[] = "GetItemCount"; static constexpr char ScriptReserved_SetInvItemCount[] = "SetItemCount"; +static constexpr char ScriptReserved_GetChosenItem[] = "GetChosenItem"; +static constexpr char ScriptReserved_SetChosenItem[] = "SetChosenItem"; +static constexpr char ScriptReserved_ClearChosenItem[] = "ClearChosenItem"; static constexpr char ScriptReserved_GetMoveableByName[] = "GetMoveableByName"; static constexpr char ScriptReserved_GetStaticByName[] = "GetStaticByName"; static constexpr char ScriptReserved_GetMoveablesBySlot[] = "GetMoveablesBySlot"; diff --git a/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp b/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp index 1eb1414ba..a570cebfd 100644 --- a/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp @@ -1,12 +1,14 @@ #include "framework.h" #include "Scripting/Internal/TEN/Inventory/InventoryHandler.h" +#include "Game/gui.h" #include "Game/Hud/Hud.h" #include "Game/Lara/lara.h" #include "Game/pickup/pickup.h" #include "Scripting/Internal/ReservedScriptNames.h" using namespace TEN::Hud; +using namespace TEN::Gui; /*** Inventory manipulation @@ -59,6 +61,36 @@ namespace TEN::Scripting::InventoryHandler SetInventoryCount(objectID, count); } + /// Get last selected item in the player's inventory. + // This value will be valid only for a single frame after exiting inventory, after which Lara says "No". + // Therefore, this function must be preferably used either in OnLoop events or callbacks. + // If you have used this function and you want to avoid "No" sound, you should use ClearChosenItem function. + //@function GetChosenItem + //@treturn Objects.ObjID Last selected item in the inventory. + static GAME_OBJECT_ID GetChosenItem() + { + return (GAME_OBJECT_ID)g_Gui.GetInventoryItemChosen(); + } + + /// Set last selected item in the player's inventory. + // You will be able to select only objects which already exist in inventory. + // Will only be valid for the next frame. If not processed by the game, Lara will say "No". + //@function SetChosenItem + //@tparam Objects.ObjID objectID Object ID of the item to select from inventory. + static void SetChosenItem(GAME_OBJECT_ID objectID) + { + if (g_Gui.IsObjectInInventory(objectID)) + g_Gui.SetInventoryItemChosen(objectID); + } + + /// Clear last selected item in the player's inventory. + // This function is needed to avoid Lara saying "No" after selecting particular item in inventory. + //@function ClearChosenItem + static void ClearChosenItem() + { + g_Gui.SetInventoryItemChosen(GAME_OBJECT_ID::ID_NO_OBJECT); + } + void Register(sol::state* state, sol::table& parent) { auto tableInventory = sol::table{ state->lua_state(), sol::create }; @@ -68,5 +100,8 @@ namespace TEN::Scripting::InventoryHandler tableInventory.set_function(ScriptReserved_TakeInvItem, &TakeItem); tableInventory.set_function(ScriptReserved_GetInvItemCount, &GetItemCount); tableInventory.set_function(ScriptReserved_SetInvItemCount, &SetItemCount); + tableInventory.set_function(ScriptReserved_SetChosenItem, &SetChosenItem); + tableInventory.set_function(ScriptReserved_GetChosenItem, &GetChosenItem); + tableInventory.set_function(ScriptReserved_ClearChosenItem, &ClearChosenItem); } } From 809d54d8115d9d9ce265da2ed0d1f8f84f62423c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:32:32 +0200 Subject: [PATCH 093/410] Update docs --- Documentation/Changes.txt | 2 + Documentation/doc/1 modules/Inventory.html | 76 ++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index d15337e7d..542f6fb9a 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -3,6 +3,8 @@ Version 1.5 * Fixed original issue with classic switch off trigger wrongly activating some trigger actions. +Lua API changes: +* Added Inventory.GetChosenItem(), Inventory.SetChosenItem() and Inventory.ClearChosenItem() functions. Version 1.4 =========== diff --git a/Documentation/doc/1 modules/Inventory.html b/Documentation/doc/1 modules/Inventory.html index e5fd825ec..f0df17c5b 100644 --- a/Documentation/doc/1 modules/Inventory.html +++ b/Documentation/doc/1 modules/Inventory.html @@ -124,6 +124,18 @@ SetItemCount(objectID, count) Set the amount of an item in the player's inventory. + + GetChosenItem() + Get last selected item in the player's inventory. + + + SetChosenItem(objectID) + Set last selected item in the player's inventory. + + + ClearChosenItem() + Clear last selected item in the player's inventory. +
    @@ -245,6 +257,70 @@ + +
    + + GetChosenItem() +
    +
    + Get last selected item in the player's inventory. + This value will be valid only for a single frame after exiting inventory, after which Lara says "No". + Therefore, this function must be preferably used either in OnLoop events or callbacks. + If you have used this function and you want to avoid "No" sound, you should use ClearChosenItem function. + + + + +

    Returns:

    +
      + + ObjID + Last selected item in the inventory. +
    + + + + +
    +
    + + SetChosenItem(objectID) +
    +
    + Set last selected item in the player's inventory. + You will be able to select only objects which already exist in inventory. + Will only be valid for the next frame. If not processed by the game, Lara will say "No". + + + +

    Parameters:

    +
      +
    • objectID + ObjID + Object ID of the item to select from inventory. +
    • +
    + + + + + +
    +
    + + ClearChosenItem() +
    +
    + Clear last selected item in the player's inventory. + This function is needed to avoid Lara saying "No" after selecting particular item in inventory. + + + + + + + +
    From 30a72eb71b4f8ac3cc109ebd6514f0ccd1f276f2 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:42:00 +0200 Subject: [PATCH 094/410] Filter out code bits for legacy soundtrack mask --- TombEngine/Game/control/trigger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index fa24bc70f..740cb4088 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -761,7 +761,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, Activator activator, bo if (switchOff) break; - PlaySoundTrack(value, flags); + PlaySoundTrack(value, flags & CODE_BITS); break; case TO_CUTSCENE: From 9dc4f9e24e50f6f43cb7e120fe24cc6ad3d75029 Mon Sep 17 00:00:00 2001 From: Adngel <60930991+Adngel@users.noreply.github.com> Date: Wed, 24 Apr 2024 07:25:22 +0200 Subject: [PATCH 095/410] Adngel small fixes (#1355) * Update tr2_worker_shotgun.cpp Added enumerators for Animations and States. * Fix Worker Shotgun walking attack Now the enemy can hurt Lara with every shooting he does while walking. * Fix skidoo driver lack of AI * Update tr2_worker_shotgun.cpp Use TestProbability() --------- Co-authored-by: Sezz --- TombEngine/Objects/TR2/Entity/tr2_skidman.cpp | 3 + .../Objects/TR2/Entity/tr2_worker_shotgun.cpp | 105 ++++++++++++------ 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp index 4b573f7b5..17c95d586 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp @@ -131,6 +131,9 @@ namespace TEN::Entities::Creatures::TR2 int skidooItemNumber = (short)riderItem.ItemFlags[0]; auto* skidooItem = &g_Level.Items[skidooItemNumber]; + if (!CreatureActive(skidooItemNumber)) + return; + if (!skidooItem->Data) { EnableEntityAI(skidooItemNumber, true); diff --git a/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp b/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp index 0d365e113..7694f559e 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_worker_shotgun.cpp @@ -5,29 +5,61 @@ #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/effects/effects.h" -#include "Game/items.h" #include "Game/itemdata/creature_info.h" +#include "Game/items.h" #include "Game/misc.h" #include "Game/people.h" #include "Game/Setup.h" +#include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Math; + namespace TEN::Entities::Creatures::TR2 { constexpr auto WORKER_SHOTGUN_NUM_SHOTS = 6; const auto WorkerShotgunBite = CreatureBiteInfo(Vector3(0, 350, 40), 9); - // TODO enum ShotgunWorkerState { - + // No state 0. + WORKER_SHOTGUN_STATE_WALK = 1, + WORKER_SHOTGUN_STATE_IDLE = 2, + WORKER_SHOTGUN_STATE_REST = 3, + WORKER_SHOTGUN_STATE_STANDING_ATTACK = 4, + WORKER_SHOTGUN_STATE_RUN = 5, + WORKER_SHOTGUN_STATE_WALKING_ATTACK = 6, + WORKER_SHOTGUN_STATE_DEATH = 7, + WORKER_SHOTGUN_STATE_STANDING_ATTACK_AIM = 8, + WORKER_SHOTGUN_STATE_KNEEL_ATTACK_AIM = 9, + WORKER_SHOTGUN_STATE_KNEEL_ATTACK = 10 }; - // TODO enum ShotgunWorkerAnim { - + WORKER_SHOTGUN_ANIM_WALK = 0, + WORKER_SHOTGUN_ANIM_STANDING_ATTACK_AIM = 1, + WORKER_SHOTGUN_ANIM_STANDING_ATTACK_SHOOT = 2, + WORKER_SHOTGUN_ANIM_STANDING_ATTACK_STOP = 3, + WORKER_SHOTGUN_ANIM_WALK_TO_IDLE = 4, + WORKER_SHOTGUN_ANIM_IDLE = 5, + WORKER_SHOTGUN_ANIM_IDLE_TO_WALK = 6, + WORKER_SHOTGUN_ANIM_WALKING_ATTACK_AIM = 7, + WORKER_SHOTGUN_ANIM_WALKING_ATTACK_SHOOT = 8, + WORKER_SHOTGUN_ANIM_REST_TO_IDLE = 9, + WORKER_SHOTGUN_ANIM_REST = 10, + WORKER_SHOTGUN_ANIM_REST_TO_STANDING_ATTACK = 11, + WORKER_SHOTGUN_ANIM_IDLE_TO_REST = 12, + WORKER_SHOTGUN_ANIM_STANDING_ATTACK_TO_IDLE = 13, + WORKER_SHOTGUN_ANIM_WALK_TO_RUN = 14, + WORKER_SHOTGUN_ANIM_RUN_TO_WALK = 15, + WORKER_SHOTGUN_ANIM_IDLE_TO_RUN = 16, + WORKER_SHOTGUN_ANIM_RUN = 17, + WORKER_SHOTGUN_ANIM_DEATH = 18, + WORKER_SHOTGUN_ANIM_KNEEL_ATTACK_AIM = 19, + WORKER_SHOTGUN_ANIM_KNEEL_ATTACK_SHOOT = 20, + WORKER_SHOTGUN_ANIM_KNEEL_ATTACK_STOP = 21 }; static void ShootWorkerShotgun(ItemInfo& item, AI_INFO& ai, const CreatureBiteInfo& bite, short headingAngle, int damage) @@ -62,8 +94,8 @@ namespace TEN::Entities::Creatures::TR2 if (item->HitPoints <= 0) { - if (item->Animation.ActiveState != 7) - SetAnimation(item, 18); + if (item->Animation.ActiveState != WORKER_SHOTGUN_STATE_DEATH) + SetAnimation(item, WORKER_SHOTGUN_ANIM_DEATH); } else { @@ -77,7 +109,7 @@ namespace TEN::Entities::Creatures::TR2 switch (item->Animation.ActiveState) { - case 2: + case WORKER_SHOTGUN_STATE_IDLE: creature->MaxTurn = 0; creature->Flags = 0; @@ -89,38 +121,38 @@ namespace TEN::Entities::Creatures::TR2 if (creature->Mood == MoodType::Escape) { - item->Animation.TargetState = 5; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_RUN; } else if (Targetable(item, &ai)) { if (ai.distance < SQUARE(BLOCK(3)) || ai.zoneNumber != ai.enemyZone) { - item->Animation.TargetState = (GetRandomControl() >= 0x4000) ? 9 : 8; + item->Animation.TargetState = Random::TestProbability(1 / 2.0f) ? WORKER_SHOTGUN_STATE_KNEEL_ATTACK_AIM : WORKER_SHOTGUN_STATE_STANDING_ATTACK_AIM; } else { - item->Animation.TargetState = 1; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_WALK; } } else if (creature->Mood == MoodType::Attack || !ai.ahead) { if (ai.distance <= SQUARE(BLOCK(2))) { - item->Animation.TargetState = 1; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_WALK; } else { - item->Animation.TargetState = 5; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_RUN; } } else { - item->Animation.TargetState = 3; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_REST; } break; - case 3: + case WORKER_SHOTGUN_STATE_REST: if (ai.ahead) { extraHeadRot.x = ai.xAngle; @@ -129,16 +161,16 @@ namespace TEN::Entities::Creatures::TR2 if (Targetable(item, &ai)) { - item->Animation.TargetState = 4; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_STANDING_ATTACK; } else if (creature->Mood == MoodType::Attack || !ai.ahead) { - item->Animation.TargetState = 2; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_IDLE; } break; - case 1: + case WORKER_SHOTGUN_STATE_WALK: creature->MaxTurn = ANGLE(3.0f); if (ai.ahead) @@ -149,32 +181,33 @@ namespace TEN::Entities::Creatures::TR2 if (creature->Mood == MoodType::Escape) { - item->Animation.TargetState = 5; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_RUN; } else if (Targetable(item, &ai)) { if (ai.distance < SQUARE(BLOCK(3)) || ai.zoneNumber != ai.enemyZone) { - item->Animation.TargetState = 2; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_IDLE; } else { - item->Animation.TargetState = 6; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_WALKING_ATTACK; + creature->Flags = 0; } } else if (creature->Mood == MoodType::Attack || !ai.ahead) { if (ai.distance > SQUARE(BLOCK(2))) - item->Animation.TargetState = 5; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_RUN; } else { - item->Animation.TargetState = 2; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_IDLE; } break; - case 5: + case WORKER_SHOTGUN_STATE_RUN: creature->MaxTurn = ANGLE(5.0f); tiltAngle = headingAngle / 2; @@ -188,18 +221,18 @@ namespace TEN::Entities::Creatures::TR2 { if (Targetable(item, &ai)) { - item->Animation.TargetState = 1; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_WALK; } else if (creature->Mood == MoodType::Bored || creature->Mood == MoodType::Stalk) { - item->Animation.TargetState = 1; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_WALK; } } break; - case 8: - case 9: + case WORKER_SHOTGUN_STATE_STANDING_ATTACK_AIM: + case WORKER_SHOTGUN_STATE_KNEEL_ATTACK_AIM: creature->Flags = 0; if (ai.ahead) @@ -210,20 +243,20 @@ namespace TEN::Entities::Creatures::TR2 if (Targetable(item, &ai)) { - if (item->Animation.ActiveState == 8) + if (item->Animation.ActiveState == WORKER_SHOTGUN_STATE_STANDING_ATTACK_AIM) { - item->Animation.TargetState = 4; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_STANDING_ATTACK; } else { - item->Animation.TargetState = 10; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_KNEEL_ATTACK; } } break; - case 4: - case 10: + case WORKER_SHOTGUN_STATE_STANDING_ATTACK: + case WORKER_SHOTGUN_STATE_KNEEL_ATTACK: if (ai.ahead) { extraTorsoRot.x = ai.xAngle; @@ -238,15 +271,15 @@ namespace TEN::Entities::Creatures::TR2 creature->Flags = 1; } - if (item->Animation.ActiveState == 4 && item->Animation.TargetState != 2 && + if (item->Animation.ActiveState == WORKER_SHOTGUN_STATE_STANDING_ATTACK && item->Animation.TargetState != WORKER_SHOTGUN_STATE_IDLE && (creature->Mood == MoodType::Escape || ai.distance > SQUARE(BLOCK(3)) || !Targetable(item, &ai))) { - item->Animation.TargetState = 2; + item->Animation.TargetState = WORKER_SHOTGUN_STATE_IDLE; } break; - case 6: + case WORKER_SHOTGUN_STATE_WALKING_ATTACK: if (ai.ahead) { extraTorsoRot.x = ai.xAngle; From 15bd3d52172f1991c24407a6fbd298c948b8e022 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 25 Apr 2024 19:38:39 +1000 Subject: [PATCH 096/410] Add bridge check to player move test over death sectors --- TombEngine/Game/Lara/PlayerContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/Lara/PlayerContext.cpp b/TombEngine/Game/Lara/PlayerContext.cpp index b9944df22..6bf992c6e 100644 --- a/TombEngine/Game/Lara/PlayerContext.cpp +++ b/TombEngine/Game/Lara/PlayerContext.cpp @@ -190,7 +190,7 @@ namespace TEN::Entities::Player } // 3) Check for death floor (if applicable). - if (setup.TestDeathFloor && pointColl.Block->Flags.Death) + if (setup.TestDeathFloor && pointColl.Block->Flags.Death && pointColl.Position.Bridge == NO_VALUE) return false; // LOS setup at upper floor bound. From 546034ecc133658a3759a18473b21501381f8d00 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 26 Apr 2024 15:49:27 +1000 Subject: [PATCH 097/410] Apply PR comments --- TombEngine/Game/collision/Point.cpp | 52 +++++++++---------- TombEngine/Game/collision/Point.h | 6 +-- .../Object/Pushable/PushableCollision.cpp | 4 -- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index 19312969d..51701b4ab 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -34,56 +34,56 @@ namespace TEN::Collision::Point FloorInfo& PointCollisionData::GetSector() { - if (_sectorPtr != nullptr) - return *_sectorPtr; + if (_sector != nullptr) + return *_sector; - // Set current sector pointer. + // Set current sector. short probeRoomNumber = _roomNumber; - _sectorPtr = GetFloor(_position.x, _position.y, _position.z, &probeRoomNumber); + _sector = GetFloor(_position.x, _position.y, _position.z, &probeRoomNumber); - return *_sectorPtr; + return *_sector; } FloorInfo& PointCollisionData::GetBottomSector() { - if (_bottomSectorPtr != nullptr) - return *_bottomSectorPtr; + if (_bottomSector != nullptr) + return *_bottomSector; - // Set bottom sector pointer. - auto* bottomSectorPtr = &GetSector(); - auto roomNumberBelow = bottomSectorPtr->GetNextRoomNumber(_position, true); + // Set bottom sector. + auto* bottomSector = &GetSector(); + auto roomNumberBelow = bottomSector->GetNextRoomNumber(_position, true); while (roomNumberBelow.has_value()) { - int roomNumber = roomNumberBelow.value_or(bottomSectorPtr->RoomNumber); + int roomNumber = roomNumberBelow.value_or(bottomSector->RoomNumber); auto& room = g_Level.Rooms[roomNumber]; - bottomSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); - roomNumberBelow = bottomSectorPtr->GetNextRoomNumber(_position, true); + bottomSector = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); + roomNumberBelow = bottomSector->GetNextRoomNumber(_position, true); } - _bottomSectorPtr = bottomSectorPtr; + _bottomSector = bottomSector; - return *_bottomSectorPtr; + return *_bottomSector; } FloorInfo& PointCollisionData::GetTopSector() { - if (_topSectorPtr != nullptr) - return *_topSectorPtr; + if (_topSector != nullptr) + return *_topSector; - // Set top sector pointer. - auto* topSectorPtr = &GetSector(); - auto roomNumberAbove = topSectorPtr->GetNextRoomNumber(_position, false); + // Set top sector. + auto* topSector = &GetSector(); + auto roomNumberAbove = topSector->GetNextRoomNumber(_position, false); while (roomNumberAbove.has_value()) { - int roomNumber = roomNumberAbove.value_or(topSectorPtr->RoomNumber); + int roomNumber = roomNumberAbove.value_or(topSector->RoomNumber); auto& room = g_Level.Rooms[roomNumber]; - topSectorPtr = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); - roomNumberAbove = topSectorPtr->GetNextRoomNumber(_position, false); + topSector = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); + roomNumberAbove = topSector->GetNextRoomNumber(_position, false); } - _topSectorPtr = topSectorPtr; + _topSector = topSector; - return *_topSectorPtr; + return *_topSector; } int PointCollisionData::GetFloorHeight() @@ -340,7 +340,7 @@ namespace TEN::Collision::Point PointCollisionData GetPointCollision(const Vector3i& pos, int roomNumber) { // HACK: Ensure room number is correct if position extends to another room. - // Accounts for some calls to this function which directly pass offset position instead of using dedicated overloads to probe. + // Accounts for some calls to this function which directly pass offset position instead of using dedicated probe overloads. GetFloor(pos.x, pos.y, pos.z, (short*)&roomNumber); return PointCollisionData(pos, roomNumber); diff --git a/TombEngine/Game/collision/Point.h b/TombEngine/Game/collision/Point.h index 318082c42..cf8150b60 100644 --- a/TombEngine/Game/collision/Point.h +++ b/TombEngine/Game/collision/Point.h @@ -17,9 +17,9 @@ namespace TEN::Collision::Point Vector3i _position = Vector3i::Zero; int _roomNumber = 0; - FloorInfo* _sectorPtr = nullptr; - FloorInfo* _bottomSectorPtr = nullptr; - FloorInfo* _topSectorPtr = nullptr; + FloorInfo* _sector = nullptr; + FloorInfo* _bottomSector = nullptr; + FloorInfo* _topSector = nullptr; std::optional _floorHeight = std::nullopt; std::optional _ceilingHeight = std::nullopt; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 52c681f52..39ac6d5e7 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -37,10 +37,6 @@ namespace TEN::Entities::Generic pointColl = GetPointCollision(pushableItem); AddPushableBridge(pushableItem); } - else - { - pointColl = GetPointCollision(pushableItem); - } // 1) Check for wall. if (pointColl.GetSector().IsWall(pushableItem.Pose.Position.x, pushableItem.Pose.Position.z)) From bcd689b8ba7afe653d044273b76ef91a6ca9f5b8 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 26 Apr 2024 15:53:02 +1000 Subject: [PATCH 098/410] Update collide_room.cpp --- TombEngine/Game/collision/collide_room.cpp | 176 ++++++++++----------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 438c8fa7c..52ac15f32 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -823,11 +823,11 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) // Get front floor block auto room = GetRoomVector(item->Location, Vector3i(ffpX, y, ffpZ)).RoomNumber; - auto sectorPtr = &GetPointCollision(Vector3i(ffpX, y, ffpZ), room).GetSector(); + auto sector = &GetPointCollision(Vector3i(ffpX, y, ffpZ), room).GetSector(); // Get front floor surface heights - auto floorHeight = GetSurfaceHeight(RoomVector(sectorPtr->RoomNumber, y), ffpX, ffpZ, true).value_or(NO_HEIGHT); - auto ceilingHeight = GetSurfaceHeight(RoomVector(sectorPtr->RoomNumber, y), ffpX, ffpZ, false).value_or(NO_HEIGHT); + auto floorHeight = GetSurfaceHeight(RoomVector(sector->RoomNumber, y), ffpX, ffpZ, true).value_or(NO_HEIGHT); + auto ceilingHeight = GetSurfaceHeight(RoomVector(sector->RoomNumber, y), ffpX, ffpZ, false).value_or(NO_HEIGHT); // If probe landed inside wall (i.e. both floor/ceiling heights are NO_HEIGHT), make a fake // ledge for algorithm to further succeed. @@ -840,7 +840,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) int height = useCeilingLedge ? ceilingHeight : floorHeight; // Determine if there is a bridge in front. - auto bridge = sectorPtr->GetInsideBridgeItemNumber(Vector3i(ffpX, height, ffpZ), true, y == height); + auto bridge = sector->GetInsideBridgeItemNumber(Vector3i(ffpX, height, ffpZ), true, y == height); // Determine floor probe offset. // This must be slightly in front of own coll radius so no bridge misfires occur. @@ -853,7 +853,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) // Get true room number and block, based on derived height room = GetRoomVector(item->Location, Vector3i(fpX, height, fpZ)).RoomNumber; - sectorPtr = &GetPointCollision(Vector3i(fpX, height, fpZ), room).GetSector(); + sector = &GetPointCollision(Vector3i(fpX, height, fpZ), room).GetSector(); // We don't need actual corner heights to build planes, so just use normalized value here. auto fY = height - 1; @@ -911,7 +911,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) else { // Determine if we should use floor or ceiling split angle based on early tests. - auto splitAngle = (useCeilingLedge ? TO_RAD(sectorPtr->CeilingSurface.SplitAngle) : TO_RAD(sectorPtr->FloorSurface.SplitAngle)); + auto splitAngle = (useCeilingLedge ? TO_RAD(sector->CeilingSurface.SplitAngle) : TO_RAD(sector->FloorSurface.SplitAngle)); // Get horizontal block corner coordinates. auto fX = floor(eX / BLOCK(1)) * BLOCK(1) - 1; @@ -939,7 +939,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) }; // If split angle exists, take split plane into account too. - auto useSplitAngle = (useCeilingLedge ? sectorPtr->IsSurfaceSplit(false) : sectorPtr->IsSurfaceSplit(true)); + auto useSplitAngle = (useCeilingLedge ? sector->IsSurfaceSplit(false) : sector->IsSurfaceSplit(true)); // Find closest block edge plane. for (int i = 0; i < (useSplitAngle ? 5 : 4); i++) @@ -966,7 +966,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) if (i == 4) { - auto usedSectorPlane = useCeilingLedge ? sectorPtr->GetSurfaceTriangleID(eX, eZ, false) : sectorPtr->GetSurfaceTriangleID(eX, eZ, true); + auto usedSectorPlane = useCeilingLedge ? sector->GetSurfaceTriangleID(eX, eZ, false) : sector->GetSurfaceTriangleID(eX, eZ, true); result[p] = FROM_RAD(splitAngle) + ANGLE(usedSectorPlane * 180.0f) + ANGLE(90.0f); } else @@ -1085,31 +1085,31 @@ int GetDistanceToFloor(int itemNumber, bool precise) int GetWaterSurface(int x, int y, int z, short roomNumber) { - auto* roomPtr = &g_Level.Rooms[roomNumber]; - auto* sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); + auto* room = &g_Level.Rooms[roomNumber]; + auto* sector = GetSector(room, x - room->x, z - room->z); - if (TestEnvironment(ENV_FLAG_WATER, roomPtr)) + if (TestEnvironment(ENV_FLAG_WATER, room)) { - while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_ROOM) != NO_ROOM) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_VALUE) != NO_VALUE) { - roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sectorPtr->RoomNumber)]; - if (!TestEnvironment(ENV_FLAG_WATER, roomPtr)) - return (sectorPtr->GetSurfaceHeight(x, z, false)); + room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; + if (!TestEnvironment(ENV_FLAG_WATER, room)) + return (sector->GetSurfaceHeight(x, z, false)); - sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); + sector = GetSector(room, x - room->x, z - room->z); } return NO_HEIGHT; } else { - while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) { - roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sectorPtr->RoomNumber)]; - if (TestEnvironment(ENV_FLAG_WATER, roomPtr)) - return (sectorPtr->GetSurfaceHeight(x, z, true)); + room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; + if (TestEnvironment(ENV_FLAG_WATER, room)) + return (sector->GetSurfaceHeight(x, z, true)); - sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); + sector = GetSector(room, x - room->x, z - room->z); } } @@ -1123,14 +1123,14 @@ int GetWaterSurface(ItemInfo* item) int GetWaterDepth(int x, int y, int z, short roomNumber) { - FloorInfo* sectorPtr = nullptr; - auto* roomPtr = &g_Level.Rooms[roomNumber]; + FloorInfo* sector = nullptr; + auto* room = &g_Level.Rooms[roomNumber]; - int adjoiningRoomNumber = NO_ROOM; + int adjoiningRoomNumber = NO_VALUE; do { - int xFloor = (x - roomPtr->x) / BLOCK(1); - int zFloor = (z - roomPtr->z) / BLOCK(1); + int xFloor = (x - room->x) / BLOCK(1); + int zFloor = (z - room->z) / BLOCK(1); if (zFloor <= 0) { @@ -1139,77 +1139,77 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) { xFloor = 1; } - else if (xFloor > (roomPtr->xSize - 2)) + else if (xFloor > (room->xSize - 2)) { - xFloor = roomPtr->xSize - 2; + xFloor = room->xSize - 2; } } - else if (zFloor >= (roomPtr->zSize - 1)) + else if (zFloor >= (room->zSize - 1)) { - zFloor = roomPtr->zSize - 1; + zFloor = room->zSize - 1; if (xFloor < 1) { xFloor = 1; } - else if (xFloor > (roomPtr->xSize - 2)) + else if (xFloor > (room->xSize - 2)) { - xFloor = roomPtr->xSize - 2; + xFloor = room->xSize - 2; } } else if (xFloor < 0) { xFloor = 0; } - else if (xFloor >= roomPtr->xSize) + else if (xFloor >= room->xSize) { - xFloor = roomPtr->xSize - 1; + xFloor = room->xSize - 1; } - sectorPtr = &roomPtr->floor[zFloor + (xFloor * roomPtr->zSize)]; - adjoiningRoomNumber = sectorPtr->SidePortalRoomNumber; - if (adjoiningRoomNumber != NO_ROOM) + sector = &room->floor[zFloor + (xFloor * room->zSize)]; + adjoiningRoomNumber = sector->SidePortalRoomNumber; + if (adjoiningRoomNumber != NO_VALUE) { roomNumber = adjoiningRoomNumber; - roomPtr = &g_Level.Rooms[adjoiningRoomNumber]; + room = &g_Level.Rooms[adjoiningRoomNumber]; } } - while (adjoiningRoomNumber != NO_ROOM); + while (adjoiningRoomNumber != NO_VALUE); - if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || - TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) + if (TestEnvironment(ENV_FLAG_WATER, room) || + TestEnvironment(ENV_FLAG_SWAMP, room)) { - while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_ROOM) != NO_ROOM) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_VALUE) != NO_VALUE) { - roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sectorPtr->RoomNumber)]; + room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; - if (!TestEnvironment(ENV_FLAG_WATER, roomPtr) && - !TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) + if (!TestEnvironment(ENV_FLAG_WATER, room) && + !TestEnvironment(ENV_FLAG_SWAMP, room)) { - int waterHeight = sectorPtr->GetSurfaceHeight(x, z, false); - int floorHeight = GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetBottomSector().GetSurfaceHeight(x, z, true); + int waterHeight = sector->GetSurfaceHeight(x, z, false); + int floorHeight = GetPointCollision(Vector3i(x, y, z), sector->RoomNumber).GetBottomSector().GetSurfaceHeight(x, z, true); return (floorHeight - waterHeight); } - sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); + sector = GetSector(room, x - room->x, z - room->z); } return DEEP_WATER; } else { - while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) { - roomPtr = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sectorPtr->RoomNumber)]; + room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; - if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || - TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) + if (TestEnvironment(ENV_FLAG_WATER, room) || + TestEnvironment(ENV_FLAG_SWAMP, room)) { - int waterHeight = sectorPtr->GetSurfaceHeight(x, z, true); - sectorPtr = GetFloor(x, y, z, &roomNumber); - return (GetFloorHeight(sectorPtr, x, y, z) - waterHeight); + int waterHeight = sector->GetSurfaceHeight(x, z, true); + sector = GetFloor(x, y, z, &roomNumber); + return (GetFloorHeight(sector, x, y, z) - waterHeight); } - sectorPtr = GetSector(roomPtr, x - roomPtr->x, z - roomPtr->z); + sector = GetSector(room, x - room->x, z - room->z); } return NO_HEIGHT; @@ -1223,14 +1223,14 @@ int GetWaterDepth(ItemInfo* item) int GetWaterHeight(int x, int y, int z, short roomNumber) { - FloorInfo* sectorPtr = nullptr; - auto* roomPtr = &g_Level.Rooms[roomNumber]; + FloorInfo* sector = nullptr; + auto* room = &g_Level.Rooms[roomNumber]; - int adjoiningRoomNumber = NO_ROOM; + int adjoiningRoomNumber = NO_VALUE; do { - int xBlock = (x - roomPtr->x) / BLOCK(1); - int zBlock = (z - roomPtr->z) / BLOCK(1); + int xBlock = (x - room->x) / BLOCK(1); + int zBlock = (z - room->z) / BLOCK(1); if (zBlock <= 0) { @@ -1239,52 +1239,52 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) { xBlock = 1; } - else if (xBlock > (roomPtr->xSize - 2)) + else if (xBlock > (room->xSize - 2)) { - xBlock = roomPtr->xSize - 2; + xBlock = room->xSize - 2; } } - else if (zBlock >= (roomPtr->zSize - 1)) + else if (zBlock >= (room->zSize - 1)) { - zBlock = roomPtr->zSize - 1; + zBlock = room->zSize - 1; if (xBlock < 1) { xBlock = 1; } - else if (xBlock > (roomPtr->xSize - 2)) + else if (xBlock > (room->xSize - 2)) { - xBlock = roomPtr->xSize - 2; + xBlock = room->xSize - 2; } } else if (xBlock < 0) { xBlock = 0; } - else if (xBlock >= roomPtr->xSize) + else if (xBlock >= room->xSize) { - xBlock = roomPtr->xSize - 1; + xBlock = room->xSize - 1; } - sectorPtr = &roomPtr->floor[zBlock + (xBlock * roomPtr->zSize)]; - adjoiningRoomNumber = sectorPtr->SidePortalRoomNumber; + sector = &room->floor[zBlock + (xBlock * room->zSize)]; + adjoiningRoomNumber = sector->SidePortalRoomNumber; - if (adjoiningRoomNumber != NO_ROOM) + if (adjoiningRoomNumber != NO_VALUE) { roomNumber = adjoiningRoomNumber; - roomPtr = &g_Level.Rooms[adjoiningRoomNumber]; + room = &g_Level.Rooms[adjoiningRoomNumber]; } } - while (adjoiningRoomNumber != NO_ROOM); + while (adjoiningRoomNumber != NO_VALUE); - if (sectorPtr->IsWall(x, z)) + if (sector->IsWall(x, z)) return NO_HEIGHT; - if (TestEnvironment(ENV_FLAG_WATER, roomPtr) || - TestEnvironment(ENV_FLAG_SWAMP, roomPtr)) + if (TestEnvironment(ENV_FLAG_WATER, room) || + TestEnvironment(ENV_FLAG_SWAMP, room)) { - while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_ROOM) != NO_ROOM) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_VALUE) != NO_VALUE) { - auto* room = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sectorPtr->RoomNumber)]; + auto* room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; if (!TestEnvironment(ENV_FLAG_WATER, room) && !TestEnvironment(ENV_FLAG_SWAMP, room)) @@ -1292,27 +1292,27 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) break; } - sectorPtr = GetSector(room, x - room->x, z - room->z); + sector = GetSector(room, x - room->x, z - room->z); } - return GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), false); + return GetPointCollision(Vector3i(x, y, z), sector->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), false); } - else if (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) + else if (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) { - while (sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_ROOM) != NO_ROOM) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) { - auto* roomPtr2 = &g_Level.Rooms[sectorPtr->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sectorPtr->RoomNumber)]; + auto* room2 = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; - if (TestEnvironment(ENV_FLAG_WATER, roomPtr2) || - TestEnvironment(ENV_FLAG_SWAMP, roomPtr2)) + if (TestEnvironment(ENV_FLAG_WATER, room2) || + TestEnvironment(ENV_FLAG_SWAMP, room2)) { break; } - sectorPtr = GetSector(roomPtr2, x - roomPtr2->x, z - roomPtr2->z); + sector = GetSector(room2, x - room2->x, z - room2->z); } - return GetPointCollision(Vector3i(x, y, z), sectorPtr->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), true); + return GetPointCollision(Vector3i(x, y, z), sector->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), true); } return NO_HEIGHT; From b73b31784c9eaee23691b64db219fcf5399a0835 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 26 Apr 2024 16:30:44 +1000 Subject: [PATCH 099/410] Add TODOs --- TombEngine/Game/collision/Point.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index 51701b4ab..7c8b12c59 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -177,7 +177,7 @@ namespace TEN::Collision::Point if (_waterSurfaceHeight.has_value()) return *_waterSurfaceHeight; - // Set water surface height. + // Set water surface height. TODO: Calculate here. _waterSurfaceHeight = GetWaterSurface(_position.x, _position.y, _position.z, _roomNumber); return *_waterSurfaceHeight; @@ -188,7 +188,7 @@ namespace TEN::Collision::Point if (_waterBottomHeight.has_value()) return *_waterBottomHeight; - // Set water bottom height. + // Set water bottom height. TODO: Calculate here. _waterBottomHeight = GetWaterDepth(_position.x, _position.y, _position.z, _roomNumber); return *_waterBottomHeight; @@ -199,7 +199,7 @@ namespace TEN::Collision::Point if (_waterTopHeight.has_value()) return *_waterTopHeight; - // Set water top height. + // Set water top height. TODO: Calculate here. _waterTopHeight = GetWaterHeight(_position.x, _position.y, _position.z, _roomNumber); return *_waterTopHeight; From ad8215830191637e1d4048d3ca9e55f4e078ce48 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 26 Apr 2024 17:51:53 +1000 Subject: [PATCH 100/410] Illegal slope -> steep slope --- TombEngine/Game/Lara/PlayerContext.cpp | 12 ++++++------ TombEngine/Game/Lara/lara_overhang.cpp | 2 +- TombEngine/Game/Lara/lara_tests.cpp | 4 ++-- TombEngine/Game/collision/Point.cpp | 16 ++++++++-------- TombEngine/Game/collision/Point.h | 4 ++-- TombEngine/Game/collision/collide_room.cpp | 4 ++-- TombEngine/Game/collision/collide_room.h | 4 ++-- TombEngine/Game/collision/floordata.cpp | 2 +- TombEngine/Game/collision/floordata.h | 8 ++++---- TombEngine/Game/misc.cpp | 2 +- TombEngine/Game/pickup/pickup.cpp | 4 ++-- .../Object/Pushable/PushableCollision.cpp | 2 +- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 2 +- TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 2 +- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 2 +- TombEngine/Objects/TR3/Vehicles/quad_bike.cpp | 2 +- TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp | 2 +- TombEngine/Objects/TR4/Vehicles/jeep.cpp | 2 +- TombEngine/Objects/TR4/Vehicles/motorbike.cpp | 2 +- TombEngine/Specific/level.cpp | 8 ++++---- 20 files changed, 43 insertions(+), 43 deletions(-) diff --git a/TombEngine/Game/Lara/PlayerContext.cpp b/TombEngine/Game/Lara/PlayerContext.cpp index 0bffbec87..8d71d80a7 100644 --- a/TombEngine/Game/Lara/PlayerContext.cpp +++ b/TombEngine/Game/Lara/PlayerContext.cpp @@ -179,14 +179,14 @@ namespace TEN::Entities::Player // 1) Check for illegal slope below floor (if applicable). if (setup.TestIllegalFloorBelow && - (pointColl.IsIllegalFloor() && abs(aspectAngleDelta) <= SLOPE_ASPECT_ANGLE_DELTA_MAX)) + (pointColl.IsSteepFloor() && abs(aspectAngleDelta) <= SLOPE_ASPECT_ANGLE_DELTA_MAX)) { return false; } // 1) Check for illegal slope above floor (if applicable). if (setup.TestIllegalFloorAbove && - (pointColl.IsIllegalFloor() && abs(aspectAngleDelta) >= SLOPE_ASPECT_ANGLE_DELTA_MAX)) + (pointColl.IsSteepFloor() && abs(aspectAngleDelta) >= SLOPE_ASPECT_ANGLE_DELTA_MAX)) { return false; } @@ -407,7 +407,7 @@ namespace TEN::Entities::Player // 2) Assess point collision. if (abs(relFloorHeight) <= ABS_FLOOR_BOUND && // Floor height is within upper/lower floor bounds. - pointColl.IsIllegalFloor()) // Floor is a slippery slope. + pointColl.IsSteepFloor()) // Floor is a slippery slope. { return true; } @@ -543,7 +543,7 @@ namespace TEN::Entities::Player // Assess point collision. if (floorHeightDelta > FLOOR_BOUND || // Avoid floor height delta beyond crawl stepup threshold. floorToCeilHeight <= FLOOR_TO_CEIL_HEIGHT_MAX || // Avoid narrow spaces. - pointColl1.IsIllegalFloor()) // Avoid slippery floor slopes. + pointColl1.IsSteepFloor()) // Avoid slippery floor slopes. { return false; } @@ -609,7 +609,7 @@ namespace TEN::Entities::Player auto pointColl = GetPointCollision(item); // 2) Test for slippery ceiling slope and check if overhang climb is disabled. - if (pointColl.IsIllegalCeiling() && !g_GameFlow->HasOverhangClimb()) + if (pointColl.IsSteepCeiling() && !g_GameFlow->HasOverhangClimb()) return true; // 3) Assess point collision. @@ -667,7 +667,7 @@ namespace TEN::Entities::Player return false; // 2) Test for illegal ceiling. - if (pointColl.IsIllegalCeiling()) + if (pointColl.IsSteepCeiling()) return false; int vPos = item.Pose.Position.y; diff --git a/TombEngine/Game/Lara/lara_overhang.cpp b/TombEngine/Game/Lara/lara_overhang.cpp index 72cc86ad0..12f04361e 100644 --- a/TombEngine/Game/Lara/lara_overhang.cpp +++ b/TombEngine/Game/Lara/lara_overhang.cpp @@ -972,7 +972,7 @@ bool LadderMonkeyExtra(ItemInfo* item, CollisionInfo* coll) { auto probe = GetPointCollision(*item); - if (probe.IsIllegalCeiling()) + if (probe.IsSteepCeiling()) return false; if (probe.GetBottomSector().Flags.Monkeyswing && (item->Pose.Position.y - coll->Setup.Height - CLICK(0.5f) <= probe.GetCeilingHeight())) diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 4612b0217..9d24bc0ea 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -881,7 +881,7 @@ bool TestPlayerWaterStepOut(ItemInfo* item, CollisionInfo* coll) int vPos = item->Pose.Position.y; if (coll->CollisionType == CollisionType::Front || - pointColl.IsIllegalFloor() || + pointColl.IsSteepFloor() || (pointColl.GetFloorHeight() - vPos) <= 0) { return false; @@ -1602,7 +1602,7 @@ CrawlVaultTestResult TestLaraCrawlVaultTolerance(ItemInfo* item, CollisionInfo* auto probeB = GetPointCollision(*item, item->Pose.Orientation.y, testSetup.DestDist, -LARA_HEIGHT_CRAWL); // Approximate destination. auto probeMiddle = GetPointCollision(*item); - bool isSlope = testSetup.CheckSlope ? probeB.IsIllegalFloor() : false; + bool isSlope = testSetup.CheckSlope ? probeB.IsSteepFloor() : false; bool isDeath = testSetup.CheckDeath ? probeB.GetSector().Flags.Death : false; // Discard walls. diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index 7c8b12c59..8790423a3 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -211,24 +211,24 @@ namespace TEN::Collision::Point GetFloorHeight() <= GetCeilingHeight()); } - bool PointCollisionData::IsIllegalFloor() + bool PointCollisionData::IsSteepFloor() { short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetFloorNormal()); - short illegalSlopeAngle = (GetFloorBridgeItemNumber() != NO_VALUE) ? - DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE : + short steepSlopeAngle = (GetFloorBridgeItemNumber() != NO_VALUE) ? + DEFAULT_STEEP_FLOOR_SLOPE_ANGLE : GetBottomSector().GetSurfaceIllegalSlopeAngle(_position.x, _position.z, true); - return (abs(slopeAngle) >= illegalSlopeAngle); + return (abs(slopeAngle) >= steepSlopeAngle); } - bool PointCollisionData::IsIllegalCeiling() + bool PointCollisionData::IsSteepCeiling() { short slopeAngle = Geometry::GetSurfaceSlopeAngle(GetCeilingNormal(), -Vector3::UnitY); - short illegalSlopeAngle = (GetCeilingBridgeItemNumber() != NO_VALUE) ? - DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE : + short steepSlopeAngle = (GetCeilingBridgeItemNumber() != NO_VALUE) ? + DEFAULT_STEEP_CEILING_SLOPE_ANGLE : GetTopSector().GetSurfaceIllegalSlopeAngle(_position.x, _position.z, false); - return (abs(slopeAngle) >= illegalSlopeAngle); + return (abs(slopeAngle) >= steepSlopeAngle); } bool PointCollisionData::IsDiagonalFloorStep() diff --git a/TombEngine/Game/collision/Point.h b/TombEngine/Game/collision/Point.h index cf8150b60..9f1651f10 100644 --- a/TombEngine/Game/collision/Point.h +++ b/TombEngine/Game/collision/Point.h @@ -57,8 +57,8 @@ namespace TEN::Collision::Point // Inquirers bool IsWall(); - bool IsIllegalFloor(); - bool IsIllegalCeiling(); + bool IsSteepFloor(); + bool IsSteepCeiling(); bool IsDiagonalFloorStep(); bool IsDiagonalCeilingStep(); bool IsDiagonalFloorSplit(); diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 52ac15f32..3ca9517cd 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -128,8 +128,8 @@ static CollisionPositionData GetCollisionPosition(PointCollisionData& pointColl) collPos.Ceiling = pointColl.GetCeilingHeight(); collPos.Bridge = pointColl.GetFloorBridgeItemNumber(); collPos.SplitAngle = pointColl.GetBottomSector().FloorSurface.SplitAngle; - collPos.FloorSlope = pointColl.IsIllegalFloor(); - collPos.CeilingSlope = pointColl.IsIllegalCeiling(); + collPos.FloorSlope = pointColl.IsSteepFloor(); + collPos.CeilingSlope = pointColl.IsSteepCeiling(); collPos.DiagonalStep = pointColl.IsDiagonalFloorStep(); return collPos; diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 52a215687..1dc1c5ef2 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -16,8 +16,8 @@ constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBou constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound. constexpr auto COLLISION_CHECK_DISTANCE = BLOCK(8); -constexpr auto DEFAULT_ILLEGAL_FLOOR_SLOPE_ANGLE = ANGLE(36.0f); -constexpr auto DEFAULT_ILLEGAL_CEILING_SLOPE_ANGLE = ANGLE(45.0f); +constexpr auto DEFAULT_STEEP_FLOOR_SLOPE_ANGLE = ANGLE(36.0f); +constexpr auto DEFAULT_STEEP_CEILING_SLOPE_ANGLE = ANGLE(45.0f); enum class CollisionType { diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 470df2dc7..a15e2d8fe 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -62,7 +62,7 @@ Vector3 FloorInfo::GetSurfaceNormal(int x, int z, bool isFloor) const short FloorInfo::GetSurfaceIllegalSlopeAngle(int x, int z, bool isFloor) const { const auto& tri = GetSurfaceTriangle(x, z, isFloor); - return tri.IllegalSlopeAngle; + return tri.SteepSlopeAngle; } MaterialType FloorInfo::GetSurfaceMaterial(int x, int z, bool isFloor) const diff --git a/TombEngine/Game/collision/floordata.h b/TombEngine/Game/collision/floordata.h index 16662eeca..891e130f5 100644 --- a/TombEngine/Game/collision/floordata.h +++ b/TombEngine/Game/collision/floordata.h @@ -74,10 +74,10 @@ public: struct SectorSurfaceTriangleData { - Plane Plane = {}; - int PortalRoomNumber = 0; - short IllegalSlopeAngle = 0; - MaterialType Material = MaterialType::Stone; + Plane Plane = {}; + int PortalRoomNumber = 0; + short SteepSlopeAngle = 0; + MaterialType Material = MaterialType::Stone; }; struct SectorSurfaceData diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 3f5af7186..b9d789402 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -55,7 +55,7 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist) return false; // Test for slippery slope. - if (pointColl.IsIllegalFloor()) + if (pointColl.IsSteepFloor()) return false; // Flat floor. diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index 86d2fee4b..0dff72dda 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -860,7 +860,7 @@ void DropPickups(ItemInfo* item) auto collPoint = GetPointCollision(candidatePos, item->RoomNumber); // If position is inside a wall or on a slope, don't use it. - if (collPoint.GetFloorHeight() == NO_HEIGHT || collPoint.IsIllegalFloor()) + if (collPoint.GetFloorHeight() == NO_HEIGHT || collPoint.IsSteepFloor()) continue; // Remember floor position for a tested point. @@ -872,7 +872,7 @@ void DropPickups(ItemInfo* item) collPoint = GetPointCollision(candidatePos, item->RoomNumber); // If position is inside a wall or on a slope, don't use it. - if (collPoint.GetFloorHeight() == NO_HEIGHT || collPoint.IsIllegalFloor()) + if (collPoint.GetFloorHeight() == NO_HEIGHT || collPoint.IsSteepFloor()) continue; // If position is not in the same room, don't use it. diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 39ac6d5e7..733ae4c86 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -86,7 +86,7 @@ namespace TEN::Entities::Generic } // 3) Check for slippery floor slope. - if (pointColl.IsIllegalFloor()) + if (pointColl.IsSteepFloor()) return false; // 4) Check for diagonal floor step. diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index 47ec2fa3c..0032ae11b 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -189,7 +189,7 @@ namespace TEN::Entities::Vehicles auto probe = GetPointCollision(*skidooItem, angle, -SKIDOO_DISMOUNT_DISTANCE); - if ((probe.IsIllegalFloor() || probe.GetFloorHeight() == NO_HEIGHT) || + if ((probe.IsSteepFloor() || probe.GetFloorHeight() == NO_HEIGHT) || abs(probe.GetFloorHeight() - skidooItem->Pose.Position.y) > CLICK(2) || ((probe.GetCeilingHeight() - skidooItem->Pose.Position.y) > -LARA_HEIGHT || (probe.GetFloorHeight() - probe.GetCeilingHeight()) < LARA_HEIGHT)) diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index 037c06ab8..f0914c1b7 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -244,7 +244,7 @@ namespace TEN::Entities::Vehicles if ((probe.GetFloorHeight() - speedboatItem->Pose.Position.y) < -CLICK(2)) return false; - if (probe.IsIllegalFloor() || + if (probe.IsSteepFloor() || probe.GetFloorHeight() == NO_HEIGHT) { return false; diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index 21215c3f9..75de38a5e 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -264,7 +264,7 @@ namespace TEN::Entities::Vehicles auto probe = GetPointCollision(*minecartItem, angle, -MINECART_DISMOUNT_DISTANCE); - if (probe.IsIllegalFloor() || probe.GetFloorHeight() == NO_HEIGHT) + if (probe.IsSteepFloor() || probe.GetFloorHeight() == NO_HEIGHT) return false; if (abs(probe.GetFloorHeight() - minecartItem->Pose.Position.y) > CLICK(2)) diff --git a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp index 6dc3a4f5f..c8ae399b1 100644 --- a/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp +++ b/TombEngine/Objects/TR3/Vehicles/quad_bike.cpp @@ -240,7 +240,7 @@ namespace TEN::Entities::Vehicles auto pointColl = GetPointCollision(Vector3i(x, y, z), quadBikeItem->RoomNumber); - if (pointColl.IsIllegalFloor() || + if (pointColl.IsSteepFloor() || pointColl.GetFloorHeight() == NO_HEIGHT) { return false; diff --git a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp index 4466ff811..ef36e34c7 100644 --- a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp +++ b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp @@ -611,7 +611,7 @@ namespace TEN::Entities::Vehicles if ((pointColl.GetFloorHeight() - sBoatItem->Pose.Position.y) < -512) return false; - if (pointColl.IsIllegalFloor() || pointColl.GetFloorHeight() == NO_HEIGHT) + if (pointColl.IsSteepFloor() || pointColl.GetFloorHeight() == NO_HEIGHT) return false; if ((pointColl.GetCeilingHeight() - sBoatItem->Pose.Position.y) > -LARA_HEIGHT || diff --git a/TombEngine/Objects/TR4/Vehicles/jeep.cpp b/TombEngine/Objects/TR4/Vehicles/jeep.cpp index 169e254e6..70258a975 100644 --- a/TombEngine/Objects/TR4/Vehicles/jeep.cpp +++ b/TombEngine/Objects/TR4/Vehicles/jeep.cpp @@ -376,7 +376,7 @@ namespace TEN::Entities::Vehicles auto probe = GetPointCollision(Vector3i(x, y, z), jeepItem->RoomNumber); - if (probe.IsIllegalFloor() || probe.GetFloorHeight() == NO_HEIGHT) + if (probe.IsSteepFloor() || probe.GetFloorHeight() == NO_HEIGHT) return false; if (abs(probe.GetFloorHeight() - jeepItem->Pose.Position.y) > BLOCK(1 / 2.0f)) diff --git a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp index 985ab5360..8ccee05d0 100644 --- a/TombEngine/Objects/TR4/Vehicles/motorbike.cpp +++ b/TombEngine/Objects/TR4/Vehicles/motorbike.cpp @@ -749,7 +749,7 @@ namespace TEN::Entities::Vehicles short angle = motorbikeItem->Pose.Orientation.y + ANGLE(90.0f); auto collResult = GetPointCollision(*motorbikeItem, angle, MOTORBIKE_RADIUS); - if (collResult.IsIllegalFloor() || collResult.GetFloorHeight() == NO_HEIGHT) // Was previously set to -NO_HEIGHT by TokyoSU -- Lwmte 23.08.21 + if (collResult.IsSteepFloor() || collResult.GetFloorHeight() == NO_HEIGHT) // Was previously set to -NO_HEIGHT by TokyoSU -- Lwmte 23.08.21 return false; if (abs(collResult.GetFloorHeight() - motorbikeItem->Pose.Position.y) > CLICK(1)) diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index 6e5941fe8..d3e4e1fbc 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -790,16 +790,16 @@ void ReadRooms() sector.Stopper = (bool)ReadInt32(); sector.FloorSurface.SplitAngle = FROM_RAD(ReadFloat()); - sector.FloorSurface.Triangles[0].IllegalSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; - sector.FloorSurface.Triangles[1].IllegalSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; + sector.FloorSurface.Triangles[0].SteepSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; + sector.FloorSurface.Triangles[1].SteepSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; sector.FloorSurface.Triangles[0].PortalRoomNumber = ReadInt32(); sector.FloorSurface.Triangles[1].PortalRoomNumber = ReadInt32(); sector.FloorSurface.Triangles[0].Plane = ConvertFakePlaneToPlane(ReadVector3(), true); sector.FloorSurface.Triangles[1].Plane = ConvertFakePlaneToPlane(ReadVector3(), true); sector.CeilingSurface.SplitAngle = FROM_RAD(ReadFloat()); - sector.CeilingSurface.Triangles[0].IllegalSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; - sector.CeilingSurface.Triangles[1].IllegalSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; + sector.CeilingSurface.Triangles[0].SteepSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; + sector.CeilingSurface.Triangles[1].SteepSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; sector.CeilingSurface.Triangles[0].PortalRoomNumber = ReadInt32(); sector.CeilingSurface.Triangles[1].PortalRoomNumber = ReadInt32(); sector.CeilingSurface.Triangles[0].Plane = ConvertFakePlaneToPlane(ReadVector3(), false); From 29a5fc74113eebab067430d220a85c403974351a Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 26 Apr 2024 12:43:10 +0300 Subject: [PATCH 101/410] UseItem event (#1357) * Implement UseItem event, refactor item usage a bit * Decopypaste medipack hotkey usage code * Prevent small and large medipacks from being used simultaneously; tidy up UseItem() --------- Co-authored-by: Sezz --- Documentation/doc/1 modules/Inventory.html | 40 +- Documentation/doc/1 modules/Logic.html | 3 +- TombEngine/Game/Lara/lara_helpers.cpp | 55 +-- TombEngine/Game/control/event.h | 1 + TombEngine/Game/control/volume.cpp | 6 +- TombEngine/Game/control/volume.h | 2 +- TombEngine/Game/gui.cpp | 408 ++++++++---------- TombEngine/Game/gui.h | 4 +- .../Scripting/Include/ScriptInterfaceGame.h | 3 +- .../Scripting/Internal/ReservedScriptNames.h | 42 +- .../TEN/Inventory/InventoryHandler.cpp | 34 +- .../Internal/TEN/Logic/LogicHandler.cpp | 12 +- .../Internal/TEN/Logic/LogicHandler.h | 2 + 13 files changed, 281 insertions(+), 331 deletions(-) diff --git a/Documentation/doc/1 modules/Inventory.html b/Documentation/doc/1 modules/Inventory.html index f0df17c5b..3d0cf51a8 100644 --- a/Documentation/doc/1 modules/Inventory.html +++ b/Documentation/doc/1 modules/Inventory.html @@ -125,16 +125,16 @@ Set the amount of an item in the player's inventory. - GetChosenItem() - Get last selected item in the player's inventory. + GetUsedItem() + Get last item used in the player's inventory. - SetChosenItem(objectID) - Set last selected item in the player's inventory. + SetUsedItem(objectID) + Set last item used in the player's inventory. - ClearChosenItem() - Clear last selected item in the player's inventory. + ClearUsedItem() + Clear last item used in the player's inventory. @@ -259,14 +259,13 @@
    - - GetChosenItem() + + GetUsedItem()
    - Get last selected item in the player's inventory. + Get last item used in the player's inventory. This value will be valid only for a single frame after exiting inventory, after which Lara says "No". - Therefore, this function must be preferably used either in OnLoop events or callbacks. - If you have used this function and you want to avoid "No" sound, you should use ClearChosenItem function. + Therefore, this function must be preferably used either in OnLoop or OnUseItem events. @@ -275,7 +274,7 @@
      ObjID - Last selected item in the inventory. + Last item used in the inventory.
    @@ -283,12 +282,12 @@
    - - SetChosenItem(objectID) + + SetUsedItem(objectID)
    - Set last selected item in the player's inventory. - You will be able to select only objects which already exist in inventory. + Set last item used in the player's inventory. + You will be able to specify only objects which already exist in the inventory. Will only be valid for the next frame. If not processed by the game, Lara will say "No". @@ -307,12 +306,13 @@
    - - ClearChosenItem() + + ClearUsedItem()
    - Clear last selected item in the player's inventory. - This function is needed to avoid Lara saying "No" after selecting particular item in inventory. + Clear last item used in the player's inventory. + When this function is used in OnUseItem level function, it allows to override existing item functionality. + For items without existing functionality, this function is needed to avoid Lara saying "No" after using it. diff --git a/Documentation/doc/1 modules/Logic.html b/Documentation/doc/1 modules/Logic.html index e190f3c99..3bf36c12d 100644 --- a/Documentation/doc/1 modules/Logic.html +++ b/Documentation/doc/1 modules/Logic.html @@ -263,7 +263,8 @@ LOAD SAVE START END -LOOP +LOOP +USEITEM

    Parameters:

    diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 80ea111fc..3b137afe9 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -276,49 +276,6 @@ void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWa } } -static void UsePlayerMedipack(ItemInfo& item) -{ - auto& player = GetLaraInfo(item); - - // Can't use medipack; return early. - if (item.HitPoints <= 0 || - (item.HitPoints >= LARA_HEALTH_MAX && player.Status.Poison == 0)) - { - return; - } - - bool hasUsedMedipack = false; - - if (IsClicked(In::SmallMedipack) && - player.Inventory.TotalSmallMedipacks != 0) - { - hasUsedMedipack = true; - - item.HitPoints += LARA_HEALTH_MAX / 2; - if (item.HitPoints > LARA_HEALTH_MAX) - item.HitPoints = LARA_HEALTH_MAX; - - if (player.Inventory.TotalSmallMedipacks != -1) - player.Inventory.TotalSmallMedipacks--; - } - else if (IsClicked(In::LargeMedipack) && - player.Inventory.TotalLargeMedipacks != 0) - { - hasUsedMedipack = true; - item.HitPoints = LARA_HEALTH_MAX; - - if (player.Inventory.TotalLargeMedipacks != -1) - player.Inventory.TotalLargeMedipacks--; - } - - if (hasUsedMedipack) - { - player.Status.Poison = 0; - SaveGame::Statistics.Game.HealthUsed++; - SoundEffect(SFX_TR4_MENU_MEDI, nullptr, SoundEnvironment::Always); - } -} - static std::optional GetPlayerScrolledWeaponType(const ItemInfo& item, LaraWeaponType currentWeaponType, bool getPrev) { static const auto SCROLL_WEAPON_TYPES = std::vector @@ -376,8 +333,14 @@ void HandlePlayerQuickActions(ItemInfo& item) auto& player = GetLaraInfo(item); // Handle medipacks. - if (IsClicked(In::SmallMedipack) || IsClicked(In::LargeMedipack)) - UsePlayerMedipack(item); + if (IsClicked(In::SmallMedipack)) + { + g_Gui.UseItem(item, GAME_OBJECT_ID::ID_SMALLMEDI_ITEM); + } + else if (IsClicked(In::LargeMedipack)) + { + g_Gui.UseItem(item, GAME_OBJECT_ID::ID_BIGMEDI_ITEM); + } // Handle weapon scroll request. if (IsClicked(In::PreviousWeapon) || IsClicked(In::NextWeapon)) @@ -419,7 +382,7 @@ void HandlePlayerQuickActions(ItemInfo& item) // TODO: 10th possible weapon, probably grapple gun. /*if (IsClicked(In::Weapon10) && player.Weapons[(int)LaraWeaponType::].Present) - player.Control.Weapon.RequestGunType = LaraWeaponType::;*/ + player.Control.Weapon.RequestGunType = LaraWeaponType::;*/ } bool CanPlayerLookAround(const ItemInfo& item) diff --git a/TombEngine/Game/control/event.h b/TombEngine/Game/control/event.h index 771b60112..2b712efec 100644 --- a/TombEngine/Game/control/event.h +++ b/TombEngine/Game/control/event.h @@ -41,6 +41,7 @@ namespace TEN::Control::Volumes Save, Start, End, + UseItem, Count }; diff --git a/TombEngine/Game/control/volume.cpp b/TombEngine/Game/control/volume.cpp index a15f4ad2a..80984208a 100644 --- a/TombEngine/Game/control/volume.cpp +++ b/TombEngine/Game/control/volume.cpp @@ -89,14 +89,16 @@ namespace TEN::Control::Volumes return nullptr; } - void HandleEvent(Event& event, Activator& activator) + bool HandleEvent(Event& event, Activator& activator) { if (event.Function.empty() || event.CallCounter == 0 || event.CallCounter < NO_CALL_COUNTER) - return; + return false; g_GameScript->ExecuteFunction(event.Function, activator, event.Data); if (event.CallCounter != NO_CALL_COUNTER) event.CallCounter--; + + return true; } bool HandleEvent(const std::string& name, EventType eventType, Activator activator) diff --git a/TombEngine/Game/control/volume.h b/TombEngine/Game/control/volume.h index 9d9fc6a84..28694aef8 100644 --- a/TombEngine/Game/control/volume.h +++ b/TombEngine/Game/control/volume.h @@ -43,7 +43,7 @@ namespace TEN::Control::Volumes void TestVolumes(short roomNumber, MESH_INFO* mesh); void TestVolumes(CAMERA_INFO* camera); - void HandleEvent(Event& event, Activator& activator); + bool HandleEvent(Event& event, Activator& activator); bool HandleEvent(const std::string& name, EventType eventType, Activator activator); void HandleAllGlobalEvents(EventType type, Activator& activator); bool SetEventState(const std::string& name, EventType eventType, bool enabled); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index e1e74e083..2e2bf148d 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -6,6 +6,7 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/control/control.h" +#include "Game/control/volume.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_fire.h" @@ -1876,7 +1877,7 @@ namespace TEN::Gui AlterFOV(ANGLE(DEFAULT_FOV), false); lara->Inventory.IsBusy = false; InventoryItemChosen = NO_VALUE; - UseItem = false; + ItemUsed = false; if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite()) { @@ -2030,16 +2031,16 @@ namespace TEN::Gui } } - void GuiController::UseCurrentItem(ItemInfo* item) + void GuiController::UseItem(ItemInfo& item, int objectNumber) { - const std::vector CrouchStates = + const auto CROUCH_STATES = std::vector { LS_CROUCH_IDLE, LS_CROUCH_TURN_LEFT, LS_CROUCH_TURN_RIGHT, LS_CROUCH_TURN_180 }; - const std::vector CrawlStates = + const auto CRAWL_STATES = std::vector { LS_CRAWL_IDLE, LS_CRAWL_FORWARD, @@ -2050,265 +2051,232 @@ namespace TEN::Gui LS_CRAWL_TO_HANG }; - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(item); - int prevOpticRange = lara->Control.Look.OpticRange; - short inventoryObject = Rings[(int)RingTypes::Inventory].CurrentObjectList[Rings[(int)RingTypes::Inventory].CurrentObjectInList].InventoryItem; - short gameObject = InventoryObjectTable[inventoryObject].ObjectNumber; + short prevOpticRange = player.Control.Look.OpticRange; + player.Control.Look.OpticRange = 0; + player.Inventory.OldBusy = false; + item.MeshBits = ALL_JOINT_BITS; - item->MeshBits = ALL_JOINT_BITS; - lara->Control.Look.OpticRange = 0; - lara->Inventory.OldBusy = false; + InventoryItemChosen = objectNumber; - if (lara->Control.WaterStatus == WaterStatus::Dry || - lara->Control.WaterStatus == WaterStatus::Wade) + // Use item event handling. + g_GameScript->OnUseItem((GAME_OBJECT_ID)InventoryItemChosen); + HandleAllGlobalEvents(EventType::UseItem, (Activator)item.Index); + + // Quickly discard further processing if chosen item was reset in script. + if (InventoryItemChosen == NO_VALUE) + return; + + if (InventoryItemChosen == ID_PISTOLS_ITEM || + InventoryItemChosen == ID_UZI_ITEM || + InventoryItemChosen == ID_REVOLVER_ITEM) { - if (gameObject == ID_PISTOLS_ITEM) + if (player.Control.WaterStatus != WaterStatus::Dry && + player.Control.WaterStatus != WaterStatus::Wade) { - lara->Control.Weapon.RequestGunType = LaraWeaponType::Pistol; - - if (lara->Control.HandStatus != HandStatus::Free) - return; - - if (lara->Control.Weapon.GunType == LaraWeaponType::Pistol) - lara->Control.HandStatus = HandStatus::WeaponDraw; - return; } - if (gameObject == ID_UZI_ITEM) + switch (InventoryItemChosen) { - lara->Control.Weapon.RequestGunType = LaraWeaponType::Uzi; + case ID_PISTOLS_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::Pistol; + break; - if (lara->Control.HandStatus != HandStatus::Free) + case ID_UZI_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::Uzi; + break; + + case ID_REVOLVER_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::Revolver; + break; + + default: return; - - if (lara->Control.Weapon.GunType == LaraWeaponType::Uzi) - lara->Control.HandStatus = HandStatus::WeaponDraw; - - return; } + + if (player.Control.HandStatus == HandStatus::Free && + player.Control.Weapon.GunType == player.Control.Weapon.RequestGunType) + { + player.Control.HandStatus = HandStatus::WeaponDraw; + } + + InventoryItemChosen = NO_VALUE; + return; } - if (gameObject != ID_SHOTGUN_ITEM && - gameObject != ID_REVOLVER_ITEM && - gameObject != ID_HK_ITEM && - gameObject != ID_CROSSBOW_ITEM && - gameObject != ID_GRENADE_GUN_ITEM && - gameObject != ID_ROCKET_LAUNCHER_ITEM && - gameObject != ID_HARPOON_ITEM) + if (InventoryItemChosen == ID_SHOTGUN_ITEM || + InventoryItemChosen == ID_HK_ITEM || + InventoryItemChosen == ID_CROSSBOW_ITEM || + InventoryItemChosen == ID_GRENADE_GUN_ITEM || + InventoryItemChosen == ID_ROCKET_LAUNCHER_ITEM || + InventoryItemChosen == ID_HARPOON_ITEM) { - if (gameObject == ID_FLARE_INV_ITEM) + if (InventoryItemChosen != ID_HARPOON_ITEM && + player.Control.WaterStatus != WaterStatus::Dry && + player.Control.WaterStatus != WaterStatus::Wade) { - if (lara->Control.HandStatus == HandStatus::Free) - { - if (!TestState(item->Animation.ActiveState, CrawlStates)) - { - if (lara->Control.Weapon.GunType != LaraWeaponType::Flare) - { - // HACK. - ClearAllActions(); - ActionMap[(int)In::Flare].Update(1.0f); - - HandleWeapon(*item); - ClearAllActions(); - } - - return; - } - } - - SayNo(); return; } - switch (inventoryObject) + if (TestState(item.Animation.ActiveState, CROUCH_STATES) || + TestState(item.Animation.ActiveState, CRAWL_STATES)) { - case INV_OBJECT_BINOCULARS: - if (((item->Animation.ActiveState == LS_IDLE && item->Animation.AnimNumber == LA_STAND_IDLE) || - (lara->Control.IsLow && !IsHeld(In::Crouch))) && - !UseSpotCam && !TrackCameraInit) - { - lara->Control.Look.OpticRange = 128; - lara->Control.Look.IsUsingBinoculars = true; - lara->Inventory.OldBusy = true; - - // TODO: To prevent Lara from crouching or performing other actions, the inherent state of - // LA_BINOCULARS_IDLE must be changed to LS_IDLE. @Sezz 2022.05.19 - //SetAnimation(item, LA_BINOCULARS_IDLE); - - if (lara->Control.HandStatus != HandStatus::Free) - lara->Control.HandStatus = HandStatus::WeaponUndraw; - } - - if (prevOpticRange) - { - lara->Control.Look.OpticRange = prevOpticRange; - } - else - { - BinocularOldCamera = Camera.oldType; - } - - return; - - case INV_OBJECT_SMALL_MEDIPACK: - - if ((item->HitPoints <= 0 || item->HitPoints >= LARA_HEALTH_MAX) && - lara->Status.Poison == 0) - { - SayNo(); - return; - } - - if (lara->Inventory.TotalSmallMedipacks != 0) - { - if (lara->Inventory.TotalSmallMedipacks != -1) - lara->Inventory.TotalSmallMedipacks--; - - lara->Status.Poison = 0; - item->HitPoints += LARA_HEALTH_MAX / 2; - - if (item->HitPoints > LARA_HEALTH_MAX) - item->HitPoints = LARA_HEALTH_MAX; - - SoundEffect(SFX_TR4_MENU_MEDI, nullptr, SoundEnvironment::Always); - SaveGame::Statistics.Game.HealthUsed++; - } - else - SayNo(); - - return; - - case INV_OBJECT_LARGE_MEDIPACK: - - if ((item->HitPoints <= 0 || item->HitPoints >= LARA_HEALTH_MAX) && - lara->Status.Poison == 0) - { - SayNo(); - return; - } - - if (lara->Inventory.TotalLargeMedipacks != 0) - { - if (lara->Inventory.TotalLargeMedipacks != -1) - lara->Inventory.TotalLargeMedipacks--; - - lara->Status.Poison = 0; - item->HitPoints = LARA_HEALTH_MAX; - - SoundEffect(SFX_TR4_MENU_MEDI, nullptr, SoundEnvironment::Always); - SaveGame::Statistics.Game.HealthUsed++; - } - else - SayNo(); - - return; - - default: - InventoryItemChosen = gameObject; return; } + switch (InventoryItemChosen) + { + case ID_SHOTGUN_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::Shotgun; + break; + + case ID_REVOLVER_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::Revolver; + break; + + case ID_HK_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::HK; + break; + + case ID_CROSSBOW_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::Crossbow; + break; + + case ID_GRENADE_GUN_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::GrenadeLauncher; + break; + + case ID_HARPOON_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::HarpoonGun; + break; + + case ID_ROCKET_LAUNCHER_ITEM: + player.Control.Weapon.RequestGunType = LaraWeaponType::RocketLauncher; + break; + + default: + return; + } + + if (player.Control.HandStatus == HandStatus::Free && + player.Control.Weapon.GunType == player.Control.Weapon.RequestGunType) + { + player.Control.HandStatus = HandStatus::WeaponDraw; + } + + InventoryItemChosen = NO_VALUE; return; } - if (lara->Control.HandStatus == HandStatus::Busy) + switch (InventoryItemChosen) { - SayNo(); - return; - } - - if (TestState(item->Animation.ActiveState, CrouchStates) || - TestState(item->Animation.ActiveState, CrawlStates)) - { - SayNo(); - return; - } - - if (gameObject == ID_SHOTGUN_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::Shotgun; - - if (lara->Control.HandStatus != HandStatus::Free) + case ID_FLARE_INV_ITEM: + if (player.Control.HandStatus != HandStatus::Free) return; - if (lara->Control.Weapon.GunType == LaraWeaponType::Shotgun) - lara->Control.HandStatus = HandStatus::WeaponDraw; + if (!TestState(item.Animation.ActiveState, CRAWL_STATES)) + { + if (player.Control.Weapon.GunType != LaraWeaponType::Flare) + { + // HACK. + ClearAllActions(); + ActionMap[(int)In::Flare].Update(1.0f); + HandleWeapon(item); + ClearAllActions(); + } + } + + InventoryItemChosen = NO_VALUE; return; - } - if (gameObject == ID_REVOLVER_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::Revolver; + case ID_BINOCULARS_ITEM: + if (((item.Animation.ActiveState == LS_IDLE && item.Animation.AnimNumber == LA_STAND_IDLE) || + (player.Control.IsLow && !IsHeld(In::Crouch))) && + !UseSpotCam && !TrackCameraInit) + { + player.Control.Look.OpticRange = ANGLE(0.7f); + player.Control.Look.IsUsingBinoculars = true; + player.Inventory.OldBusy = true; - if (lara->Control.HandStatus != HandStatus::Free) - return; + // TODO: To prevent Lara from crouching or performing other actions, the inherent state of + // LA_BINOCULARS_IDLE must be changed to LS_IDLE. @Sezz 2022.05.19 + //SetAnimation(item, LA_BINOCULARS_IDLE); - if (lara->Control.Weapon.GunType == LaraWeaponType::Revolver) - lara->Control.HandStatus = HandStatus::WeaponDraw; + if (player.Control.HandStatus != HandStatus::Free) + player.Control.HandStatus = HandStatus::WeaponUndraw; + } + if (prevOpticRange != ANGLE(0.0f)) + { + player.Control.Look.OpticRange = prevOpticRange; + } + else + { + BinocularOldCamera = Camera.oldType; + } + + InventoryItemChosen = NO_VALUE; return; - } - else if (gameObject == ID_HK_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::HK; - if (lara->Control.HandStatus != HandStatus::Free) + case ID_SMALLMEDI_ITEM: + if ((item.HitPoints <= 0 || item.HitPoints >= LARA_HEALTH_MAX) && + player.Status.Poison == 0) + { return; + } - if (lara->Control.Weapon.GunType == LaraWeaponType::HK) - lara->Control.HandStatus = HandStatus::WeaponDraw; + if (player.Inventory.TotalSmallMedipacks != 0) + { + if (player.Inventory.TotalSmallMedipacks != NO_VALUE) + player.Inventory.TotalSmallMedipacks--; + player.Status.Poison = 0; + item.HitPoints += LARA_HEALTH_MAX / 2; + + if (item.HitPoints > LARA_HEALTH_MAX) + item.HitPoints = LARA_HEALTH_MAX; + + SoundEffect(SFX_TR4_MENU_MEDI, nullptr, SoundEnvironment::Always); + SaveGame::Statistics.Game.HealthUsed++; + } + else + { + return; + } + + InventoryItemChosen = NO_VALUE; return; - } - else if (gameObject == ID_CROSSBOW_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::Crossbow; - if (lara->Control.HandStatus != HandStatus::Free) + case ID_BIGMEDI_ITEM: + if ((item.HitPoints <= 0 || item.HitPoints >= LARA_HEALTH_MAX) && + player.Status.Poison == 0) + { return; + } - if (lara->Control.Weapon.GunType == LaraWeaponType::Crossbow) - lara->Control.HandStatus = HandStatus::WeaponDraw; + if (player.Inventory.TotalLargeMedipacks != 0) + { + if (player.Inventory.TotalLargeMedipacks != NO_VALUE) + player.Inventory.TotalLargeMedipacks--; + player.Status.Poison = 0; + item.HitPoints = LARA_HEALTH_MAX; + + SoundEffect(SFX_TR4_MENU_MEDI, nullptr, SoundEnvironment::Always); + SaveGame::Statistics.Game.HealthUsed++; + } + else + { + return; + } + + InventoryItemChosen = NO_VALUE; return; - } - else if (gameObject == ID_GRENADE_GUN_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::GrenadeLauncher; - - if (lara->Control.HandStatus != HandStatus::Free) - return; - - if (lara->Control.Weapon.GunType == LaraWeaponType::GrenadeLauncher) - lara->Control.HandStatus = HandStatus::WeaponDraw; - - return; - } - else if (gameObject == ID_HARPOON_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::HarpoonGun; - - if (lara->Control.HandStatus != HandStatus::Free) - return; - - if (lara->Control.Weapon.GunType == LaraWeaponType::HarpoonGun) - lara->Control.HandStatus = HandStatus::WeaponDraw; - - return; - } - else if (gameObject == ID_ROCKET_LAUNCHER_ITEM) - { - lara->Control.Weapon.RequestGunType = LaraWeaponType::RocketLauncher; - - if (lara->Control.HandStatus != HandStatus::Free) - return; - - if (lara->Control.Weapon.GunType == LaraWeaponType::RocketLauncher) - lara->Control.HandStatus = HandStatus::WeaponDraw; + default: return; } } @@ -2654,7 +2622,7 @@ namespace TEN::Gui case MenuType::Equip: case MenuType::Use: MenuActive = false; - UseItem = true; + ItemUsed = true; break; case MenuType::Diary: @@ -3382,7 +3350,7 @@ namespace TEN::Gui break; } - if (UseItem && NoAction()) + if (ItemUsed && NoAction()) exitLoop = true; SetEnterInventory(NO_VALUE); @@ -3393,8 +3361,8 @@ namespace TEN::Gui LastInvItem = Rings[(int)RingTypes::Inventory].CurrentObjectList[Rings[(int)RingTypes::Inventory].CurrentObjectInList].InventoryItem; UpdateWeaponStatus(item); - if (UseItem) - UseCurrentItem(item); + if (ItemUsed) + UseItem(*item, InventoryObjectTable[LastInvItem].ObjectNumber); AlterFOV(LastFOV); ResumeAllSounds(SoundPauseMode::Inventory); diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h index f456889bd..bf4a4baea 100644 --- a/TombEngine/Game/gui.h +++ b/TombEngine/Game/gui.h @@ -139,7 +139,7 @@ namespace TEN::Gui // Inventory variables short CombineObject1; short CombineObject2; - bool UseItem; + bool ItemUsed; char SeperateTypeFlag; char CombineTypeFlag; InventoryRing Rings[2]; @@ -181,6 +181,7 @@ namespace TEN::Gui bool PerformWaterskinCombine(ItemInfo* item, bool flag); void DrawCompass(ItemInfo* item); void CancelInventorySelection(); + void UseItem(ItemInfo& item, int objectNumber); // Getters const InventoryRing& GetRing(RingTypes ringType); @@ -221,7 +222,6 @@ namespace TEN::Gui void SeparateObject(ItemInfo* item, int objectNumber); void InsertObjectIntoList(int objectNumber); void InsertObjectIntoList_v2(int objectNumber); - void UseCurrentItem(ItemInfo* item); void SpinBack(EulerAngles& orient); void UpdateWeaponStatus(ItemInfo* item); void DoStatisticsMode(); diff --git a/TombEngine/Scripting/Include/ScriptInterfaceGame.h b/TombEngine/Scripting/Include/ScriptInterfaceGame.h index 7be1be9ec..81958aaaf 100644 --- a/TombEngine/Scripting/Include/ScriptInterfaceGame.h +++ b/TombEngine/Scripting/Include/ScriptInterfaceGame.h @@ -57,8 +57,9 @@ public: virtual void OnLoop(float deltaTime, bool postLoop) = 0; virtual void OnSave() = 0; virtual void OnEnd(GameStatus reason) = 0; - virtual void ShortenTENCalls() = 0; + virtual void OnUseItem(GAME_OBJECT_ID objectNumber) = 0; + virtual void ShortenTENCalls() = 0; virtual void FreeLevelScripts() = 0; virtual void ResetScripts(bool clearGameVars) = 0; virtual void ExecuteScriptFile(const std::string& luaFileName) = 0; diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 181e94953..8d0e58181 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -53,14 +53,6 @@ static constexpr char ScriptReserved_DisplayStringSetScale[] = "SetScale"; static constexpr char ScriptReserved_DisplayStringSetColor[] = "SetColor"; static constexpr char ScriptReserved_DisplaySpriteDraw[] = "Draw"; -// Built-in LevelFuncs -static constexpr char ScriptReserved_OnStart[] = "OnStart"; -static constexpr char ScriptReserved_OnLoad[] = "OnLoad"; -static constexpr char ScriptReserved_OnLoop[] = "OnLoop"; -static constexpr char ScriptReserved_OnControlPhase[] = "OnControlPhase"; // DEPRECATED -static constexpr char ScriptReserved_OnSave[] = "OnSave"; -static constexpr char ScriptReserved_OnEnd[] = "OnEnd"; - static constexpr char ScriptReserved_EndReasonExitToTitle[] = "EXITTOTITLE"; static constexpr char ScriptReserved_EndReasonLevelComplete[] = "LEVELCOMPLETE"; static constexpr char ScriptReserved_EndReasonLoadGame[] = "LOADGAME"; @@ -81,15 +73,25 @@ static constexpr char ScriptReserved_PostLoop[] = "POSTLOOP"; static constexpr char ScriptReserved_PreControlPhase[] = "PRECONTROLPHASE"; static constexpr char ScriptReserved_PostControlPhase[] = "POSTCONTROLPHASE"; -// Event types -static constexpr char ScriptReserved_EventOnEnter[] = "ENTER"; -static constexpr char ScriptReserved_EventOnInside[] = "INSIDE"; -static constexpr char ScriptReserved_EventOnLeave[] = "LEAVE"; -static constexpr char ScriptReserved_EventOnLoad[] = "LOAD"; -static constexpr char ScriptReserved_EventOnSave[] = "SAVE"; -static constexpr char ScriptReserved_EventOnStart[] = "START"; -static constexpr char ScriptReserved_EventOnEnd[] = "END"; -static constexpr char ScriptReserved_EventOnLoop[] = "LOOP"; +// Built-in LevelFuncs +static constexpr char ScriptReserved_OnStart[] = "OnStart"; +static constexpr char ScriptReserved_OnLoad[] = "OnLoad"; +static constexpr char ScriptReserved_OnLoop[] = "OnLoop"; +static constexpr char ScriptReserved_OnControlPhase[] = "OnControlPhase"; // DEPRECATED +static constexpr char ScriptReserved_OnSave[] = "OnSave"; +static constexpr char ScriptReserved_OnEnd[] = "OnEnd"; +static constexpr char ScriptReserved_OnUseItem[] = "OnUseItem"; + +// Event types (volume events + global events) +static constexpr char ScriptReserved_EventOnEnter[] = "ENTER"; +static constexpr char ScriptReserved_EventOnInside[] = "INSIDE"; +static constexpr char ScriptReserved_EventOnLeave[] = "LEAVE"; +static constexpr char ScriptReserved_EventOnStart[] = "START"; +static constexpr char ScriptReserved_EventOnLoad[] = "LOAD"; +static constexpr char ScriptReserved_EventOnLoop[] = "LOOP"; +static constexpr char ScriptReserved_EventOnSave[] = "SAVE"; +static constexpr char ScriptReserved_EventOnEnd[] = "END"; +static constexpr char ScriptReserved_EventOnUseItem[] = "USEITEM"; // Member functions static constexpr char ScriptReserved_New[] = "New"; @@ -259,9 +261,9 @@ static constexpr char ScriptReserved_GiveInvItem[] = "GiveItem"; static constexpr char ScriptReserved_TakeInvItem[] = "TakeItem"; static constexpr char ScriptReserved_GetInvItemCount[] = "GetItemCount"; static constexpr char ScriptReserved_SetInvItemCount[] = "SetItemCount"; -static constexpr char ScriptReserved_GetChosenItem[] = "GetChosenItem"; -static constexpr char ScriptReserved_SetChosenItem[] = "SetChosenItem"; -static constexpr char ScriptReserved_ClearChosenItem[] = "ClearChosenItem"; +static constexpr char ScriptReserved_GetUsedItem[] = "GetUsedItem"; +static constexpr char ScriptReserved_SetUsedItem[] = "SetUsedItem"; +static constexpr char ScriptReserved_ClearUsedItem[] = "ClearUsedItem"; static constexpr char ScriptReserved_GetMoveableByName[] = "GetMoveableByName"; static constexpr char ScriptReserved_GetStaticByName[] = "GetStaticByName"; static constexpr char ScriptReserved_GetMoveablesBySlot[] = "GetMoveablesBySlot"; diff --git a/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp b/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp index a570cebfd..8cce6990e 100644 --- a/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Inventory/InventoryHandler.cpp @@ -61,32 +61,32 @@ namespace TEN::Scripting::InventoryHandler SetInventoryCount(objectID, count); } - /// Get last selected item in the player's inventory. + /// Get last item used in the player's inventory. // This value will be valid only for a single frame after exiting inventory, after which Lara says "No". - // Therefore, this function must be preferably used either in OnLoop events or callbacks. - // If you have used this function and you want to avoid "No" sound, you should use ClearChosenItem function. - //@function GetChosenItem - //@treturn Objects.ObjID Last selected item in the inventory. - static GAME_OBJECT_ID GetChosenItem() + // Therefore, this function must be preferably used either in OnLoop or OnUseItem events. + //@function GetUsedItem + //@treturn Objects.ObjID Last item used in the inventory. + static GAME_OBJECT_ID GetUsedItem() { return (GAME_OBJECT_ID)g_Gui.GetInventoryItemChosen(); } - /// Set last selected item in the player's inventory. - // You will be able to select only objects which already exist in inventory. + /// Set last item used in the player's inventory. + // You will be able to specify only objects which already exist in the inventory. // Will only be valid for the next frame. If not processed by the game, Lara will say "No". - //@function SetChosenItem + //@function SetUsedItem //@tparam Objects.ObjID objectID Object ID of the item to select from inventory. - static void SetChosenItem(GAME_OBJECT_ID objectID) + static void SetUsedItem(GAME_OBJECT_ID objectID) { if (g_Gui.IsObjectInInventory(objectID)) g_Gui.SetInventoryItemChosen(objectID); } - /// Clear last selected item in the player's inventory. - // This function is needed to avoid Lara saying "No" after selecting particular item in inventory. - //@function ClearChosenItem - static void ClearChosenItem() + /// Clear last item used in the player's inventory. + // When this function is used in OnUseItem level function, it allows to override existing item functionality. + // For items without existing functionality, this function is needed to avoid Lara saying "No" after using it. + //@function ClearUsedItem + static void ClearUsedItem() { g_Gui.SetInventoryItemChosen(GAME_OBJECT_ID::ID_NO_OBJECT); } @@ -100,8 +100,8 @@ namespace TEN::Scripting::InventoryHandler tableInventory.set_function(ScriptReserved_TakeInvItem, &TakeItem); tableInventory.set_function(ScriptReserved_GetInvItemCount, &GetItemCount); tableInventory.set_function(ScriptReserved_SetInvItemCount, &SetItemCount); - tableInventory.set_function(ScriptReserved_SetChosenItem, &SetChosenItem); - tableInventory.set_function(ScriptReserved_GetChosenItem, &GetChosenItem); - tableInventory.set_function(ScriptReserved_ClearChosenItem, &ClearChosenItem); + tableInventory.set_function(ScriptReserved_SetUsedItem, &SetUsedItem); + tableInventory.set_function(ScriptReserved_GetUsedItem, &GetUsedItem); + tableInventory.set_function(ScriptReserved_ClearUsedItem, &ClearUsedItem); } } diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp index cef0ba8b2..9b96d12d7 100644 --- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp @@ -65,7 +65,8 @@ static const std::unordered_map EVENT_TYPES { ScriptReserved_EventOnLoad, EventType::Load }, { ScriptReserved_EventOnSave, EventType::Save }, { ScriptReserved_EventOnStart, EventType::Start }, - { ScriptReserved_EventOnEnd, EventType::End } + { ScriptReserved_EventOnEnd, EventType::End }, + { ScriptReserved_EventOnUseItem, EventType::UseItem } }; enum class LevelEndReason @@ -293,6 +294,7 @@ Possible event type values: START END LOOP + USEITEM @function HandleEvent @tparam string name Name of the event set to find. @@ -457,6 +459,7 @@ void LogicHandler::FreeLevelScripts() m_onLoop = sol::nil; m_onSave = sol::nil; m_onEnd = sol::nil; + m_onUseItem = sol::nil; m_handler.GetState()->collect_garbage(); } @@ -999,6 +1002,12 @@ void LogicHandler::OnEnd(GameStatus reason) CallLevelFuncByName(name, endReason); } +void LogicHandler::OnUseItem(GAME_OBJECT_ID objectNumber) +{ + if (m_onUseItem.valid()) + CallLevelFunc(m_onUseItem, objectNumber); +} + /*** Special tables TombEngine uses the following tables for specific things. @@ -1142,4 +1151,5 @@ void LogicHandler::InitCallbacks() assignCB(m_onLoop, ScriptReserved_OnLoop); assignCB(m_onSave, ScriptReserved_OnSave); assignCB(m_onEnd, ScriptReserved_OnEnd); + assignCB(m_onUseItem, ScriptReserved_OnUseItem); } diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h index 1e1b485f9..c1f4f2108 100644 --- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h @@ -56,6 +56,7 @@ private: sol::protected_function m_onLoop{}; sol::protected_function m_onSave{}; sol::protected_function m_onEnd{}; + sol::protected_function m_onUseItem{}; std::unordered_set m_callbacksPreSave; std::unordered_set m_callbacksPostSave; @@ -170,4 +171,5 @@ public: void OnLoop(float deltaTime, bool postLoop) override; void OnSave() override; void OnEnd(GameStatus reason) override; + void OnUseItem(GAME_OBJECT_ID item) override; }; From 571f87f35f5e9ec7520359679b81ca14226cdeaa Mon Sep 17 00:00:00 2001 From: Kubsy <80340234+Jakub768@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:45:40 +0100 Subject: [PATCH 102/410] Update Changes.txt --- Documentation/Changes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 542f6fb9a..b92da2a99 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -4,7 +4,7 @@ Version 1.5 * Fixed original issue with classic switch off trigger wrongly activating some trigger actions. Lua API changes: -* Added Inventory.GetChosenItem(), Inventory.SetChosenItem() and Inventory.ClearChosenItem() functions. +* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. Version 1.4 =========== From 05376122b03020151ee3e43bb5dcbd4c94395b74 Mon Sep 17 00:00:00 2001 From: Jakub Date: Fri, 26 Apr 2024 10:52:01 +0100 Subject: [PATCH 103/410] fix compile error --- TombEngine/Game/collision/collide_item.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index b879bd0a4..8698d01df 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -1291,7 +1291,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, { int bs = 0; - if (pointColl.IsIllegalFloor() && prevPointColl.GetFloorHeight() < pointColl.GetFloorHeight()) + if (pointColl.IsSteepFloor() && prevPointColl.GetFloorHeight() < pointColl.GetFloorHeight()) { int yAngle = (long)((unsigned short)item->Pose.Orientation.y); @@ -1360,7 +1360,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv, item->Pose.Position.z = z; } // Hit a steep slope? - else if (pointColl.IsIllegalFloor()) + else if (pointColl.IsSteepFloor()) { // Need to know which direction the slope is. From 1d2f3dc64da671df785ca6c90f17d4f9707df216 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 27 Apr 2024 00:01:08 +1000 Subject: [PATCH 104/410] Rename struct member --- TombEngine/Game/Lara/PlayerContextData.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/Lara/PlayerContextData.h b/TombEngine/Game/Lara/PlayerContextData.h index 8e3b315e2..c5fca5052 100644 --- a/TombEngine/Game/Lara/PlayerContextData.h +++ b/TombEngine/Game/Lara/PlayerContextData.h @@ -8,9 +8,9 @@ namespace TEN::Entities::Player int LowerFloorBound = 0; int UpperFloorBound = 0; - bool TestIllegalFloorBelow = true; - bool TestIllegalFloorAbove = true; - bool TestDeathFloor = true; + bool TestSteepFloorBelow = true; + bool TestSteepFloorAbove = true; + bool TestDeathFloor = true; }; struct MonkeySwingMovementSetupData From 4d59cb6d0379937576b08d6d51b3b3e7dfd8b278 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 27 Apr 2024 00:24:09 +1000 Subject: [PATCH 105/410] Fix water ripple, splash sound, vehicle bugs --- TombEngine/Game/Lara/PlayerContext.cpp | 4 ++-- TombEngine/Game/Lara/lara_helpers.cpp | 14 ++++---------- TombEngine/Game/collision/Point.cpp | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/TombEngine/Game/Lara/PlayerContext.cpp b/TombEngine/Game/Lara/PlayerContext.cpp index 8d71d80a7..99ac6a5b9 100644 --- a/TombEngine/Game/Lara/PlayerContext.cpp +++ b/TombEngine/Game/Lara/PlayerContext.cpp @@ -178,14 +178,14 @@ namespace TEN::Entities::Player short aspectAngleDelta = Geometry::GetShortestAngle(setup.HeadingAngle, aspectAngle); // 1) Check for illegal slope below floor (if applicable). - if (setup.TestIllegalFloorBelow && + if (setup.TestSteepFloorBelow && (pointColl.IsSteepFloor() && abs(aspectAngleDelta) <= SLOPE_ASPECT_ANGLE_DELTA_MAX)) { return false; } // 1) Check for illegal slope above floor (if applicable). - if (setup.TestIllegalFloorAbove && + if (setup.TestSteepFloorAbove && (pointColl.IsSteepFloor() && abs(aspectAngleDelta) >= SLOPE_ASPECT_ANGLE_DELTA_MAX)) { return false; diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index d38ee2e44..ae37d3d7a 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -1252,20 +1252,14 @@ LaraInfo*& GetLaraInfo(ItemInfo* item) PlayerWaterData GetPlayerWaterData(ItemInfo& item) { - bool isWater = TestEnvironment(ENV_FLAG_WATER, &item); - bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, &item); - bool isCold = TestEnvironment(ENV_FLAG_COLD, &item); - - int waterDepth = GetWaterDepth(&item); - int waterHeight = GetWaterHeight(&item); - auto pointColl = GetPointCollision(item); - int heightFromWater = (waterHeight == NO_HEIGHT) ? NO_HEIGHT : (std::min(item.Pose.Position.y, pointColl.GetFloorHeight()) - waterHeight); + int heightFromWater = (pointColl.GetWaterTopHeight() == NO_HEIGHT) ? + NO_HEIGHT : (std::min(item.Pose.Position.y, pointColl.GetFloorHeight()) - pointColl.GetWaterTopHeight()); return PlayerWaterData { - isWater, isSwamp, isCold, - waterDepth, waterHeight, heightFromWater + TestEnvironment(ENV_FLAG_WATER, &item), TestEnvironment(ENV_FLAG_SWAMP, &item), TestEnvironment(ENV_FLAG_COLD, &item), + pointColl.GetWaterBottomHeight(), pointColl.GetWaterTopHeight(), heightFromWater }; } diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index 8790423a3..45f1b3fc2 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -372,7 +372,7 @@ namespace TEN::Collision::Point PointCollisionData GetPointCollision(const ItemInfo& item) { - return PointCollisionData(item.Pose.Position, item.RoomNumber); + return GetPointCollision(item.Pose.Position, item.RoomNumber); } PointCollisionData GetPointCollision(const ItemInfo& item, const Vector3& dir, float dist) From abb77ced54e7a137a02bfb1b35856c89a6e25335 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 27 Apr 2024 01:25:16 +1000 Subject: [PATCH 106/410] Remove pointless const --- TombEngine/Game/collision/collide_room.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 3ca9517cd..aa90ae3ec 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -1051,7 +1051,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) FloorInfo* GetFloor(int x, int y, int z, short* roomNumber) { - const auto location = GetRoomVector(RoomVector(*roomNumber, y), Vector3i(x, y, z)); + auto location = GetRoomVector(RoomVector(*roomNumber, y), Vector3i(x, y, z)); *roomNumber = location.RoomNumber; return &GetFloor(*roomNumber, x, z); } From 1e38baf8fc79011c3aade6451a378f7be54f6317 Mon Sep 17 00:00:00 2001 From: Joey Quint Date: Fri, 26 Apr 2024 18:48:54 +0200 Subject: [PATCH 107/410] Fix incorrect diving animation when swandiving from a high place --- TombEngine/Game/Lara/lara.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 07a251277..e4b47469b 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -152,7 +152,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) } else if (item->Animation.ActiveState == LS_FREEFALL_DIVE) { - SetAnimation(item, LA_SWANDIVE_DIVE); + SetAnimation(item, LA_SWANDIVE_FREEFALL_DIVE); item->Animation.Velocity.y /= 2; item->Pose.Orientation.x = ANGLE(-85.0f); player.Control.HandStatus = HandStatus::Free; From dbfaf6c7fd93dcada48976617f341e5bdc5a6361 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 27 Apr 2024 04:13:18 +1000 Subject: [PATCH 108/410] Update water functions --- TombEngine/Game/collision/collide_room.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index aa90ae3ec..137d8d62e 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -1090,7 +1090,7 @@ int GetWaterSurface(int x, int y, int z, short roomNumber) if (TestEnvironment(ENV_FLAG_WATER, room)) { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_VALUE) != NO_VALUE) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).has_value()) { room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; if (!TestEnvironment(ENV_FLAG_WATER, room)) @@ -1103,7 +1103,7 @@ int GetWaterSurface(int x, int y, int z, short roomNumber) } else { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).has_value()) { room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; if (TestEnvironment(ENV_FLAG_WATER, room)) @@ -1282,7 +1282,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) if (TestEnvironment(ENV_FLAG_WATER, room) || TestEnvironment(ENV_FLAG_SWAMP, room)) { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_VALUE) != NO_VALUE) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).has_value()) { auto* room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; @@ -1295,11 +1295,11 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) sector = GetSector(room, x - room->x, z - room->z); } - return GetPointCollision(Vector3i(x, y, z), sector->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), false); + return sector->GetSurfaceHeight(Vector3i(x, y, z), false); } - else if (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) + else if (sector->GetNextRoomNumber(Vector3i(x, y, z), true).has_value()) { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) + while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).has_value()) { auto* room2 = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; @@ -1312,7 +1312,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) sector = GetSector(room2, x - room2->x, z - room2->z); } - return GetPointCollision(Vector3i(x, y, z), sector->RoomNumber).GetSector().GetSurfaceHeight(Vector3i(x, y, z), true); + return sector->GetSurfaceHeight(Vector3i(x, y, z), true); } return NO_HEIGHT; From 9df06e0a635bae59a0dc13d46d311cfd094a6b30 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:00:18 +0200 Subject: [PATCH 109/410] Update Changes.txt --- Documentation/Changes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index b92da2a99..035d60ef2 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -2,6 +2,8 @@ Version 1.5 =========== * Fixed original issue with classic switch off trigger wrongly activating some trigger actions. +* Fixed incorrect diving animation when swandiving from a high place. +* Fixed AI for skidoo driver and worker with shotgun TR2 enemies. Lua API changes: * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. From 7f9f5c619a46aabf4ebaaabf411aa724d1b9b6cc Mon Sep 17 00:00:00 2001 From: Nemoel-Tomo Date: Sat, 27 Apr 2024 20:48:39 +0200 Subject: [PATCH 110/410] Bugfix: ember emitter, cleaner and squishy block (get valid sector) (#1358) * bugfix, ember emitter, cleaner and squishy * formatting * Update misc.cpp --------- Co-authored-by: Sezz --- TombEngine/Game/misc.cpp | 33 +++++++++++++++---- TombEngine/Game/misc.h | 2 +- TombEngine/Objects/Effects/EmberEmitter.cpp | 7 ++-- .../Objects/TR3/Trap/ElectricCleaner.cpp | 6 ++-- TombEngine/Objects/TR4/Trap/SquishyBlock.cpp | 2 +- 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 878281da8..ab9345203 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -40,7 +40,7 @@ void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature) } } -bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist) +bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat) { auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, dist); auto pointColl = GetCollision(item.Pose.Position, item.RoomNumber, dir, dist); @@ -59,16 +59,29 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist) { // Test for step. int relFloorHeight = abs(pointColl.Position.Floor - item.Pose.Position.y); - if (relFloorHeight >= CLICK(1) && item.Pose.Position.y >= pointColl.Position.Floor) + + if (relFloorHeight >= CLICK(1) && item.Pose.Position.y >= pointColl.Position.Floor && canFloat) + { return false; + } + else if (relFloorHeight >= CLICK(1) && !canFloat) + { + return false; + } } // Sloped floor. else { // Half block. int relFloorHeight = abs(pointColl.Position.Floor - item.Pose.Position.y); - if (relFloorHeight > CLICK(1)) + if (relFloorHeight > CLICK(1) && canFloat) + { return false; + } + else if (relFloorHeight > CLICK(2) && !canFloat) + { + return false; + } short slopeAngle = ANGLE(0.0f); if (pointColl.FloorTilt.x > 0) @@ -104,8 +117,16 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist) // Test ceiling height. int relCeilHeight = abs(pointColl.Position.Ceiling - pointColl.Position.Floor); - if (relCeilHeight <= height) - return false; + if (canFloat) + { + if (relCeilHeight <= height) + return false; + } + else + { + if (relCeilHeight < BLOCK(1)) + return false; + } // Check for blocked grey box. if (g_Level.Boxes[pointColl.Block->Box].flags & BLOCKABLE) @@ -123,4 +144,4 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist) return false; return true; -} \ No newline at end of file +} diff --git a/TombEngine/Game/misc.h b/TombEngine/Game/misc.h index ef00bf1fd..d3e4b6e65 100644 --- a/TombEngine/Game/misc.h +++ b/TombEngine/Game/misc.h @@ -19,4 +19,4 @@ enum LaraMeshMask CreatureInfo* GetCreatureInfo(ItemInfo* item); void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature); -bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist); +bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat); diff --git a/TombEngine/Objects/Effects/EmberEmitter.cpp b/TombEngine/Objects/Effects/EmberEmitter.cpp index 096ade6e1..4aef9f6de 100644 --- a/TombEngine/Objects/Effects/EmberEmitter.cpp +++ b/TombEngine/Objects/Effects/EmberEmitter.cpp @@ -27,10 +27,13 @@ namespace TEN::Effects::EmberEmitter if (item.TriggerFlags < 0) { + if (item.TriggerFlags > -11) + item.TriggerFlags = -11; + if (!item.ItemFlags[2]) { - int div = abs(item.TriggerFlags) % 10 << 10; - int mod = abs(item.TriggerFlags) / 10 << 10; + int div = (abs(item.TriggerFlags) % 10) << 10; + int mod = (abs(item.TriggerFlags) / 10) << 10; // TODO: Use Random::GenerateInt() item.ItemFlags[0] = GetRandomControl() % div; diff --git a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp index 84343ccc5..ba40d9323 100644 --- a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp +++ b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp @@ -72,13 +72,13 @@ namespace TEN::Entities::Traps static Vector3 GetElectricCleanerMovementDirection(const ItemInfo& item, const Vector3& dir0, const Vector3& dir1, const Vector3& dir2) { - if (IsNextSectorValid(item, dir0, BLOCK(1))) + if (IsNextSectorValid(item, dir0, BLOCK(1), false)) return dir0; - if (IsNextSectorValid(item, dir1, BLOCK(1))) + if (IsNextSectorValid(item, dir1, BLOCK(1), false)) return dir1; - if (IsNextSectorValid(item, dir2, BLOCK(1))) + if (IsNextSectorValid(item, dir2, BLOCK(1), false)) return dir2; return Vector3::Zero; diff --git a/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp b/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp index 3423d3890..ddab6f7bc 100644 --- a/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp +++ b/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp @@ -99,7 +99,7 @@ namespace TEN::Entities::Traps if (pointColl.RoomNumber != item.RoomNumber) ItemNewRoom(itemNumber, pointColl.RoomNumber); - if (!IsNextSectorValid(item, forwardDir, BLOCK(0.5f))) + if (!IsNextSectorValid(item, forwardDir, BLOCK(0.5f), true)) { switch (headingAngle) { From 1d30d43aac46df2208676ec88932b211d80c2f4e Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 28 Apr 2024 06:31:59 +0200 Subject: [PATCH 111/410] Added color to lens flare; Added LUA api for starfield and lens flare; --- Documentation/doc/1 modules/Effects.html | 2 + Documentation/doc/1 modules/Flow.html | 2 + Documentation/doc/1 modules/Input.html | 2 + Documentation/doc/1 modules/Inventory.html | 2 + Documentation/doc/1 modules/Logic.html | 2 + Documentation/doc/1 modules/Objects.html | 2 + Documentation/doc/1 modules/Sound.html | 2 + Documentation/doc/1 modules/Strings.html | 2 + Documentation/doc/1 modules/Util.html | 2 + Documentation/doc/1 modules/View.html | 2 + .../doc/2 classes/Flow.Animations.html | 2 + Documentation/doc/2 classes/Flow.Fog.html | 2 + .../doc/2 classes/Flow.InventoryItem.html | 2 + .../doc/2 classes/Flow.LensFlare.html | 223 +++++++++++++ Documentation/doc/2 classes/Flow.Level.html | 40 +++ Documentation/doc/2 classes/Flow.Mirror.html | 2 + .../doc/2 classes/Flow.Settings.html | 2 + .../doc/2 classes/Flow.SkyLayer.html | 15 +- .../doc/2 classes/Flow.Starfield.html | 303 ++++++++++++++++++ .../doc/2 classes/Objects.AIObject.html | 2 + .../doc/2 classes/Objects.Camera.html | 2 + .../doc/2 classes/Objects.LaraObject.html | 2 + .../doc/2 classes/Objects.Moveable.html | 2 + Documentation/doc/2 classes/Objects.Room.html | 2 + Documentation/doc/2 classes/Objects.Sink.html | 2 + .../doc/2 classes/Objects.SoundSource.html | 2 + .../doc/2 classes/Objects.Static.html | 2 + .../doc/2 classes/Objects.Volume.html | 2 + .../doc/2 classes/Strings.DisplayString.html | 2 + .../doc/2 classes/View.DisplaySprite.html | 2 + .../doc/3 primitive classes/Color.html | 2 + .../doc/3 primitive classes/Rotation.html | 2 + .../doc/3 primitive classes/Vec2.html | 2 + .../doc/3 primitive classes/Vec3.html | 2 + .../doc/4 enums/Effects.BlendID.html | 2 + .../doc/4 enums/Effects.EffectID.html | 2 + .../doc/4 enums/Flow.GameStatus.html | 2 + Documentation/doc/4 enums/Input.ActionID.html | 2 + .../doc/4 enums/Objects.AmmoType.html | 2 + .../doc/4 enums/Objects.MoveableStatus.html | 2 + Documentation/doc/4 enums/Objects.ObjID.html | 2 + .../doc/4 enums/Objects.RoomFlagID.html | 2 + .../doc/4 enums/Objects.RoomReverb.html | 2 + .../doc/4 enums/Sound.SoundTrackType.html | 2 + Documentation/doc/4 enums/Util.LogLevel.html | 2 + Documentation/doc/4 enums/View.AlignMode.html | 2 + .../doc/4 enums/View.CameraType.html | 2 + .../doc/4 enums/View.PostProcessMode.html | 2 + Documentation/doc/4 enums/View.ScaleMode.html | 2 + .../5 lua utility modules/EventSequence.html | 2 + .../doc/5 lua utility modules/Timer.html | 2 + Documentation/doc/index.html | 10 + TombEngine/Game/control/control.cpp | 10 +- TombEngine/Game/effects/weather.cpp | 92 +++--- TombEngine/Game/effects/weather.h | 28 +- TombEngine/Objects/Effects/lens_flare.cpp | 31 +- TombEngine/Objects/Effects/lens_flare.h | 8 +- .../ConstantBuffers/PostProcessBuffer.h | 5 +- TombEngine/Renderer/RendererDraw.cpp | 17 +- TombEngine/Renderer/RendererFrame.cpp | 12 +- TombEngine/Renderer/RendererPostProcess.cpp | 1 + .../Renderer/Structures/RendererLensFlare.h | 4 +- .../Scripting/Include/ScriptInterfaceLevel.h | 10 + .../Internal/TEN/Flow/FlowHandler.cpp | 4 +- .../Internal/TEN/Flow/LensFlare/LensFlare.cpp | 85 +++++ .../Internal/TEN/Flow/LensFlare/LensFlare.h | 34 ++ .../Internal/TEN/Flow/Level/FlowLevel.cpp | 58 ++++ .../Internal/TEN/Flow/Level/FlowLevel.h | 17 +- .../Internal/TEN/Flow/SkyLayer/SkyLayer.cpp | 116 +++---- .../Internal/TEN/Flow/Starfield/Starfield.cpp | 127 ++++++++ .../Internal/TEN/Flow/Starfield/Starfield.h | 36 +++ TombEngine/Shaders/CBPostProcess.hlsli | 5 +- TombEngine/Shaders/PostProcess.fx | 11 +- TombEngine/TombEngine.vcxproj | 6 +- 74 files changed, 1246 insertions(+), 156 deletions(-) create mode 100644 Documentation/doc/2 classes/Flow.LensFlare.html create mode 100644 Documentation/doc/2 classes/Flow.Starfield.html create mode 100644 TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp create mode 100644 TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h create mode 100644 TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp create mode 100644 TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h diff --git a/Documentation/doc/1 modules/Effects.html b/Documentation/doc/1 modules/Effects.html index c9aaf46b4..fbdd34565 100644 --- a/Documentation/doc/1 modules/Effects.html +++ b/Documentation/doc/1 modules/Effects.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index 46af015e4..79f548b42 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Input.html b/Documentation/doc/1 modules/Input.html index 61d495f1c..245afbb73 100644 --- a/Documentation/doc/1 modules/Input.html +++ b/Documentation/doc/1 modules/Input.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Inventory.html b/Documentation/doc/1 modules/Inventory.html index e5fd825ec..026463dc8 100644 --- a/Documentation/doc/1 modules/Inventory.html +++ b/Documentation/doc/1 modules/Inventory.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Logic.html b/Documentation/doc/1 modules/Logic.html index e190f3c99..5a4e0f59f 100644 --- a/Documentation/doc/1 modules/Logic.html +++ b/Documentation/doc/1 modules/Logic.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Objects.html b/Documentation/doc/1 modules/Objects.html index 2cb40e8e6..e2254f3e5 100644 --- a/Documentation/doc/1 modules/Objects.html +++ b/Documentation/doc/1 modules/Objects.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Sound.html b/Documentation/doc/1 modules/Sound.html index 109ac6e89..ef08ef33e 100644 --- a/Documentation/doc/1 modules/Sound.html +++ b/Documentation/doc/1 modules/Sound.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Strings.html b/Documentation/doc/1 modules/Strings.html index 63f90605b..32c538451 100644 --- a/Documentation/doc/1 modules/Strings.html +++ b/Documentation/doc/1 modules/Strings.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/Util.html b/Documentation/doc/1 modules/Util.html index d9f5352d1..967e94298 100644 --- a/Documentation/doc/1 modules/Util.html +++ b/Documentation/doc/1 modules/Util.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/1 modules/View.html b/Documentation/doc/1 modules/View.html index 34b89cba7..fb8ac12f0 100644 --- a/Documentation/doc/1 modules/View.html +++ b/Documentation/doc/1 modules/View.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Flow.Animations.html b/Documentation/doc/2 classes/Flow.Animations.html index fa6b9a829..138c78dee 100644 --- a/Documentation/doc/2 classes/Flow.Animations.html +++ b/Documentation/doc/2 classes/Flow.Animations.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Flow.Fog.html b/Documentation/doc/2 classes/Flow.Fog.html index a55a11544..e90cb08d9 100644 --- a/Documentation/doc/2 classes/Flow.Fog.html +++ b/Documentation/doc/2 classes/Flow.Fog.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Flow.InventoryItem.html b/Documentation/doc/2 classes/Flow.InventoryItem.html index ccfe68f21..d8eba55a3 100644 --- a/Documentation/doc/2 classes/Flow.InventoryItem.html +++ b/Documentation/doc/2 classes/Flow.InventoryItem.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Flow.LensFlare.html b/Documentation/doc/2 classes/Flow.LensFlare.html new file mode 100644 index 000000000..8ae3ca788 --- /dev/null +++ b/Documentation/doc/2 classes/Flow.LensFlare.html @@ -0,0 +1,223 @@ + + + + + TombEngine 1.4 Lua API + + + + +
    + +
    + +
    +
    +
    + + +
    + + + + + + +
    + +

    Class Flow.LensFlare

    +

    LensFlare

    +

    + +

    + + +

    Members

    + + + + + + + + + +
    lensFlareColor(Color) RGB lens flare color
    lensFlarePosition(Vec2) Lens flare orientation.
    +

    Functions

    + + + + + +
    LensFlare(yawPitchInDegrees, color) + +
    + +
    +
    + + +

    Members

    + +
    +
    + + lensFlareColor +
    +
    + (Color) RGB lens flare color + + + + + + + + +
    +
    + + lensFlarePosition +
    +
    + +

    (Vec2) Lens flare orientation.

    + +
        This is the position of the lens flare in the sky. The X value is the horizontal position, and the Y value is the vertical position. Angles must be specified in degrees.
    +
    + + + + + + + + + + +
    +
    +

    Functions

    + +
    +
    + + LensFlare(yawPitchInDegrees, color) +
    +
    + + + + + + +

    Parameters:

    +
      +
    • yawPitchInDegrees + Vec2 + Position of the lens flare (yaw and pitch) in degrees +
    • +
    • color + Color + RGB color +
    • +
    + +

    Returns:

    +
      + + LensFlare + A lens flare object. +
    + + + + +
    +
    + + +
    +
    +
    +generated by TEN-LDoc (a fork of LDoc 1.4.6) +
    +
    + + diff --git a/Documentation/doc/2 classes/Flow.Level.html b/Documentation/doc/2 classes/Flow.Level.html index 6c505e3e8..a3309e70d 100644 --- a/Documentation/doc/2 classes/Flow.Level.html +++ b/Documentation/doc/2 classes/Flow.Level.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • @@ -135,6 +137,14 @@ (Flow.SkyLayer) Secondary sky layer + starfield + (Flow.Starfield) Starfield + + + lensFlare + (Flow.LensFlare) Global lens flare + + fog (Flow.Fog) omni fog RGB color and distance. @@ -307,6 +317,36 @@ +
    +
    + + starfield +
    +
    + (Flow.Starfield) Starfield + + + + + + + + +
    +
    + + lensFlare +
    +
    + (Flow.LensFlare) Global lens flare + + + + + + + +
    diff --git a/Documentation/doc/2 classes/Flow.Mirror.html b/Documentation/doc/2 classes/Flow.Mirror.html index a391b693d..26e8fbfb4 100644 --- a/Documentation/doc/2 classes/Flow.Mirror.html +++ b/Documentation/doc/2 classes/Flow.Mirror.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Flow.Settings.html b/Documentation/doc/2 classes/Flow.Settings.html index a5f64f145..a29324f2e 100644 --- a/Documentation/doc/2 classes/Flow.Settings.html +++ b/Documentation/doc/2 classes/Flow.Settings.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Flow.SkyLayer.html b/Documentation/doc/2 classes/Flow.SkyLayer.html index 6ec6adcf9..f3863417a 100644 --- a/Documentation/doc/2 classes/Flow.SkyLayer.html +++ b/Documentation/doc/2 classes/Flow.SkyLayer.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • @@ -154,13 +156,14 @@
    (int) cloud speed.

    -

    Values can be between [-32768, 32767], with positive numbers resulting in a sky that scrolls from -west to east, and negative numbers resulting in one that travels east to west.

    - -

    Please note that speeds outside of the range of about [-1000, 1000] will cause the -sky to scroll so fast that it will no longer appear as a coherent stream of clouds. -Less is more. City of The Dead, for example, uses a speed value of 16. +

        Values can be between [-32768, 32767], with positive numbers resulting in a sky that scrolls from
    +    west to east, and negative numbers resulting in one that travels east to west.
     
    +    Please note that speeds outside of the range of about [-1000, 1000] will cause the
    +    sky to scroll so fast that it will no longer appear as a coherent stream of clouds.
    +    Less is more. City of The Dead, for example, uses a speed value of 16.
    +
    +

    diff --git a/Documentation/doc/2 classes/Flow.Starfield.html b/Documentation/doc/2 classes/Flow.Starfield.html new file mode 100644 index 000000000..9b75c5427 --- /dev/null +++ b/Documentation/doc/2 classes/Flow.Starfield.html @@ -0,0 +1,303 @@ + + + + + TombEngine 1.4 Lua API + + + + +

    + +
    + +
    +
    +
    + + +
    + + + + + + +
    + +

    Class Flow.Starfield

    +

    Starfield

    +

    + +

    + + +

    Members

    + + + + + + + + + + + + + + + + + +
    starsCount(int) Stars count.
    meteorsCount(int) Meteors count.
    meteorsSpawnDensity(int) Meteors spawn density.
    meteorsSpeed(float) Meteors speed.
    +

    Functions

    + + + + + + + + + +
    Starfield(starsCount) + +
    Starfield(starsCount, meteorsCount) + +
    + +
    +
    + + +

    Members

    + +
    +
    + + starsCount +
    +
    + +

    (int) Stars count.

    + +
        Values can be between [0, 6000], 0 resulting in no stars being rendered, and 6000 resulting in the maximum number of stars being rendered.
    +
    + + + + + + + + + + +
    +
    + + meteorsCount +
    +
    + +

    (int) Meteors count.

    + +
        Values can be between [0, 100], 0 resulting in no meteors being rendered, and 100 resulting in the maximum number of meteors being rendered.
    +
    + + + + + + + + + + +
    +
    + + meteorsSpawnDensity +
    +
    + (int) Meteors spawn density. + + + + + + + + +
    +
    + + meteorsSpeed +
    +
    + (float) Meteors speed. + + + + + + + + +
    +
    +

    Functions

    + +
    +
    + + Starfield(starsCount) +
    +
    + + + + + + +

    Parameters:

    +
      +
    • starsCount + int + Stars count +
    • +
    + +

    Returns:

    +
      + + Starfield + A starfield object with only stars enabled. +
    + + + + +
    +
    + + Starfield(starsCount, meteorsCount) +
    +
    + + + + + + +

    Parameters:

    +
      +
    • starsCount + int + Stars count +
    • +
    • meteorsCount + int + Stars count +
    • +
    + +

    Returns:

    +
      + + Starfield + A starfield object with boths stars and meteors enabled. +
    + + + + +
    +
    + + +
    +
    +
    +generated by TEN-LDoc (a fork of LDoc 1.4.6) +
    +
    + + diff --git a/Documentation/doc/2 classes/Objects.AIObject.html b/Documentation/doc/2 classes/Objects.AIObject.html index a8816eb21..8b8095d28 100644 --- a/Documentation/doc/2 classes/Objects.AIObject.html +++ b/Documentation/doc/2 classes/Objects.AIObject.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.Camera.html b/Documentation/doc/2 classes/Objects.Camera.html index 297e7cb13..5729dcefa 100644 --- a/Documentation/doc/2 classes/Objects.Camera.html +++ b/Documentation/doc/2 classes/Objects.Camera.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.LaraObject.html b/Documentation/doc/2 classes/Objects.LaraObject.html index 56ae5ea19..eaf8bc408 100644 --- a/Documentation/doc/2 classes/Objects.LaraObject.html +++ b/Documentation/doc/2 classes/Objects.LaraObject.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index 00671976d..b0ecc0d54 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.Room.html b/Documentation/doc/2 classes/Objects.Room.html index d49f8c93b..c4e632774 100644 --- a/Documentation/doc/2 classes/Objects.Room.html +++ b/Documentation/doc/2 classes/Objects.Room.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.Sink.html b/Documentation/doc/2 classes/Objects.Sink.html index ca807b417..f88a0f3f6 100644 --- a/Documentation/doc/2 classes/Objects.Sink.html +++ b/Documentation/doc/2 classes/Objects.Sink.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.SoundSource.html b/Documentation/doc/2 classes/Objects.SoundSource.html index 24e4f3b7d..6221a947d 100644 --- a/Documentation/doc/2 classes/Objects.SoundSource.html +++ b/Documentation/doc/2 classes/Objects.SoundSource.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.Static.html b/Documentation/doc/2 classes/Objects.Static.html index c91209d0e..9b23623cc 100644 --- a/Documentation/doc/2 classes/Objects.Static.html +++ b/Documentation/doc/2 classes/Objects.Static.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Objects.Volume.html b/Documentation/doc/2 classes/Objects.Volume.html index a23618fc7..575b2cbbf 100644 --- a/Documentation/doc/2 classes/Objects.Volume.html +++ b/Documentation/doc/2 classes/Objects.Volume.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/Strings.DisplayString.html b/Documentation/doc/2 classes/Strings.DisplayString.html index eff4085fd..9a7d4ae31 100644 --- a/Documentation/doc/2 classes/Strings.DisplayString.html +++ b/Documentation/doc/2 classes/Strings.DisplayString.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/2 classes/View.DisplaySprite.html b/Documentation/doc/2 classes/View.DisplaySprite.html index 4edcad83e..f17aabb51 100644 --- a/Documentation/doc/2 classes/View.DisplaySprite.html +++ b/Documentation/doc/2 classes/View.DisplaySprite.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/3 primitive classes/Color.html b/Documentation/doc/3 primitive classes/Color.html index 58efaffe6..fe9932009 100644 --- a/Documentation/doc/3 primitive classes/Color.html +++ b/Documentation/doc/3 primitive classes/Color.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/3 primitive classes/Rotation.html b/Documentation/doc/3 primitive classes/Rotation.html index d3f49a53a..81269805f 100644 --- a/Documentation/doc/3 primitive classes/Rotation.html +++ b/Documentation/doc/3 primitive classes/Rotation.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/3 primitive classes/Vec2.html b/Documentation/doc/3 primitive classes/Vec2.html index 30cb5546b..1968ad094 100644 --- a/Documentation/doc/3 primitive classes/Vec2.html +++ b/Documentation/doc/3 primitive classes/Vec2.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/3 primitive classes/Vec3.html b/Documentation/doc/3 primitive classes/Vec3.html index d5c81d100..ce6afe46f 100644 --- a/Documentation/doc/3 primitive classes/Vec3.html +++ b/Documentation/doc/3 primitive classes/Vec3.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Effects.BlendID.html b/Documentation/doc/4 enums/Effects.BlendID.html index cbc48754f..176648f3d 100644 --- a/Documentation/doc/4 enums/Effects.BlendID.html +++ b/Documentation/doc/4 enums/Effects.BlendID.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Effects.EffectID.html b/Documentation/doc/4 enums/Effects.EffectID.html index 585cd7cfa..a4f375d07 100644 --- a/Documentation/doc/4 enums/Effects.EffectID.html +++ b/Documentation/doc/4 enums/Effects.EffectID.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Flow.GameStatus.html b/Documentation/doc/4 enums/Flow.GameStatus.html index d7b9af20a..913f32956 100644 --- a/Documentation/doc/4 enums/Flow.GameStatus.html +++ b/Documentation/doc/4 enums/Flow.GameStatus.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Input.ActionID.html b/Documentation/doc/4 enums/Input.ActionID.html index 960659276..f6baf89fd 100644 --- a/Documentation/doc/4 enums/Input.ActionID.html +++ b/Documentation/doc/4 enums/Input.ActionID.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Objects.AmmoType.html b/Documentation/doc/4 enums/Objects.AmmoType.html index c21a2221d..1d0acd788 100644 --- a/Documentation/doc/4 enums/Objects.AmmoType.html +++ b/Documentation/doc/4 enums/Objects.AmmoType.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Objects.MoveableStatus.html b/Documentation/doc/4 enums/Objects.MoveableStatus.html index 2407fc1f4..d72b97b7a 100644 --- a/Documentation/doc/4 enums/Objects.MoveableStatus.html +++ b/Documentation/doc/4 enums/Objects.MoveableStatus.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 9372f1014..450b7e795 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Objects.RoomFlagID.html b/Documentation/doc/4 enums/Objects.RoomFlagID.html index bdac34926..99800c4a7 100644 --- a/Documentation/doc/4 enums/Objects.RoomFlagID.html +++ b/Documentation/doc/4 enums/Objects.RoomFlagID.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Objects.RoomReverb.html b/Documentation/doc/4 enums/Objects.RoomReverb.html index 839bad41c..2602f78a7 100644 --- a/Documentation/doc/4 enums/Objects.RoomReverb.html +++ b/Documentation/doc/4 enums/Objects.RoomReverb.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Sound.SoundTrackType.html b/Documentation/doc/4 enums/Sound.SoundTrackType.html index 64c9e8ba1..a940321bc 100644 --- a/Documentation/doc/4 enums/Sound.SoundTrackType.html +++ b/Documentation/doc/4 enums/Sound.SoundTrackType.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/Util.LogLevel.html b/Documentation/doc/4 enums/Util.LogLevel.html index 78844e1a5..6b21b58ee 100644 --- a/Documentation/doc/4 enums/Util.LogLevel.html +++ b/Documentation/doc/4 enums/Util.LogLevel.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/View.AlignMode.html b/Documentation/doc/4 enums/View.AlignMode.html index 92542e66b..568016c03 100644 --- a/Documentation/doc/4 enums/View.AlignMode.html +++ b/Documentation/doc/4 enums/View.AlignMode.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/View.CameraType.html b/Documentation/doc/4 enums/View.CameraType.html index d2b629311..ffd8a8402 100644 --- a/Documentation/doc/4 enums/View.CameraType.html +++ b/Documentation/doc/4 enums/View.CameraType.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/View.PostProcessMode.html b/Documentation/doc/4 enums/View.PostProcessMode.html index 9caf7b0be..37ddb7709 100644 --- a/Documentation/doc/4 enums/View.PostProcessMode.html +++ b/Documentation/doc/4 enums/View.PostProcessMode.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/4 enums/View.ScaleMode.html b/Documentation/doc/4 enums/View.ScaleMode.html index 192589739..1460c4610 100644 --- a/Documentation/doc/4 enums/View.ScaleMode.html +++ b/Documentation/doc/4 enums/View.ScaleMode.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/5 lua utility modules/EventSequence.html b/Documentation/doc/5 lua utility modules/EventSequence.html index 93464f9ff..c1f7495c3 100644 --- a/Documentation/doc/5 lua utility modules/EventSequence.html +++ b/Documentation/doc/5 lua utility modules/EventSequence.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/5 lua utility modules/Timer.html b/Documentation/doc/5 lua utility modules/Timer.html index 1a3645b43..542dce9e2 100644 --- a/Documentation/doc/5 lua utility modules/Timer.html +++ b/Documentation/doc/5 lua utility modules/Timer.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index 77f425919..6ae912f78 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -49,10 +49,12 @@
  • Flow.Animations
  • Flow.Fog
  • Flow.InventoryItem
  • +
  • Flow.LensFlare
  • Flow.Level
  • Flow.Mirror
  • Flow.Settings
  • Flow.SkyLayer
  • +
  • Flow.Starfield
  • Objects.AIObject
  • Objects.Camera
  • Objects.LaraObject
  • @@ -183,6 +185,10 @@ local door = GetMoveableByName("door_type4_14") Flow.InventoryItem Represents the properties of an object as it appears in the inventory. + + Flow.LensFlare + LensFlare + Flow.Level Stores level metadata. @@ -199,6 +205,10 @@ local door = GetMoveableByName("door_type4_14") Flow.SkyLayer Describes a layer of moving clouds. + + Flow.Starfield + Starfield + Objects.AIObject AI object diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index d3fa54462..e7c064dc9 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -243,8 +243,16 @@ GameStatus ControlPhase(int numFrames) UpdateBeetleSwarm(); UpdateLocusts(); UpdateUnderwaterBloodParticles(); - SetupGlobalLensFlare(180.0f, 30.0f); + if (g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareEnabled()) + { + SetupGlobalLensFlare( + g_GameFlow->GetLevel(CurrentLevel)->GetLensFlarePosition(), + g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareColor(), + g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSpriteID() + ); + } + // Update HUD. g_Hud.Update(*LaraItem); UpdateFadeScreenAndCinematicBars(); diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index f6269b983..f1379adf3 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -18,33 +18,6 @@ using namespace TEN::Math::Random; namespace TEN::Effects::Environment { - constexpr auto WEATHER_PARTICLES_SPAWN_DENSITY = 32; - constexpr auto WEATHER_PARTICLES_MAX_COUNT = 2048; - constexpr auto WEATHER_PARTICLES_MAX_COLL_CHECK_DELAY = 5.0f; - - constexpr auto MAX_DUST_SIZE = 25.0f; - constexpr auto MAX_SNOW_SIZE = 32.0f; - constexpr auto MAX_RAIN_SIZE = 128.0f; - - constexpr auto WEATHER_PARTICLE_HORIZONTAL_SPEED = 8.0f; - constexpr auto MAX_SNOW_SPEED = 128.0f; - constexpr auto MAX_RAIN_SPEED = 256.0f; - constexpr auto MAX_DUST_SPEED = 1.0f; - - constexpr auto WEATHER_PARTICLES_TRANSPARENCY = 0.8f; - constexpr auto WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE = 20.0f; - constexpr auto WEATHER_PARTICLES_NEAR_DEATH_MELT_FACTOR = 1.0f - (1.0f / (WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE * 2)); - - constexpr auto DUST_SPAWN_DENSITY = 300; - constexpr auto DUST_LIFE = 40; - constexpr auto DUST_SPAWN_RADIUS = (10 * 1024); - - constexpr auto METEOR_PARTICLES_MAX_COUNT = 10; - constexpr auto METEOR_PARTICLES_MAX_LIFE = 150; - constexpr auto METEOR_PARTICLES_SPEED = 32.0f; - constexpr auto METEOR_PARTICLES_SPAWN_DENSITY = 4; - constexpr auto METEOR_PARTICLES_FADE_TIME = 30; - EnvironmentController Weather; float WeatherParticle::Transparency() const @@ -236,12 +209,17 @@ namespace TEN::Effects::Environment void EnvironmentController::UpdateStarfield(ScriptInterfaceLevel* level) { + if (!level->GetStarfieldEnabled()) + return; + if (ResetStarField) { - Stars.clear(); - Stars.reserve(StarsCount); + int starsCount = level->GetStarfieldStarsCount(); - for (int i = 0; i < StarsCount; i++) + Stars.clear(); + Stars.reserve(starsCount); + + for (int i = 0; i < starsCount; i++) { Vector3 starDirection = Random::GenerateDirectionInCone(-Vector3::UnitY, 70.0f); starDirection.Normalize(); @@ -279,29 +257,30 @@ namespace TEN::Effects::Environment s.Blinking = Random::GenerateFloat(0.5f, 1.0f); } - for (auto& m : Meteors) + if (level->GetStarfieldMeteorsEnabled()) { - //p.StoreInterpolationData(); - - m.Life--; - - if (m.Life <= 0) + for (auto& m : Meteors) { - m.Active = false; - continue; + m.Life--; + + if (m.Life <= 0) + { + m.Active = false; + continue; + } + + m.StoreInterpolationData(); + + if (m.Life <= METEOR_PARTICLES_FADE_TIME) + m.Fade = m.Life / (float)METEOR_PARTICLES_FADE_TIME; + else if (m.Life >= METEOR_PARTICLES_MAX_LIFE - METEOR_PARTICLES_FADE_TIME) + m.Fade = (METEOR_PARTICLES_MAX_LIFE - m.Life) / (float)METEOR_PARTICLES_FADE_TIME; + else + m.Fade = 1.0f; + + m.Position += m.Direction * level->GetStarfieldMeteorsSpeed(); } - - m.StoreInterpolationData(); - - if (m.Life <= METEOR_PARTICLES_FADE_TIME) - m.Fade = m.Life / (float)METEOR_PARTICLES_FADE_TIME; - else if (m.Life >= METEOR_PARTICLES_MAX_LIFE - METEOR_PARTICLES_FADE_TIME) - m.Fade = (METEOR_PARTICLES_MAX_LIFE - m.Life) / (float)METEOR_PARTICLES_FADE_TIME; - else - m.Fade = 1.0f; - - m.Position += m.Direction * METEOR_PARTICLES_SPEED; - } + } } void EnvironmentController::UpdateWeather(ScriptInterfaceLevel* level) @@ -609,15 +588,16 @@ namespace TEN::Effects::Environment if (Meteors.size() > 0) Meteors.erase(std::remove_if(Meteors.begin(), Meteors.end(), [](const MeteorParticle& part) { return !part.Active; }), Meteors.end()); - //if (level->GetWeatherType() == WeatherType::None || level->GetWeatherStrength() == 0.0f) - // return; + if (!level->GetStarfieldMeteorsEnabled()) + return; int newParticlesCount = 0; - int density = METEOR_PARTICLES_SPAWN_DENSITY; + int density = level->GetStarfieldMeteorsSpawnDensity(); + int meteorsCount = level->GetStarfieldMeteorsCount(); - if (density > 0.0f /* && level->GetWeatherType() != WeatherType::None */) - { - while (Meteors.size() < METEOR_PARTICLES_MAX_COUNT) + if (density > 0) + { + while (Meteors.size() < meteorsCount) { if (newParticlesCount > density) break; diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index 43daf02d9..07ac92765 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -8,6 +8,33 @@ using namespace TEN::Entities::Effects; namespace TEN::Effects::Environment { + constexpr auto WEATHER_PARTICLES_SPAWN_DENSITY = 32; + constexpr auto WEATHER_PARTICLES_MAX_COUNT = 2048; + constexpr auto WEATHER_PARTICLES_MAX_COLL_CHECK_DELAY = 5.0f; + + constexpr auto MAX_DUST_SIZE = 25.0f; + constexpr auto MAX_SNOW_SIZE = 32.0f; + constexpr auto MAX_RAIN_SIZE = 128.0f; + + constexpr auto WEATHER_PARTICLE_HORIZONTAL_SPEED = 8.0f; + constexpr auto MAX_SNOW_SPEED = 128.0f; + constexpr auto MAX_RAIN_SPEED = 256.0f; + constexpr auto MAX_DUST_SPEED = 1.0f; + + constexpr auto WEATHER_PARTICLES_TRANSPARENCY = 0.8f; + constexpr auto WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE = 20.0f; + constexpr auto WEATHER_PARTICLES_NEAR_DEATH_MELT_FACTOR = 1.0f - (1.0f / (WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE * 2)); + + constexpr auto DUST_SPAWN_DENSITY = 300; + constexpr auto DUST_LIFE = 40; + constexpr auto DUST_SPAWN_RADIUS = (10 * 1024); + + constexpr auto METEOR_PARTICLES_MAX_COUNT = 10; + constexpr auto METEOR_PARTICLES_MAX_LIFE = 150; + constexpr auto METEOR_PARTICLES_SPEED = 32.0f; + constexpr auto METEOR_PARTICLES_SPAWN_DENSITY = 4; + constexpr auto METEOR_PARTICLES_FADE_TIME = 30; + struct StarParticle { Vector3 Position = Vector3::Zero; @@ -116,7 +143,6 @@ namespace TEN::Effects::Environment byte StormSkyColor2 = 1; // Starfield - int StarsCount = 3000; std::vector Stars; std::vector Meteors; bool ResetStarField = true; diff --git a/TombEngine/Objects/Effects/lens_flare.cpp b/TombEngine/Objects/Effects/lens_flare.cpp index fd06249b8..2d585bae7 100644 --- a/TombEngine/Objects/Effects/lens_flare.cpp +++ b/TombEngine/Objects/Effects/lens_flare.cpp @@ -14,7 +14,12 @@ namespace TEN::Entities::Effects if (TriggerActive(item)) { - SetupLensFlare(item->Pose.Position.ToVector3(), item->RoomNumber, false); + SetupLensFlare( + item->Pose.Position.ToVector3(), + Vector3::One, + item->RoomNumber, + false, + SPR_LENSFLARE3); } } @@ -23,19 +28,23 @@ namespace TEN::Entities::Effects LensFlares.clear(); } - void SetupGlobalLensFlare(float yaw, float pitch) + void SetupGlobalLensFlare(Vector2 yawAndPitchInDegrees, Vector3 color, int spriteIndex) { Vector3 position = Camera.pos.ToVector3(); - Matrix rotation = Matrix::CreateFromYawPitchRoll(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), 0); + Matrix rotation = Matrix::CreateFromYawPitchRoll( + DEG_TO_RAD(yawAndPitchInDegrees.x), + DEG_TO_RAD(yawAndPitchInDegrees.y), + 0 + ); position += Vector3::Transform(Vector3(0, 0, BLOCK(256)), rotation); - SetupLensFlare(position, NO_VALUE, true); + SetupLensFlare(position, color, NO_VALUE, true, spriteIndex); } - void SetupLensFlare(Vector3 position, short roomNumber, bool sun) + void SetupLensFlare(Vector3 position, Vector3 color, short roomNumber, bool global, int spriteIndex) { Vector3 lensFlarePosition; - if (sun) + if (global) { if (g_Level.Rooms[Camera.pos.RoomNumber].flags & ENV_FLAG_NO_LENSFLARE) { @@ -80,7 +89,7 @@ namespace TEN::Entities::Effects if (roomNumber != NO_VALUE) { - if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_NOT_NEAR_OUTSIDE || !sun) + if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_NOT_NEAR_OUTSIDE || !global) { GameVector source = { Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber }; GameVector destination = { (int)lensFlarePosition.x, (int)lensFlarePosition.y, (int)lensFlarePosition.z, roomNumber }; @@ -88,15 +97,19 @@ namespace TEN::Entities::Effects } } - if (!flareVisible && !sun) + if (!flareVisible && !global) { return; } LensFlare lensFlare; + lensFlare.Position = position; lensFlare.RoomNumber = roomNumber; - lensFlare.Sun = sun; + lensFlare.Global = global; + lensFlare.Color = color; + lensFlare.SpriteIndex = spriteIndex; + LensFlares.push_back(lensFlare); } } \ No newline at end of file diff --git a/TombEngine/Objects/Effects/lens_flare.h b/TombEngine/Objects/Effects/lens_flare.h index 0f0901338..553866f4f 100644 --- a/TombEngine/Objects/Effects/lens_flare.h +++ b/TombEngine/Objects/Effects/lens_flare.h @@ -10,14 +10,16 @@ namespace TEN::Entities::Effects struct LensFlare { Vector3 Position; + Vector3 Color; short RoomNumber; - bool Sun; + bool Global; + int SpriteIndex; }; extern std::vector LensFlares; void LensFlareControl(short itemNumber); void ClearLensFlares(); - void SetupLensFlare(Vector3 position, short roomNumber, bool global); - void SetupGlobalLensFlare(float yaw, float pitch); + void SetupLensFlare(Vector3 position, Vector3 color, short roomNumber, bool global, int spriteIndex); + void SetupGlobalLensFlare(Vector2 yawAndPitchInDegrees, Vector3 color, int spriteIndex); } \ No newline at end of file diff --git a/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h b/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h index 130136463..40658395b 100644 --- a/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h +++ b/TombEngine/Renderer/ConstantBuffers/PostProcessBuffer.h @@ -8,7 +8,10 @@ namespace TEN::Renderer::ConstantBuffers struct alignas(16) ShaderLensFlare { Vector3 Position; - float Padding; + float Padding1; + //-- + Vector3 Color; + float Padding2; }; struct alignas(16) CPostProcessBuffer diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 30a4e11bb..6c110c6cc 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2821,8 +2821,7 @@ namespace TEN::Renderer _context->ClearDepthStencilView(depthTarget, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); - int starsCount = (int)Weather.GetStars().size(); - if (starsCount > 0) + if (Weather.GetStars().size() > 0) { SetDepthState(DepthState::Read); SetBlendMode(BlendMode::Additive); @@ -2841,6 +2840,8 @@ namespace TEN::Renderer BindTexture(TextureRegister::ColorMap, _sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3].Texture, SamplerStateRegister::LinearClamp); int drawnStars = 0; + int starsCount = (int)Weather.GetStars().size(); + while (drawnStars < starsCount) { int starsToDraw = (starsCount - drawnStars) > 100 ? 100 : (starsCount - drawnStars); @@ -2851,7 +2852,7 @@ namespace TEN::Renderer auto& s = Weather.GetStars()[drawnStars + i]; RendererSpriteToDraw rDrawSprite; - rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; constexpr auto STAR_SIZE = 2; @@ -2890,7 +2891,7 @@ namespace TEN::Renderer drawnStars += starsToDraw; } - // Draw meteor + // Draw meteors if (Weather.GetMeteors().size() > 0) { RendererSpriteToDraw rDrawSprite; @@ -2907,8 +2908,8 @@ namespace TEN::Renderer continue; rDrawSprite.Type = SpriteType::CustomBillboard; - rDrawSprite.pos = - renderView.Camera.WorldPosition + + rDrawSprite.pos = + renderView.Camera.WorldPosition + Vector3::Lerp(meteor.OldPosition, meteor.Position, _interpolationFactor); rDrawSprite.Rotation = 0; rDrawSprite.Scale = 1; @@ -2995,7 +2996,7 @@ namespace TEN::Renderer } // Eventually draw the sun sprite - if (renderView.LensFlaresToDraw.size() > 0 && renderView.LensFlaresToDraw[0].Sun) + if (renderView.LensFlaresToDraw.size() > 0 && renderView.LensFlaresToDraw[0].Global) { SetDepthState(DepthState::Read); SetBlendMode(BlendMode::Additive); @@ -3012,7 +3013,7 @@ namespace TEN::Renderer _context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); RendererSpriteToDraw rDrawSprite; - rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + renderView.LensFlaresToDraw[0].SpriteIndex]; constexpr auto SUN_SIZE = 64; diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 041d11aad..e552f5772 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -110,7 +110,7 @@ namespace TEN::Renderer { Vector3 lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; float distance = 0.0f; - if (!lensFlare.Sun) + if (!lensFlare.Global) { distance = lensFlareToCamera.Length(); } @@ -122,10 +122,14 @@ namespace TEN::Renderer if (lensFlareToCamera.Dot(cameraDirection) >= 0.0f) { RendererLensFlare lensFlareToDraw; + lensFlareToDraw.Position = lensFlare.Position; lensFlareToDraw.Distance = distance; + lensFlareToDraw.Color = lensFlare.Color; + lensFlareToDraw.SpriteIndex = lensFlare.SpriteIndex; lensFlareToDraw.Direction = lensFlareToCamera; - lensFlareToDraw.Sun = lensFlare.Sun; + lensFlareToDraw.Global = lensFlare.Global; + tempLensFlares.push_back(lensFlareToDraw); } } @@ -135,9 +139,9 @@ namespace TEN::Renderer tempLensFlares.end(), [](const RendererLensFlare& lensFlare0, const RendererLensFlare& lensFlare1) { - if (lensFlare0.Sun && !lensFlare1.Sun) + if (lensFlare0.Global && !lensFlare1.Global) return true; - else if (!lensFlare0.Sun && lensFlare1.Sun) + else if (!lensFlare0.Global && lensFlare1.Global) return false; else return lensFlare0.Distance < lensFlare1.Distance; diff --git a/TombEngine/Renderer/RendererPostProcess.cpp b/TombEngine/Renderer/RendererPostProcess.cpp index 3393dfacc..d34e05187 100644 --- a/TombEngine/Renderer/RendererPostProcess.cpp +++ b/TombEngine/Renderer/RendererPostProcess.cpp @@ -87,6 +87,7 @@ namespace TEN::Renderer for (int i = 0; i < view.LensFlaresToDraw.size(); i++) { _stPostProcessBuffer.LensFlares[i].Position = view.LensFlaresToDraw[i].Position; + _stPostProcessBuffer.LensFlares[i].Color = view.LensFlaresToDraw[i].Color; } _stPostProcessBuffer.NumLensFlares = (int)view.LensFlaresToDraw.size(); _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get()); diff --git a/TombEngine/Renderer/Structures/RendererLensFlare.h b/TombEngine/Renderer/Structures/RendererLensFlare.h index 2fc8b74ae..1c88d8fb3 100644 --- a/TombEngine/Renderer/Structures/RendererLensFlare.h +++ b/TombEngine/Renderer/Structures/RendererLensFlare.h @@ -9,8 +9,10 @@ namespace TEN::Renderer::Structures struct RendererLensFlare { Vector3 Position; + Vector3 Color; Vector3 Direction; float Distance; - bool Sun; + bool Global; + int SpriteIndex; }; } \ No newline at end of file diff --git a/TombEngine/Scripting/Include/ScriptInterfaceLevel.h b/TombEngine/Scripting/Include/ScriptInterfaceLevel.h index 072bee854..1302d22d7 100644 --- a/TombEngine/Scripting/Include/ScriptInterfaceLevel.h +++ b/TombEngine/Scripting/Include/ScriptInterfaceLevel.h @@ -48,4 +48,14 @@ public: virtual int GetSecrets() const = 0; virtual std::string GetAmbientTrack() const = 0; virtual bool GetResetHubEnabled() const = 0; + virtual bool GetLensFlareEnabled() const = 0; + virtual Vector2 GetLensFlarePosition() const = 0; + virtual RGBAColor8Byte GetLensFlareColor() const = 0; + virtual int GetLensFlareSpriteID() const = 0; + virtual bool GetStarfieldEnabled() const = 0; + virtual bool GetStarfieldMeteorsEnabled() const = 0; + virtual int GetStarfieldStarsCount() const = 0; + virtual int GetStarfieldMeteorsCount() const = 0; + virtual int GetStarfieldMeteorsSpawnDensity() const = 0; + virtual float GetStarfieldMeteorsSpeed() const = 0; }; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp index 5240789f8..455fb73cf 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp @@ -264,7 +264,9 @@ Specify which translations in the strings table correspond to which languages. Animations::Register(tableFlow); Settings::Register(tableFlow); Fog::Register(tableFlow); - + LensFlare::Register(tableFlow); + Starfield::Register(tableFlow); + m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_WeatherType, WEATHER_TYPES); m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_LaraType, PLAYER_TYPES); m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_RotationAxis, ROTATION_AXES); diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp new file mode 100644 index 000000000..690e1a214 --- /dev/null +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp @@ -0,0 +1,85 @@ +#include "framework.h" +#include "LensFlare.h" +#include + +/*** +LensFlare + +@tenclass Flow.LensFlare +@pragma nostrip +*/ + +void LensFlare::Register(sol::table& parent) +{ + using ctors = sol::constructors; + parent.new_usertype("LensFlare", + ctors(), + sol::call_constructor, ctors(), + + /// (@{Color}) RGB lens flare color + //@mem lensFlareColor + "color", sol::property(&LensFlare::GetColor, &LensFlare::SetColor), + + /*** (@{Vec2}) Lens flare orientation. + + This is the position of the lens flare in the sky. The X value is the horizontal position, and the Y value is the vertical position. Angles must be specified in degrees. + + @mem lensFlarePosition*/ + "position", sol::property(&LensFlare::GetPosition, &LensFlare::SetPosition) + ); +} + +/*** +@tparam Vec2 yawPitchInDegrees Position of the lens flare (yaw and pitch) in degrees +@tparam Color color RGB color +@treturn LensFlare A lens flare object. +@function LensFlare +*/ +LensFlare::LensFlare(Vec2 const& yawPitchInDegrees, ScriptColor const& col) +{ + SetColor(col); + SetPosition(yawPitchInDegrees); + Enabled = true; +} + +void LensFlare::SetColor(ScriptColor const& col) +{ + R = col.GetR(); + G = col.GetG(); + B = col.GetB(); +} + + +ScriptColor LensFlare::GetColor() const +{ + return ScriptColor{ R, G, B }; +} + +void LensFlare::SetPosition(Vec2 const& yawPitchInDegrees) +{ + Yaw = yawPitchInDegrees.x; + Pitch = yawPitchInDegrees.y; +} + + +Vec2 LensFlare::GetPosition() const +{ + return Vec2{ Yaw, Pitch }; +} + +bool LensFlare::GetEnabled() const +{ + return Enabled; +} + +void LensFlare::SetSunSpriteID(int const& spriteIndex) +{ + assertion(spriteIndex >= 0 && spriteIndex < g_Level.Sprites.size(), "Sprite Index must be in a valid range"); + + SunSpriteID = spriteIndex; +} + +int LensFlare::GetSunSpriteID() const +{ + return SunSpriteID; +} \ No newline at end of file diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h new file mode 100644 index 000000000..d14f4c7b6 --- /dev/null +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h @@ -0,0 +1,34 @@ +#pragma once + +#include "Scripting/Internal/TEN/Color/Color.h" +#include "Scripting/Internal/TEN/Vec2/Vec2.h" +#include "Objects/objectslist.h" + +namespace sol { class state; } + +struct LensFlare +{ + bool Enabled; + int SunSpriteID = SPR_LENSFLARE3; // Index into sprites + byte R; + byte G; + byte B; + float Yaw; + float Pitch; + + LensFlare() = default; + LensFlare(Vec2 const& yawPitchInDegrees, ScriptColor const& col); + + void SetColor(ScriptColor const& color); + ScriptColor GetColor() const; + + void SetPosition(Vec2 const& yawPitchInDegrees); + Vec2 GetPosition() const; + + void SetSunSpriteID(int const& spriteIndex); + int GetSunSpriteID() const; + + bool GetEnabled() const; + + static void Register(sol::table&); +}; \ No newline at end of file diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp index 55067e76a..919174fdd 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp @@ -52,6 +52,14 @@ void Level::Register(sol::table& parent) //@mem layer2 "layer2", &Level::Layer2, +/// (@{Flow.Starfield}) Starfield +//@mem starfield + "starfield", & Level::Starfield, + +/// (@{Flow.LensFlare}) Global lens flare +//@mem lensFlare + "lensFlare", & Level::LensFlare, + /// (@{Flow.Fog}) omni fog RGB color and distance. // As seen in TR4's Desert Railroad. // If not provided, distance fog will be black. @@ -277,3 +285,53 @@ std::string Level::GetAmbientTrack() const { return AmbientTrack; } + +bool Level::GetLensFlareEnabled() const +{ + return LensFlare.GetEnabled(); +} + +Vector2 Level::GetLensFlarePosition() const +{ + return LensFlare.GetPosition(); +} + +RGBAColor8Byte Level::GetLensFlareColor() const +{ + return LensFlare.GetColor(); +} + +int Level::GetLensFlareSpriteID() const +{ + return LensFlare.GetSunSpriteID(); +} + +bool Level::GetStarfieldEnabled() const +{ + return Starfield.GetEnabled(); +} + +bool Level::GetStarfieldMeteorsEnabled() const +{ + return Starfield.GetMeteorsEnabled(); +} + +int Level::GetStarfieldStarsCount() const +{ + return Starfield.GetStarsCount(); +} + +int Level::GetStarfieldMeteorsCount() const +{ + return Starfield.GetMeteorsCount(); +} + +int Level::GetStarfieldMeteorsSpawnDensity() const +{ + return Starfield.GetMeteorsSpawnDensity(); +} + +float Level::GetStarfieldMeteorsSpeed() const +{ + return Starfield.GetMeteorsSpeed(); +} \ No newline at end of file diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h index e3d632e80..0460e6a9b 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h @@ -1,6 +1,8 @@ #pragma once #include #include "Scripting/Internal/TEN/Flow/SkyLayer/SkyLayer.h" +#include "Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h" +#include "Scripting/Internal/TEN/Flow/Starfield/Starfield.h" #include "Scripting/Internal/TEN/Flow/Mirror/Mirror.h" #include "Scripting/Internal/TEN/Flow/Fog/Fog.h" #include "Scripting/Include/ScriptInterfaceLevel.h" @@ -31,7 +33,10 @@ struct Level : public ScriptInterfaceLevel Mirror Mirror = {}; int LevelFarView = 0; std::string AmbientTrack = {}; - + + LensFlare LensFlare = {}; + Starfield Starfield = {}; + WeatherType Weather = WeatherType::None; float WeatherStrength = 1.0f; bool Storm = false; @@ -62,4 +67,14 @@ struct Level : public ScriptInterfaceLevel int GetSecrets() const override; std::string GetAmbientTrack() const override; bool GetResetHubEnabled() const override; + bool GetLensFlareEnabled() const override; + Vector2 GetLensFlarePosition() const override; + RGBAColor8Byte GetLensFlareColor() const override; + int GetLensFlareSpriteID() const override; + bool GetStarfieldEnabled() const override; + bool GetStarfieldMeteorsEnabled() const override; + int GetStarfieldStarsCount() const override; + int GetStarfieldMeteorsCount() const override; + int GetStarfieldMeteorsSpawnDensity() const override; + float GetStarfieldMeteorsSpeed() const override; }; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/SkyLayer/SkyLayer.cpp b/TombEngine/Scripting/Internal/TEN/Flow/SkyLayer/SkyLayer.cpp index 5e9586a5f..e37d1dbeb 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/SkyLayer/SkyLayer.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/SkyLayer/SkyLayer.cpp @@ -1,58 +1,58 @@ -#include "framework.h" -#include "SkyLayer.h" - -/*** Describes a layer of moving clouds. -As seen in TR4's City of the Dead. - -@tenclass Flow.SkyLayer -@pragma nostrip -*/ - -void SkyLayer::Register(sol::table & parent) -{ - using ctors = sol::constructors; - parent.new_usertype("SkyLayer", - ctors(), - sol::call_constructor, ctors(), - -/// (@{Color}) RGB sky color -//@mem color - "color", sol::property(&SkyLayer::GetColor, &SkyLayer::SetColor), - -/*** (int) cloud speed. - -Values can be between [-32768, 32767], with positive numbers resulting in a sky that scrolls from -west to east, and negative numbers resulting in one that travels east to west. - -Please note that speeds outside of the range of about [-1000, 1000] will cause the -sky to scroll so fast that it will no longer appear as a coherent stream of clouds. -Less is more. City of The Dead, for example, uses a speed value of 16. - -@mem speed*/ - "speed", &SkyLayer::CloudSpeed - ); -} - -/*** -@tparam Color color RGB color -@tparam int speed cloud speed -@treturn SkyLayer A SkyLayer object. -@function SkyLayer -*/ -SkyLayer::SkyLayer(ScriptColor const& col, short speed) -{ - SetColor(col); - CloudSpeed = speed; - Enabled = true; -} - -void SkyLayer::SetColor(ScriptColor const & col) -{ - R = col.GetR(); - G = col.GetG(); - B = col.GetB(); -} - -ScriptColor SkyLayer::GetColor() const { - return ScriptColor{ R, G, B }; -} +#include "framework.h" +#include "SkyLayer.h" + +/*** Describes a layer of moving clouds. +As seen in TR4's City of the Dead. + +@tenclass Flow.SkyLayer +@pragma nostrip +*/ + +void SkyLayer::Register(sol::table & parent) +{ + using ctors = sol::constructors; + parent.new_usertype("SkyLayer", + ctors(), + sol::call_constructor, ctors(), + + /// (@{Color}) RGB sky color + //@mem color + "color", sol::property(&SkyLayer::GetColor, &SkyLayer::SetColor), + + /*** (int) cloud speed. + + Values can be between [-32768, 32767], with positive numbers resulting in a sky that scrolls from + west to east, and negative numbers resulting in one that travels east to west. + + Please note that speeds outside of the range of about [-1000, 1000] will cause the + sky to scroll so fast that it will no longer appear as a coherent stream of clouds. + Less is more. City of The Dead, for example, uses a speed value of 16. + + @mem speed*/ + "speed", &SkyLayer::CloudSpeed + ); +} + +/*** +@tparam Color color RGB color +@tparam int speed cloud speed +@treturn SkyLayer A SkyLayer object. +@function SkyLayer +*/ +SkyLayer::SkyLayer(ScriptColor const& col, short speed) +{ + SetColor(col); + CloudSpeed = speed; + Enabled = true; +} + +void SkyLayer::SetColor(ScriptColor const & col) +{ + R = col.GetR(); + G = col.GetG(); + B = col.GetB(); +} + +ScriptColor SkyLayer::GetColor() const { + return ScriptColor{ R, G, B }; +} diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp new file mode 100644 index 000000000..56f957300 --- /dev/null +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp @@ -0,0 +1,127 @@ +#include "framework.h" +#include "Starfield.h" +#include "Specific/level.h" +#include "Game/effects/weather.h" + +using namespace TEN::Effects::Environment; + +/*** +Starfield + +@tenclass Flow.Starfield +@pragma nostrip +*/ + +void Starfield::Register(sol::table& parent) +{ + using ctors = sol::constructors; + parent.new_usertype("Starfield", + ctors(), + sol::call_constructor, ctors(), + + /*** (int) Stars count. + + Values can be between [0, 6000], 0 resulting in no stars being rendered, and 6000 resulting in the maximum number of stars being rendered. + + @mem starsCount*/ + "starsCount", sol::property(&Starfield::GetStarsCount, &Starfield::SetStarsCount), + + /*** (int) Meteors count. + + Values can be between [0, 100], 0 resulting in no meteors being rendered, and 100 resulting in the maximum number of meteors being rendered. + + @mem meteorsCount*/ + "meteorsCount", sol::property(&Starfield::GetMeteorsCount, &Starfield::SetMeteorsCount), + + /*** (int) Meteors spawn density. + + @mem meteorsSpawnDensity*/ + "meteorsSpawnDensity", sol::property(&Starfield::GetMeteorsSpawnDensity, &Starfield::SetMeteorsSpawnDensity), + + /*** (float) Meteors speed. + + @mem meteorsSpeed*/ + "meteorsSpeed", sol::property(&Starfield::GetMeteorsSpeed, &Starfield::SetMeteorsSpeed) + ); +} + +/*** +@tparam int starsCount Stars count +@treturn Starfield A starfield object with only stars enabled. +@function Starfield +*/ +Starfield::Starfield(int starsCount) +{ + SetStarsCount(starsCount); + SetMeteorsCount(0); +} + +/*** +@tparam int starsCount Stars count +@tparam int meteorsCount Stars count +@treturn Starfield A starfield object with boths stars and meteors enabled. +@function Starfield +*/ +Starfield::Starfield(int starsCount, int meteorsCount, int meteorsSpawnDensity, int meteorsSpawnSpeed) +{ + SetStarsCount(starsCount); + SetMeteorsCount(meteorsCount); + SetMeteorsSpawnDensity(meteorsSpawnDensity); + SetMeteorsSpeed(meteorsSpawnSpeed); +} + +void Starfield::SetStarsCount(int const& starsCount) +{ + assertion(starsCount >= 0 && starsCount <= 6000, "Stars count must be in the range 0 ... 6000"); + StarsCount = starsCount; +} + + +int Starfield::GetStarsCount() const +{ + return StarsCount; +} + +void Starfield::SetMeteorsCount(int const& meteorsCount) +{ + assertion(meteorsCount >= 0 && meteorsCount <= 100, "Stars count must be in the range 0 ... 100"); + MeteorsCount = meteorsCount; +} + + +int Starfield::GetMeteorsCount() const +{ + return MeteorsCount; +} + +void Starfield::SetMeteorsSpawnDensity(int const& meteorsSpawnDensity) +{ + MeteorsSpawnDensity = meteorsSpawnDensity; +} + + +int Starfield::GetMeteorsSpawnDensity() const +{ + return MeteorsSpawnDensity; +} + +void Starfield::SetMeteorsSpeed(float const& meteorsSpeed) +{ + MeteorsSpeed = meteorsSpeed; +} + + +float Starfield::GetMeteorsSpeed() const +{ + return MeteorsSpeed; +} + +bool Starfield::GetEnabled() const +{ + return (StarsCount > 0); +} + +bool Starfield::GetMeteorsEnabled() const +{ + return (MeteorsCount > 0); +} \ No newline at end of file diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h new file mode 100644 index 000000000..4144bb516 --- /dev/null +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Scripting/Internal/TEN/Color/Color.h" +#include "Scripting/Internal/TEN/Vec2/Vec2.h" + +namespace sol { class state; } + +struct Starfield +{ + int StarsCount = 0; // No need for StarryNight flag, if stars count = 0, shader is bypassed + + int MeteorsCount = 0; // No need for EnableMeteors flag, if meteors count = 0, shader is bypassed + int MeteorsSpawnDensity = 0; + int MeteorsSpeed = 0; + + Starfield() = default; + Starfield(int starsCount); + Starfield(int starsCount, int meteorsCount, int meteorsSpawnDensity, int meteorsSpeed); + + void SetStarsCount(int const& starsCount); + int GetStarsCount() const; + + void SetMeteorsCount(int const& meteorsCount); + int GetMeteorsCount() const; + + void SetMeteorsSpawnDensity(int const& spawnDensity); + int GetMeteorsSpawnDensity() const; + + void SetMeteorsSpeed(float const& meteorsSpeed); + float GetMeteorsSpeed() const; + + bool GetEnabled() const; + bool GetMeteorsEnabled() const; + + static void Register(sol::table&); +}; \ No newline at end of file diff --git a/TombEngine/Shaders/CBPostProcess.hlsli b/TombEngine/Shaders/CBPostProcess.hlsli index dfe6f2514..f31a7d75f 100644 --- a/TombEngine/Shaders/CBPostProcess.hlsli +++ b/TombEngine/Shaders/CBPostProcess.hlsli @@ -3,7 +3,10 @@ struct ShaderLensFlare { float3 Position; - float Padding; + float Padding1; + //-- + float3 Color; + float Padding2; }; cbuffer CBPostProcess : register(b7) diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx index 1fa91fb39..3d7b7b786 100644 --- a/TombEngine/Shaders/PostProcess.fx +++ b/TombEngine/Shaders/PostProcess.fx @@ -102,9 +102,9 @@ float3 LensFlare(float2 uv, float2 pos) float f1 = max(0.01f - pow(length(uv + 1.2f * pos), 1.9f), 0.0f) * 7.0f; - float f2 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.8f * pos), 2.0f)), 0.0f) * 00.1f; - float f22 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.85f * pos), 2.0f)), 0.0f) * 00.08f; - float f23 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.9f * pos), 2.0f)), 0.0f) * 00.06f; + float f2 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.8f * pos), 2.0f)), 0.0f) * 0.1f; + float f22 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.85f * pos), 2.0f)), 0.0f) * 0.08f; + float f23 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.9f * pos), 2.0f)), 0.0f) * 0.06f; float2 uvx = lerp(uv, uvd, -0.5f); @@ -154,7 +154,10 @@ float4 PSLensFlare(PixelShaderInput input) : SV_Target lensFlarePosition = mul(mul(lensFlarePosition, View), Projection); lensFlarePosition.xyz /= lensFlarePosition.w; - float3 lensFlareColor = max(float3(0.0f, 0.0f, 0.0f), float3(4.5f, 3.6f, 3.6f) * LensFlare(position.xy, lensFlarePosition.xy)); + float3 lensFlareColor = max(float3(0.0f, 0.0f, 0.0f), + LensFlares[i].Color * + float3(4.5f, 3.6f, 3.6f) * + LensFlare(position.xy, lensFlarePosition.xy)); lensFlareColor = LensFlareColorCorrection(lensFlareColor, 0.5f, 0.1f); totalLensFlareColor += lensFlareColor; } diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 6464b9af8..e734a2fb8 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -1,4 +1,4 @@ - + @@ -777,10 +777,12 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + + @@ -1208,10 +1210,12 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + + From b3f8261c9bf7ea252e23358af5d6d29ef34dc0f5 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 28 Apr 2024 11:07:03 +0200 Subject: [PATCH 112/410] Fix sound update --- TombEngine/Game/control/control.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 629ab4e9a..e4b7ecd8f 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -270,6 +270,7 @@ GameStatus ControlPhase(int numFrames) RumbleScreen(); PlaySoundSources(); + Sound_UpdateScene(); DoFlipEffect(FlipEffect, LaraItem); // Post-loop script and event handling. @@ -661,8 +662,6 @@ GameStatus DoGameLoop(int levelIndex) float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); DrawPhase(!levelIndex, interpolateFactor); drawCalls++; - - Sound_UpdateScene(); } EndGameLoop(levelIndex, status); From 6e551b97df1f6080f8e8df7f15efde4a723628eb Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 28 Apr 2024 13:54:16 +0200 Subject: [PATCH 113/410] Make some order in renderer functions, fix flickering user strings and sprites --- TombEngine/Game/control/control.cpp | 11 +++++------ TombEngine/Renderer/Renderer.cpp | 10 ---------- TombEngine/Renderer/Renderer.h | 2 +- TombEngine/Renderer/RendererDraw.cpp | 25 +++++++++++++++---------- TombEngine/Renderer/RendererString.cpp | 3 --- 5 files changed, 21 insertions(+), 30 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e4b7ecd8f..5712c6f08 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -126,9 +126,6 @@ int DrawPhase(bool isTitle, float interpolateFactor) g_Renderer.Render(interpolateFactor); } - // Clear display sprites. - ClearDisplaySprites(); - //Camera.numberFrames = g_Renderer.Synchronize(); return Camera.numberFrames; } @@ -139,10 +136,11 @@ GameStatus ControlPhase(int numFrames) bool isTitle = (CurrentLevel == 0); - ClearFires(); - g_Renderer.ClearDynamicLights(); + g_Renderer.PrepareScene(); RegeneratePickups(); + ClearFires(); ClearLensFlares(); + ClearDisplaySprites(); numFrames = std::clamp(numFrames, 0, 10); @@ -270,9 +268,10 @@ GameStatus ControlPhase(int numFrames) RumbleScreen(); PlaySoundSources(); - Sound_UpdateScene(); DoFlipEffect(FlipEffect, LaraItem); + Sound_UpdateScene(); + // Post-loop script and event handling. g_GameScript->OnLoop(DELTA_TIME, true); diff --git a/TombEngine/Renderer/Renderer.cpp b/TombEngine/Renderer/Renderer.cpp index 3b6b4d87e..144eb2542 100644 --- a/TombEngine/Renderer/Renderer.cpp +++ b/TombEngine/Renderer/Renderer.cpp @@ -34,8 +34,6 @@ namespace TEN::Renderer { _shadowLight = nullptr; - ClearSceneItems(); - _moveableObjects.resize(0); _staticObjects.resize(0); _sprites.resize(0); @@ -60,14 +58,6 @@ namespace TEN::Renderer } } - void Renderer::ClearSceneItems() - { - _lines2DToDraw.clear(); - _lines3DToDraw.clear(); - _triangles3DToDraw.clear(); - _gameCamera.Clear(); - } - void Renderer::Lock() { _isLocked = true; diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index f84914316..2154befb1 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -598,6 +598,7 @@ namespace TEN::Renderer void DumpGameScene(); void RenderInventory(); void RenderScene(RenderTarget2D* renderTarget, bool doAntialiasing, RenderView& view); + void PrepareScene(); void ClearScene(); void SaveScreenshot(); void PrintDebugMessage(LPCSTR message, ...); @@ -616,7 +617,6 @@ namespace TEN::Renderer void SetFullScreen(); bool IsFullsScreen(); void RenderTitleImage(); - void ClearDynamicLights(); void AddLine2D(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 6c110c6cc..736eaac32 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1627,22 +1627,26 @@ namespace TEN::Renderer _dynamicLights.push_back(dynamicLight); } - void Renderer::ClearDynamicLights() + void Renderer::PrepareScene() { _dynamicLights.clear(); - } - - void Renderer::ClearScene() - { - ResetAnimations(); - - ClearSceneItems(); - ClearShadowMap(); + _lines2DToDraw.clear(); + _lines3DToDraw.clear(); + _triangles3DToDraw.clear(); + _stringsToDraw.clear(); _currentCausticsFrame++; _currentCausticsFrame %= 32; - CalculateFrameRate(); + _isBlinkUpdated = false; + } + + void Renderer::ClearScene() + { + _gameCamera.Clear(); + + ResetAnimations(); + ClearShadowMap(); } void Renderer::RenderScene(RenderTarget2D* renderTarget, bool doAntialiasing, RenderView& view) @@ -1934,6 +1938,7 @@ namespace TEN::Renderer DrawAllStrings(); ClearScene(); + CalculateFrameRate(); } void Renderer::RenderSimpleSceneToParaboloid(RenderTarget2D* renderTarget, Vector3 position, int emisphere) diff --git a/TombEngine/Renderer/RendererString.cpp b/TombEngine/Renderer/RendererString.cpp index b26196f44..1aacef836 100644 --- a/TombEngine/Renderer/RendererString.cpp +++ b/TombEngine/Renderer/RendererString.cpp @@ -127,8 +127,5 @@ namespace TEN::Renderer } _spriteBatch->End(); - - _isBlinkUpdated = false; - _stringsToDraw.clear(); } } From 08ca9bacef86fe7f1f422f86754bdf3956ab4e4d Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 28 Apr 2024 13:59:56 +0200 Subject: [PATCH 114/410] Update Renderer.h --- TombEngine/Renderer/Renderer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 2154befb1..9a2f37bd5 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -407,7 +407,6 @@ namespace TEN::Renderer void CollectLightsForCamera(); void CalculateLightFades(RendererItem* item); void CollectEffects(short roomNumber); - void ClearSceneItems(); void ClearShadowMap(); void CalculateSSAO(RenderView& view); void UpdateItemAnimations(RenderView& view); From f2a55eec8b940443b8b7d5686f88a33244642965 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 28 Apr 2024 15:18:24 +0200 Subject: [PATCH 115/410] Fix double-draw in menus and title flyby --- TombEngine/Game/control/control.cpp | 86 ++++++++++---------------- TombEngine/Game/gui.cpp | 3 + TombEngine/Renderer/Renderer.h | 3 +- TombEngine/Renderer/RendererDraw.cpp | 16 ++++- TombEngine/Renderer/RendererString.cpp | 17 ----- 5 files changed, 49 insertions(+), 76 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 5712c6f08..3528c0528 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -126,14 +126,17 @@ int DrawPhase(bool isTitle, float interpolateFactor) g_Renderer.Render(interpolateFactor); } + g_Renderer.Lock(); + //Camera.numberFrames = g_Renderer.Synchronize(); return Camera.numberFrames; } GameStatus ControlPhase(int numFrames) { - auto time1 = std::chrono::high_resolution_clock::now(); + static int framesCount = 0; + auto time1 = std::chrono::high_resolution_clock::now(); bool isTitle = (CurrentLevel == 0); g_Renderer.PrepareScene(); @@ -152,9 +155,6 @@ GameStatus ControlPhase(int numFrames) g_GameStringsHandler->ProcessDisplayStrings(DELTA_TIME); - bool isFirstTime = true; - static int framesCount = 0; - // Save current state to old variables for interpolation SaveOldState(); g_Renderer.SaveOldState(); @@ -282,13 +282,6 @@ GameStatus ControlPhase(int numFrames) GameTimer++; GlobalCounter++; - // Add renderer objects on the first processed frame. - if (isFirstTime) - { - g_Renderer.Lock(); - isFirstTime = false; - } - using ns = std::chrono::nanoseconds; using get_time = std::chrono::steady_clock; @@ -622,41 +615,8 @@ GameStatus DoGameLoop(int levelIndex) controlCalls++; } - if (!levelIndex) - { - UpdateInputActions(LaraItem); - - auto invStatus = g_Gui.TitleOptions(LaraItem); - - switch (invStatus) - { - case InventoryResult::NewGame: - case InventoryResult::NewGameSelectedLevel: - status = GameStatus::NewGame; - break; - - case InventoryResult::LoadGame: - status = GameStatus::LoadGame; - break; - - case InventoryResult::ExitGame: - status = GameStatus::ExitGame; - break; - } - - if (invStatus != InventoryResult::None) - break; - } - else - { - if (status == GameStatus::ExitToTitle || - status == GameStatus::LaraDead || - status == GameStatus::LoadGame || - status == GameStatus::LevelComplete) - { - break; - } - } + if (status != GameStatus::Normal) + break; float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); DrawPhase(!levelIndex, interpolateFactor); @@ -686,24 +646,40 @@ void SaveOldState() void HandleControls(bool isTitle) { // Poll input devices and update input variables. - if (!isTitle) - { - // TODO: To allow cutscene skipping later, don't clear Deselect action. - UpdateInputActions(LaraItem, true); - } - else - { + // TODO: To allow cutscene skipping later, don't clear Deselect action. + UpdateInputActions(LaraItem, true); + + if (isTitle) ClearAction(In::Look); - } } GameStatus HandleMenuCalls(bool isTitle) { auto result = GameStatus::Normal; - if (isTitle || ScreenFading) + if (ScreenFading) return result; + if (isTitle) + { + auto invStatus = g_Gui.TitleOptions(LaraItem); + + switch (invStatus) + { + case InventoryResult::NewGame: + case InventoryResult::NewGameSelectedLevel: + return GameStatus::NewGame; + + case InventoryResult::LoadGame: + return GameStatus::LoadGame; + + case InventoryResult::ExitGame: + return GameStatus::ExitGame; + } + + return result; + } + // Does the player want to enter inventory? if (IsClicked(In::Save) && LaraItem->HitPoints > 0 && g_Gui.GetInventoryMode() != InventoryMode::Save && diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index a283317e2..51332bd7c 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -274,7 +274,9 @@ namespace TEN::Gui void GuiController::DrawInventory() { + g_Renderer.PrepareScene(); g_Renderer.RenderInventory(); + g_Renderer.Lock(); // TODO: When inventory is converted to 60 FPS, move this lock call outside of render loop. } InventoryResult GuiController::TitleOptions(ItemInfo* item) @@ -3374,6 +3376,7 @@ namespace TEN::Gui UseItem(*item, InventoryObjectTable[LastInvItem].ObjectNumber); AlterFOV(LastFOV); + g_Renderer.PrepareScene(); ResumeAllSounds(SoundPauseMode::Inventory); lara->Inventory.IsBusy = lara->Inventory.OldBusy; diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 9a2f37bd5..8a4dad0b6 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -202,7 +202,6 @@ namespace TEN::Renderer std::vector _stringsToDraw; float _blinkColorValue = 0.0f; float _blinkTime = 0.0f; - bool _isBlinkUpdated = false; // Graphics resources Texture2D _logo; @@ -309,7 +308,7 @@ namespace TEN::Renderer bool _isWindowed; float _farView = DEFAULT_FAR_VIEW; - // A flag to prevent extra renderer object addition + // A flag to prevent extra renderer object additions bool _isLocked = false; // Caching state changes diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 736eaac32..cf23ac649 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1638,7 +1638,19 @@ namespace TEN::Renderer _currentCausticsFrame++; _currentCausticsFrame %= 32; - _isBlinkUpdated = false; + constexpr auto BLINK_VALUE_MAX = 1.0f; + constexpr auto BLINK_VALUE_MIN = 0.1f; + constexpr auto BLINK_TIME_STEP = 0.2f; + + // Calculate blink increment based on sine wave. + _blinkColorValue = ((sin(_blinkTime) + BLINK_VALUE_MAX) * 0.5f) + BLINK_VALUE_MIN; + + // Update blink time. + _blinkTime += BLINK_TIME_STEP; + if (_blinkTime > PI_MUL_2) + _blinkTime -= PI_MUL_2; + + _isLocked = false; } void Renderer::ClearScene() @@ -1655,7 +1667,6 @@ namespace TEN::Renderer using get_time = std::chrono::steady_clock; ResetDebugVariables(); - _isLocked = false; _doingFullscreenPass = false; auto& level = *g_GameFlow->GetLevel(CurrentLevel); @@ -3098,6 +3109,7 @@ namespace TEN::Renderer //_gameCamera = _currentGameCamera; RenderScene(&_backBuffer, true, _gameCamera); + _context->ClearState(); _swapChain->Present(1, 0); } diff --git a/TombEngine/Renderer/RendererString.cpp b/TombEngine/Renderer/RendererString.cpp index 1aacef836..3f8325389 100644 --- a/TombEngine/Renderer/RendererString.cpp +++ b/TombEngine/Renderer/RendererString.cpp @@ -22,10 +22,6 @@ namespace TEN::Renderer void Renderer::AddString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags) { - constexpr auto BLINK_VALUE_MAX = 1.0f; - constexpr auto BLINK_VALUE_MIN = 0.1f; - constexpr auto BLINK_TIME_STEP = 0.2f; - if (_isLocked) return; @@ -75,19 +71,6 @@ namespace TEN::Renderer if (flags & (int)PrintStringFlags::Blink) { rString.Color *= _blinkColorValue; - - if (!_isBlinkUpdated) - { - // Calculate blink increment based on sine wave. - _blinkColorValue = ((sin(_blinkTime) + BLINK_VALUE_MAX) * 0.5f) + BLINK_VALUE_MIN; - - // Update blink time. - _blinkTime += BLINK_TIME_STEP; - if (_blinkTime > PI_MUL_2) - _blinkTime -= PI_MUL_2; - - _isBlinkUpdated = true; - } } yOffset += size.y; From 33807e8198a4cc0504694089c5c5a3ae34f943cd Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 28 Apr 2024 15:51:51 +0200 Subject: [PATCH 116/410] Remove locked flag checks from internal renderer sprite methods --- TombEngine/Renderer/RendererSprites.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/TombEngine/Renderer/RendererSprites.cpp b/TombEngine/Renderer/RendererSprites.cpp index b969a0efe..28d3cc8ad 100644 --- a/TombEngine/Renderer/RendererSprites.cpp +++ b/TombEngine/Renderer/RendererSprites.cpp @@ -10,9 +10,6 @@ namespace TEN::Renderer void Renderer::AddSpriteBillboard(RendererSprite* sprite, const Vector3& pos, const Vector4& color, float orient2D, float scale, Vector2 size, BlendMode blendMode, bool isSoftParticle, RenderView& view, SpriteRenderType renderType) { - if (_isLocked) - return; - if (scale <= 0.0f) scale = 1.0f; @@ -44,9 +41,6 @@ namespace TEN::Renderer float scale, Vector2 size, BlendMode blendMode, const Vector3& constrainAxis, bool softParticles, RenderView& view, SpriteRenderType renderType) { - if (_isLocked) - return; - if (scale <= 0.0f) scale = 1.0f; @@ -79,9 +73,6 @@ namespace TEN::Renderer float scale, Vector2 size, BlendMode blendMode, const Vector3& lookAtAxis, bool isSoftParticle, RenderView& view, SpriteRenderType renderType) { - if (_isLocked) - return; - if (scale <= 0.0f) scale = 1.0f; @@ -121,9 +112,6 @@ namespace TEN::Renderer const Vector4& color0, const Vector4& color1, const Vector4& color2, const Vector4& color3, float orient2D, float scale, Vector2 size, BlendMode blendMode, bool isSoftParticle, RenderView& view, SpriteRenderType renderType) { - if (_isLocked) - return; - if (scale <= 0.0f) scale = 1.0f; @@ -164,9 +152,6 @@ namespace TEN::Renderer const Vector4& color0, const Vector4& color1, const Vector4& color2, const Vector4& color3, BlendMode blendMode, RenderView& view, SpriteRenderType renderType) { - if (_isLocked) - return; - auto sprite = RendererSpriteToDraw{}; sprite.Type = SpriteType::ThreeD; From 77cd0644f76f587e9554f4e521e588bb4a1b20f7 Mon Sep 17 00:00:00 2001 From: Joey Quint Date: Sun, 28 Apr 2024 22:05:58 +0200 Subject: [PATCH 117/410] Fixed camera rotating with Lara's hips when climbing out of water - fixes #1311 --- Documentation/Changes.txt | 1 + TombEngine/Game/Lara/lara_surface.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 035d60ef2..08900121d 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -3,6 +3,7 @@ Version 1.5 * Fixed original issue with classic switch off trigger wrongly activating some trigger actions. * Fixed incorrect diving animation when swandiving from a high place. +* Fixed camera rotating with Lara's hips when climbing out of water. * Fixed AI for skidoo driver and worker with shotgun TR2 enemies. Lua API changes: diff --git a/TombEngine/Game/Lara/lara_surface.cpp b/TombEngine/Game/Lara/lara_surface.cpp index c79e89cd3..9ec72f52f 100644 --- a/TombEngine/Game/Lara/lara_surface.cpp +++ b/TombEngine/Game/Lara/lara_surface.cpp @@ -273,6 +273,5 @@ void lara_as_surface_climb_out(ItemInfo* item, CollisionInfo* coll) player.Control.Look.Mode = LookMode::None; coll->Setup.EnableObjectPush = false; coll->Setup.EnableSpasm = false; - Camera.flags = CF_FOLLOW_CENTER; - Camera.laraNode = LM_HIPS; // Forces the camera to follow Lara instead of snapping. + Camera.flags = CF_FOLLOW_CENTER; // Forces the camera to follow Lara instead of snapping. } From f5adbec7c88074213610f1695f216fa80c87e655 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 29 Apr 2024 05:18:11 +0200 Subject: [PATCH 118/410] Added DisableInterpolation flag for items; Fixed shaders; --- TombEngine/Game/animation.cpp | 2 ++ TombEngine/Game/control/control.cpp | 9 ++++--- TombEngine/Game/control/control.h | 2 +- TombEngine/Game/control/flipeffect.cpp | 2 ++ TombEngine/Game/items.h | 2 ++ TombEngine/Renderer/Renderer.h | 2 +- TombEngine/Renderer/RendererDraw.cpp | 25 +++---------------- TombEngine/Renderer/RendererFrame.cpp | 19 +++++++++++--- .../TEN/Objects/Moveable/MoveableObject.cpp | 4 +++ TombEngine/Shaders/CBCamera.hlsli | 7 +++++- TombEngine/Shaders/ShaderLight.hlsli | 1 + 11 files changed, 44 insertions(+), 31 deletions(-) diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 3003f6292..823c67cbf 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -60,6 +60,8 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased) { UpdateItemRoom(item.Index); } + + item.DisableInterpolation = true; } commandDataPtr += 3; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 629ab4e9a..72a7dec23 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -158,7 +158,7 @@ GameStatus ControlPhase(int numFrames) static int framesCount = 0; // Save current state to old variables for interpolation - SaveOldState(); + SetupInterpolation(); g_Renderer.SaveOldState(); // Controls are polled before OnLoop, so input data could be @@ -680,9 +680,12 @@ void EndGameLoop(int levelIndex, GameStatus reason) StopRumble(); } -void SaveOldState() +void SetupInterpolation() { - + for (int i = 0; i < g_Level.Items.size(); i++) + { + g_Level.Items[i].DisableInterpolation = false; + } } void HandleControls(bool isTitle) diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index c8191810d..b9b8b78d2 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -105,6 +105,6 @@ void InitializeOrLoadGame(bool loadGame); void InitializeScripting(int levelIndex, LevelLoadType type); void DeInitializeScripting(int levelIndex); -void SaveOldState(); +void SetupInterpolation(); unsigned CALLBACK GameMain(void*); diff --git a/TombEngine/Game/control/flipeffect.cpp b/TombEngine/Game/control/flipeffect.cpp index b128351a8..76ccbeba5 100644 --- a/TombEngine/Game/control/flipeffect.cpp +++ b/TombEngine/Game/control/flipeffect.cpp @@ -331,6 +331,8 @@ void Turn180(ItemInfo* item) item->Pose.Orientation.x = -item->Pose.Orientation.x; item->Pose.Orientation.y += ANGLE(180.0f); item->Pose.Orientation.z = -item->Pose.Orientation.z; + + item->DisableInterpolation = true; } void FinishLevel(ItemInfo* item) diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index 9e0faed69..86c4045ff 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -174,6 +174,8 @@ struct ItemInfo bool IsCreature() const; bool IsBridge() const; + bool DisableInterpolation = false; + void StoreInterpolationData() { OldPose = Pose; diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index f84914316..7988baced 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -502,7 +502,7 @@ namespace TEN::Renderer void SetScissor(RendererRectangle rectangle); bool SetupBlendModeAndAlphaTest(BlendMode blendMode, RendererPass rendererPass, int drawPass); void SortAndPrepareSprites(RenderView& view); - void ResetAnimations(); + void ResetItems(); void ResetScissor(); void ResetDebugVariables(); float CalculateFrameRate(); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 6c110c6cc..30008a2d6 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1634,7 +1634,7 @@ namespace TEN::Renderer void Renderer::ClearScene() { - ResetAnimations(); + ResetItems(); ClearSceneItems(); ClearShadowMap(); @@ -3057,26 +3057,7 @@ namespace TEN::Renderer { //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); - /*RenderView oldCamera = RenderView( - &PreviousCamera, - 0, - TO_RAD(CurrentFOV / 1.333333f) , - 32, 100*1024, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); - - RenderView newCamera = RenderView( - &Camera, - 0, - TO_RAD(CurrentFOV / 1.333333f), - 32, 100 * 1024, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); - - _gameCamera.Camera = oldCamera.Camera; - _gameCamera.Camera.WorldPosition = Vector3::Lerp(oldCamera.Camera.WorldPosition, newCamera.Camera.WorldPosition, interpolateFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(oldCamera.Camera.WorldDirection, newCamera.Camera.WorldDirection, interpolateFactor); - _gameCamera.Camera.View = Matrix::Lerp(oldCamera.Camera.View, newCamera.Camera.View, interpolateFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(oldCamera.Camera.Projection, newCamera.Camera.Projection, interpolateFactor); - _gameCamera.Camera.View = _gameCamera.Camera.View * _gameCamera.Camera.Projection; -*/ - + // Interpolate camera _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolateFactor); _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolateFactor); _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolateFactor); @@ -3091,8 +3072,8 @@ namespace TEN::Renderer _interpolationFactor = interpolateFactor; - //_gameCamera = _currentGameCamera; RenderScene(&_backBuffer, true, _gameCamera); + _context->ClearState(); _swapChain->Present(1, 0); } diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index e552f5772..3c8171dd5 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -420,7 +420,7 @@ namespace TEN::Renderer // Blow up sphere radius by half for cases of too small calculated spheres. if (renderView.Camera.Frustum.SphereInFrustum(spheres[i].Center, spheres[i].Radius * 1.5f)) inFrustum = true; - + if (!inFrustum) continue; } @@ -436,12 +436,23 @@ namespace TEN::Renderer newItem->Scale = Matrix::CreateScale(1.0f); newItem->World = newItem->Rotation * newItem->Translation; + if (item->DisableInterpolation) + { + // In this way the interpolation will return always the same result + newItem->OldPosition = newItem->Position; + newItem->OldTranslation = newItem->Translation; + newItem->OldRotation = newItem->Rotation; + newItem->OldWorld = newItem->World; + for (int j = 0; j < MAX_BONES; j++) + newItem->OldAnimationTransforms[j] = newItem->AnimationTransforms[j]; + } + newItem->InterpolatedPosition = Vector3::Lerp(newItem->OldPosition, newItem->Position, _interpolationFactor); newItem->InterpolatedTranslation = Matrix::Lerp(newItem->OldTranslation, newItem->Translation, _interpolationFactor); newItem->InterpolatedRotation = Matrix::Lerp(newItem->InterpolatedRotation, newItem->Rotation, _interpolationFactor); newItem->InterpolatedWorld = Matrix::Lerp(newItem->OldWorld, newItem->World, _interpolationFactor); for (int j = 0; j < MAX_BONES; j++) - newItem->InterpolatedAnimationTransforms[j] = Matrix::Lerp(newItem->OldAnimationTransforms[j], newItem->AnimationTransforms[j], _interpolationFactor); + newItem->InterpolatedAnimationTransforms[j] = Matrix::Lerp(newItem->OldAnimationTransforms[j], newItem->AnimationTransforms[j], _interpolationFactor); CalculateLightFades(newItem); CollectLightsForItem(newItem); @@ -884,10 +895,12 @@ namespace TEN::Renderer } } - void Renderer::ResetAnimations() + void Renderer::ResetItems() { for (int i = 0; i < ITEM_COUNT_MAX; i++) + { _items[i].DoneAnimations = false; + } } diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 76610d3f1..4e5a62952 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -601,6 +601,8 @@ void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) if (m_item->IsBridge()) UpdateBridgeItem(*m_item); + + m_item->DisableInterpolation = true; } Vec3 Moveable::GetJointPos(int jointIndex) const @@ -631,6 +633,8 @@ void Moveable::SetRot(const Rotation& rot) if (m_item->IsBridge()) UpdateBridgeItem(*m_item); + + m_item->DisableInterpolation = true; } short Moveable::GetHP() const diff --git a/TombEngine/Shaders/CBCamera.hlsli b/TombEngine/Shaders/CBCamera.hlsli index ff1f232db..85dc4ac3d 100644 --- a/TombEngine/Shaders/CBCamera.hlsli +++ b/TombEngine/Shaders/CBCamera.hlsli @@ -1,3 +1,6 @@ +#ifndef CBCAMERASHADER +#define CBCAMERASHADER + #include "./Math.hlsli" cbuffer CBCamera : register(b0) @@ -34,4 +37,6 @@ cbuffer CBCamera : register(b0) float3 Padding2; //-- ShaderFogBulb FogBulbs[MAX_FOG_BULBS]; -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/TombEngine/Shaders/ShaderLight.hlsli b/TombEngine/Shaders/ShaderLight.hlsli index eae69ab08..64c47f13e 100644 --- a/TombEngine/Shaders/ShaderLight.hlsli +++ b/TombEngine/Shaders/ShaderLight.hlsli @@ -1,6 +1,7 @@ #ifndef SHADER_LIGHT #define SHADER_LIGHT +#include "./CBCamera.hlsli" #include "./Math.hlsli" float3 DoSpecularPoint(float3 pos, float3 n, ShaderLight light, float strength) From 539bafc1b08d51b3bcba496a87ea7668340f844c Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 29 Apr 2024 09:09:35 +0200 Subject: [PATCH 119/410] Added debris interpolation; Added effects interpolation (missiles, projectiles...); --- TombEngine/Game/effects/debris.cpp | 2 ++ TombEngine/Game/effects/debris.h | 6 +++++ TombEngine/Game/effects/effects.h | 2 ++ TombEngine/Game/items.cpp | 5 ---- TombEngine/Game/items.h | 6 ----- TombEngine/Renderer/RendererDrawEffect.cpp | 4 ++-- TombEngine/Renderer/RendererFrame.cpp | 24 +++++++++++++++---- .../Renderer/Structures/RendererEffect.h | 15 ++++++++++++ 8 files changed, 47 insertions(+), 17 deletions(-) diff --git a/TombEngine/Game/effects/debris.cpp b/TombEngine/Game/effects/debris.cpp index 9d98a0ada..e0faa1630 100644 --- a/TombEngine/Game/effects/debris.cpp +++ b/TombEngine/Game/effects/debris.cpp @@ -217,6 +217,8 @@ void UpdateDebris() { if (deb.active) { + deb.StoreInterpolationData(); + FloorInfo* floor; short roomNumber; diff --git a/TombEngine/Game/effects/debris.h b/TombEngine/Game/effects/debris.h index 1c2df5372..513d096ed 100644 --- a/TombEngine/Game/effects/debris.h +++ b/TombEngine/Game/effects/debris.h @@ -71,6 +71,12 @@ struct DebrisFragment bool active; bool isStatic; Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; extern SHATTER_ITEM ShatterItem; diff --git a/TombEngine/Game/effects/effects.h b/TombEngine/Game/effects/effects.h index ba45f28c4..bb87f3a04 100644 --- a/TombEngine/Game/effects/effects.h +++ b/TombEngine/Game/effects/effects.h @@ -89,6 +89,8 @@ struct FX_INFO Vector4 color; short flag1; short flag2; + + bool DisableInterpolation; }; struct NODEOFFSET_INFO diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 590de6614..29a4cf9bc 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -745,11 +745,6 @@ int FindItem(ItemInfo* item) void UpdateAllItems() { - for (int i = 0; i < g_Level.Items.size(); i++) - { - g_Level.Items[i].StoreInterpolationData(); - } - InItemControlLoop = true; short itemNumber = NextItemActive; diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index 86c4045ff..f5ea6aa21 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -122,7 +122,6 @@ struct ItemInfo EntityEffectData Effect = {}; EntityModelData Model = {}; - Pose OldPose = Pose::Zero; Pose StartPose = Pose::Zero; Pose Pose = Pose::Zero; RoomVector Location = {}; // NOTE: Describes vertical position in room. @@ -175,11 +174,6 @@ struct ItemInfo bool IsBridge() const; bool DisableInterpolation = false; - - void StoreInterpolationData() - { - OldPose = Pose; - } }; bool TestState(int refState, const std::vector& stateList); diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 26e6e40b3..0c4cab6c0 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -1320,7 +1320,7 @@ namespace TEN::Renderer { const auto& room = _rooms[effect->RoomNumber]; - _stStatic.World = effect->World; + _stStatic.World = effect->InterpolatedWorld; _stStatic.Color = effect->Color; _stStatic.AmbientLight = effect->AmbientLight; _stStatic.LightMode = (int)LightMode::Dynamic; @@ -1419,7 +1419,7 @@ namespace TEN::Renderer BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[deb.mesh.tex]), SamplerStateRegister::LinearClamp); } - _stStatic.World = deb.Transform; + _stStatic.World = Matrix::Lerp(deb.OldTransform, deb.Transform, _interpolationFactor); _stStatic.Color = deb.color; _stStatic.AmbientLight = _rooms[deb.roomNumber].AmbientLight; _stStatic.LightMode = (int)deb.lightMode; diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 3c8171dd5..9a59de126 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -878,17 +878,33 @@ namespace TEN::Renderer RendererEffect *newEffect = &_effects[fxNum]; - Matrix translation = Matrix::CreateTranslation(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z); - Matrix rotation = fx->pos.Orientation.ToRotationMatrix(); - + newEffect->Translation = Matrix::CreateTranslation(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z); + newEffect->Rotation = fx->pos.Orientation.ToRotationMatrix(); + newEffect->Scale = Matrix::CreateScale(1.0f); + newEffect->World = newEffect->Rotation * newEffect->Translation; newEffect->ObjectNumber = fx->objectNumber; newEffect->RoomNumber = fx->roomNumber; newEffect->Position = fx->pos.Position.ToVector3(); newEffect->AmbientLight = room.AmbientLight; newEffect->Color = fx->color; - newEffect->World = rotation * translation; newEffect->Mesh = GetMesh(obj->nmeshes ? obj->meshIndex : fx->frameNumber); + if (fx->DisableInterpolation) + { + // In this way the interpolation will return always the same result + newEffect->OldPosition = newEffect->Position; + newEffect->OldTranslation = newEffect->Translation; + newEffect->OldRotation = newEffect->Rotation; + newEffect->OldWorld = newEffect->World; + newEffect->OldScale = newEffect->Scale; + } + + newEffect->InterpolatedPosition = Vector3::Lerp(newEffect->OldPosition, newEffect->Position, _interpolationFactor); + newEffect->InterpolatedTranslation = Matrix::Lerp(newEffect->OldTranslation, newEffect->Translation, _interpolationFactor); + newEffect->InterpolatedRotation = Matrix::Lerp(newEffect->InterpolatedRotation, newEffect->Rotation, _interpolationFactor); + newEffect->InterpolatedWorld = Matrix::Lerp(newEffect->OldWorld, newEffect->World, _interpolationFactor); + newEffect->InterpolatedScale = Matrix::Lerp(newEffect->OldScale, newEffect->Scale, _interpolationFactor); + CollectLightsForEffect(fx->roomNumber, newEffect); room.EffectsToDraw.push_back(newEffect); diff --git a/TombEngine/Renderer/Structures/RendererEffect.h b/TombEngine/Renderer/Structures/RendererEffect.h index e4c7904e7..492df404d 100644 --- a/TombEngine/Renderer/Structures/RendererEffect.h +++ b/TombEngine/Renderer/Structures/RendererEffect.h @@ -13,9 +13,24 @@ namespace TEN::Renderer::Structures int RoomNumber; Vector3 Position; Matrix World; + Matrix Translation; + Matrix Rotation; + Matrix Scale; Vector4 Color; Vector4 AmbientLight; RendererMesh* Mesh; std::vector LightsToDraw; + + Vector3 OldPosition; + Matrix OldWorld; + Matrix OldTranslation; + Matrix OldRotation; + Matrix OldScale; + + Vector3 InterpolatedPosition; + Matrix InterpolatedWorld; + Matrix InterpolatedTranslation; + Matrix InterpolatedRotation; + Matrix InterpolatedScale; }; } From d83a84036e0860dfc16ba6966c2a4075248d6442 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:55:59 +0100 Subject: [PATCH 120/410] Update Changes.txt --- Documentation/Changes.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt index 08900121d..61d2938c7 100644 --- a/Documentation/Changes.txt +++ b/Documentation/Changes.txt @@ -5,6 +5,8 @@ Version 1.5 * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with Lara's hips when climbing out of water. * Fixed AI for skidoo driver and worker with shotgun TR2 enemies. +* Fixed Ember emitter crashing when ocb is between -1 and -10 +* Fixed Electric cleaner and Squishy block not detecting collision with certain block heights. Lua API changes: * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. From 2122a14d0e102aa8932dcf3746fcdd59d26b66bf Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 30 Apr 2024 10:29:01 +0200 Subject: [PATCH 121/410] Variable framerate now is optional --- TombEngine/Game/camera.cpp | 1 - TombEngine/Game/camera.h | 1 - TombEngine/Game/control/control.cpp | 26 +++++++++++++------ TombEngine/Game/gui.cpp | 14 +++++++++- TombEngine/Renderer/RendererDrawMenu.cpp | 9 +++++-- .../Scripting/Internal/LanguageScript.h | 1 + TombEngine/Specific/configuration.cpp | 9 +++++-- TombEngine/Specific/configuration.h | 2 ++ 8 files changed, 48 insertions(+), 15 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index ee176e7d7..1fd9628d4 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -58,7 +58,6 @@ GameVector LookCamPosition; GameVector LookCamTarget; Vector3i CamOldPos; CAMERA_INFO Camera; -CAMERA_INFO PreviousCamera; ObjectCameraInfo ItemCamera; GameVector ForcedFixedCamera; int UseForcedFixedCamera; diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 55453957b..504a59ed4 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -66,7 +66,6 @@ constexpr auto FADE_SCREEN_SPEED = 16.0f / 255.0f; constexpr auto DEFAULT_FOV = 80.0f; extern CAMERA_INFO Camera; -extern CAMERA_INFO PreviousCamera; extern GameVector ForcedFixedCamera; extern int UseForcedFixedCamera; extern CameraType BinocularOldCamera; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e5de091c1..e2d577141 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -587,8 +587,6 @@ GameStatus DoGameLoop(int levelIndex) int controlCalls = 0; int drawCalls = 0; - memcpy(&PreviousCamera , &Camera, sizeof(CAMERA_INFO)); - while (DoTheGame) { if (App.ResetClock) @@ -609,18 +607,30 @@ GameStatus DoGameLoop(int levelIndex) while (controlLag >= controlFrameTime) { - memcpy(&PreviousCamera, &Camera, sizeof(CAMERA_INFO)); status = ControlPhase(0); controlLag -= controlFrameTime; controlCalls++; + + if (!g_Configuration.EnableVariableFramerate) + { + if (status != GameStatus::Normal) + break; + + float interpolateFactor = 0.0f; + DrawPhase(!levelIndex, interpolateFactor); + drawCalls++; + } } - if (status != GameStatus::Normal) - break; + if (g_Configuration.EnableVariableFramerate) + { + if (status != GameStatus::Normal) + break; - float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); - DrawPhase(!levelIndex, interpolateFactor); - drawCalls++; + float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + DrawPhase(!levelIndex, interpolateFactor); + drawCalls++; + } } EndGameLoop(levelIndex, status); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 51332bd7c..f256de218 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -470,11 +470,12 @@ namespace TEN::Gui Caustics, Antialiasing, AmbientOcclusion, + VariableFramerate, Save, Cancel }; - static const int numDisplaySettingsOptions = 7; + static const int numDisplaySettingsOptions = 8; OptionCount = numDisplaySettingsOptions; @@ -531,6 +532,12 @@ namespace TEN::Gui SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableAmbientOcclusion = !CurrentSettings.Configuration.EnableAmbientOcclusion; break; + + case DisplaySettingsOption::VariableFramerate: + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + CurrentSettings.Configuration.EnableVariableFramerate = !CurrentSettings.Configuration.EnableVariableFramerate; + break; + } } @@ -577,6 +584,11 @@ namespace TEN::Gui SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableAmbientOcclusion = !CurrentSettings.Configuration.EnableAmbientOcclusion; break; + + case DisplaySettingsOption::VariableFramerate: + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + CurrentSettings.Configuration.EnableVariableFramerate = !CurrentSettings.Configuration.EnableVariableFramerate; + break; } } diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 8289f1453..58ca41759 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -189,14 +189,19 @@ namespace TEN::Renderer // Enable SSAO AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_AMBIENT_OCCLUSION), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 5)); AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAmbientOcclusion), PRINTSTRING_COLOR_WHITE, SF(titleOption == 5)); + GetNextLinePosition(&y); + + // Enable variable framerate + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_VARIABLE_FRAMERATE), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 6)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableVariableFramerate), PRINTSTRING_COLOR_WHITE, SF(titleOption == 6)); GetNextBlockPosition(&y); // Apply - AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_APPLY), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 6)); + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_APPLY), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 7)); GetNextLinePosition(&y); // Cancel - AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_CANCEL), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 7)); + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_CANCEL), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 8)); break; case Menu::OtherSettings: diff --git a/TombEngine/Scripting/Internal/LanguageScript.h b/TombEngine/Scripting/Internal/LanguageScript.h index a2c04feaf..4b2b7a35c 100644 --- a/TombEngine/Scripting/Internal/LanguageScript.h +++ b/TombEngine/Scripting/Internal/LanguageScript.h @@ -71,6 +71,7 @@ #define STRING_VOLUMETRIC_FOG "volumetric_fog" #define STRING_ANTIALIASING "antialiasing" #define STRING_AMBIENT_OCCLUSION "ambient_occlusion" +#define STRING_VARIABLE_FRAMERATE "variable_framerate" #define STRING_ANTIALIASING_NONE "none" #define STRING_ANTIALIASING_LOW "low" #define STRING_ANTIALIASING_MEDIUM "medium" diff --git a/TombEngine/Specific/configuration.cpp b/TombEngine/Specific/configuration.cpp index 6e0b39d26..bd971c961 100644 --- a/TombEngine/Specific/configuration.cpp +++ b/TombEngine/Specific/configuration.cpp @@ -187,7 +187,8 @@ bool SaveConfiguration() SetDWORDRegKey(graphicsKey, REGKEY_SHADOW_BLOBS_MAX, g_Configuration.ShadowBlobsMax) != ERROR_SUCCESS || SetBoolRegKey(graphicsKey, REGKEY_ENABLE_CAUSTICS, g_Configuration.EnableCaustics) != ERROR_SUCCESS || SetDWORDRegKey(graphicsKey, REGKEY_ANTIALIASING_MODE, (DWORD)g_Configuration.AntialiasingMode) != ERROR_SUCCESS || - SetBoolRegKey(graphicsKey, REGKEY_AMBIENT_OCCLUSION, g_Configuration.EnableAmbientOcclusion) != ERROR_SUCCESS) + SetBoolRegKey(graphicsKey, REGKEY_AMBIENT_OCCLUSION, g_Configuration.EnableAmbientOcclusion) != ERROR_SUCCESS || + SetBoolRegKey(graphicsKey, REGKEY_VARIABLE_FRAMERATE, g_Configuration.EnableVariableFramerate) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -314,6 +315,7 @@ void InitDefaultConfiguration() g_Configuration.EnableCaustics = true; g_Configuration.AntialiasingMode = AntialiasingMode::Medium; g_Configuration.EnableAmbientOcclusion = true; + g_Configuration.EnableVariableFramerate = true; g_Configuration.SoundDevice = 1; g_Configuration.EnableSound = true; @@ -362,6 +364,7 @@ bool LoadConfiguration() bool enableCaustics = false; DWORD antialiasingMode = 1; bool enableAmbientOcclusion = false; + bool enableVariableFramerate = false; // Load Graphics keys. if (GetDWORDRegKey(graphicsKey, REGKEY_SCREEN_WIDTH, &screenWidth, 0) != ERROR_SUCCESS || @@ -372,7 +375,8 @@ bool LoadConfiguration() GetDWORDRegKey(graphicsKey, REGKEY_SHADOW_BLOBS_MAX, &shadowBlobsMax, GameConfiguration::DEFAULT_SHADOW_BLOBS_MAX) != ERROR_SUCCESS || GetBoolRegKey(graphicsKey, REGKEY_ENABLE_CAUSTICS, &enableCaustics, true) != ERROR_SUCCESS || GetDWORDRegKey(graphicsKey, REGKEY_ANTIALIASING_MODE, &antialiasingMode, true) != ERROR_SUCCESS || - GetBoolRegKey(graphicsKey, REGKEY_AMBIENT_OCCLUSION, &enableAmbientOcclusion, false) != ERROR_SUCCESS) + GetBoolRegKey(graphicsKey, REGKEY_AMBIENT_OCCLUSION, &enableAmbientOcclusion, false) != ERROR_SUCCESS || + GetBoolRegKey(graphicsKey, REGKEY_VARIABLE_FRAMERATE, &enableVariableFramerate, false) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -500,6 +504,7 @@ bool LoadConfiguration() g_Configuration.AntialiasingMode = AntialiasingMode(antialiasingMode); g_Configuration.ShadowMapSize = shadowMapSize; g_Configuration.EnableAmbientOcclusion = enableAmbientOcclusion; + g_Configuration.EnableVariableFramerate = enableVariableFramerate; g_Configuration.EnableSound = enableSound; g_Configuration.EnableReverb = enableReverb; diff --git a/TombEngine/Specific/configuration.h b/TombEngine/Specific/configuration.h index cf10f970c..25c6b0d7e 100644 --- a/TombEngine/Specific/configuration.h +++ b/TombEngine/Specific/configuration.h @@ -23,6 +23,7 @@ constexpr auto REGKEY_SHADOW_BLOBS_MAX = "ShadowBlobsMax"; constexpr auto REGKEY_ENABLE_CAUSTICS = "EnableCaustics"; constexpr auto REGKEY_ANTIALIASING_MODE = "AntialiasingMode"; constexpr auto REGKEY_AMBIENT_OCCLUSION = "AmbientOcclusion"; +constexpr auto REGKEY_VARIABLE_FRAMERATE = "EnableVariableFramerate"; // Sound keys constexpr auto REGKEY_SOUND_DEVICE = "SoundDevice"; @@ -58,6 +59,7 @@ struct GameConfiguration int ShadowBlobsMax = DEFAULT_SHADOW_BLOBS_MAX; bool EnableCaustics = false; bool EnableAmbientOcclusion = false; + bool EnableVariableFramerate = true; AntialiasingMode AntialiasingMode = AntialiasingMode::None; // Sound From b2f7c83372566518351c62415b3e0ed0915dd253 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 30 Apr 2024 11:16:14 +0200 Subject: [PATCH 122/410] Started working on 60 fps inventory --- TombEngine/Game/gui.cpp | 11 +++++++---- TombEngine/Renderer/RendererDrawMenu.cpp | 10 ++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index f256de218..6dedb76b1 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -2801,6 +2801,9 @@ namespace TEN::Gui const auto& player = GetLaraInfo(*item); auto& ring = Rings[(int)ringType]; + float multiplier = g_Configuration.EnableVariableFramerate ? 2.0f : 1.0f; + + if (ring.CurrentObjectList <= 0) return; @@ -3188,17 +3191,17 @@ namespace TEN::Gui if (ring.NumObjectsInList != 1 && (ringType != RingTypes::Ammo || CombineRingFadeVal == 128)) { if (ring.ObjectListMovement > 0) - ring.ObjectListMovement += ANGLE(45.0f); + ring.ObjectListMovement += ANGLE(45.0f / multiplier); if (ring.ObjectListMovement < 0) - ring.ObjectListMovement -= ANGLE(45.0f); + ring.ObjectListMovement -= ANGLE(45.0f / multiplier); if (IsHeld(In::Left)) { if (!ring.ObjectListMovement) { SoundEffect(SFX_TR4_MENU_ROTATE, nullptr, SoundEnvironment::Always); - ring.ObjectListMovement += ANGLE(45.0f); + ring.ObjectListMovement += ANGLE(45.0f / multiplier); if (AmmoSelectorFlag) AmmoSelectorFadeDir = 2; @@ -3210,7 +3213,7 @@ namespace TEN::Gui if (!ring.ObjectListMovement) { SoundEffect(SFX_TR4_MENU_ROTATE, nullptr, SoundEnvironment::Always); - ring.ObjectListMovement -= ANGLE(45.0f); + ring.ObjectListMovement -= ANGLE(45.0f / multiplier); if (AmmoSelectorFlag) AmmoSelectorFadeDir = 2; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 58ca41759..8011391c1 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1108,6 +1108,16 @@ namespace TEN::Renderer RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 0.5f); _swapChain->Present(0, 0); + + if (g_Configuration.EnableVariableFramerate) + { + _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); + _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); + + RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 0.5f); + + _swapChain->Present(0, 0); + } } void Renderer::RenderTitle() From c4f532268d2e7e60f34b888456d647f3cd066ab1 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Tue, 30 Apr 2024 16:19:30 +0100 Subject: [PATCH 123/410] Updated system strings for Variable Framerate --- Scripts/SystemStrings.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Scripts/SystemStrings.lua b/Scripts/SystemStrings.lua index 2bb0d2e47..69009d8eb 100644 --- a/Scripts/SystemStrings.lua +++ b/Scripts/SystemStrings.lua @@ -113,6 +113,7 @@ local strings = vehicle_actions = { "Vehicle Actions" }, view = { "View" }, volumetric_fog = { "Volumetric Fog" }, + variable_framerate = { "Variable Framerate" }, waiting_for_input = { "Waiting For Input" }, window_title = { "TombEngine" }, windowed = { "Windowed" }, From 368f74e75415870cf9df37c7f7bf40a7b314cf50 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 1 May 2024 05:32:49 +0200 Subject: [PATCH 124/410] Added interpolation for title level --- TombEngine/Game/control/control.cpp | 19 +++++++------------ TombEngine/Game/control/control.h | 2 +- TombEngine/Game/gui.cpp | 2 +- TombEngine/Renderer/Renderer.h | 4 ++-- TombEngine/Renderer/RendererDraw.cpp | 12 ++++++------ TombEngine/Renderer/RendererDrawMenu.cpp | 16 +++++++++++++++- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e2d577141..d71e3ab63 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -115,21 +115,18 @@ short NextFxFree; int ControlPhaseTime; -int DrawPhase(bool isTitle, float interpolateFactor) +void DrawPhase(bool isTitle, float interpolationFactor) { if (isTitle) { - g_Renderer.RenderTitle(); + g_Renderer.RenderTitle(interpolationFactor); } else { - g_Renderer.Render(interpolateFactor); + g_Renderer.Render(interpolationFactor); } g_Renderer.Lock(); - - //Camera.numberFrames = g_Renderer.Synchronize(); - return Camera.numberFrames; } GameStatus ControlPhase(int numFrames) @@ -155,9 +152,7 @@ GameStatus ControlPhase(int numFrames) g_GameStringsHandler->ProcessDisplayStrings(DELTA_TIME); - // Save current state to old variables for interpolation SetupInterpolation(); - g_Renderer.SaveOldState(); // Controls are polled before OnLoop, so input data could be // overwritten by script API methods. @@ -616,8 +611,8 @@ GameStatus DoGameLoop(int levelIndex) if (status != GameStatus::Normal) break; - float interpolateFactor = 0.0f; - DrawPhase(!levelIndex, interpolateFactor); + float interpolationFactor = 0.0f; + DrawPhase(!levelIndex, interpolationFactor); drawCalls++; } } @@ -627,8 +622,8 @@ GameStatus DoGameLoop(int levelIndex) if (status != GameStatus::Normal) break; - float interpolateFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); - DrawPhase(!levelIndex, interpolateFactor); + float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + DrawPhase(!levelIndex, interpolationFactor); drawCalls++; } } diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index b9b8b78d2..cd44f11e2 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -81,7 +81,7 @@ extern int ControlPhaseTime; extern std::vector OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE]; -int DrawPhase(bool isTitle, float interpolateFactor); +void DrawPhase(bool isTitle, float interpolationFactor); GameStatus ControlPhase(int numFrames); GameStatus DoLevel(int levelIndex, bool loadGame = false); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 6dedb76b1..0e5d311a9 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -749,7 +749,7 @@ namespace TEN::Gui } else { - g_Renderer.RenderTitle(); + g_Renderer.RenderTitle(0); Camera.numberFrames = g_Renderer.Synchronize(); int numFrames = Camera.numberFrames; ControlPhase(numFrames); diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index dc8f19993..527c7a33d 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -587,8 +587,8 @@ namespace TEN::Renderer void DrawBar(float percent, const RendererHudBar& bar, GAME_OBJECT_ID textureSlot, int frame, bool poison); void Create(); void Initialize(int w, int h, bool windowed, HWND handle); - void Render(float interpolateFactor); - void RenderTitle(); + void Render(float interpolationFactor); + void RenderTitle(float interpolationFactor); void Lock(); bool PrepareDataForTheRenderer(); void UpdateCameraMatrices(CAMERA_INFO* cam, float roll, float fov, float farView); diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 102c37040..04da60923 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3069,15 +3069,15 @@ namespace TEN::Renderer _context->ClearDepthStencilView(depthTarget, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } - void Renderer::Render(float interpolateFactor) + void Renderer::Render(float interpolationFactor) { //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); // Interpolate camera - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolateFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolateFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolateFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpolateFactor); + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolationFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolationFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolationFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpolationFactor); _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum=_currentGameCamera.Camera.Frustum; @@ -3086,7 +3086,7 @@ namespace TEN::Renderer _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - _interpolationFactor = interpolateFactor; + _interpolationFactor = interpolationFactor; RenderScene(&_backBuffer, true, _gameCamera); diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 8011391c1..3955c77a8 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1120,8 +1120,22 @@ namespace TEN::Renderer } } - void Renderer::RenderTitle() + void Renderer::RenderTitle(float interpolationFactor) { + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolationFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolationFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolationFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpolationFactor); + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; + _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; + _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; + _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; + _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; + _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; + + _interpolationFactor = interpolationFactor; + RenderScene(&_dumpScreenRenderTarget, false, _gameCamera); _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); From 62d28a08d1e4b1d9fe0d4d05dffb93849118f57c Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 1 May 2024 06:11:49 +0200 Subject: [PATCH 125/410] Fixed corrupted items --- TombEngine/Game/control/control.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index d71e3ab63..dfeab3584 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -153,6 +153,7 @@ GameStatus ControlPhase(int numFrames) g_GameStringsHandler->ProcessDisplayStrings(DELTA_TIME); SetupInterpolation(); + g_Renderer.SaveOldState(); // Controls are polled before OnLoop, so input data could be // overwritten by script API methods. From b868d6c5186a0f8b6784ae64d19cc4f1373d3e83 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 1 May 2024 21:27:54 +1000 Subject: [PATCH 126/410] Remove Ptr suffix usage in floordata --- TombEngine/Game/collision/floordata.cpp | 172 ++++++++++++------------ TombEngine/Game/collision/floordata.h | 12 +- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index a15e2d8fe..f1efec5bc 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -424,22 +424,22 @@ namespace TEN::Collision::Floordata return roomGridCoords; } - std::vector GetNeighborSectorPtrs(const Vector3i& pos, int roomNumber, unsigned int searchDepth) + std::vector GetNeighborSectors(const Vector3i& pos, int roomNumber, unsigned int searchDepth) { - auto sectorPtrs = std::vector{}; + auto sectors = std::vector{}; // Run through neighbor rooms. auto& room = g_Level.Rooms[roomNumber]; for (int neighborRoomNumber : room.neighbors) { - // Collect neighbor sector pointers. + // Collect neighbor sectors. auto roomGridCoords = GetNeighborRoomGridCoords(pos, neighborRoomNumber, searchDepth); for (const auto& roomGridCoord : roomGridCoords) - sectorPtrs.push_back(&GetFloor(neighborRoomNumber, roomGridCoord)); + sectors.push_back(&GetFloor(neighborRoomNumber, roomGridCoord)); } - // Return neighbor sector pointers. - return sectorPtrs; + // Return neighbor sectors. + return sectors; } FloorInfo& GetFloor(int roomNumber, const Vector2i& roomGridCoord) @@ -458,88 +458,88 @@ namespace TEN::Collision::Floordata FloorInfo& GetFarthestSector(int roomNumber, int x, int z, bool isBottom) { - auto* sectorPtr = &GetSideSector(roomNumber, x, z); + auto* sector = &GetSideSector(roomNumber, x, z); // Find bottom or top sector. - bool isWall = sectorPtr->IsWall(x, z); + bool isWall = sector->IsWall(x, z); while (isWall) { - auto nextRoomNumber = sectorPtr->GetNextRoomNumber(x, z, isBottom); + auto nextRoomNumber = sector->GetNextRoomNumber(x, z, isBottom); if (!nextRoomNumber.has_value()) break; // TODO: Check. - sectorPtr = &GetSideSector(*nextRoomNumber, x, z); - isWall = sectorPtr->IsWall(x, z); + sector = &GetSideSector(*nextRoomNumber, x, z); + isWall = sector->IsWall(x, z); } - return *sectorPtr; + return *sector; } FloorInfo& GetSideSector(int roomNumber, int x, int z) { - auto* sectorPtr = &GetFloor(roomNumber, x, z); + auto* sector = &GetFloor(roomNumber, x, z); // Find side sector. - auto sideRoomNumber = sectorPtr->GetSideRoomNumber(); + auto sideRoomNumber = sector->GetSideRoomNumber(); while (sideRoomNumber.has_value()) { - sectorPtr = &GetFloor(*sideRoomNumber, x, z); - sideRoomNumber = sectorPtr->GetSideRoomNumber(); + sector = &GetFloor(*sideRoomNumber, x, z); + sideRoomNumber = sector->GetSideRoomNumber(); } - return *sectorPtr; + return *sector; } static std::optional GetFarthestHeightData(FloorInfo& currentSector, Vector3i pos, bool isBottom) { // Find bottom or top height while bridge exists(?). - auto* sectorPtr = ¤tSector; + auto* sector = ¤tSector; do { // Set vertical position to lowest bridge ceiling height or highest bridge floor height. - pos.y = sectorPtr->GetBridgeSurfaceHeight(pos, !isBottom); + pos.y = sector->GetBridgeSurfaceHeight(pos, !isBottom); // Find sector at lowest bridge floor height or highest bridge ceiling height. while (isBottom ? - (pos.y >= sectorPtr->GetSurfaceHeight(pos.x, pos.z, true)) : - (pos.y <= sectorPtr->GetSurfaceHeight(pos.x, pos.z, false))) + (pos.y >= sector->GetSurfaceHeight(pos.x, pos.z, true)) : + (pos.y <= sector->GetSurfaceHeight(pos.x, pos.z, false))) { - auto nextRoomNumber = sectorPtr->GetNextRoomNumber(pos.x, pos.z, isBottom); + auto nextRoomNumber = sector->GetNextRoomNumber(pos.x, pos.z, isBottom); if (!nextRoomNumber.has_value()) return std::nullopt; - sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z); + sector = &GetSideSector(*nextRoomNumber, pos.x, pos.z); } } - while (sectorPtr->GetInsideBridgeItemNumber(pos, isBottom, !isBottom) != NO_VALUE); + while (sector->GetInsideBridgeItemNumber(pos, isBottom, !isBottom) != NO_VALUE); - return FarthestHeightData{ *sectorPtr, pos.y }; + return FarthestHeightData{ *sector, pos.y }; } std::optional GetSurfaceHeight(const RoomVector& location, int x, int z, bool isFloor) { - auto* sectorPtr = &GetSideSector(location.RoomNumber, x, z); + auto* sector = &GetSideSector(location.RoomNumber, x, z); auto pos = Vector3i(x, location.Height, z); int polarity = 0; - if (sectorPtr->IsWall(x, z)) + if (sector->IsWall(x, z)) { - sectorPtr = &GetFarthestSector(location.RoomNumber, x, z, !isFloor); + sector = &GetFarthestSector(location.RoomNumber, x, z, !isFloor); - if (!sectorPtr->IsWall(x, z)) + if (!sector->IsWall(x, z)) { - pos.y = sectorPtr->GetSurfaceHeight(x, z, isFloor); + pos.y = sector->GetSurfaceHeight(x, z, isFloor); polarity = isFloor ? -1 : 1; } else { - sectorPtr = &GetFarthestSector(location.RoomNumber, x, z, isFloor); + sector = &GetFarthestSector(location.RoomNumber, x, z, isFloor); - if (!sectorPtr->IsWall(x, z)) + if (!sector->IsWall(x, z)) { - pos.y = sectorPtr->GetSurfaceHeight(x, z, !isFloor); + pos.y = sector->GetSurfaceHeight(x, z, !isFloor); polarity = isFloor ? 1 : -1; } else @@ -549,81 +549,81 @@ namespace TEN::Collision::Floordata } } - int floorHeight = sectorPtr->GetSurfaceHeight(pos, true); - int ceilingHeight = sectorPtr->GetSurfaceHeight(pos, false); + int floorHeight = sector->GetSurfaceHeight(pos, true); + int ceilingHeight = sector->GetSurfaceHeight(pos, false); pos.y = std::clamp(pos.y, std::min(floorHeight, ceilingHeight), std::max(floorHeight, ceilingHeight)); bool testFloorBorder = (pos.y == ceilingHeight); bool testCeilBorder = (pos.y == floorHeight); - int insideBridgeItemNumber = sectorPtr->GetInsideBridgeItemNumber(pos, testFloorBorder, testCeilBorder); + int insideBridgeItemNumber = sector->GetInsideBridgeItemNumber(pos, testFloorBorder, testCeilBorder); if (insideBridgeItemNumber != NO_VALUE) { if (isFloor ? (polarity <= 0) : (polarity >= 0)) { - auto heightData = GetFarthestHeightData(*sectorPtr, pos, !isFloor); + auto heightData = GetFarthestHeightData(*sector, pos, !isFloor); if (heightData.has_value()) return heightData->Height; } if (isFloor ? (polarity >= 0) : (polarity <= 0)) { - auto heightData = GetFarthestHeightData(*sectorPtr, pos, isFloor); + auto heightData = GetFarthestHeightData(*sector, pos, isFloor); if (!heightData.has_value()) return std::nullopt; - sectorPtr = &heightData->Sector; + sector = &heightData->Sector; pos.y = heightData->Height; } } if (isFloor ? (polarity >= 0) : (polarity <= 0)) { - auto nextRoomNumber = sectorPtr->GetNextRoomNumber(pos, isFloor); + auto nextRoomNumber = sector->GetNextRoomNumber(pos, isFloor); while (nextRoomNumber.has_value()) { - sectorPtr = &GetSideSector(*nextRoomNumber, x, z); - nextRoomNumber = sectorPtr->GetNextRoomNumber(pos, isFloor); + sector = &GetSideSector(*nextRoomNumber, x, z); + nextRoomNumber = sector->GetNextRoomNumber(pos, isFloor); } } - return sectorPtr->GetSurfaceHeight(pos, isFloor); + return sector->GetSurfaceHeight(pos, isFloor); } static std::optional GetFarthestRoomVector(RoomVector location, const Vector3i& pos, bool isBottom) { - auto* sectorPtr = &GetSideSector(location.RoomNumber, pos.x, pos.z); - location.RoomNumber = sectorPtr->RoomNumber; + auto* sector = &GetSideSector(location.RoomNumber, pos.x, pos.z); + location.RoomNumber = sector->RoomNumber; - if (sectorPtr->IsWall(pos.x, pos.z)) + if (sector->IsWall(pos.x, pos.z)) { - sectorPtr = &GetFarthestSector(location.RoomNumber, pos.x, pos.z, isBottom); - location.RoomNumber = sectorPtr->RoomNumber; + sector = &GetFarthestSector(location.RoomNumber, pos.x, pos.z, isBottom); + location.RoomNumber = sector->RoomNumber; - if (sectorPtr->IsWall(pos.x, pos.z)) + if (sector->IsWall(pos.x, pos.z)) return std::nullopt; - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, !isBottom); + location.Height = sector->GetSurfaceHeight(pos.x, pos.z, !isBottom); } - int floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - int ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + int floorHeight = sector->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + int ceilingHeight = sector->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); location.Height = std::clamp(location.Height, std::min(ceilingHeight, floorHeight), std::max(ceilingHeight, floorHeight)); bool testFloorBorder = (location.Height == ceilingHeight); bool testCeilBorder = (location.Height == floorHeight); - int insideBridgeItemNumber = sectorPtr->GetInsideBridgeItemNumber(Vector3i(pos.x, location.Height, pos.z), testFloorBorder, testCeilBorder); + int insideBridgeItemNumber = sector->GetInsideBridgeItemNumber(Vector3i(pos.x, location.Height, pos.z), testFloorBorder, testCeilBorder); if (insideBridgeItemNumber != NO_VALUE) { - auto heightData = GetFarthestHeightData(*sectorPtr, Vector3i(pos.x, location.Height, pos.z), isBottom); + auto heightData = GetFarthestHeightData(*sector, Vector3i(pos.x, location.Height, pos.z), isBottom); if (!heightData.has_value()) return std::nullopt; - sectorPtr = &heightData->Sector; - location.RoomNumber = sectorPtr->RoomNumber; + sector = &heightData->Sector; + location.RoomNumber = sector->RoomNumber; location.Height = heightData->Height; } @@ -633,19 +633,19 @@ namespace TEN::Collision::Floordata { if (!isFirstSector) { - sectorPtr = &GetSideSector(*nextRoomNumber, pos.x, pos.z); - location.RoomNumber = sectorPtr->RoomNumber; - location.Height = sectorPtr->GetSurfaceHeight(pos.x, pos.z, !isBottom); + sector = &GetSideSector(*nextRoomNumber, pos.x, pos.z); + location.RoomNumber = sector->RoomNumber; + location.Height = sector->GetSurfaceHeight(pos.x, pos.z, !isBottom); } isFirstSector = false; if (isBottom) { - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); - if (pos.y < ceilingHeight && sectorPtr->GetNextRoomNumber(Vector3i(pos.x, location.Height, pos.z), false)) + ceilingHeight = sector->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + if (pos.y < ceilingHeight && sector->GetNextRoomNumber(Vector3i(pos.x, location.Height, pos.z), false)) return std::nullopt; - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + floorHeight = sector->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); if (pos.y <= floorHeight) { location.Height = std::max(pos.y, ceilingHeight); @@ -654,11 +654,11 @@ namespace TEN::Collision::Floordata } else { - floorHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); - if (pos.y > floorHeight && sectorPtr->GetNextRoomNumber(Vector3i(pos.x, location.Height, pos.z), true)) + floorHeight = sector->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), true); + if (pos.y > floorHeight && sector->GetNextRoomNumber(Vector3i(pos.x, location.Height, pos.z), true)) return std::nullopt; - ceilingHeight = sectorPtr->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); + ceilingHeight = sector->GetSurfaceHeight(Vector3i(pos.x, location.Height, pos.z), false); if (pos.y >= ceilingHeight) { location.Height = std::min(pos.y, floorHeight); @@ -666,7 +666,7 @@ namespace TEN::Collision::Floordata } } - nextRoomNumber = sectorPtr->GetNextRoomNumber(Vector3i(pos.x, location.Height, pos.z), isBottom); + nextRoomNumber = sector->GetNextRoomNumber(Vector3i(pos.x, location.Height, pos.z), isBottom); } return std::nullopt; @@ -696,34 +696,34 @@ namespace TEN::Collision::Floordata x += bridgeItem.Pose.Position.x; z += bridgeItem.Pose.Position.z; - auto* sectorPtr = &GetSideSector(bridgeItem.RoomNumber, x, z); - sectorPtr->AddBridge(itemNumber); + auto* sector = &GetSideSector(bridgeItem.RoomNumber, x, z); + sector->AddBridge(itemNumber); if (bridge.GetFloorBorder != nullptr) { int floorBorder = bridge.GetFloorBorder(bridgeItem); - while (floorBorder <= sectorPtr->GetSurfaceHeight(x, z, false)) + while (floorBorder <= sector->GetSurfaceHeight(x, z, false)) { - auto roomNumberAbove = sectorPtr->GetNextRoomNumber(x, z, false); + auto roomNumberAbove = sector->GetNextRoomNumber(x, z, false); if (!roomNumberAbove.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberAbove, x, z); - sectorPtr->AddBridge(itemNumber); + sector = &GetSideSector(*roomNumberAbove, x, z); + sector->AddBridge(itemNumber); } } if (bridge.GetCeilingBorder != nullptr) { int ceilingBorder = bridge.GetCeilingBorder(bridgeItem); - while (ceilingBorder >= sectorPtr->GetSurfaceHeight(x, z, true)) + while (ceilingBorder >= sector->GetSurfaceHeight(x, z, true)) { - auto roomNumberBelow = sectorPtr->GetNextRoomNumber(x, z, true); + auto roomNumberBelow = sector->GetNextRoomNumber(x, z, true); if (!roomNumberBelow.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberBelow, x, z); - sectorPtr->AddBridge(itemNumber); + sector = &GetSideSector(*roomNumberBelow, x, z); + sector->AddBridge(itemNumber); } } } @@ -739,34 +739,34 @@ namespace TEN::Collision::Floordata x += bridgeItem.Pose.Position.x; z += bridgeItem.Pose.Position.z; - auto* sectorPtr = &GetSideSector(bridgeItem.RoomNumber, x, z); - sectorPtr->RemoveBridge(itemNumber); + auto* sector = &GetSideSector(bridgeItem.RoomNumber, x, z); + sector->RemoveBridge(itemNumber); if (bridge.GetFloorBorder != nullptr) { int floorBorder = bridge.GetFloorBorder(bridgeItem); - while (floorBorder <= sectorPtr->GetSurfaceHeight(x, z, false)) + while (floorBorder <= sector->GetSurfaceHeight(x, z, false)) { - auto roomNumberAbove = sectorPtr->GetNextRoomNumber(x, z, false); + auto roomNumberAbove = sector->GetNextRoomNumber(x, z, false); if (!roomNumberAbove.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberAbove, x, z); - sectorPtr->RemoveBridge(itemNumber); + sector = &GetSideSector(*roomNumberAbove, x, z); + sector->RemoveBridge(itemNumber); } } if (bridge.GetCeilingBorder != nullptr) { int ceilingBorder = bridge.GetCeilingBorder(bridgeItem); - while (ceilingBorder >= sectorPtr->GetSurfaceHeight(x, z, true)) + while (ceilingBorder >= sector->GetSurfaceHeight(x, z, true)) { - auto roomNumberBelow = sectorPtr->GetNextRoomNumber(x, z, true); + auto roomNumberBelow = sector->GetNextRoomNumber(x, z, true); if (!roomNumberBelow.has_value()) break; - sectorPtr = &GetSideSector(*roomNumberBelow, x, z); - sectorPtr->RemoveBridge(itemNumber); + sector = &GetSideSector(*roomNumberBelow, x, z); + sector->RemoveBridge(itemNumber); } } } diff --git a/TombEngine/Game/collision/floordata.h b/TombEngine/Game/collision/floordata.h index 891e130f5..be6e2c456 100644 --- a/TombEngine/Game/collision/floordata.h +++ b/TombEngine/Game/collision/floordata.h @@ -49,10 +49,10 @@ enum class MaterialType enum class ClimbDirectionFlags { - North = (1 << 8), - East = (1 << 9), - South = (1 << 10), - West = (1 << 11) + North = 1 << 8, + East = 1 << 9, + South = 1 << 10, + West = 1 << 11 }; // NOTE: Describes vertical room location. @@ -135,7 +135,7 @@ struct SectorFlagData class FloorInfo { public: - // Components + // Members int RoomNumber = 0; int SidePortalRoomNumber = 0; SectorSurfaceData FloorSurface = {}; @@ -184,7 +184,7 @@ namespace TEN::Collision::Floordata Vector2i GetSectorPoint(int x, int z); Vector2i GetRoomGridCoord(int roomNumber, int x, int z, bool clampToBounds = true); std::vector GetNeighborRoomGridCoords(const Vector3i& pos, int roomNumber, unsigned int searchDepth); - std::vector GetNeighborSectorPtrs(const Vector3i& pos, int roomNumber, unsigned int searchDepth); + std::vector GetNeighborSectors(const Vector3i& pos, int roomNumber, unsigned int searchDepth); FloorInfo& GetFloor(int roomNumber, const Vector2i& roomGridCoord); FloorInfo& GetFloor(int roomNumber, int x, int z); From 37267e99f198fac77080d61e42323162728efe01 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 2 May 2024 00:39:12 +1000 Subject: [PATCH 127/410] Give meaning to magic numbers --- TombEngine/Game/collision/floordata.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index f1efec5bc..356997d3e 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -519,10 +519,17 @@ namespace TEN::Collision::Floordata std::optional GetSurfaceHeight(const RoomVector& location, int x, int z, bool isFloor) { + enum class Polarity + { + None, + Floor, + Ceiling + }; + auto* sector = &GetSideSector(location.RoomNumber, x, z); auto pos = Vector3i(x, location.Height, z); - int polarity = 0; + auto polarity = Polarity::None; if (sector->IsWall(x, z)) { @@ -531,7 +538,7 @@ namespace TEN::Collision::Floordata if (!sector->IsWall(x, z)) { pos.y = sector->GetSurfaceHeight(x, z, isFloor); - polarity = isFloor ? -1 : 1; + polarity = isFloor ? Polarity::Floor : Polarity::Ceiling; } else { @@ -540,7 +547,7 @@ namespace TEN::Collision::Floordata if (!sector->IsWall(x, z)) { pos.y = sector->GetSurfaceHeight(x, z, !isFloor); - polarity = isFloor ? 1 : -1; + polarity = isFloor ? Polarity::Ceiling : Polarity::Floor; } else { @@ -560,14 +567,14 @@ namespace TEN::Collision::Floordata if (insideBridgeItemNumber != NO_VALUE) { - if (isFloor ? (polarity <= 0) : (polarity >= 0)) + if (polarity == Polarity::None || (isFloor ? (polarity == Polarity::Floor) : (polarity == Polarity::Ceiling))) { auto heightData = GetFarthestHeightData(*sector, pos, !isFloor); if (heightData.has_value()) return heightData->Height; } - if (isFloor ? (polarity >= 0) : (polarity <= 0)) + if (polarity == Polarity::None || (isFloor ? (polarity == Polarity::Ceiling) : (polarity == Polarity::Floor))) { auto heightData = GetFarthestHeightData(*sector, pos, isFloor); if (!heightData.has_value()) @@ -578,7 +585,7 @@ namespace TEN::Collision::Floordata } } - if (isFloor ? (polarity >= 0) : (polarity <= 0)) + if (polarity == Polarity::None || (isFloor ? (polarity == Polarity::Ceiling) : (polarity == Polarity::Floor))) { auto nextRoomNumber = sector->GetNextRoomNumber(pos, isFloor); while (nextRoomNumber.has_value()) From 54346e4d85ce59082f1a2bab39213628e8e1795e Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 2 May 2024 06:03:56 +0200 Subject: [PATCH 128/410] Fixed flickering of strings in title level --- TombEngine/Renderer/RendererDrawMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 3955c77a8..1f940ff8f 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1141,7 +1141,7 @@ namespace TEN::Renderer _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); - RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 1.0f); + RenderInventoryScene(&_backBuffer, nullptr, 1.0f); DrawAllStrings(); _swapChain->Present(0, 0); From e3563bffb1da34ab521d439cda583db26109b95f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 2 May 2024 09:19:25 +0300 Subject: [PATCH 129/410] Fix hair glitch when stepping up --- TombEngine/Game/Lara/lara_helpers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 35596d7df..31cc6e48c 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -1048,6 +1048,8 @@ void HandlePlayerElevationChange(ItemInfo* item, CollisionInfo* coll) if (CanStepUp(*item, *coll)) { item->Animation.TargetState = LS_STEP_UP; + item->DisableInterpolation = true; + if (GetStateDispatch(item, GetAnimData(*item))) { item->Pose.Position.y += coll->Middle.Floor; From 63a8de13f8a3ab6eccbf34e4514c95ce680b27a6 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 2 May 2024 09:42:00 +0300 Subject: [PATCH 130/410] Fix leveljumps if 60 FPS is off --- TombEngine/Game/control/control.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index dfeab3584..1d548b664 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -609,9 +609,6 @@ GameStatus DoGameLoop(int levelIndex) if (!g_Configuration.EnableVariableFramerate) { - if (status != GameStatus::Normal) - break; - float interpolationFactor = 0.0f; DrawPhase(!levelIndex, interpolationFactor); drawCalls++; @@ -620,13 +617,14 @@ GameStatus DoGameLoop(int levelIndex) if (g_Configuration.EnableVariableFramerate) { - if (status != GameStatus::Normal) - break; - float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); DrawPhase(!levelIndex, interpolationFactor); drawCalls++; } + + if (status != GameStatus::Normal) + break; + } EndGameLoop(levelIndex, status); From 0a28ddb7cf50f362cbaa563bebc0e1eb20557f68 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 2 May 2024 09:47:53 +0300 Subject: [PATCH 131/410] Fix garbage frames on game status change --- TombEngine/Game/control/control.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 1d548b664..6537743d2 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -601,20 +601,6 @@ GameStatus DoGameLoop(int levelIndex) controlLag += frameTime; } - while (controlLag >= controlFrameTime) - { - status = ControlPhase(0); - controlLag -= controlFrameTime; - controlCalls++; - - if (!g_Configuration.EnableVariableFramerate) - { - float interpolationFactor = 0.0f; - DrawPhase(!levelIndex, interpolationFactor); - drawCalls++; - } - } - if (g_Configuration.EnableVariableFramerate) { float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); @@ -622,9 +608,21 @@ GameStatus DoGameLoop(int levelIndex) drawCalls++; } + while (controlLag >= controlFrameTime) + { + if (!g_Configuration.EnableVariableFramerate) + { + DrawPhase(!levelIndex, 0.0f); + drawCalls++; + } + + status = ControlPhase(0); + controlLag -= controlFrameTime; + controlCalls++; + } + if (status != GameStatus::Normal) break; - } EndGameLoop(levelIndex, status); From 4e9d4940a7aac84e56a19f1f69f4803b78a41298 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 2 May 2024 09:53:21 +0300 Subject: [PATCH 132/410] Simplify code --- TombEngine/Game/control/control.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 6537743d2..13237c9bf 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -601,28 +601,28 @@ GameStatus DoGameLoop(int levelIndex) controlLag += frameTime; } - if (g_Configuration.EnableVariableFramerate) - { - float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); - DrawPhase(!levelIndex, interpolationFactor); - drawCalls++; - } - while (controlLag >= controlFrameTime) { + status = ControlPhase(0); + controlLag -= controlFrameTime; + controlCalls++; + if (!g_Configuration.EnableVariableFramerate) { DrawPhase(!levelIndex, 0.0f); drawCalls++; } - - status = ControlPhase(0); - controlLag -= controlFrameTime; - controlCalls++; } if (status != GameStatus::Normal) break; + + if (!g_Configuration.EnableVariableFramerate) + continue; + + float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + DrawPhase(!levelIndex, interpolationFactor); + drawCalls++; } EndGameLoop(levelIndex, status); From cd7583ab7a74d5ca6079f5b41973670d9042cc01 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 2 May 2024 14:19:34 +0200 Subject: [PATCH 133/410] Enabled vsync; Better mode switch between 30 and 60 fps; Fixed flickering of strings in level (except for title); --- TombEngine/Game/control/control.cpp | 8 +++----- TombEngine/Game/control/control.h | 2 +- TombEngine/Game/gui.cpp | 19 +++++++++++++------ TombEngine/Renderer/RendererDrawMenu.cpp | 23 ++++++++--------------- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 13237c9bf..2e408359a 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -129,7 +129,7 @@ void DrawPhase(bool isTitle, float interpolationFactor) g_Renderer.Lock(); } -GameStatus ControlPhase(int numFrames) +GameStatus ControlPhase() { static int framesCount = 0; @@ -142,8 +142,6 @@ GameStatus ControlPhase(int numFrames) ClearLensFlares(); ClearDisplaySprites(); - numFrames = std::clamp(numFrames, 0, 10); - if (TrackCameraInit) { UseSpotCam = false; @@ -568,7 +566,7 @@ GameStatus DoGameLoop(int levelIndex) // Before entering actual game loop, ControlPhase must be // called once to sort out various runtime shenanigangs (e.g. hair). - status = ControlPhase(numFrames); + status = ControlPhase(); LARGE_INTEGER lastTime; LARGE_INTEGER currentTime; @@ -603,7 +601,7 @@ GameStatus DoGameLoop(int levelIndex) while (controlLag >= controlFrameTime) { - status = ControlPhase(0); + status = ControlPhase(); controlLag -= controlFrameTime; controlCalls++; diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index cd44f11e2..955729e68 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -83,7 +83,7 @@ extern std::vector OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE]; void DrawPhase(bool isTitle, float interpolationFactor); -GameStatus ControlPhase(int numFrames); +GameStatus ControlPhase(); GameStatus DoLevel(int levelIndex, bool loadGame = false); GameStatus DoGameLoop(int levelIndex); void EndGameLoop(int levelIndex, GameStatus reason); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 0e5d311a9..18cb9d315 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -745,14 +745,19 @@ namespace TEN::Gui if (fromPauseMenu) { g_Renderer.RenderInventory(); - Camera.numberFrames = g_Renderer.Synchronize(); + if (!g_Configuration.EnableVariableFramerate) + { + g_Renderer.Synchronize(); + } } else { g_Renderer.RenderTitle(0); - Camera.numberFrames = g_Renderer.Synchronize(); - int numFrames = Camera.numberFrames; - ControlPhase(numFrames); + if (!g_Configuration.EnableVariableFramerate) + { + g_Renderer.Synchronize(); + } + ControlPhase(); } } } @@ -3323,7 +3328,6 @@ namespace TEN::Gui } DrawInventory(); - DrawCompass(item); switch (InvMode) { @@ -3381,7 +3385,10 @@ namespace TEN::Gui SetEnterInventory(NO_VALUE); - Camera.numberFrames = g_Renderer.Synchronize(); + if (!g_Configuration.EnableVariableFramerate) + { + g_Renderer.Synchronize(); + } } LastInvItem = Rings[(int)RingTypes::Inventory].CurrentObjectList[Rings[(int)RingTypes::Inventory].CurrentObjectInList].InventoryItem; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 1f940ff8f..6fc1176aa 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -876,7 +876,7 @@ namespace TEN::Renderer DrawFullScreenImage(texture.ShaderResourceView.Get(), Smoothstep(currentFade), _backBuffer.RenderTargetView.Get(), _backBuffer.DepthStencilView.Get()); Synchronize(); - _swapChain->Present(0, 0); + _swapChain->Present(1, 0); _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } } @@ -957,6 +957,9 @@ namespace TEN::Renderer _context->RSSetViewports(1, &_viewport); ResetScissor(); + _context->ClearDepthStencilView(_renderTarget.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); + _context->ClearRenderTargetView(_renderTarget.RenderTargetView.Get(), Colors::Black); + if (background != nullptr) { DrawFullScreenImage(background->ShaderResourceView.Get(), backgroundFade, _renderTarget.RenderTargetView.Get(), _renderTarget.DepthStencilView.Get()); @@ -1091,7 +1094,7 @@ namespace TEN::Renderer if (ScreenFadeCurrent && percentage > 0.0f && percentage < 100.0f) DrawLoadingBar(percentage); - _swapChain->Present(0, 0); + _swapChain->Present(1, 0); _context->ClearState(); Synchronize(); @@ -1107,17 +1110,7 @@ namespace TEN::Renderer RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 0.5f); - _swapChain->Present(0, 0); - - if (g_Configuration.EnableVariableFramerate) - { - _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); - _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); - - RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 0.5f); - - _swapChain->Present(0, 0); - } + _swapChain->Present(1, 0); } void Renderer::RenderTitle(float interpolationFactor) @@ -1141,10 +1134,10 @@ namespace TEN::Renderer _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); - RenderInventoryScene(&_backBuffer, nullptr, 1.0f); + RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 1.0f); DrawAllStrings(); - _swapChain->Present(0, 0); + _swapChain->Present(1, 0); } void Renderer::DrawDebugInfo(RenderView& view) From 2c59e89fc4b4ed72727dc20d2770b0e8e778d633 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 2 May 2024 16:31:22 +0200 Subject: [PATCH 134/410] Fixed vsync at screen initialization; Fixed rotation of inventory objects; --- TombEngine/Game/gui.cpp | 7 +++---- TombEngine/Renderer/RendererInit.cpp | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 18cb9d315..7767da684 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -2808,7 +2808,6 @@ namespace TEN::Gui float multiplier = g_Configuration.EnableVariableFramerate ? 2.0f : 1.0f; - if (ring.CurrentObjectList <= 0) return; @@ -3134,13 +3133,13 @@ namespace TEN::Gui if (!i && !ring.ObjectListMovement) { if (invObject.RotFlags & INV_ROT_X) - listObject.Orientation.x += ANGLE(5.0f); + listObject.Orientation.x += ANGLE(5.0f / multiplier); if (invObject.RotFlags & INV_ROT_Y) - listObject.Orientation.y += ANGLE(5.0f); + listObject.Orientation.y += ANGLE(5.0f / multiplier); if (invObject.RotFlags & INV_ROT_Z) - listObject.Orientation.z += ANGLE(5.0f); + listObject.Orientation.z += ANGLE(5.0f / multiplier); } else { diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp index b918d6a4d..9eb926176 100644 --- a/TombEngine/Renderer/RendererInit.cpp +++ b/TombEngine/Renderer/RendererInit.cpp @@ -463,8 +463,18 @@ namespace TEN::Renderer DXGI_SWAP_CHAIN_DESC sd; sd.BufferDesc.Width = w; sd.BufferDesc.Height = h; - sd.BufferDesc.RefreshRate.Numerator = 0; - sd.BufferDesc.RefreshRate.Denominator = 0; + if (!g_Configuration.EnableVariableFramerate) + { + sd.BufferDesc.RefreshRate.Numerator = 0; + sd.BufferDesc.RefreshRate.Denominator = 0; + } + else + { + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + } + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; sd.BufferDesc.Scaling = DXGI_MODE_SCALING_STRETCHED; From 46d2de40a0bbc978ee5005c07f00d2b627767aaf Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Fri, 3 May 2024 09:01:36 +0200 Subject: [PATCH 135/410] Possible fix for debug mode --- TombEngine/Game/control/control.cpp | 12 ++++++++++++ TombEngine/Renderer/RendererDrawMenu.cpp | 1 + 2 files changed, 13 insertions(+) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 2e408359a..19c97faea 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -601,6 +601,18 @@ GameStatus DoGameLoop(int levelIndex) while (controlLag >= controlFrameTime) { +#if _DEBUG + + constexpr auto DEBUG_SKIP_FRAMES = 10; + + if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) + { + TENLog("Game loop is running too slow!", LogLevel::Warning); + App.ResetClock = true; + break; + } +#endif + status = ControlPhase(); controlLag -= controlFrameTime; controlCalls++; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 6fc1176aa..f38ba9add 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1137,6 +1137,7 @@ namespace TEN::Renderer RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 1.0f); DrawAllStrings(); + _context->ClearState(); _swapChain->Present(1, 0); } From 57cf323d7325b800200198a05218fc51cb3d303c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 3 May 2024 10:16:32 +0300 Subject: [PATCH 136/410] Add autodelete parameter to ShowString --- Documentation/doc/1 modules/Strings.html | 11 +++++++++-- .../Scripting/Internal/TEN/Strings/StringsHandler.cpp | 9 +++++++-- .../Scripting/Internal/TEN/Strings/StringsHandler.h | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Documentation/doc/1 modules/Strings.html b/Documentation/doc/1 modules/Strings.html index 63f90605b..c56b1fd46 100644 --- a/Documentation/doc/1 modules/Strings.html +++ b/Documentation/doc/1 modules/Strings.html @@ -109,7 +109,7 @@

    Functions

    - + @@ -131,7 +131,7 @@
    - ShowString(str, time) + ShowString(str, time, autoDelete)
    Show some text on-screen. @@ -151,6 +151,13 @@ If not given, the string will have an "infinite" life, and will show until HideString is called or until the level is finished. Default: nil (i.e. infinite) +
  • autoDelete + bool + should be string automatically deleted after timeout is reached. +If not given, the string will remain allocated even after timeout is reached, and can be +shown again without re-initialization. +Default: false +
  • diff --git a/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp b/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp index d2b5ba582..2f34efd13 100644 --- a/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp @@ -27,6 +27,10 @@ Show some text on-screen. If not given, the string will have an "infinite" life, and will show until @{HideString} is called or until the level is finished. Default: nil (i.e. infinite) +@tparam bool autoDelete should be string automatically deleted after timeout is reached. +If not given, the string will remain allocated even after timeout is reached, and can be +shown again without re-initialization. +Default: false */ table.set_function(ScriptReserved_ShowString, &StringsHandler::ShowString, this); @@ -36,7 +40,7 @@ Hide some on-screen text. @tparam DisplayString str the string object to hide. Must previously have been shown with a call to @{ShowString}, or this function will have no effect. */ - table.set_function(ScriptReserved_HideString, [this](const DisplayString& string) { ShowString(string, 0.0f); }); + table.set_function(ScriptReserved_HideString, [this](const DisplayString& string) { ShowString(string, 0.0f, false); }); /*** Checks if the string is shown @@ -84,11 +88,12 @@ bool StringsHandler::SetDisplayString(DisplayStringID id, const UserDisplayStrin return m_userDisplayStrings.insert_or_assign(id, displayString).second; } -void StringsHandler::ShowString(const DisplayString& str, sol::optional numSeconds) +void StringsHandler::ShowString(const DisplayString& str, sol::optional numSeconds, sol::optional autoDelete) { auto it = m_userDisplayStrings.find(str.GetID()); it->second._timeRemaining = numSeconds.value_or(0.0f); it->second._isInfinite = !numSeconds.has_value(); + it->second._deleteWhenZero = autoDelete.value_or(false); } bool StringsHandler::IsStringDisplaying(const DisplayString& displayString) diff --git a/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.h b/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.h index 6b28edf85..96c10f7db 100644 --- a/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.h @@ -26,7 +26,7 @@ public: std::optional> GetDisplayString(DisplayStringID id); bool ScheduleRemoveDisplayString(DisplayStringID id); - void ShowString(DisplayString const&, sol::optional nSeconds); + void ShowString(DisplayString const&, sol::optional nSeconds, sol::optional autoDelete); bool IsStringDisplaying(DisplayString const& str); From 1bf60287e3ac5c4be06ac51edd71d357650c0c92 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 3 May 2024 23:55:31 +1000 Subject: [PATCH 137/410] Fix bouncing pushables --- .../Generic/Object/Pushable/PushableCollision.cpp | 9 +++++---- .../Objects/Generic/Object/Pushable/PushableObject.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 733ae4c86..b41cf3b11 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -13,8 +13,8 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -using namespace TEN::Collision::Point; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::Point; using namespace TEN::Entities::Generic; using namespace TEN::Input; @@ -307,7 +307,9 @@ namespace TEN::Entities::Generic RemovePushableBridge(item); pointColl = GetPointCollision(item); - waterHeight = GetWaterSurface(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber); + pointColl.GetFloorHeight(); + + waterHeight = pointColl.GetWaterSurfaceHeight(); if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) waterHeight = g_Level.Rooms[item.RoomNumber].maxceiling; @@ -316,8 +318,7 @@ namespace TEN::Entities::Generic } else { - pointColl = GetPointCollision(item); - waterHeight = GetWaterSurface(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber); + waterHeight = pointColl.GetWaterSurfaceHeight(); if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) waterHeight = g_Level.Rooms[item.RoomNumber].maxceiling; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp index 491caea4f..4ef806982 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableObject.cpp @@ -227,7 +227,7 @@ namespace TEN::Entities::Generic void SetPushableStopperFlag(bool isStopper, const Vector3i& pos, int roomNumber) { auto pointColl = GetPointCollision(pos, roomNumber); - pointColl.GetSector().Stopper = isStopper; + pointColl.GetSector().Stopper = isStopper; // TODO: There is a problem, it also has to set/reset the flag in the flipped room. // Because when flipmaps happens, it forgets about the old flag. From 3faf25c92f2cbfd0f48c071465f7e61cd09eddd3 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 3 May 2024 23:59:38 +1000 Subject: [PATCH 138/410] Fix pushable grab ban --- .../Objects/Generic/Object/Pushable/PushableCollision.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index b41cf3b11..bf526c49a 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -34,7 +34,10 @@ namespace TEN::Entities::Generic if (pushable.UseRoomCollision) { RemovePushableBridge(pushableItem); + pointColl = GetPointCollision(pushableItem); + pointColl.GetFloorHeight(); + AddPushableBridge(pushableItem); } From 7b7473b660ce93c82ebc48dd218b4a035a075734 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 4 May 2024 06:02:44 +0200 Subject: [PATCH 139/410] Added laser beams interpolation; Addes streamer interpolation; Added sparks interpolation; Cleaned smoke interpolation; --- TombEngine/Game/control/control.cpp | 1 - TombEngine/Game/effects/Streamer.cpp | 9 ++ TombEngine/Game/effects/Streamer.h | 4 + TombEngine/Game/effects/smoke.cpp | 38 +------- TombEngine/Game/effects/smoke.h | 9 ++ TombEngine/Game/effects/spark.cpp | 2 + TombEngine/Game/effects/spark.h | 9 ++ TombEngine/Objects/TR5/Trap/LaserBeam.cpp | 12 +++ TombEngine/Objects/TR5/Trap/LaserBeam.h | 5 + TombEngine/Renderer/RendererDrawEffect.cpp | 103 ++++++++++++++++----- 10 files changed, 130 insertions(+), 62 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 19c97faea..942b3d875 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -602,7 +602,6 @@ GameStatus DoGameLoop(int levelIndex) while (controlLag >= controlFrameTime) { #if _DEBUG - constexpr auto DEBUG_SKIP_FRAMES = 10; if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) diff --git a/TombEngine/Game/effects/Streamer.cpp b/TombEngine/Game/effects/Streamer.cpp index ec7bad158..48ffb14f8 100644 --- a/TombEngine/Game/effects/Streamer.cpp +++ b/TombEngine/Game/effects/Streamer.cpp @@ -21,6 +21,8 @@ namespace TEN::Effects::Streamer void Streamer::StreamerSegment::Update() { + StoreInterpolationData(); + // Update opacity. if (Color.w > 0.0f) Color.w = InterpolateCos(0.0f, OpacityMax, Life / LifeMax); @@ -36,6 +38,13 @@ namespace TEN::Effects::Streamer Life -= 1.0f; } + void Streamer::StreamerSegment::StoreInterpolationData() + { + OldVertices[0] = Vertices[0]; + OldVertices[1] = Vertices[1]; + OldColor = Color; + } + void Streamer::StreamerSegment::TransformVertices(float vel, float scaleRate) { // Apply expansion. diff --git a/TombEngine/Game/effects/Streamer.h b/TombEngine/Game/effects/Streamer.h index ea712a44a..5a189d83d 100644 --- a/TombEngine/Game/effects/Streamer.h +++ b/TombEngine/Game/effects/Streamer.h @@ -39,11 +39,15 @@ namespace TEN::Effects::Streamer std::array Vertices = {}; + std::array OldVertices = {}; + Vector4 OldColor = Vector4::Zero; + void InitializeVertices(const Vector3& pos, float width); void Update(); private: void TransformVertices(float vel, float scaleRate); + void StoreInterpolationData(); }; // Members diff --git a/TombEngine/Game/effects/smoke.cpp b/TombEngine/Game/effects/smoke.cpp index a428f893f..ed5c78535 100644 --- a/TombEngine/Game/effects/smoke.cpp +++ b/TombEngine/Game/effects/smoke.cpp @@ -45,6 +45,8 @@ namespace TEN::Effects::Smoke if (!s.active) continue; + s.StoreInterpolationData(); + s.age += 1; if (s.age > s.life) { @@ -52,12 +54,6 @@ namespace TEN::Effects::Smoke continue; } - // Interpolation - s.oldPosition = s.position; - s.oldColor = s.color; - s.oldRotation = s.rotation; - s.oldSize = s.size; - s.velocity.y += s.gravity; if (s.terminalVelocity != 0) @@ -114,11 +110,6 @@ namespace TEN::Effects::Smoke s.affectedByWind = true; s.active = true; s.room = room; - - s.oldPosition = s.position; - s.oldColor = s.color; - s.oldRotation = s.rotation; - s.oldSize = s.size; } //TODO: add additional "Weapon Special" param or something. Currently initial == 2 means Rocket Launcher backwards smoke. @@ -205,11 +196,6 @@ namespace TEN::Effects::Smoke s.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4); s.angularDrag = 0.95f; s.room = roomNumber; - - s.oldPosition = s.position; - s.oldColor = s.color; - s.oldRotation = s.rotation; - s.oldSize = s.size; } void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving) @@ -233,11 +219,6 @@ namespace TEN::Effects::Smoke s.destinationSize = Random::GenerateFloat(128, 160); s.angularVelocity = Random::GenerateFloat(-1, 1); s.angularDrag = Random::GenerateFloat(0.97f, 0.999f); - - s.oldPosition = s.position; - s.oldColor = s.color; - s.oldRotation = s.rotation; - s.oldSize = s.size; } void TriggerRocketSmoke(int x, int y, int z) @@ -257,11 +238,6 @@ namespace TEN::Effects::Smoke s.destinationSize = Random::GenerateFloat(1024, 1152); s.angularVelocity = Random::GenerateFloat(-0.6f, 0.6f); s.angularDrag = Random::GenerateFloat(0.87f, 0.99f); - - s.oldPosition = s.position; - s.oldColor = s.color; - s.oldRotation = s.rotation; - s.oldSize = s.size; } void SpawnCorpseEffect(const Vector3& pos) @@ -285,11 +261,6 @@ namespace TEN::Effects::Smoke smoke.destinationSize = Random::GenerateFloat(BLOCK(1), BLOCK(1.1f)); smoke.angularVelocity = Random::GenerateFloat(-0.1f, 0.1f); smoke.angularDrag = Random::GenerateFloat(0.8f, 0.9f); - - smoke.oldPosition = smoke.position; - smoke.oldColor = smoke.color; - smoke.oldRotation = smoke.rotation; - smoke.oldSize = smoke.size; } void TriggerBreathSmoke(long x, long y, long z, short angle) @@ -313,10 +284,5 @@ namespace TEN::Effects::Smoke s.destinationSize = Random::GenerateFloat(128, 160); s.angularVelocity = Random::GenerateFloat(-0.5f, 0.5f); s.angularDrag = Random::GenerateFloat(0.95f, 0.95f); - - s.oldPosition = s.position; - s.oldColor = s.color; - s.oldRotation = s.rotation; - s.oldSize = s.size; } } diff --git a/TombEngine/Game/effects/smoke.h b/TombEngine/Game/effects/smoke.h index 41fef8a8f..fb0dfb7ab 100644 --- a/TombEngine/Game/effects/smoke.h +++ b/TombEngine/Game/effects/smoke.h @@ -27,10 +27,19 @@ namespace TEN::Effects::Smoke float terminalVelocity; bool affectedByWind; bool active; + Vector4 oldColor; Vector3 oldPosition; float oldRotation; float oldSize; + + void StoreInterpolationData() + { + oldColor = color; + oldPosition = position; + oldRotation = rotation; + oldSize = size; + } }; extern std::array SmokeParticles; diff --git a/TombEngine/Game/effects/spark.cpp b/TombEngine/Game/effects/spark.cpp index 3cf7fcb9f..521906e6d 100644 --- a/TombEngine/Game/effects/spark.cpp +++ b/TombEngine/Game/effects/spark.cpp @@ -23,6 +23,8 @@ namespace TEN::Effects::Spark if (!s.active) continue; + + s.StoreInterpolationData(); s.age += 1; if (s.age > s.life) diff --git a/TombEngine/Game/effects/spark.h b/TombEngine/Game/effects/spark.h index 308d43f41..34fe6b386 100644 --- a/TombEngine/Game/effects/spark.h +++ b/TombEngine/Game/effects/spark.h @@ -22,6 +22,15 @@ namespace TEN::Effects::Spark float width; float height; bool active; + + Vector3 oldPos; + Vector3 oldVelocity; + + void StoreInterpolationData() + { + oldPos = pos; + oldVelocity = velocity; + } }; extern std::array SparkParticles; diff --git a/TombEngine/Objects/TR5/Trap/LaserBeam.cpp b/TombEngine/Objects/TR5/Trap/LaserBeam.cpp index ae227bcbc..130d30cb2 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBeam.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBeam.cpp @@ -80,6 +80,16 @@ namespace TEN::Traps::TR5 TriggerDynamicLight(pos, color * intensityNorm, FALLOFF); } + void LaserBeamEffect::StoreInterpolationData() + { + for (int i = 0; i < Vertices.size(); i++) + { + OldVertices[i] = Vertices[i]; + } + + OldColor = Color; + } + void LaserBeamEffect::Update(const ItemInfo& item) { auto orient = EulerAngles(item.Pose.Orientation.x + ANGLE(180.0f), item.Pose.Orientation.y, item.Pose.Orientation.z); @@ -154,6 +164,8 @@ namespace TEN::Traps::TR5 return; } + beam.StoreInterpolationData(); + // Brightness fade-in and distortion. if (item.Model.Color.w < 1.0f) item.Model.Color.w += 0.02f; diff --git a/TombEngine/Objects/TR5/Trap/LaserBeam.h b/TombEngine/Objects/TR5/Trap/LaserBeam.h index 168e1e2fc..64a6056d6 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBeam.h +++ b/TombEngine/Objects/TR5/Trap/LaserBeam.h @@ -22,8 +22,13 @@ namespace TEN::Traps::TR5 bool IsLethal = false; bool IsHeavyActivator = false; + std::array OldVertices = {}; + Vector4 OldColor; + void Initialize(const ItemInfo& item); void Update(const ItemInfo& item); + + void StoreInterpolationData(); }; extern std::unordered_map LaserBeams; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 0c4cab6c0..8b4dfe37a 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -88,14 +88,32 @@ namespace TEN::Renderer { bool isLastSubdivision = (i == (LaserBeamEffect::SUBDIVISION_COUNT - 1)); + Vector4 color = Vector4::Lerp(beam.OldColor, beam.Color, _interpolationFactor); + AddColoredQuad( - beam.Vertices[i], - beam.Vertices[isLastSubdivision ? 0 : (i + 1)], - beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + (isLastSubdivision ? 0 : (i + 1))], - beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + i], - beam.Color, beam.Color, - beam.Color, beam.Color, - BlendMode::Additive, view, SpriteRenderType::LaserBeam); + Vector3::Lerp( + beam.OldVertices[i], + beam.Vertices[i], + _interpolationFactor), + Vector3::Lerp( + beam.OldVertices[isLastSubdivision ? 0 : (i + 1)], + beam.Vertices[isLastSubdivision ? 0 : (i + 1)], + _interpolationFactor), + Vector3::Lerp( + beam.OldVertices[LaserBeamEffect::SUBDIVISION_COUNT + (isLastSubdivision ? 0 : (i + 1))], + beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + (isLastSubdivision ? 0 : (i + 1))], + _interpolationFactor), + Vector3::Lerp( + beam.OldVertices[LaserBeamEffect::SUBDIVISION_COUNT + i], + beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + i], + _interpolationFactor), + color, + color, + color, + color, + BlendMode::Additive, + view, + SpriteRenderType::LaserBeam); } } } @@ -126,29 +144,44 @@ namespace TEN::Renderer if (segment.Flags & (int)StreamerFlags::FadeLeft) { AddColoredQuad( - segment.Vertices[0], segment.Vertices[1], - prevSegment.Vertices[1], prevSegment.Vertices[0], - Vector4::Zero, segment.Color, - prevSegment.Color, Vector4::Zero, - blendMode, view); + Vector3::Lerp(segment.OldVertices[0], segment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.OldVertices[1], segment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.OldVertices[1], prevSegment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.OldVertices[0], prevSegment.Vertices[0], _interpolationFactor), + Vector4::Zero, + Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + Vector4::Zero, + blendMode, + view); } else if (segment.Flags & (int)StreamerFlags::FadeRight) { AddColoredQuad( - segment.Vertices[0], segment.Vertices[1], - prevSegment.Vertices[1], prevSegment.Vertices[0], - segment.Color, Vector4::Zero, - Vector4::Zero, prevSegment.Color, - blendMode, view); + Vector3::Lerp(segment.OldVertices[0], segment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.OldVertices[1], segment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.OldVertices[1], prevSegment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.OldVertices[0], prevSegment.Vertices[0], _interpolationFactor), + Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), + Vector4::Zero, + Vector4::Zero, + Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + blendMode, + view); } else { AddColoredQuad( - segment.Vertices[0], segment.Vertices[1], - prevSegment.Vertices[1], prevSegment.Vertices[0], - segment.Color, segment.Color, - prevSegment.Color, prevSegment.Color, - blendMode, view); + Vector3::Lerp(segment.OldVertices[0], segment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.OldVertices[1], segment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.OldVertices[1], prevSegment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.OldVertices[0], prevSegment.Vertices[0], _interpolationFactor), + Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), + Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + blendMode, + view); } } } @@ -1505,16 +1538,36 @@ namespace TEN::Renderer if (!s.active) continue; if (!CheckIfSlotExists(ID_SPARK_SPRITE, "Spark particle rendering")) + { return; + } - Vector3 v; - s.velocity.Normalize(v); + Vector3 oldVelocity; + Vector3 velocity; + s.oldVelocity.Normalize(oldVelocity); + s.velocity.Normalize(velocity); + + velocity = Vector3::Lerp(oldVelocity, velocity, _interpolationFactor); + velocity.Normalize(); float normalizedLife = s.age / s.life; auto height = Lerp(1.0f, 0.0f, normalizedLife); auto color = Vector4::Lerp(s.sourceColor, s.destinationColor, normalizedLife); - AddSpriteBillboardConstrained(&_sprites[Objects[ID_SPARK_SPRITE].meshIndex], s.pos, color, 0, 1, { s.width, s.height * height }, BlendMode::Additive, -v, false, view); + AddSpriteBillboardConstrained( + &_sprites[Objects[ID_SPARK_SPRITE].meshIndex], + Vector3::Lerp(s.oldPos, s.pos, _interpolationFactor), + color, + 0, + 1, + { + s.width, + s.height * height + }, + BlendMode::Additive, + -velocity, + false, + view); } } From ee3bc5db0f8c5c6bf5d5007c537e307aff4b3053 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 5 May 2024 05:54:21 +0200 Subject: [PATCH 140/410] Fixed display sprites multiple draws --- TombEngine/Game/Hud/Speedometer.cpp | 6 ++++-- TombEngine/Game/Hud/TargetHighlighter.cpp | 4 ++-- TombEngine/Game/control/control.cpp | 4 ++-- TombEngine/Game/effects/DisplaySprite.cpp | 13 +++++++++++-- TombEngine/Game/effects/DisplaySprite.h | 14 ++++++++++++-- TombEngine/Renderer/RendererDraw.cpp | 5 +++++ .../TEN/DisplaySprite/ScriptDisplaySprite.cpp | 3 ++- 7 files changed, 38 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/Hud/Speedometer.cpp b/TombEngine/Game/Hud/Speedometer.cpp index 5768c69cf..edd22a230 100644 --- a/TombEngine/Game/Hud/Speedometer.cpp +++ b/TombEngine/Game/Hud/Speedometer.cpp @@ -64,13 +64,15 @@ namespace TEN::Hud AddDisplaySprite( ID_SPEEDOMETER, DIAL_ELEMENT_SPRITE_ID, POS, 0, SCALE, color, - DIAL_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend); + DIAL_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend, + DisplaySpriteSource::DrawPhase); // Draw pointer. AddDisplaySprite( ID_SPEEDOMETER, POINTER_ELEMENT_SPRITE_ID, POS, _pointerAngle + ORIENT_OFFSET, SCALE, color, - POINTER_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend); + POINTER_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend, + DisplaySpriteSource::DrawPhase); } void SpeedometerController::Clear() diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 34638f991..8ad619221 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -144,7 +144,7 @@ namespace TEN::Hud AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, STATIC_ELEMENT_SPRITE_ID, *Position, Orientation, Vector2(Scale), Color, - PRIORITY, ALIGN_MODE, SCALE_MODE, BLEND_MODE); + PRIORITY, ALIGN_MODE, SCALE_MODE, BLEND_MODE, DisplaySpriteSource::DrawPhase); // Draw animated outer segment elements. for (const auto& segment : Segments) @@ -156,7 +156,7 @@ namespace TEN::Hud AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, SEGMENT_ELEMENT_SPRITE_ID, pos, orient, scale, Color, - PRIORITY, ALIGN_MODE, SCALE_MODE, BLEND_MODE); + PRIORITY, ALIGN_MODE, SCALE_MODE, BLEND_MODE, DisplaySpriteSource::DrawPhase); } } diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 942b3d875..a0a3b981b 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -140,7 +140,7 @@ GameStatus ControlPhase() RegeneratePickups(); ClearFires(); ClearLensFlares(); - ClearDisplaySprites(); + ClearAllDisplaySprites(); if (TrackCameraInit) { @@ -438,7 +438,7 @@ void CleanUp() StreamerEffect.Clear(); ClearUnderwaterBloodParticles(); ClearBubbles(); - ClearDisplaySprites(); + ClearAllDisplaySprites(); ClearFootprints(); ClearDrips(); ClearRipples(); diff --git a/TombEngine/Game/effects/DisplaySprite.cpp b/TombEngine/Game/effects/DisplaySprite.cpp index 9a6b410c3..efcfb1236 100644 --- a/TombEngine/Game/effects/DisplaySprite.cpp +++ b/TombEngine/Game/effects/DisplaySprite.cpp @@ -14,7 +14,8 @@ namespace TEN::Effects::DisplaySprite std::vector DisplaySprites = {}; void AddDisplaySprite(GAME_OBJECT_ID objectID, int spriteID, const Vector2& pos, short orient, const Vector2& scale, const Vector4& color, - int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode, BlendMode blendMode) + int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode, + BlendMode blendMode, DisplaySpriteSource source) { auto displaySprite = DisplaySprite{}; displaySprite.ObjectID = objectID; @@ -27,12 +28,20 @@ namespace TEN::Effects::DisplaySprite displaySprite.AlignMode = alignMode; displaySprite.ScaleMode = scaleMode; displaySprite.BlendMode = blendMode; + displaySprite.Source = source; DisplaySprites.push_back(displaySprite); } - void ClearDisplaySprites() + void ClearAllDisplaySprites() { DisplaySprites.clear(); } + + void ClearDrawPhaseDisplaySprites() + { + DisplaySprites.erase(std::remove_if(DisplaySprites.begin(), DisplaySprites.end(), + [](const DisplaySprite& displaySprite) { return displaySprite.Source == DisplaySpriteSource::DrawPhase; }), + DisplaySprites.end()); + } } diff --git a/TombEngine/Game/effects/DisplaySprite.h b/TombEngine/Game/effects/DisplaySprite.h index 2f9eb4564..26947e796 100644 --- a/TombEngine/Game/effects/DisplaySprite.h +++ b/TombEngine/Game/effects/DisplaySprite.h @@ -23,6 +23,12 @@ namespace TEN::Effects::DisplaySprite Fill, Stretch }; + + enum class DisplaySpriteSource + { + ControlPhase, + DrawPhase + }; struct DisplaySprite { @@ -38,11 +44,15 @@ namespace TEN::Effects::DisplaySprite DisplaySpriteAlignMode AlignMode = DisplaySpriteAlignMode::Center; DisplaySpriteScaleMode ScaleMode = DisplaySpriteScaleMode::Fit; BlendMode BlendMode = BlendMode::AlphaBlend; + + DisplaySpriteSource Source = DisplaySpriteSource::ControlPhase; }; extern std::vector DisplaySprites; void AddDisplaySprite(GAME_OBJECT_ID objectID, int spriteID, const Vector2& pos, short orient, const Vector2& scale, const Vector4& color, - int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode, BlendMode blendMode); - void ClearDisplaySprites(); + int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode, + BlendMode blendMode, DisplaySpriteSource source); + void ClearAllDisplaySprites(); + void ClearDrawPhaseDisplaySprites(); } diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 04da60923..b2571b504 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -32,6 +32,7 @@ #include "Specific/winmain.h" #include "Renderer/Structures/RendererSortableObject.h" #include "Game/effects/weather.h" +#include "Game/effects/DisplaySprite.h" using namespace std::chrono; using namespace TEN::Effects::Hair; @@ -40,6 +41,7 @@ using namespace TEN::Entities::Generic; using namespace TEN::Hud; using namespace TEN::Renderer::Structures; using namespace TEN::Effects::Environment; +using namespace TEN::Effects::DisplaySprite; extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; @@ -1667,6 +1669,7 @@ namespace TEN::Renderer using get_time = std::chrono::steady_clock; ResetDebugVariables(); + _doingFullscreenPass = false; auto& level = *g_GameFlow->GetLevel(CurrentLevel); @@ -1902,6 +1905,8 @@ namespace TEN::Renderer DrawTriangles3D(view); // Draw HUD. + ClearDrawPhaseDisplaySprites(); + _context->ClearDepthStencilView(_renderTarget.DepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); g_Hud.Draw(*LaraItem); diff --git a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp index 12529806d..63de5efcf 100644 --- a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp +++ b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp @@ -220,6 +220,7 @@ namespace TEN::Scripting::DisplaySprite priority.value_or(DEFAULT_PRIORITY), alignMode.value_or(DEFAULT_ALIGN_MODE), scaleMode.value_or(DEFAULT_SCALE_MODE), - blendMode.value_or(DEFAULT_BLEND_MODE)); + blendMode.value_or(DEFAULT_BLEND_MODE), + DisplaySpriteSource::ControlPhase); } } From 9f27821ff6ff854e9a3e7451aca478fd1d7773cd Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 6 May 2024 05:56:08 +0200 Subject: [PATCH 141/410] Fixed hairs detached from head --- TombEngine/Renderer/RendererLara.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index b36f8113f..2685390bc 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -345,7 +345,7 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render // First matrix is Lara's head matrix, then all hair unit segment matrices. // Bones are adjusted at load time to account for this. _stItem.World = Matrix::Identity; - _stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimationTransforms[LM_HEAD] * _laraWorldMatrix; + _stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimationTransforms[LM_HEAD] * itemToDraw->InterpolatedWorld; for (int i = 0; i < unit.Segments.size(); i++) { From 8995973c2a4d98c8fcdf38b7c7590555cf399b5d Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 7 May 2024 05:33:54 +0200 Subject: [PATCH 142/410] Fixed GPU not reset after sun sprite draw --- TombEngine/Renderer/RendererDraw.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index b2571b504..9b838b6bf 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3072,6 +3072,11 @@ namespace TEN::Renderer // Clear just the Z-buffer to start drawing on top of horizon. _context->ClearDepthStencilView(depthTarget, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + // Reset the GPU state + SetDepthState(DepthState::Write); + SetBlendMode(BlendMode::Opaque); + SetCullMode(CullMode::CounterClockwise); } void Renderer::Render(float interpolationFactor) From fb0519eb49c33e76edebee58ab84d4e5e5992af3 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 03:13:52 +1000 Subject: [PATCH 143/410] Lens flare cleanup --- TombEngine/Game/control/control.cpp | 5 +- TombEngine/Game/effects/weather.h | 5 +- TombEngine/Objects/Effects/LensFlare.cpp | 99 +++++++++++++++ TombEngine/Objects/Effects/LensFlare.h | 21 ++++ TombEngine/Objects/Effects/effect_objects.cpp | 11 +- TombEngine/Objects/Effects/lens_flare.cpp | 115 ------------------ TombEngine/Objects/Effects/lens_flare.h | 25 ---- .../Objects/Effects/tr5_electricity.cpp | 2 +- .../Objects/TR5/Entity/tr5_roman_statue.cpp | 2 +- .../Objects/TR5/Entity/tr5_submarine.cpp | 2 +- TombEngine/Objects/objectslist.h | 12 +- .../ConstantBuffers/PostProcessBuffer.h | 5 +- TombEngine/Renderer/RendererDraw.cpp | 72 ++++++----- TombEngine/Renderer/RendererFrame.cpp | 58 ++++----- TombEngine/Renderer/RendererPostProcess.cpp | 38 +++--- .../Renderer/Structures/RendererLensFlare.h | 19 ++- .../Internal/TEN/Flow/LensFlare/LensFlare.h | 2 +- TombEngine/Specific/RGBAColor8Byte.cpp | 5 + TombEngine/Specific/RGBAColor8Byte.h | 1 + TombEngine/TombEngine.vcxproj | 4 +- 20 files changed, 239 insertions(+), 264 deletions(-) create mode 100644 TombEngine/Objects/Effects/LensFlare.cpp create mode 100644 TombEngine/Objects/Effects/LensFlare.h delete mode 100644 TombEngine/Objects/Effects/lens_flare.cpp delete mode 100644 TombEngine/Objects/Effects/lens_flare.h diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index a0a3b981b..9a4347a1b 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -40,6 +40,7 @@ #include "Game/Setup.h" #include "Game/spotcam.h" #include "Math/Math.h" +#include "Objects/Effects/LensFlare.h" #include "Objects/Effects/tr4_locusts.h" #include "Objects/Generic/Object/objects.h" #include "Objects/Generic/Object/rope.h" @@ -60,7 +61,6 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" #include "Specific/winmain.h" -#include "Objects/Effects/lens_flare.h" using namespace std::chrono; using namespace TEN::Effects; @@ -249,8 +249,7 @@ GameStatus ControlPhase() SetupGlobalLensFlare( g_GameFlow->GetLevel(CurrentLevel)->GetLensFlarePosition(), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareColor(), - g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSpriteID() - ); + g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSpriteID()); } // Update HUD. diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index 07ac92765..677ef175b 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -1,8 +1,7 @@ #pragma once -#include -#include "Scripting/Include/ScriptInterfaceLevel.h" #include "Math/Math.h" -#include "Objects/Effects/lens_flare.h" +#include "Objects/Effects/LensFlare.h" +#include "Scripting/Include/ScriptInterfaceLevel.h" using namespace TEN::Entities::Effects; diff --git a/TombEngine/Objects/Effects/LensFlare.cpp b/TombEngine/Objects/Effects/LensFlare.cpp new file mode 100644 index 000000000..8f320e137 --- /dev/null +++ b/TombEngine/Objects/Effects/LensFlare.cpp @@ -0,0 +1,99 @@ +#include "framework.h" +#include "Objects/Effects/LensFlare.h" + +#include "Game/camera.h" +#include "Game/control/los.h" +#include "Specific/level.h" + +namespace TEN::Entities::Effects +{ + std::vector LensFlares; + + static void SetupLensFlare(const Vector3& pos, int roomNumber, const Color& color, bool isGlobal, int spriteIndex) + { + auto lensFlarePos = Vector3::Zero; + if (isGlobal) + { + if (TestEnvironment(ENV_FLAG_NO_LENSFLARE, Camera.pos.RoomNumber)) + return; + + lensFlarePos = pos; + auto delta = (lensFlarePos - Camera.pos.ToVector3()) / 16.0f; + while (abs(delta.x) > BLOCK(200) || abs(delta.y) > BLOCK(200) || abs(delta.z) > BLOCK(200)) + lensFlarePos -= delta; + + delta = (lensFlarePos - Camera.pos.ToVector3()) / 16.0f; + while (abs(delta.x) > BLOCK(32) || abs(delta.y) > BLOCK(32) || abs(delta.z) > BLOCK(32)) + lensFlarePos -= delta; + + delta = (lensFlarePos - Camera.pos.ToVector3()) / 16.0f; + for (int i = 0; i < 16; i++) + { + int foundRoomNumber = IsRoomOutside(lensFlarePos.x, lensFlarePos.y, lensFlarePos.z); + if (foundRoomNumber != NO_VALUE) + { + roomNumber = foundRoomNumber; + break; + } + + lensFlarePos -= delta; + } + } + else + { + float dist = Vector3::Distance(pos, Camera.pos.ToVector3()); + if (dist > BLOCK(32)) + return; + + lensFlarePos = pos; + } + + bool isVisible = false; + if (roomNumber != NO_VALUE) + { + if (TestEnvironment(ENV_FLAG_NOT_NEAR_OUTSIDE, roomNumber) || !isGlobal) + { + auto origin = Camera.pos; + auto target = GameVector(lensFlarePos, roomNumber); + isVisible = LOS(&origin, &target); + } + } + + if (!isVisible && !isGlobal) + return; + + auto lensFlare = LensFlare{}; + lensFlare.Position = pos; + lensFlare.RoomNumber = roomNumber; + lensFlare.IsGlobal = isGlobal; + lensFlare.Color = color; + lensFlare.SpriteIndex = spriteIndex; + + LensFlares.push_back(lensFlare); + } + + void ControlLensFlare(int itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (TriggerActive(&item)) + SetupLensFlare(item.Pose.Position.ToVector3(), item.RoomNumber, Color(), false, SPR_LENS_FLARE_3); + } + + void ClearLensFlares() + { + LensFlares.clear(); + } + + void SetupGlobalLensFlare(const Vector2& yawAndPitchInDegrees, const Color& color, int spriteIndex) + { + auto pos = Camera.pos.ToVector3(); + auto rotMatrix = Matrix::CreateFromYawPitchRoll( + DEG_TO_RAD(yawAndPitchInDegrees.x), + DEG_TO_RAD(yawAndPitchInDegrees.y), + 0.0f); + + pos += Vector3::Transform(Vector3(0.0f, 0.0f, BLOCK(256)), rotMatrix); + SetupLensFlare(pos, NO_VALUE, color, true, spriteIndex); + } +} diff --git a/TombEngine/Objects/Effects/LensFlare.h b/TombEngine/Objects/Effects/LensFlare.h new file mode 100644 index 000000000..6beca5e52 --- /dev/null +++ b/TombEngine/Objects/Effects/LensFlare.h @@ -0,0 +1,21 @@ +#pragma once + +namespace TEN::Entities::Effects +{ + struct LensFlare + { + int SpriteIndex = 0; + + Vector3 Position = Vector3::Zero; + int RoomNumber = 0; + Color Color = {}; + + bool IsGlobal = false; + }; + + extern std::vector LensFlares; + + void ControlLensFlare(int itemNumber); + void ClearLensFlares(); + void SetupGlobalLensFlare(const Vector2& yawAndPitchInDegrees, const Color& color, int spriteIndex); +} diff --git a/TombEngine/Objects/Effects/effect_objects.cpp b/TombEngine/Objects/Effects/effect_objects.cpp index 1449d8ed2..0b6b1f9ec 100644 --- a/TombEngine/Objects/Effects/effect_objects.cpp +++ b/TombEngine/Objects/Effects/effect_objects.cpp @@ -2,9 +2,9 @@ #include "Objects/Effects/effect_objects.h" #include "Game/Setup.h" -#include "Objects/Effects/flame_emitters.h" #include "Objects/Effects/enemy_missile.h" -#include "Objects/Effects/lens_flare.h" +#include "Objects/Effects/flame_emitters.h" +#include "Objects/Effects/LensFlare.h" using namespace TEN::Entities::Effects; @@ -58,8 +58,5 @@ void InitializeEffectsObjects() obj = &Objects[ID_LENS_FLARE]; if (obj->loaded) - { - obj->control = LensFlareControl; - } - -} \ No newline at end of file + obj->control = ControlLensFlare; +} diff --git a/TombEngine/Objects/Effects/lens_flare.cpp b/TombEngine/Objects/Effects/lens_flare.cpp deleted file mode 100644 index 2d585bae7..000000000 --- a/TombEngine/Objects/Effects/lens_flare.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "framework.h" -#include "Objects/Effects/lens_flare.h" -#include "Specific/level.h" -#include "Game/camera.h" -#include "Game/control/los.h" - -namespace TEN::Entities::Effects -{ - std::vector LensFlares; - - void LensFlareControl(short itemNumber) - { - auto* item = &g_Level.Items[itemNumber]; - - if (TriggerActive(item)) - { - SetupLensFlare( - item->Pose.Position.ToVector3(), - Vector3::One, - item->RoomNumber, - false, - SPR_LENSFLARE3); - } - } - - void ClearLensFlares() - { - LensFlares.clear(); - } - - void SetupGlobalLensFlare(Vector2 yawAndPitchInDegrees, Vector3 color, int spriteIndex) - { - Vector3 position = Camera.pos.ToVector3(); - Matrix rotation = Matrix::CreateFromYawPitchRoll( - DEG_TO_RAD(yawAndPitchInDegrees.x), - DEG_TO_RAD(yawAndPitchInDegrees.y), - 0 - ); - position += Vector3::Transform(Vector3(0, 0, BLOCK(256)), rotation); - SetupLensFlare(position, color, NO_VALUE, true, spriteIndex); - } - - void SetupLensFlare(Vector3 position, Vector3 color, short roomNumber, bool global, int spriteIndex) - { - Vector3 lensFlarePosition; - - if (global) - { - if (g_Level.Rooms[Camera.pos.RoomNumber].flags & ENV_FLAG_NO_LENSFLARE) - { - return; - } - - lensFlarePosition = position; - Vector3 delta = (lensFlarePosition - Camera.pos.ToVector3()) / 16.0f; - while (abs(delta.x) > BLOCK(200) || abs(delta.y) > BLOCK(200) || abs(delta.z) > BLOCK(200)) - { - lensFlarePosition -= delta; - } - - delta = (lensFlarePosition - Camera.pos.ToVector3()) / 16.0f; - while (abs(delta.x) > BLOCK(32) || abs(delta.y) > BLOCK(32) || abs(delta.z) > BLOCK(32)) - { - lensFlarePosition -= delta; - } - - delta = (lensFlarePosition - Camera.pos.ToVector3()) / 16.0f; - for (int i = 0; i < 16; i++) - { - short foundRoomNumber = IsRoomOutside(lensFlarePosition.x, lensFlarePosition.y, lensFlarePosition.z); - if (foundRoomNumber != NO_VALUE) - { - roomNumber = foundRoomNumber; - break; - } - lensFlarePosition -= delta; - } - } - else - { - if (Vector3::Distance(position, Camera.pos.ToVector3()) > BLOCK(32)) - { - return; - } - lensFlarePosition = position; - } - - bool flareVisible = false; - - if (roomNumber != NO_VALUE) - { - if (g_Level.Rooms[roomNumber].flags & ENV_FLAG_NOT_NEAR_OUTSIDE || !global) - { - GameVector source = { Camera.pos.x, Camera.pos.y, Camera.pos.z, Camera.pos.RoomNumber }; - GameVector destination = { (int)lensFlarePosition.x, (int)lensFlarePosition.y, (int)lensFlarePosition.z, roomNumber }; - flareVisible = LOS(&source, &destination); - } - } - - if (!flareVisible && !global) - { - return; - } - - LensFlare lensFlare; - - lensFlare.Position = position; - lensFlare.RoomNumber = roomNumber; - lensFlare.Global = global; - lensFlare.Color = color; - lensFlare.SpriteIndex = spriteIndex; - - LensFlares.push_back(lensFlare); - } -} \ No newline at end of file diff --git a/TombEngine/Objects/Effects/lens_flare.h b/TombEngine/Objects/Effects/lens_flare.h deleted file mode 100644 index 553866f4f..000000000 --- a/TombEngine/Objects/Effects/lens_flare.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -namespace TEN::Entities::Effects -{ - using namespace DirectX::SimpleMath; - - struct LensFlare - { - Vector3 Position; - Vector3 Color; - short RoomNumber; - bool Global; - int SpriteIndex; - }; - - extern std::vector LensFlares; - - void LensFlareControl(short itemNumber); - void ClearLensFlares(); - void SetupLensFlare(Vector3 position, Vector3 color, short roomNumber, bool global, int spriteIndex); - void SetupGlobalLensFlare(Vector2 yawAndPitchInDegrees, Vector3 color, int spriteIndex); -} \ No newline at end of file diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index abfd748a3..5eecfe617 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -75,7 +75,7 @@ void TriggerElectricityWireSparks(int x, int z, byte objNum, byte node, bool glo if (glow) { spark->scalar = 1; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE_LIGHT; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE__LIGHT; spark->size = spark->sSize = (GetRandomControl() & 0x1F) + 160; } else diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index 24770e50b..fdd46a288 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -160,7 +160,7 @@ namespace TEN::Entities::Creatures::TR5 spark->flags = SP_SCALE | SP_DEF; spark->scalar = 3; spark->maxYvel = 0; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE_LIGHT; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE__LIGHT; spark->gravity = 0; spark->dSize = spark->sSize = spark->size = size + (GetRandomControl() & 3); } diff --git a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp index 081e13aa8..d9a9d57b7 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp @@ -65,7 +65,7 @@ namespace TEN::Entities::Creatures::TR5 spark->maxYvel = 0; spark->gravity = 0; spark->scalar = 1; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE_LIGHT; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE__LIGHT; spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 7) + 192; } diff --git a/TombEngine/Objects/objectslist.h b/TombEngine/Objects/objectslist.h index 73f48b3b1..ea4d252d3 100644 --- a/TombEngine/Objects/objectslist.h +++ b/TombEngine/Objects/objectslist.h @@ -32,8 +32,8 @@ template std::enable_if_t std::enable_if_t #include "Renderer/RendererEnums.h" namespace TEN::Renderer::ConstantBuffers { - using namespace DirectX::SimpleMath; - struct alignas(16) ShaderLensFlare { Vector3 Position; @@ -30,4 +27,4 @@ namespace TEN::Renderer::ConstantBuffers //-- int NumLensFlares; }; -} \ No newline at end of file +} diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 9b838b6bf..d7490688d 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2782,6 +2782,9 @@ namespace TEN::Renderer void Renderer::DrawHorizonAndSky(RenderView& renderView, ID3D11DepthStencilView* depthTarget) { + constexpr auto STAR_SIZE = 2; + constexpr auto SUN_SIZE = 64; + auto* levelPtr = g_GameFlow->GetLevel(CurrentLevel); bool anyOutsideRooms = false; @@ -2858,38 +2861,36 @@ namespace TEN::Renderer UINT offset = 0; _context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); - BindTexture(TextureRegister::ColorMap, _sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3].Texture, SamplerStateRegister::LinearClamp); + BindTexture(TextureRegister::ColorMap, _sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_3].Texture, SamplerStateRegister::LinearClamp); int drawnStars = 0; - int starsCount = (int)Weather.GetStars().size(); + int starCount = (int)Weather.GetStars().size(); - while (drawnStars < starsCount) + while (drawnStars < starCount) { - int starsToDraw = (starsCount - drawnStars) > 100 ? 100 : (starsCount - drawnStars); + int starsToDraw = (starCount - drawnStars) > 100 ? 100 : (starCount - drawnStars); int i = 0; for (int i = 0; i < starsToDraw; i++) { - auto& s = Weather.GetStars()[drawnStars + i]; + auto& star = Weather.GetStars()[drawnStars + i]; RendererSpriteToDraw rDrawSprite; - rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; - - constexpr auto STAR_SIZE = 2; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_3]; rDrawSprite.Type = SpriteType::Billboard; - rDrawSprite.pos = renderView.Camera.WorldPosition + s.Direction * BLOCK(1); + rDrawSprite.pos = renderView.Camera.WorldPosition + star.Direction * BLOCK(1); rDrawSprite.Rotation = 0; rDrawSprite.Scale = 1; - rDrawSprite.Width = STAR_SIZE * s.Scale; - rDrawSprite.Height = STAR_SIZE * s.Scale; + rDrawSprite.Width = STAR_SIZE * star.Scale; + rDrawSprite.Height = STAR_SIZE * star.Scale; _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); _stInstancedSpriteBuffer.Sprites[i].Color = Vector4( - s.Color.x, - s.Color.y, - s.Color.z, - s.Blinking * s.Extinction); + star.Color.x, + star.Color.y, + star.Color.z, + star.Blinking * star.Extinction); _stInstancedSpriteBuffer.Sprites[i].IsBillboard = 1; _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; @@ -2916,14 +2917,14 @@ namespace TEN::Renderer if (Weather.GetMeteors().size() > 0) { RendererSpriteToDraw rDrawSprite; - rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENSFLARE3]; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_3]; BindTexture(TextureRegister::ColorMap, rDrawSprite.Sprite->Texture, SamplerStateRegister::LinearClamp); - int meteorsCount = 0; + int meteorCount = 0; for (int i = 0; i < Weather.GetMeteors().size(); i++) { - MeteorParticle meteor = Weather.GetMeteors()[i]; + auto meteor = Weather.GetMeteors()[i]; if (meteor.Active == false) continue; @@ -2938,33 +2939,32 @@ namespace TEN::Renderer rDrawSprite.Height = 192; rDrawSprite.ConstrainAxis = meteor.Direction; - _stInstancedSpriteBuffer.Sprites[meteorsCount].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); - _stInstancedSpriteBuffer.Sprites[meteorsCount].Color = Vector4( + _stInstancedSpriteBuffer.Sprites[meteorCount].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); + _stInstancedSpriteBuffer.Sprites[meteorCount].Color = Vector4( meteor.Color.x, meteor.Color.y, meteor.Color.z, - Lerp(meteor.OldFade, meteor.Fade, _interpolationFactor) - ); - _stInstancedSpriteBuffer.Sprites[meteorsCount].IsBillboard = 1; + Lerp(meteor.OldFade, meteor.Fade, _interpolationFactor)); + _stInstancedSpriteBuffer.Sprites[meteorCount].IsBillboard = 1; _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; // NOTE: Strange packing due to particular HLSL 16 byte alignment requirements. - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].x = rDrawSprite.Sprite->UV[0].x; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].y = rDrawSprite.Sprite->UV[1].x; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].z = rDrawSprite.Sprite->UV[2].x; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[0].w = rDrawSprite.Sprite->UV[3].x; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].x = rDrawSprite.Sprite->UV[0].y; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].y = rDrawSprite.Sprite->UV[1].y; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].z = rDrawSprite.Sprite->UV[2].y; - _stInstancedSpriteBuffer.Sprites[meteorsCount].UV[1].w = rDrawSprite.Sprite->UV[3].y; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].x = rDrawSprite.Sprite->UV[0].x; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].y = rDrawSprite.Sprite->UV[1].x; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].z = rDrawSprite.Sprite->UV[2].x; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].w = rDrawSprite.Sprite->UV[3].x; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].x = rDrawSprite.Sprite->UV[0].y; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].y = rDrawSprite.Sprite->UV[1].y; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].z = rDrawSprite.Sprite->UV[2].y; + _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].w = rDrawSprite.Sprite->UV[3].y; - meteorsCount++; + meteorCount++; } _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); // Draw sprites with instancing. - DrawInstancedTriangles(4, meteorsCount, 0); + DrawInstancedTriangles(4, meteorCount, 0); } _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); @@ -3016,8 +3016,8 @@ namespace TEN::Renderer } } - // Eventually draw the sun sprite - if (renderView.LensFlaresToDraw.size() > 0 && renderView.LensFlaresToDraw[0].Global) + // Eventually draw the sun sprite. + if (!renderView.LensFlaresToDraw.empty() && renderView.LensFlaresToDraw[0].IsGlobal) { SetDepthState(DepthState::Read); SetBlendMode(BlendMode::Additive); @@ -3036,8 +3036,6 @@ namespace TEN::Renderer RendererSpriteToDraw rDrawSprite; rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + renderView.LensFlaresToDraw[0].SpriteIndex]; - constexpr auto SUN_SIZE = 64; - rDrawSprite.Type = SpriteType::Billboard; rDrawSprite.pos = renderView.Camera.WorldPosition + renderView.LensFlaresToDraw[0].Direction * BLOCK(1); rDrawSprite.Rotation = 0; diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 9a59de126..b4c11ea62 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -1,22 +1,22 @@ #include "framework.h" #include "Renderer/Renderer.h" -#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/items.h" #include "Game/Lara/lara.h" -#include "Game/spotcam.h" #include "Game/Setup.h" +#include "Game/spotcam.h" #include "Math/Math.h" -#include "Specific/level.h" +#include "Objects/Effects/LensFlare.h" #include "Renderer/RenderView.h" -#include "Objects/Effects/lens_flare.h" +#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" +#include "Specific/level.h" -using namespace TEN::Math; using namespace TEN::Entities::Effects; +using namespace TEN::Math; namespace TEN::Renderer { @@ -92,8 +92,7 @@ namespace TEN::Renderer } std::sort( - tempFogBulbs.begin(), - tempFogBulbs.end(), + tempFogBulbs.begin(), tempFogBulbs.end(), [](const RendererFogBulb& bulb0, const RendererFogBulb& bulb1) { return bulb0.Distance < bulb1.Distance; @@ -102,55 +101,56 @@ namespace TEN::Renderer for (int i = 0; i < std::min(MAX_FOG_BULBS_DRAW, (int)tempFogBulbs.size()); i++) renderView.FogBulbsToDraw.push_back(tempFogBulbs[i]); - // Collect lens flares - std::vector tempLensFlares; + // Collect lens flares. + auto tempLensFlares = std::vector{}; tempLensFlares.reserve(MAX_LENS_FLARES_DRAW); - for (auto lensFlare : LensFlares) + for (const auto& lensFlare : LensFlares) { - Vector3 lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; - float distance = 0.0f; - if (!lensFlare.Global) - { - distance = lensFlareToCamera.Length(); - } + auto lensFlareToCamera = lensFlare.Position - renderView.Camera.WorldPosition; + + float dist = 0.0f; + if (!lensFlare.IsGlobal) + dist = lensFlareToCamera.Length(); lensFlareToCamera.Normalize(); - Vector3 cameraDirection = renderView.Camera.WorldDirection; - cameraDirection.Normalize(); + auto cameraDir = renderView.Camera.WorldDirection; + cameraDir.Normalize(); - if (lensFlareToCamera.Dot(cameraDirection) >= 0.0f) + if (lensFlareToCamera.Dot(cameraDir) >= 0.0f) { - RendererLensFlare lensFlareToDraw; - + auto lensFlareToDraw = RendererLensFlare{}; lensFlareToDraw.Position = lensFlare.Position; - lensFlareToDraw.Distance = distance; + lensFlareToDraw.Distance = dist; lensFlareToDraw.Color = lensFlare.Color; lensFlareToDraw.SpriteIndex = lensFlare.SpriteIndex; lensFlareToDraw.Direction = lensFlareToCamera; - lensFlareToDraw.Global = lensFlare.Global; + lensFlareToDraw.IsGlobal = lensFlare.IsGlobal; tempLensFlares.push_back(lensFlareToDraw); } } std::sort( - tempLensFlares.begin(), - tempLensFlares.end(), + tempLensFlares.begin(), tempLensFlares.end(), [](const RendererLensFlare& lensFlare0, const RendererLensFlare& lensFlare1) { - if (lensFlare0.Global && !lensFlare1.Global) + if (lensFlare0.IsGlobal && !lensFlare1.IsGlobal) + { return true; - else if (!lensFlare0.Global && lensFlare1.Global) + } + else if (!lensFlare0.IsGlobal && lensFlare1.IsGlobal) + { return false; + } else + { return lensFlare0.Distance < lensFlare1.Distance; + } }); for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++) - { renderView.LensFlaresToDraw.push_back(tempLensFlares[i]); - } } bool Renderer::CheckPortal(short parentRoomNumber, RendererDoor* door, Vector4 viewPort, Vector4* clipPort, RenderView& renderView) diff --git a/TombEngine/Renderer/RendererPostProcess.cpp b/TombEngine/Renderer/RendererPostProcess.cpp index d34e05187..1c00be4a8 100644 --- a/TombEngine/Renderer/RendererPostProcess.cpp +++ b/TombEngine/Renderer/RendererPostProcess.cpp @@ -20,15 +20,15 @@ namespace TEN::Renderer _stPostProcessBuffer.Tint = _postProcessTint; _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get()); - // Common vertex shader to all fullscreen effects + // Common vertex shader to all fullscreen effects. _context->VSSetShader(_vsPostProcess.Get(), nullptr, 0); - // We draw a fullscreen triangle + // Draw fullscreen triangle. _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); _context->IASetInputLayout(_fullscreenTriangleInputLayout.Get()); - UINT stride = sizeof(PostProcessVertex); - UINT offset = 0; + unsigned int stride = sizeof(PostProcessVertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _fullscreenTriangleVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); @@ -41,15 +41,15 @@ namespace TEN::Renderer BindRenderTargetAsTexture(TextureRegister::ColorMap, &_renderTarget, SamplerStateRegister::PointWrap); DrawTriangles(3, 0); - // Let's do ping-pong between the two post-process render targets + // Ping-pong between two post-process render targets. int currentRenderTarget = 0; - int destinationRenderTarget = 1; + int destRenderTarget = 1; - // Apply color scheme + // Apply color scheme. if (_postProcessMode != PostProcessMode::None && _postProcessStrength > EPSILON) { - _context->ClearRenderTargetView(_postProcessRenderTarget[destinationRenderTarget].RenderTargetView.Get(), clearColor); - _context->OMSetRenderTargets(1, _postProcessRenderTarget[destinationRenderTarget].RenderTargetView.GetAddressOf(), nullptr); + _context->ClearRenderTargetView(_postProcessRenderTarget[destRenderTarget].RenderTargetView.Get(), clearColor); + _context->OMSetRenderTargets(1, _postProcessRenderTarget[destRenderTarget].RenderTargetView.GetAddressOf(), nullptr); switch (_postProcessMode) { @@ -72,22 +72,22 @@ namespace TEN::Renderer BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); DrawTriangles(3, 0); - destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; - currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; + destRenderTarget = (destRenderTarget == 1) ? 0 : 1; + currentRenderTarget = (currentRenderTarget == 1) ? 0 : 1; } - // Lens flares - if (view.LensFlaresToDraw.size() > 0) + // Lens flares. + if (!view.LensFlaresToDraw.empty()) { - _context->ClearRenderTargetView(_postProcessRenderTarget[destinationRenderTarget].RenderTargetView.Get(), clearColor); - _context->OMSetRenderTargets(1, _postProcessRenderTarget[destinationRenderTarget].RenderTargetView.GetAddressOf(), nullptr); + _context->ClearRenderTargetView(_postProcessRenderTarget[destRenderTarget].RenderTargetView.Get(), clearColor); + _context->OMSetRenderTargets(1, _postProcessRenderTarget[destRenderTarget].RenderTargetView.GetAddressOf(), nullptr); _context->PSSetShader(_psPostProcessLensFlare.Get(), nullptr, 0); for (int i = 0; i < view.LensFlaresToDraw.size(); i++) { _stPostProcessBuffer.LensFlares[i].Position = view.LensFlaresToDraw[i].Position; - _stPostProcessBuffer.LensFlares[i].Color = view.LensFlaresToDraw[i].Color; + _stPostProcessBuffer.LensFlares[i].Color = view.LensFlaresToDraw[i].Color.ToVector3(); } _stPostProcessBuffer.NumLensFlares = (int)view.LensFlaresToDraw.size(); _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get()); @@ -95,11 +95,11 @@ namespace TEN::Renderer BindRenderTargetAsTexture(TextureRegister::ColorMap, &_postProcessRenderTarget[currentRenderTarget], SamplerStateRegister::PointWrap); DrawTriangles(3, 0); - destinationRenderTarget = destinationRenderTarget == 1 ? 0 : 1; - currentRenderTarget = currentRenderTarget == 1 ? 0 : 1; + destRenderTarget = (destRenderTarget) == 1 ? 0 : 1; + currentRenderTarget = (currentRenderTarget == 1) ? 0 : 1; } - // Do the final pass + // Do final pass. _context->PSSetShader(_psPostProcessFinalPass.Get(), nullptr, 0); _context->ClearRenderTargetView(renderTarget->RenderTargetView.Get(), Colors::Black); diff --git a/TombEngine/Renderer/Structures/RendererLensFlare.h b/TombEngine/Renderer/Structures/RendererLensFlare.h index 1c88d8fb3..a6e6de847 100644 --- a/TombEngine/Renderer/Structures/RendererLensFlare.h +++ b/TombEngine/Renderer/Structures/RendererLensFlare.h @@ -1,18 +1,17 @@ #pragma once -#include #include "Renderer/RendererEnums.h" namespace TEN::Renderer::Structures { - using namespace DirectX::SimpleMath; - struct RendererLensFlare { - Vector3 Position; - Vector3 Color; - Vector3 Direction; - float Distance; - bool Global; - int SpriteIndex; + int SpriteIndex = 0; + + Vector3 Position = Vector3::Zero; + Vector3 Direction = Vector3::Zero; + Color Color = {}; + + float Distance = 0.0f; + bool IsGlobal = false; }; -} \ No newline at end of file +} diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h index d14f4c7b6..2970bd4dc 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h @@ -9,7 +9,7 @@ namespace sol { class state; } struct LensFlare { bool Enabled; - int SunSpriteID = SPR_LENSFLARE3; // Index into sprites + int SunSpriteID = SPR_LENS_FLARE_3; // Index into sprites byte R; byte G; byte B; diff --git a/TombEngine/Specific/RGBAColor8Byte.cpp b/TombEngine/Specific/RGBAColor8Byte.cpp index b627b21e4..15e7003a9 100644 --- a/TombEngine/Specific/RGBAColor8Byte.cpp +++ b/TombEngine/Specific/RGBAColor8Byte.cpp @@ -98,6 +98,11 @@ RGBAColor8Byte::RGBAColor8Byte(Vector4 const& col) : { } +RGBAColor8Byte::operator Color() const +{ + return Color(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b)); +} + RGBAColor8Byte::operator Vector3() const { return Vector3{ ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b) }; diff --git a/TombEngine/Specific/RGBAColor8Byte.h b/TombEngine/Specific/RGBAColor8Byte.h index e89eb7cd3..7c7b63208 100644 --- a/TombEngine/Specific/RGBAColor8Byte.h +++ b/TombEngine/Specific/RGBAColor8Byte.h @@ -12,6 +12,7 @@ public: RGBAColor8Byte(Vector3 const &); RGBAColor8Byte(Vector4 const &); + operator Color() const; operator Vector3() const; operator Vector4() const; operator D3DCOLOR() const; diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 5b8ec1744..24ff002ab 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -442,7 +442,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - + @@ -956,7 +956,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - + From 2eb2ff877d20c98f3be7a3a2705cc384c1d0ae65 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 13:47:47 +1000 Subject: [PATCH 144/410] Starfield and lens flare cleanup --- .../doc/2 classes/Flow.LensFlare.html | 131 +++--- Documentation/doc/2 classes/Flow.Level.html | 28 +- .../doc/2 classes/Flow.Starfield.html | 391 ++++++++++++------ .../doc/2 classes/View.DisplaySprite.html | 2 +- Documentation/doc/index.html | 4 +- TombEngine/Game/control/control.cpp | 4 +- TombEngine/Game/effects/weather.cpp | 137 +++--- TombEngine/Game/effects/weather.h | 48 +-- TombEngine/Objects/Effects/LensFlare.cpp | 24 +- TombEngine/Objects/Effects/LensFlare.h | 6 +- .../Objects/Effects/tr5_electricity.cpp | 2 +- .../Objects/TR5/Entity/tr5_roman_statue.cpp | 2 +- .../Objects/TR5/Entity/tr5_submarine.cpp | 2 +- TombEngine/Objects/objectslist.h | 4 +- TombEngine/Renderer/RendererDraw.cpp | 20 +- TombEngine/Renderer/RendererFrame.cpp | 15 +- .../Renderer/Structures/RendererLensFlare.h | 4 +- .../Scripting/Include/ScriptInterfaceLevel.h | 24 +- .../TEN/DisplaySprite/ScriptDisplaySprite.cpp | 14 +- .../Internal/TEN/Flow/LensFlare/LensFlare.cpp | 173 ++++---- .../Internal/TEN/Flow/LensFlare/LensFlare.h | 51 +-- .../Internal/TEN/Flow/Level/FlowLevel.cpp | 71 ++-- .../Internal/TEN/Flow/Level/FlowLevel.h | 33 +- .../Internal/TEN/Flow/Starfield/Starfield.cpp | 248 ++++++----- .../Internal/TEN/Flow/Starfield/Starfield.h | 58 +-- 25 files changed, 856 insertions(+), 640 deletions(-) diff --git a/Documentation/doc/2 classes/Flow.LensFlare.html b/Documentation/doc/2 classes/Flow.LensFlare.html index 8ae3ca788..574b42065 100644 --- a/Documentation/doc/2 classes/Flow.LensFlare.html +++ b/Documentation/doc/2 classes/Flow.LensFlare.html @@ -102,30 +102,25 @@

    Class Flow.LensFlare

    -

    LensFlare

    +

    Represents a lens flare.

    -

    Members

    -
    ShowString(str, time)ShowString(str, time, autoDelete) Show some text on-screen.
    - - - - - - - - -
    lensFlareColor(Color) RGB lens flare color
    lensFlarePosition(Vec2) Lens flare orientation.

    Functions

    - - + + + + + + + + + +
    LensFlare(yawPitchInDegrees, color) - -LensFlare(Rotation., Color.)Create a LensFlare object.
    LensFlare:GetEnabled()Get the lens flare's enabled status.
    LensFlare:GetObjectID()Get the sun's sprite ID.
    @@ -133,69 +128,31 @@
    -

    Members

    - -
    -
    - - lensFlareColor -
    -
    - (Color) RGB lens flare color - - - - - - - - -
    -
    - - lensFlarePosition -
    -
    - -

    (Vec2) Lens flare orientation.

    - -
        This is the position of the lens flare in the sky. The X value is the horizontal position, and the Y value is the vertical position. Angles must be specified in degrees.
    -
    - - - - - - - - - - -
    -

    Functions

    - LensFlare(yawPitchInDegrees, color) + LensFlare(Rotation., Color.)
    - - - + Create a LensFlare object. ()

    Parameters:

      -
    • yawPitchInDegrees - Vec2 - Position of the lens flare (yaw and pitch) in degrees +
    • Rotation. + Rotation + + +
    • -
    • color +
    • Color. Color - RGB color + + +
    @@ -203,7 +160,49 @@
      LensFlare - A lens flare object. + A new LensFlare object. +
    + + + + +
    +
    + + LensFlare:GetEnabled() +
    +
    + Get the lens flare's enabled status. () + + + + +

    Returns:

    +
      + + bool + Lens flare's enabled status. +
    + + + + +
    +
    + + LensFlare:GetObjectID() +
    +
    + Get the sun's sprite ID. () + + + + +

    Returns:

    +
      + + int + Sprite ID.
    diff --git a/Documentation/doc/2 classes/Flow.Level.html b/Documentation/doc/2 classes/Flow.Level.html index a3309e70d..942ae6163 100644 --- a/Documentation/doc/2 classes/Flow.Level.html +++ b/Documentation/doc/2 classes/Flow.Level.html @@ -108,10 +108,6 @@

    Members

    - - - - @@ -138,11 +134,11 @@ - + - + @@ -208,22 +204,6 @@

    Members

    -
    - - nameKey -
    -
    - (string) string key for the level's (localised) name. - Corresponds to an entry in strings.lua. - - - - - - - - -
    scriptFile @@ -323,7 +303,7 @@ starfield
    - (Flow.Starfield) Starfield + (Flow.Starfield) Starfield. @@ -338,7 +318,7 @@ lensFlare
    - (Flow.LensFlare) Global lens flare + (Flow.LensFlare) Global lens flare . diff --git a/Documentation/doc/2 classes/Flow.Starfield.html b/Documentation/doc/2 classes/Flow.Starfield.html index 9b75c5427..07749c388 100644 --- a/Documentation/doc/2 classes/Flow.Starfield.html +++ b/Documentation/doc/2 classes/Flow.Starfield.html @@ -102,44 +102,61 @@

    Class Flow.Starfield

    -

    Starfield

    +

    Represents a starfield.

    -

    Members

    -
    nameKey(string) string key for the level's (localised) name.
    scriptFile (string) Level-specific Lua script file.
    starfield(Flow.Starfield) Starfield(Flow.Starfield) Starfield.
    lensFlare(Flow.LensFlare) Global lens flare(Flow.LensFlare) Global lens flare .
    fog
    - - - - - - - - - - - - - - - - -
    starsCount(int) Stars count.
    meteorsCount(int) Meteors count.
    meteorsSpawnDensity(int) Meteors spawn density.
    meteorsSpeed(float) Meteors speed.

    Functions

    - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Starfield(starsCount) - -Starfield(starCount)Create a starfield object with only stars.
    Starfield(starsCount, meteorsCount) - -Starfield(starCount, meteorCount)Create a starfield object with stars and meteors.
    Starfield:GetStarsEnabled()Get the starfield's enabled status of stars.
    Starfield:GetMeteorsEnabled()Get the starfield's enabled status of meteors.
    Starfield:GetStarCount()Get the starfield's number of stars.
    Starfield:GetMeteorCount()Get the starfield's number of meteors.
    Starfield:GetMeteorSpawnDensity()Get the starfield's meteor spawn density.
    Starfield:GetMeteorVelocity()Get the starfield's meteor velocity.
    Starfield:SetStarCount(New)Set the starfield's number of stars.
    Starfield:SetMeteorCount(New)Set the starfield's number of meteors.
    Starfield:SetMeteorSpawnDensity(New)Set the starfield's meteor spawn density.
    Starfield:SetMeteorVelocity(New)Set the starfield's meteor velocity.
    @@ -147,101 +164,23 @@
    -

    Members

    - -
    -
    - - starsCount -
    -
    - -

    (int) Stars count.

    - -
        Values can be between [0, 6000], 0 resulting in no stars being rendered, and 6000 resulting in the maximum number of stars being rendered.
    -
    - - - - - - - - - - -
    -
    - - meteorsCount -
    -
    - -

    (int) Meteors count.

    - -
        Values can be between [0, 100], 0 resulting in no meteors being rendered, and 100 resulting in the maximum number of meteors being rendered.
    -
    - - - - - - - - - - -
    -
    - - meteorsSpawnDensity -
    -
    - (int) Meteors spawn density. - - - - - - - - -
    -
    - - meteorsSpeed -
    -
    - (float) Meteors speed. - - - - - - - - -
    -

    Functions

    - Starfield(starsCount) + Starfield(starCount)
    - - - + Create a starfield object with only stars. ()

    Parameters:

      -
    • starsCount +
    • starCount int - Stars count + Star count.
    @@ -249,7 +188,7 @@
      Starfield - A starfield object with only stars enabled. + A new Starfield object.
    @@ -258,24 +197,22 @@
    - Starfield(starsCount, meteorsCount) + Starfield(starCount, meteorCount)
    - - - + Create a starfield object with stars and meteors. ()

    Parameters:

      -
    • starsCount +
    • starCount int - Stars count + Star count.
    • -
    • meteorsCount +
    • meteorCount int - Stars count + Meteor count.
    @@ -283,12 +220,226 @@
      Starfield - A starfield object with boths stars and meteors enabled. + A new Starfield object.
    +
    +
    + + Starfield:GetStarsEnabled() +
    +
    + Get the starfield's enabled status of stars. () + + + + +

    Returns:

    +
      + + bool + Stars enabled status. +
    + + + + +
    +
    + + Starfield:GetMeteorsEnabled() +
    +
    + Get the starfield's enabled status of meteors. () + + + + +

    Returns:

    +
      + + bool + Meteors enabled status. +
    + + + + +
    +
    + + Starfield:GetStarCount() +
    +
    + Get the starfield's number of stars. () + + + + +

    Returns:

    +
      + + int + Count. +
    + + + + +
    +
    + + Starfield:GetMeteorCount() +
    +
    + Get the starfield's number of meteors. () + + + + +

    Returns:

    +
      + + int + Count. +
    + + + + +
    +
    + + Starfield:GetMeteorSpawnDensity() +
    +
    + Get the starfield's meteor spawn density. () + + + + +

    Returns:

    +
      + + int + Spawn density. +
    + + + + +
    +
    + + Starfield:GetMeteorVelocity() +
    +
    + Get the starfield's meteor velocity. () + + + + +

    Returns:

    +
      + + float + Velocity. +
    + + + + +
    +
    + + Starfield:SetStarCount(New) +
    +
    + Set the starfield's number of stars. (int) + + + +

    Parameters:

    +
      +
    • New + int + count. +
    • +
    + + + + + +
    +
    + + Starfield:SetMeteorCount(New) +
    +
    + Set the starfield's number of meteors. (int) + + + +

    Parameters:

    +
      +
    • New + int + count. +
    • +
    + + + + + +
    +
    + + Starfield:SetMeteorSpawnDensity(New) +
    +
    + Set the starfield's meteor spawn density. (int) + + + +

    Parameters:

    +
      +
    • New + int + spawn density. +
    • +
    + + + + + +
    +
    + + Starfield:SetMeteorVelocity(New) +
    +
    + Set the starfield's meteor velocity. (float) + + + +

    Parameters:

    +
      +
    • New + int + velocity. +
    • +
    + + + + +
    diff --git a/Documentation/doc/2 classes/View.DisplaySprite.html b/Documentation/doc/2 classes/View.DisplaySprite.html index f17aabb51..376e1fc4f 100644 --- a/Documentation/doc/2 classes/View.DisplaySprite.html +++ b/Documentation/doc/2 classes/View.DisplaySprite.html @@ -180,7 +180,7 @@ DisplaySprite(ID, int, pos, rot, scale[, color])
    - Create a DisplaySprite object. + Create a DisplaySprite object. () diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index 6ae912f78..3cfe02e63 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -187,7 +187,7 @@ local door = GetMoveableByName("door_type4_14") Flow.LensFlare - LensFlare + Represents a lens flare. Flow.Level @@ -207,7 +207,7 @@ local door = GetMoveableByName("door_type4_14") Flow.Starfield - Starfield + Represents a starfield. Objects.AIObject diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 9a4347a1b..23f028319 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -247,9 +247,9 @@ GameStatus ControlPhase() if (g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareEnabled()) { SetupGlobalLensFlare( - g_GameFlow->GetLevel(CurrentLevel)->GetLensFlarePosition(), + g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareRotation(), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareColor(), - g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSpriteID()); + g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSunSpriteID()); } // Update HUD. diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index 1771554bf..e91a0f546 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -9,14 +9,15 @@ #include "Game/effects/tomb4fx.h" #include "Game/savegame.h" #include "Game/Setup.h" -#include "Math/Random.h" +#include "Math.h" +#include "Objects/game_object_ids.h" #include "Sound/sound.h" -#include "Specific/level.h" #include "Scripting/Include/ScriptInterfaceLevel.h" +#include "Specific/level.h" using namespace TEN::Collision::Point; using namespace TEN::Effects::Ripple; -using namespace TEN::Math::Random; +using namespace TEN::Math; namespace TEN::Effects::Environment { @@ -78,7 +79,7 @@ namespace TEN::Effects::Environment // Clear weather Particles.clear(); - // Clear starfield + // Clear starfield. ResetStarField = true; Meteors.clear(); } @@ -211,33 +212,32 @@ namespace TEN::Effects::Environment void EnvironmentController::UpdateStarfield(ScriptInterfaceLevel* level) { - if (!level->GetStarfieldEnabled()) + if (!level->GetStarfieldStarsEnabled()) return; if (ResetStarField) { - int starsCount = level->GetStarfieldStarsCount(); + int starCount = level->GetStarfieldStarCount(); Stars.clear(); - Stars.reserve(starsCount); + Stars.reserve(starCount); - for (int i = 0; i < starsCount; i++) + for (int i = 0; i < starCount; i++) { - Vector3 starDirection = Random::GenerateDirectionInCone(-Vector3::UnitY, 70.0f); - starDirection.Normalize(); + auto starDir = Random::GenerateDirectionInCone(-Vector3::UnitY, 70.0f); + starDir.Normalize(); - StarParticle star; - star.Direction = starDirection; + auto star = StarParticle{}; + star.Direction = starDir; star.Color = Vector3( Random::GenerateFloat(0.6f, 1.0f), Random::GenerateFloat(0.6f, 1.0f), - Random::GenerateFloat(0.6f, 1.0f) - ); + Random::GenerateFloat(0.6f, 1.0f)); star.Scale = Random::GenerateFloat(0.5f, 1.5f); - float cosine = Vector3::UnitY.Dot(starDirection); - float maxCosine = cos(DEG_TO_RAD(50)); - float minCosine = cos(DEG_TO_RAD(70)); + float cosine = Vector3::UnitY.Dot(starDir); + float maxCosine = cos(DEG_TO_RAD(50.0f)); + float minCosine = cos(DEG_TO_RAD(70.0f)); if (cosine >= minCosine && cosine <= maxCosine) { @@ -254,33 +254,37 @@ namespace TEN::Effects::Environment ResetStarField = false; } - for (auto& s : Stars) - { - s.Blinking = Random::GenerateFloat(0.5f, 1.0f); - } + for (auto& star : Stars) + star.Blinking = Random::GenerateFloat(0.5f, 1.0f); if (level->GetStarfieldMeteorsEnabled()) { - for (auto& m : Meteors) + for (auto& meteor : Meteors) { - m.Life--; + meteor.Life--; - if (m.Life <= 0) + if (meteor.Life <= 0) { - m.Active = false; + meteor.Active = false; continue; } - m.StoreInterpolationData(); + meteor.StoreInterpolationData(); - if (m.Life <= METEOR_PARTICLES_FADE_TIME) - m.Fade = m.Life / (float)METEOR_PARTICLES_FADE_TIME; - else if (m.Life >= METEOR_PARTICLES_MAX_LIFE - METEOR_PARTICLES_FADE_TIME) - m.Fade = (METEOR_PARTICLES_MAX_LIFE - m.Life) / (float)METEOR_PARTICLES_FADE_TIME; + if (meteor.Life <= METEOR_PARTICLE_FADE_TIME) + { + meteor.Fade = meteor.Life / METEOR_PARTICLE_FADE_TIME; + } + else if (meteor.Life >= METEOR_PARTICLE_LIFE_MAX - METEOR_PARTICLE_FADE_TIME) + { + meteor.Fade = (METEOR_PARTICLE_LIFE_MAX - meteor.Life) / METEOR_PARTICLE_FADE_TIME; + } else - m.Fade = 1.0f; + { + meteor.Fade = 1.0f; + } - m.Position += m.Direction * level->GetStarfieldMeteorsSpeed(); + meteor.Position += meteor.Direction * level->GetStarfieldMeteorVelocity(); } } } @@ -422,14 +426,14 @@ namespace TEN::Effects::Environment case WeatherType::Snow: if (p.Velocity.x < (WindX << 2)) - p.Velocity.x += GenerateFloat(0.5f, 2.5f); + p.Velocity.x += Random::GenerateFloat(0.5f, 2.5f); else if (p.Velocity.x > (WindX << 2)) - p.Velocity.x -= GenerateFloat(0.5f, 2.5f); + p.Velocity.x -= Random::GenerateFloat(0.5f, 2.5f); if (p.Velocity.z < (WindZ << 2)) - p.Velocity.z += GenerateFloat(0.5f, 2.5f); + p.Velocity.z += Random::GenerateFloat(0.5f, 2.5f); else if (p.Velocity.z > (WindZ << 2)) - p.Velocity.z -= GenerateFloat(0.5f, 2.5f); + p.Velocity.z -= Random::GenerateFloat(0.5f, 2.5f); if (p.Velocity.y < p.Size / 2) p.Velocity.y += p.Size / 5.0f; @@ -438,7 +442,7 @@ namespace TEN::Effects::Environment case WeatherType::Rain: - auto random = GenerateInt(); + auto random = Random::GenerateInt(); if ((random & 3) != 3) { p.Velocity.x += (float)((random & 3) - 1); @@ -489,10 +493,10 @@ namespace TEN::Effects::Environment part.Velocity = Random::GenerateDirection() * MAX_DUST_SPEED; - part.Size = GenerateFloat(MAX_DUST_SIZE / 2, MAX_DUST_SIZE); + part.Size = Random::GenerateFloat(MAX_DUST_SIZE / 2, MAX_DUST_SIZE); part.Type = WeatherType::None; - part.Life = DUST_LIFE + GenerateInt(-10, 10); + part.Life = DUST_LIFE + Random::GenerateInt(-10, 10); part.Room = roomNumber; part.Position.x = xPos; part.Position.y = yPos; @@ -531,12 +535,12 @@ namespace TEN::Effects::Environment newParticlesCount++; auto distance = level->GetWeatherType() == WeatherType::Snow ? COLLISION_CHECK_DISTANCE : COLLISION_CHECK_DISTANCE / 2; - auto radius = GenerateInt(0, distance); - short angle = GenerateInt(ANGLE(0), ANGLE(180)); + auto radius = Random::GenerateInt(0, distance); + short angle = Random::GenerateInt(ANGLE(0), ANGLE(180)); auto xPos = Camera.pos.x + ((int)(phd_cos(angle) * radius)); auto zPos = Camera.pos.z + ((int)(phd_sin(angle) * radius)); - auto yPos = Camera.pos.y - (BLOCK(4) + GenerateInt() & (BLOCK(4) - 1)); + auto yPos = Camera.pos.y - (BLOCK(4) + Random::GenerateInt() & (BLOCK(4) - 1)); auto outsideRoom = IsRoomOutside(xPos, yPos, zPos); @@ -556,20 +560,20 @@ namespace TEN::Effects::Environment switch (level->GetWeatherType()) { case WeatherType::Snow: - part.Size = GenerateFloat(MAX_SNOW_SIZE / 3, MAX_SNOW_SIZE); - part.Velocity.y = GenerateFloat(MAX_SNOW_SPEED / 4, MAX_SNOW_SPEED) * (part.Size / MAX_SNOW_SIZE); + part.Size = Random::GenerateFloat(MAX_SNOW_SIZE / 3, MAX_SNOW_SIZE); + part.Velocity.y = Random::GenerateFloat(MAX_SNOW_SPEED / 4, MAX_SNOW_SPEED) * (part.Size / MAX_SNOW_SIZE); part.Life = (MAX_SNOW_SPEED / 3) + ((MAX_SNOW_SPEED / 2) - ((int)part.Velocity.y >> 2)); break; case WeatherType::Rain: - part.Size = GenerateFloat(MAX_RAIN_SIZE / 2, MAX_RAIN_SIZE); - part.Velocity.y = GenerateFloat(MAX_RAIN_SPEED / 2, MAX_RAIN_SPEED) * (part.Size / MAX_RAIN_SIZE) * std::clamp(level->GetWeatherStrength(), 0.6f, 1.0f); + part.Size = Random::GenerateFloat(MAX_RAIN_SIZE / 2, MAX_RAIN_SIZE); + part.Velocity.y = Random::GenerateFloat(MAX_RAIN_SPEED / 2, MAX_RAIN_SPEED) * (part.Size / MAX_RAIN_SIZE) * std::clamp(level->GetWeatherStrength(), 0.6f, 1.0f); part.Life = (MAX_RAIN_SPEED * 2) - part.Velocity.y; break; } - part.Velocity.x = GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_SPEED / 2, WEATHER_PARTICLE_HORIZONTAL_SPEED); - part.Velocity.z = GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_SPEED / 2, WEATHER_PARTICLE_HORIZONTAL_SPEED); + part.Velocity.x = Random::GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_SPEED / 2, WEATHER_PARTICLE_HORIZONTAL_SPEED); + part.Velocity.z = Random::GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_SPEED / 2, WEATHER_PARTICLE_HORIZONTAL_SPEED); part.Type = level->GetWeatherType(); part.Room = outsideRoom; @@ -588,40 +592,45 @@ namespace TEN::Effects::Environment void EnvironmentController::SpawnMeteorParticles(ScriptInterfaceLevel* level) { - // Clean up dead particles - if (Meteors.size() > 0) - Meteors.erase(std::remove_if(Meteors.begin(), Meteors.end(), [](const MeteorParticle& part) { return !part.Active; }), Meteors.end()); + // Clean up dead particles. + if (!Meteors.empty()) + { + Meteors.erase( + std::remove_if( + Meteors.begin(), Meteors.end(), + [](const MeteorParticle& part) + { + return !part.Active; + }), + Meteors.end()); + } if (!level->GetStarfieldMeteorsEnabled()) return; - int newParticlesCount = 0; - int density = level->GetStarfieldMeteorsSpawnDensity(); - int meteorsCount = level->GetStarfieldMeteorsCount(); - + int density = level->GetStarfieldMeteorSpawnDensity(); if (density > 0) { - while (Meteors.size() < meteorsCount) + for (int i = 0; i < level->GetStarfieldMeteorCount(); i++) { - if (newParticlesCount > density) + if (i > density) break; - newParticlesCount++; + auto horizontalDir = Random::GenerateDirection2D(); auto part = MeteorParticle(); part.Active = true; - part.Life = METEOR_PARTICLES_MAX_LIFE; - part.StartPosition = part.Position = Random::GenerateDirectionInCone(-Vector3::UnitY, 40.0f) * BLOCK(1.5f); + part.Life = METEOR_PARTICLE_LIFE_MAX; + part.StartPosition = + part.Position = Random::GenerateDirectionInCone(-Vector3::UnitY, 40.0f) * BLOCK(1.5f); part.Fade = 0.0f; part.Color = Vector3( Random::GenerateFloat(0.6f, 1.0f), Random::GenerateFloat(0.6f, 1.0f), - Random::GenerateFloat(0.6f, 1.0f) - ); + Random::GenerateFloat(0.6f, 1.0f)); - Vector2 horizontalDirection = Random::GenerateDirection2D(); - part.Direction = Random::GenerateDirectionInCone(Vector3(horizontalDirection.x, 0, horizontalDirection.y), 10.0f); + part.Direction = Random::GenerateDirectionInCone(Vector3(horizontalDir.x, 0, horizontalDir.y), 10.0f); if (part.Direction.y < 0.0f) part.Direction.y = -part.Direction.y; diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index 677ef175b..15ff5452f 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -28,39 +28,41 @@ namespace TEN::Effects::Environment constexpr auto DUST_LIFE = 40; constexpr auto DUST_SPAWN_RADIUS = (10 * 1024); - constexpr auto METEOR_PARTICLES_MAX_COUNT = 10; - constexpr auto METEOR_PARTICLES_MAX_LIFE = 150; - constexpr auto METEOR_PARTICLES_SPEED = 32.0f; - constexpr auto METEOR_PARTICLES_SPAWN_DENSITY = 4; - constexpr auto METEOR_PARTICLES_FADE_TIME = 30; + constexpr auto METEOR_PARTICLE_COUNT_MAX = 10; + constexpr auto METEOR_PARTICLE_LIFE_MAX = 150; + constexpr auto METEOR_PARTICLE_VELOCITY = 32.0f; + constexpr auto METEOR_PARTICLE_SPAWN_DENSITY = 4; + constexpr auto METEOR_PARTICLE_FADE_TIME = 30.0f; struct StarParticle { - Vector3 Position = Vector3::Zero; + Vector3 Position = Vector3::Zero; Vector3 Direction = Vector3::Zero; - Vector3 Color = Vector3::Zero; + Vector3 Color = Vector3::Zero; + float Extinction = 1.0f; - float Scale = 1.0f; - float Blinking = 1.0f; + float Scale = 1.0f; + float Blinking = 1.0f; }; struct MeteorParticle { - Vector3 Position = Vector3::Zero; - Vector3 Direction = Vector3::Zero; + Vector3 Position = Vector3::Zero; + Vector3 Direction = Vector3::Zero; Vector3 StartPosition = Vector3::Zero; - Vector3 Color = Vector3::Zero; - float Life; - bool Active; - float Fade; + Vector3 Color = Vector3::Zero; - Vector3 OldPosition = Vector3::Zero; - float OldFade = 0.0f; + bool Active = false; + float Life = 0.0f; + float Fade = 0.0f; + + Vector3 PrevPosition = Vector3::Zero; + float PrevFade = 0.0f; void StoreInterpolationData() { - OldPosition = Position; - OldFade = Fade; + PrevPosition = Position; + PrevFade = Fade; } }; @@ -68,7 +70,7 @@ namespace TEN::Effects::Environment { WeatherType Type = WeatherType::None; - int Room = -1; + int Room = NO_VALUE; Vector3 Position = Vector3::Zero; Vector3 Velocity = Vector3::Zero; @@ -142,12 +144,12 @@ namespace TEN::Effects::Environment byte StormSkyColor2 = 1; // Starfield - std::vector Stars; - std::vector Meteors; + std::vector Stars = {}; + std::vector Meteors = {}; bool ResetStarField = true; // Lens flare - LensFlare GlobalLensFlare; + LensFlare GlobalLensFlare = {}; void UpdateStarfield(ScriptInterfaceLevel* level); void UpdateSky(ScriptInterfaceLevel* level); diff --git a/TombEngine/Objects/Effects/LensFlare.cpp b/TombEngine/Objects/Effects/LensFlare.cpp index 8f320e137..080605a63 100644 --- a/TombEngine/Objects/Effects/LensFlare.cpp +++ b/TombEngine/Objects/Effects/LensFlare.cpp @@ -3,13 +3,16 @@ #include "Game/camera.h" #include "Game/control/los.h" +#include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Math; + namespace TEN::Entities::Effects { std::vector LensFlares; - static void SetupLensFlare(const Vector3& pos, int roomNumber, const Color& color, bool isGlobal, int spriteIndex) + static void SetupLensFlare(const Vector3& pos, int roomNumber, const Color& color, bool isGlobal, int spriteID) { auto lensFlarePos = Vector3::Zero; if (isGlobal) @@ -67,7 +70,7 @@ namespace TEN::Entities::Effects lensFlare.RoomNumber = roomNumber; lensFlare.IsGlobal = isGlobal; lensFlare.Color = color; - lensFlare.SpriteIndex = spriteIndex; + lensFlare.SpriteID = spriteID; LensFlares.push_back(lensFlare); } @@ -77,7 +80,7 @@ namespace TEN::Entities::Effects auto& item = g_Level.Items[itemNumber]; if (TriggerActive(&item)) - SetupLensFlare(item.Pose.Position.ToVector3(), item.RoomNumber, Color(), false, SPR_LENS_FLARE_3); + SetupLensFlare(item.Pose.Position.ToVector3(), item.RoomNumber, Color(), false, SPRITE_TYPES::SPR_LENS_FLARE_3); } void ClearLensFlares() @@ -85,15 +88,14 @@ namespace TEN::Entities::Effects LensFlares.clear(); } - void SetupGlobalLensFlare(const Vector2& yawAndPitchInDegrees, const Color& color, int spriteIndex) + void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID) { - auto pos = Camera.pos.ToVector3(); - auto rotMatrix = Matrix::CreateFromYawPitchRoll( - DEG_TO_RAD(yawAndPitchInDegrees.x), - DEG_TO_RAD(yawAndPitchInDegrees.y), - 0.0f); + constexpr auto BASE_POS = Vector3(0.0f, 0.0f, BLOCK(256)); - pos += Vector3::Transform(Vector3(0.0f, 0.0f, BLOCK(256)), rotMatrix); - SetupLensFlare(pos, NO_VALUE, color, true, spriteIndex); + auto pos = Camera.pos.ToVector3(); + auto rotMatrix = orient.ToRotationMatrix(); + + pos += Vector3::Transform(BASE_POS, rotMatrix); + SetupLensFlare(pos, NO_VALUE, color, true, spriteID); } } diff --git a/TombEngine/Objects/Effects/LensFlare.h b/TombEngine/Objects/Effects/LensFlare.h index 6beca5e52..be1e88f8f 100644 --- a/TombEngine/Objects/Effects/LensFlare.h +++ b/TombEngine/Objects/Effects/LensFlare.h @@ -1,10 +1,12 @@ #pragma once +class EulerAngles; + namespace TEN::Entities::Effects { struct LensFlare { - int SpriteIndex = 0; + int SpriteID = 0; Vector3 Position = Vector3::Zero; int RoomNumber = 0; @@ -17,5 +19,5 @@ namespace TEN::Entities::Effects void ControlLensFlare(int itemNumber); void ClearLensFlares(); - void SetupGlobalLensFlare(const Vector2& yawAndPitchInDegrees, const Color& color, int spriteIndex); + void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID); } diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index 5eecfe617..26774f4e1 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -75,7 +75,7 @@ void TriggerElectricityWireSparks(int x, int z, byte objNum, byte node, bool glo if (glow) { spark->scalar = 1; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE__LIGHT; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_LIGHT; spark->size = spark->sSize = (GetRandomControl() & 0x1F) + 160; } else diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index fdd46a288..87ad99739 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -160,7 +160,7 @@ namespace TEN::Entities::Creatures::TR5 spark->flags = SP_SCALE | SP_DEF; spark->scalar = 3; spark->maxYvel = 0; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE__LIGHT; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_LIGHT; spark->gravity = 0; spark->dSize = spark->sSize = spark->size = size + (GetRandomControl() & 3); } diff --git a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp index d9a9d57b7..04a4b4ed3 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_submarine.cpp @@ -65,7 +65,7 @@ namespace TEN::Entities::Creatures::TR5 spark->maxYvel = 0; spark->gravity = 0; spark->scalar = 1; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE__LIGHT; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_LIGHT; spark->dSize = spark->sSize = spark->size = (GetRandomControl() & 7) + 192; } diff --git a/TombEngine/Objects/objectslist.h b/TombEngine/Objects/objectslist.h index ea4d252d3..267bbfb7a 100644 --- a/TombEngine/Objects/objectslist.h +++ b/TombEngine/Objects/objectslist.h @@ -32,8 +32,8 @@ template std::enable_if_tPSSetShader(_psInstancedSprites.Get(), nullptr, 0); // Set up vertex buffer and parameters. - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); - RendererSpriteToDraw rDrawSprite; - rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + renderView.LensFlaresToDraw[0].SpriteIndex]; + auto rDrawSprite = RendererSpriteToDraw{}; + rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + renderView.LensFlaresToDraw[0].SpriteID]; rDrawSprite.Type = SpriteType::Billboard; rDrawSprite.pos = renderView.Camera.WorldPosition + renderView.LensFlaresToDraw[0].Direction * BLOCK(1); - rDrawSprite.Rotation = 0; - rDrawSprite.Scale = 1; + rDrawSprite.Rotation = 0.0f; + rDrawSprite.Scale = 1.0f; rDrawSprite.Width = SUN_SIZE; rDrawSprite.Height = SUN_SIZE; @@ -3081,7 +3081,7 @@ namespace TEN::Renderer { //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); - // Interpolate camera + // Interpolate camera. _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolationFactor); _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolationFactor); _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolationFactor); @@ -3142,9 +3142,7 @@ namespace TEN::Renderer for (auto& bucket : mesh->Buckets) { if (bucket.NumVertices == 0) - { continue; - } if (rendererPass == RendererPass::ShadowMap) { diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index b4c11ea62..8014cb3e2 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -123,7 +123,7 @@ namespace TEN::Renderer lensFlareToDraw.Position = lensFlare.Position; lensFlareToDraw.Distance = dist; lensFlareToDraw.Color = lensFlare.Color; - lensFlareToDraw.SpriteIndex = lensFlare.SpriteIndex; + lensFlareToDraw.SpriteID = lensFlare.SpriteID; lensFlareToDraw.Direction = lensFlareToCamera; lensFlareToDraw.IsGlobal = lensFlare.IsGlobal; @@ -136,17 +136,12 @@ namespace TEN::Renderer [](const RendererLensFlare& lensFlare0, const RendererLensFlare& lensFlare1) { if (lensFlare0.IsGlobal && !lensFlare1.IsGlobal) - { return true; - } - else if (!lensFlare0.IsGlobal && lensFlare1.IsGlobal) - { + + if (!lensFlare0.IsGlobal && lensFlare1.IsGlobal) return false; - } - else - { - return lensFlare0.Distance < lensFlare1.Distance; - } + + return (lensFlare0.Distance < lensFlare1.Distance); }); for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++) diff --git a/TombEngine/Renderer/Structures/RendererLensFlare.h b/TombEngine/Renderer/Structures/RendererLensFlare.h index a6e6de847..1fa9edfdd 100644 --- a/TombEngine/Renderer/Structures/RendererLensFlare.h +++ b/TombEngine/Renderer/Structures/RendererLensFlare.h @@ -1,11 +1,11 @@ #pragma once #include "Renderer/RendererEnums.h" - + namespace TEN::Renderer::Structures { struct RendererLensFlare { - int SpriteIndex = 0; + int SpriteID = 0; Vector3 Position = Vector3::Zero; Vector3 Direction = Vector3::Zero; diff --git a/TombEngine/Scripting/Include/ScriptInterfaceLevel.h b/TombEngine/Scripting/Include/ScriptInterfaceLevel.h index 1302d22d7..b96635db7 100644 --- a/TombEngine/Scripting/Include/ScriptInterfaceLevel.h +++ b/TombEngine/Scripting/Include/ScriptInterfaceLevel.h @@ -48,14 +48,18 @@ public: virtual int GetSecrets() const = 0; virtual std::string GetAmbientTrack() const = 0; virtual bool GetResetHubEnabled() const = 0; - virtual bool GetLensFlareEnabled() const = 0; - virtual Vector2 GetLensFlarePosition() const = 0; - virtual RGBAColor8Byte GetLensFlareColor() const = 0; - virtual int GetLensFlareSpriteID() const = 0; - virtual bool GetStarfieldEnabled() const = 0; - virtual bool GetStarfieldMeteorsEnabled() const = 0; - virtual int GetStarfieldStarsCount() const = 0; - virtual int GetStarfieldMeteorsCount() const = 0; - virtual int GetStarfieldMeteorsSpawnDensity() const = 0; - virtual float GetStarfieldMeteorsSpeed() const = 0; + + // Lens flare getters + virtual bool GetLensFlareEnabled() const = 0; + virtual int GetLensFlareSunSpriteID() const = 0; + virtual EulerAngles GetLensFlareRotation() const = 0; + virtual Color GetLensFlareColor() const = 0; + + // Starfield getters + virtual bool GetStarfieldStarsEnabled() const = 0; + virtual bool GetStarfieldMeteorsEnabled() const = 0; + virtual int GetStarfieldStarCount() const = 0; + virtual int GetStarfieldMeteorCount() const = 0; + virtual int GetStarfieldMeteorSpawnDensity() const = 0; + virtual float GetStarfieldMeteorVelocity() const = 0; }; diff --git a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp index 63de5efcf..7b241639d 100644 --- a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp +++ b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp @@ -12,12 +12,10 @@ using TEN::Renderer::g_Renderer; -/*** -Represents a display sprite. - -@tenclass View.DisplaySprite -@pragma nostrip -*/ +/// Represents a display sprite. +// +// @tenclass View.DisplaySprite +// @pragma nostrip namespace TEN::Scripting::DisplaySprite { @@ -50,7 +48,7 @@ namespace TEN::Scripting::DisplaySprite } /// Create a DisplaySprite object. - // @function DisplaySprite + // @function DisplaySprite() // @tparam Objects.ObjID ID of the sprite sequence object. // @tparam int int spriteID ID of the sprite in the sequence. // @tparam Vec2 pos Display position in percent. @@ -190,7 +188,7 @@ namespace TEN::Scripting::DisplaySprite constexpr auto DEFAULT_SCALE_MODE = DisplaySpriteScaleMode::Fit; constexpr auto DEFAULT_BLEND_MODE = BlendMode::AlphaBlend; - // Object is not a sprite sequence object; return early. + // Object is not a sprite sequence; return early. if (_objectID < GAME_OBJECT_ID::ID_HORIZON || _objectID >= GAME_OBJECT_ID::ID_NUMBER_OBJECTS) { TENLog("Attempted to draw display sprite from non-sprite sequence object " + std::to_string(_objectID), LogLevel::Warning); diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp index 690e1a214..aab754268 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp @@ -1,85 +1,108 @@ #include "framework.h" -#include "LensFlare.h" -#include +#include "Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h" -/*** -LensFlare +#include "Objects/game_object_ids.h" +#include "Scripting/Internal/TEN/Rotation/Rotation.h" +#include "Specific\level.h" -@tenclass Flow.LensFlare -@pragma nostrip -*/ +/// Represents a lens flare. +// +// @tenclass Flow.LensFlare +// @pragma nostrip -void LensFlare::Register(sol::table& parent) +namespace TEN::Scripting { - using ctors = sol::constructors; - parent.new_usertype("LensFlare", - ctors(), - sol::call_constructor, ctors(), + void LensFlare::Register(sol::table& parent) + { + using ctors = sol::constructors< + LensFlare(const Rotation& rot, const ScriptColor& color)>; - /// (@{Color}) RGB lens flare color - //@mem lensFlareColor - "color", sol::property(&LensFlare::GetColor, &LensFlare::SetColor), + // Register type. + parent.new_usertype( + "LensFlare", + ctors(), + sol::call_constructor, ctors(), - /*** (@{Vec2}) Lens flare orientation. + "GetEnabled", &LensFlare::GetEnabled, + "GetSunSpriteID", &LensFlare::GetSunSpriteID, + "GetRotation", &LensFlare::GetRotation, + "GetColor", &LensFlare::GetColor, + "SetSunSpriteID", &LensFlare::SetSunSpriteID, + "SetRotation", &LensFlare::SetRotation, + "SetColor", &LensFlare::SetColor); + } - This is the position of the lens flare in the sky. The X value is the horizontal position, and the Y value is the vertical position. Angles must be specified in degrees. + /// Create a LensFlare object. + // @function LensFlare() + // @tparam Rotation Rotation. + // @tparam Color Color. + // @treturn LensFlare A new LensFlare object. + LensFlare::LensFlare(const Rotation& rot, const ScriptColor& color) + { + _isEnabled = true; + _color = color; + _rotation = rot; + } - @mem lensFlarePosition*/ - "position", sol::property(&LensFlare::GetPosition, &LensFlare::SetPosition) - ); + /// Get the lens flare's enabled status. + // @function LensFlare:GetEnabled() + // @treturn bool Lens flare's enabled status. + bool LensFlare::GetEnabled() const + { + return _isEnabled; + } + + /// Get the sun's sprite ID. + // @function LensFlare:GetObjectID() + // @treturn int Sprite ID. + int LensFlare::GetSunSpriteID() const + { + return _sunSpriteID; + } + + // Get the lens flare's euler rotation. + // @function LensFlare:GetRotation() + // @treturn Rotation Rotation. + Rotation LensFlare::GetRotation() const + { + return _rotation; + } + + // Get the lens flare's color. + // @function LensFlare:SetColor() + ScriptColor LensFlare::GetColor() const + { + return _color; + } + + // Set the lens flare's sun sprite ID. + // @function LensFlare:SetSunbjectID() + // @tparam int New sprite ID. + void LensFlare::SetSunSpriteID(int spriteID) + { + // Sprite ID out of range; return early. + if (spriteID < 0 || g_Level.Sprites.size() > spriteID) + { + TENLog("Sub sprite ID out of range."); + return; + } + + _sunSpriteID = spriteID; + } + + // Set the lens flare's euler rotation. + // @function LensFlare:SetRotation(Rotation) + // @tparam Rotation New euler rotation. + void LensFlare::SetRotation(const Rotation& rot) + { + _rotation = rot; + } + + // Set the lens flare's color. + // @function LensFlare:SetColor(Color) + // @tparam Color New color. + void LensFlare::SetColor(const ScriptColor& color) + { + _color = color; + } } - -/*** -@tparam Vec2 yawPitchInDegrees Position of the lens flare (yaw and pitch) in degrees -@tparam Color color RGB color -@treturn LensFlare A lens flare object. -@function LensFlare -*/ -LensFlare::LensFlare(Vec2 const& yawPitchInDegrees, ScriptColor const& col) -{ - SetColor(col); - SetPosition(yawPitchInDegrees); - Enabled = true; -} - -void LensFlare::SetColor(ScriptColor const& col) -{ - R = col.GetR(); - G = col.GetG(); - B = col.GetB(); -} - - -ScriptColor LensFlare::GetColor() const -{ - return ScriptColor{ R, G, B }; -} - -void LensFlare::SetPosition(Vec2 const& yawPitchInDegrees) -{ - Yaw = yawPitchInDegrees.x; - Pitch = yawPitchInDegrees.y; -} - - -Vec2 LensFlare::GetPosition() const -{ - return Vec2{ Yaw, Pitch }; -} - -bool LensFlare::GetEnabled() const -{ - return Enabled; -} - -void LensFlare::SetSunSpriteID(int const& spriteIndex) -{ - assertion(spriteIndex >= 0 && spriteIndex < g_Level.Sprites.size(), "Sprite Index must be in a valid range"); - - SunSpriteID = spriteIndex; -} - -int LensFlare::GetSunSpriteID() const -{ - return SunSpriteID; -} \ No newline at end of file diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h index 2970bd4dc..8b034b9f0 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h @@ -1,34 +1,39 @@ #pragma once - -#include "Scripting/Internal/TEN/Color/Color.h" -#include "Scripting/Internal/TEN/Vec2/Vec2.h" +#include "Objects/game_object_ids.h" #include "Objects/objectslist.h" +#include "Scripting/Internal/TEN/Color/Color.h" +#include "Scripting/Internal/TEN/Rotation/Rotation.h" namespace sol { class state; } -struct LensFlare +namespace TEN::Scripting { - bool Enabled; - int SunSpriteID = SPR_LENS_FLARE_3; // Index into sprites - byte R; - byte G; - byte B; - float Yaw; - float Pitch; + class LensFlare + { + private: + // Members + int _sunSpriteID = SPRITE_TYPES::SPR_LENS_FLARE_3; + bool _isEnabled; - LensFlare() = default; - LensFlare(Vec2 const& yawPitchInDegrees, ScriptColor const& col); + Rotation _rotation = {}; + ScriptColor _color = 0; - void SetColor(ScriptColor const& color); - ScriptColor GetColor() const; + public: + static void Register(sol::table& table); - void SetPosition(Vec2 const& yawPitchInDegrees); - Vec2 GetPosition() const; + // Constructors + LensFlare() = default; + LensFlare(const Rotation& rot, const ScriptColor& color); - void SetSunSpriteID(int const& spriteIndex); - int GetSunSpriteID() const; + // Getters + bool GetEnabled() const; + int GetSunSpriteID() const; + Rotation GetRotation() const; + ScriptColor GetColor() const; - bool GetEnabled() const; - - static void Register(sol::table&); -}; \ No newline at end of file + // Setters + void SetSunSpriteID(int spriteID); + void SetRotation(const Rotation& rot); + void SetColor(const ScriptColor& color); + }; +} diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp index 919174fdd..2f419cf1d 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp @@ -1,7 +1,10 @@ #include "framework.h" -#include "FlowLevel.h" +#include "Scripting/Internal/TEN/Flow/Level/FlowLevel.h" + #include "Scripting/Internal/ScriptAssert.h" +using namespace TEN::Scripting; + /*** Stores level metadata. These are things things which aren't present in the compiled level file itself. @@ -15,12 +18,14 @@ These are things things which aren't present in the compiled level file itself. @treturn Level a Level object */ void Level::Register(sol::table& parent) -{ - parent.new_usertype("Level", +{ + // Register type. + parent.new_usertype( + "Level", sol::constructors(), sol::call_constructor, sol::constructors(), -/// (string) string key for the level's (localised) name. -// Corresponds to an entry in strings.lua. + + // Corresponds to an entry in strings.lua. //@mem nameKey "nameKey", &Level::NameStringKey, @@ -52,13 +57,13 @@ void Level::Register(sol::table& parent) //@mem layer2 "layer2", &Level::Layer2, -/// (@{Flow.Starfield}) Starfield -//@mem starfield - "starfield", & Level::Starfield, + /// (@{Flow.Starfield}) Starfield. + // @mem starfield + "starfield", &Level::Starfield, -/// (@{Flow.LensFlare}) Global lens flare -//@mem lensFlare - "lensFlare", & Level::LensFlare, + /// (@{Flow.LensFlare}) Global lens flare . + // @mem lensFlare + "lensFlare", &Level::LensFlare, /// (@{Flow.Fog}) omni fog RGB color and distance. // As seen in TR4's Desert Railroad. @@ -291,24 +296,24 @@ bool Level::GetLensFlareEnabled() const return LensFlare.GetEnabled(); } -Vector2 Level::GetLensFlarePosition() const -{ - return LensFlare.GetPosition(); -} - -RGBAColor8Byte Level::GetLensFlareColor() const -{ - return LensFlare.GetColor(); -} - -int Level::GetLensFlareSpriteID() const +int Level::GetLensFlareSunSpriteID() const { return LensFlare.GetSunSpriteID(); } -bool Level::GetStarfieldEnabled() const +EulerAngles Level::GetLensFlareRotation() const { - return Starfield.GetEnabled(); + return LensFlare.GetRotation().ToEulerAngles(); +} + +Color Level::GetLensFlareColor() const +{ + return LensFlare.GetColor(); +} + +bool Level::GetStarfieldStarsEnabled() const +{ + return Starfield.GetStarsEnabled(); } bool Level::GetStarfieldMeteorsEnabled() const @@ -316,22 +321,22 @@ bool Level::GetStarfieldMeteorsEnabled() const return Starfield.GetMeteorsEnabled(); } -int Level::GetStarfieldStarsCount() const +int Level::GetStarfieldStarCount() const { - return Starfield.GetStarsCount(); + return Starfield.GetStarCount(); } -int Level::GetStarfieldMeteorsCount() const +int Level::GetStarfieldMeteorCount() const { - return Starfield.GetMeteorsCount(); + return Starfield.GetMeteorCount(); } -int Level::GetStarfieldMeteorsSpawnDensity() const +int Level::GetStarfieldMeteorSpawnDensity() const { - return Starfield.GetMeteorsSpawnDensity(); + return Starfield.GetMeteorSpawnDensity(); } -float Level::GetStarfieldMeteorsSpeed() const +float Level::GetStarfieldMeteorVelocity() const { - return Starfield.GetMeteorsSpeed(); -} \ No newline at end of file + return Starfield.GetMeteorVelocity(); +} diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h index 0460e6a9b..4b8610f5c 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h @@ -1,5 +1,4 @@ #pragma once -#include #include "Scripting/Internal/TEN/Flow/SkyLayer/SkyLayer.h" #include "Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h" #include "Scripting/Internal/TEN/Flow/Starfield/Starfield.h" @@ -8,6 +7,8 @@ #include "Scripting/Include/ScriptInterfaceLevel.h" #include "Scripting/Internal/TEN/Flow/InventoryItem/InventoryItem.h" +using namespace TEN::Scripting; + static const std::unordered_map WEATHER_TYPES { { "None", WeatherType::None }, @@ -34,8 +35,8 @@ struct Level : public ScriptInterfaceLevel int LevelFarView = 0; std::string AmbientTrack = {}; - LensFlare LensFlare = {}; - Starfield Starfield = {}; + LensFlare LensFlare = {}; + Starfield Starfield = {}; WeatherType Weather = WeatherType::None; float WeatherStrength = 1.0f; @@ -47,6 +48,8 @@ struct Level : public ScriptInterfaceLevel bool ResetHub = false; + // TODO: Clean up this mess. + RGBAColor8Byte GetFogColor() const override; bool GetFogEnabled() const override; float GetWeatherStrength() const override; @@ -67,14 +70,18 @@ struct Level : public ScriptInterfaceLevel int GetSecrets() const override; std::string GetAmbientTrack() const override; bool GetResetHubEnabled() const override; - bool GetLensFlareEnabled() const override; - Vector2 GetLensFlarePosition() const override; - RGBAColor8Byte GetLensFlareColor() const override; - int GetLensFlareSpriteID() const override; - bool GetStarfieldEnabled() const override; - bool GetStarfieldMeteorsEnabled() const override; - int GetStarfieldStarsCount() const override; - int GetStarfieldMeteorsCount() const override; - int GetStarfieldMeteorsSpawnDensity() const override; - float GetStarfieldMeteorsSpeed() const override; + + // Lens flare getters + bool GetLensFlareEnabled() const override; + int GetLensFlareSunSpriteID() const override; + EulerAngles GetLensFlareRotation() const override; + Color GetLensFlareColor() const override; + + // Starfield getters + bool GetStarfieldStarsEnabled() const override; + bool GetStarfieldMeteorsEnabled() const override; + int GetStarfieldStarCount() const override; + int GetStarfieldMeteorCount() const override; + int GetStarfieldMeteorSpawnDensity() const override; + float GetStarfieldMeteorVelocity() const override; }; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp index 56f957300..a2f030a6e 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp @@ -1,127 +1,157 @@ #include "framework.h" -#include "Starfield.h" -#include "Specific/level.h" +#include "Scripting/Internal/TEN/Flow/Starfield/Starfield.h" + #include "Game/effects/weather.h" +#include "Specific/level.h" using namespace TEN::Effects::Environment; -/*** -Starfield +/// Represents a starfield. +// +// @tenclass Flow.Starfield +// @pragma nostrip -@tenclass Flow.Starfield -@pragma nostrip -*/ - -void Starfield::Register(sol::table& parent) +namespace TEN::Scripting { - using ctors = sol::constructors; - parent.new_usertype("Starfield", - ctors(), - sol::call_constructor, ctors(), + void Starfield::Register(sol::table& parent) + { + using ctors = sol::constructors< + Starfield(int starCount), + Starfield(int starCount, int meteorCount, int meteorSpawnDensity, float meteorVel)>; + + // Register type. + parent.new_usertype( + "Starfield", + ctors(), + sol::call_constructor, ctors(), + + "GetStarsEnabled", &Starfield::GetStarsEnabled, + "GetMeteorsEnabled", &Starfield::GetMeteorsEnabled, + "GetStarCount", &Starfield::GetStarCount, + "GetMeteorCount", &Starfield::GetMeteorCount, + "GetMeteorSpawnDensity", &Starfield::GetMeteorSpawnDensity, + "GetMeteorVelocity", &Starfield::GetMeteorVelocity, + "SetStarCount", &Starfield::SetStarCount, + "SetMeteorCount", &Starfield::SetMeteorCount, + "SetMeteorSpawnDensity", &Starfield::SetMeteorSpawnDensity, + "SetMeteorVelocity", &Starfield::SetMeteorVelocity); + } - /*** (int) Stars count. + /// Create a starfield object with only stars. + // @function Starfield() + // @tparam int starCount Star count. + // @treturn Starfield A new Starfield object. + Starfield::Starfield(int starCount) + { + _starCount = starCount; + } - Values can be between [0, 6000], 0 resulting in no stars being rendered, and 6000 resulting in the maximum number of stars being rendered. + /// Create a starfield object with stars and meteors. + // @function Starfield() + // @tparam int starCount Star count. + // @tparam int meteorCount Meteor count. + // @treturn Starfield A new Starfield object. + Starfield::Starfield(int starCount, int meteorCount, int meteorSpawnDensity, float meteorVel) + { + _starCount = starCount; + _meteorCount = meteorCount; + _meteorSpawnDensity = meteorSpawnDensity; + _meteorVelocity = meteorVel; + } - @mem starsCount*/ - "starsCount", sol::property(&Starfield::GetStarsCount, &Starfield::SetStarsCount), + /// Get the starfield's enabled status of stars. + // @function Starfield:GetStarsEnabled() + // @treturn bool Stars enabled status. + bool Starfield::GetStarsEnabled() const + { + return (_starCount > 0); + } - /*** (int) Meteors count. + /// Get the starfield's enabled status of meteors. + // @function Starfield:GetMeteorsEnabled() + // @treturn bool Meteors enabled status. + bool Starfield::GetMeteorsEnabled() const + { + return (_meteorCount > 0); + } - Values can be between [0, 100], 0 resulting in no meteors being rendered, and 100 resulting in the maximum number of meteors being rendered. + /// Get the starfield's number of stars. + // @function Starfield:GetStarCount() + // @treturn int Count. + int Starfield::GetStarCount() const + { + return _starCount; + } - @mem meteorsCount*/ - "meteorsCount", sol::property(&Starfield::GetMeteorsCount, &Starfield::SetMeteorsCount), + /// Get the starfield's number of meteors. + // @function Starfield:GetMeteorCount() + // @treturn int Count. + int Starfield::GetMeteorCount() const + { + return _meteorCount; + } - /*** (int) Meteors spawn density. + /// Get the starfield's meteor spawn density. + // @function Starfield:GetMeteorSpawnDensity() + // @treturn int Spawn density. + int Starfield::GetMeteorSpawnDensity() const + { + return _meteorSpawnDensity; + } - @mem meteorsSpawnDensity*/ - "meteorsSpawnDensity", sol::property(&Starfield::GetMeteorsSpawnDensity, &Starfield::SetMeteorsSpawnDensity), + /// Get the starfield's meteor velocity. + // @function Starfield:GetMeteorVelocity() + // @treturn float Velocity. + float Starfield::GetMeteorVelocity() const + { + return _meteorVelocity; + } - /*** (float) Meteors speed. + /// Set the starfield's number of stars. + // @function Starfield:SetStarCount(int) + // @tparam int New count. + void Starfield::SetStarCount(int count) + { + // Star count out of range; set max. + if (count < 0 || count > STAR_COUNT_MAX) + { + TENLog("Star count must be in range [0, " + std::to_string(STAR_COUNT_MAX) + "].", LogLevel::Warning); + _starCount = STAR_COUNT_MAX; + return; + } - @mem meteorsSpeed*/ - "meteorsSpeed", sol::property(&Starfield::GetMeteorsSpeed, &Starfield::SetMeteorsSpeed) - ); + _starCount = count; + } + + /// Set the starfield's number of meteors. + // @function Starfield:SetMeteorCount(int) + // @tparam int New count. + void Starfield::SetMeteorCount(int count) + { + // Meteor count out of range; set max. + if (count < 0 || count > METEOR_COUNT_MAX) + { + TENLog("Meteor count must be in range [0, " + std::to_string(METEOR_COUNT_MAX) + "].", LogLevel::Warning); + _meteorCount = METEOR_COUNT_MAX; + return; + } + + _meteorCount = count; + } + + /// Set the starfield's meteor spawn density. + // @function Starfield:SetMeteorSpawnDensity(int) + // @tparam int New spawn density. + void Starfield::SetMeteorSpawnDensity(int spawnDensity) + { + _meteorSpawnDensity = spawnDensity; + } + + /// Set the starfield's meteor velocity. + // @function Starfield:SetMeteorVelocity(float) + // @tparam int New velocity. + void Starfield::SetMeteorVelocity(float vel) + { + _meteorVelocity = vel; + } } - -/*** -@tparam int starsCount Stars count -@treturn Starfield A starfield object with only stars enabled. -@function Starfield -*/ -Starfield::Starfield(int starsCount) -{ - SetStarsCount(starsCount); - SetMeteorsCount(0); -} - -/*** -@tparam int starsCount Stars count -@tparam int meteorsCount Stars count -@treturn Starfield A starfield object with boths stars and meteors enabled. -@function Starfield -*/ -Starfield::Starfield(int starsCount, int meteorsCount, int meteorsSpawnDensity, int meteorsSpawnSpeed) -{ - SetStarsCount(starsCount); - SetMeteorsCount(meteorsCount); - SetMeteorsSpawnDensity(meteorsSpawnDensity); - SetMeteorsSpeed(meteorsSpawnSpeed); -} - -void Starfield::SetStarsCount(int const& starsCount) -{ - assertion(starsCount >= 0 && starsCount <= 6000, "Stars count must be in the range 0 ... 6000"); - StarsCount = starsCount; -} - - -int Starfield::GetStarsCount() const -{ - return StarsCount; -} - -void Starfield::SetMeteorsCount(int const& meteorsCount) -{ - assertion(meteorsCount >= 0 && meteorsCount <= 100, "Stars count must be in the range 0 ... 100"); - MeteorsCount = meteorsCount; -} - - -int Starfield::GetMeteorsCount() const -{ - return MeteorsCount; -} - -void Starfield::SetMeteorsSpawnDensity(int const& meteorsSpawnDensity) -{ - MeteorsSpawnDensity = meteorsSpawnDensity; -} - - -int Starfield::GetMeteorsSpawnDensity() const -{ - return MeteorsSpawnDensity; -} - -void Starfield::SetMeteorsSpeed(float const& meteorsSpeed) -{ - MeteorsSpeed = meteorsSpeed; -} - - -float Starfield::GetMeteorsSpeed() const -{ - return MeteorsSpeed; -} - -bool Starfield::GetEnabled() const -{ - return (StarsCount > 0); -} - -bool Starfield::GetMeteorsEnabled() const -{ - return (MeteorsCount > 0); -} \ No newline at end of file diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h index 4144bb516..913314088 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.h @@ -1,36 +1,42 @@ #pragma once -#include "Scripting/Internal/TEN/Color/Color.h" -#include "Scripting/Internal/TEN/Vec2/Vec2.h" - namespace sol { class state; } -struct Starfield +namespace TEN::Scripting { - int StarsCount = 0; // No need for StarryNight flag, if stars count = 0, shader is bypassed + class Starfield + { + private: + // Constants + static const auto STAR_COUNT_MAX = 6000; + static const auto METEOR_COUNT_MAX = 100; - int MeteorsCount = 0; // No need for EnableMeteors flag, if meteors count = 0, shader is bypassed - int MeteorsSpawnDensity = 0; - int MeteorsSpeed = 0; + // Members + int _starCount = 0; + int _meteorCount = 0; + int _meteorSpawnDensity = 0; + float _meteorVelocity = 0; - Starfield() = default; - Starfield(int starsCount); - Starfield(int starsCount, int meteorsCount, int meteorsSpawnDensity, int meteorsSpeed); + public: + static void Register(sol::table& table); - void SetStarsCount(int const& starsCount); - int GetStarsCount() const; + // Constructors + Starfield() = default; + Starfield(int starCount); + Starfield(int starCount, int meteorCount, int meteorSpawnDensity, float meteorVel); - void SetMeteorsCount(int const& meteorsCount); - int GetMeteorsCount() const; + // Getters + bool GetStarsEnabled() const; + bool GetMeteorsEnabled() const; + int GetStarCount() const; + int GetMeteorCount() const; + int GetMeteorSpawnDensity() const; + float GetMeteorVelocity() const; - void SetMeteorsSpawnDensity(int const& spawnDensity); - int GetMeteorsSpawnDensity() const; - - void SetMeteorsSpeed(float const& meteorsSpeed); - float GetMeteorsSpeed() const; - - bool GetEnabled() const; - bool GetMeteorsEnabled() const; - - static void Register(sol::table&); -}; \ No newline at end of file + // Setters + void SetStarCount(int count); + void SetMeteorCount(int count); + void SetMeteorSpawnDensity(int spawnDensity); + void SetMeteorVelocity(float vel); + }; +} From e7889d2b8806113b5de52ee254a3bad991cae243 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 14:10:45 +1000 Subject: [PATCH 145/410] Update colour objects --- .../doc/3 primitive classes/Color.html | 72 ++------ Documentation/doc/index.html | 2 +- .../Scripting/Internal/TEN/Color/Color.cpp | 169 +++++++++--------- .../Scripting/Internal/TEN/Color/Color.h | 17 +- TombEngine/Specific/RGBAColor8Byte.cpp | 105 +++++------ TombEngine/Specific/RGBAColor8Byte.h | 46 ++--- 6 files changed, 186 insertions(+), 225 deletions(-) diff --git a/Documentation/doc/3 primitive classes/Color.html b/Documentation/doc/3 primitive classes/Color.html index 58efaffe6..f627b4d9e 100644 --- a/Documentation/doc/3 primitive classes/Color.html +++ b/Documentation/doc/3 primitive classes/Color.html @@ -100,27 +100,27 @@

    Primitive Class Color

    -

    An RGBA or RGB color.

    -

    Components are specified in bytes; all values are clamped to [0, 255].

    +

    Represents an RGBA or RGB color.

    +

    Components are specified in bytes. All values are clamped to the range [0, 255].

    Members

    - + - + - + - +
    r(int) red component(int) Red component.
    g(int) green component(int) Green component.
    b(int) blue component(int) Blue component.
    a(int) alpha component (255 = opaque, 0 = invisible)(int) Alpha component (0 = invisible, 255 = opaque).

    Functions

    @@ -129,12 +129,6 @@ Color(R, G, B) - - - - Color(R, G, B, A) - - @@ -157,7 +151,7 @@ r
    - (int) red component + (int) Red component. @@ -172,7 +166,7 @@ g
    - (int) green component + (int) Green component. @@ -187,7 +181,7 @@ b
    - (int) blue component + (int) Blue component. @@ -202,7 +196,7 @@ a
    - (int) alpha component (255 = opaque, 0 = invisible) + (int) Alpha component (0 = invisible, 255 = opaque). @@ -253,48 +247,6 @@ -
    -
    - - Color(R, G, B, A) -
    -
    - - - - - - -

    Parameters:

    -
      -
    • R - int - red component -
    • -
    • G - int - green component -
    • -
    • B - int - blue component -
    • -
    • A - int - alpha component (255 is opaque, 0 is invisible) -
    • -
    - -

    Returns:

    -
      - - Color - A new Color object. -
    - - - -
    @@ -311,7 +263,7 @@
    • color Color - this color + This color.
    @@ -319,7 +271,7 @@
      string - A string showing the r, g, b, and a values of the color + A string representing the r, g, b, and a values of the color.
    diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index 77f425919..e481a6133 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -244,7 +244,7 @@ local door = GetMoveableByName("door_type4_14") - + diff --git a/TombEngine/Scripting/Internal/TEN/Color/Color.cpp b/TombEngine/Scripting/Internal/TEN/Color/Color.cpp index ab08c199c..88af10b3f 100644 --- a/TombEngine/Scripting/Internal/TEN/Color/Color.cpp +++ b/TombEngine/Scripting/Internal/TEN/Color/Color.cpp @@ -1,150 +1,147 @@ #include "framework.h" #include "Scripting/Internal/TEN/Color/Color.h" -#include - -/*** -An RGBA or RGB color. -Components are specified in bytes; all values are clamped to [0, 255]. - -@tenprimitive Color -@pragma nostrip -*/ +/// Represents an RGBA or RGB color. +// Components are specified in bytes. All values are clamped to the range [0, 255]. +// +// @tenprimitive Color +// @pragma nostrip void ScriptColor::Register(sol::table& parent) { using ctors = sol::constructors; + + // Register type. parent.new_usertype( "Color", ctors(), sol::call_constructor, ctors(), sol::meta_function::to_string, &ScriptColor::ToString, -/// (int) red component -//@mem r + /// (int) Red component. + // @mem r "r", sol::property(&ScriptColor::GetR, &ScriptColor::SetR), -/// (int) green component -//@mem g + /// (int) Green component. + // @mem g "g", sol::property(&ScriptColor::GetG, &ScriptColor::SetG), -/// (int) blue component -//@mem b + /// (int) Blue component. + // @mem b "b", sol::property(&ScriptColor::GetB, &ScriptColor::SetB), -/// (int) alpha component (255 = opaque, 0 = invisible) -//@mem a - "a", sol::property(&ScriptColor::GetA, &ScriptColor::SetA) - ); + /// (int) Alpha component (0 = invisible, 255 = opaque). + // @mem a + "a", sol::property(&ScriptColor::GetA, &ScriptColor::SetA)); } -/*** -@int R red component -@int G green component -@int B blue component -@treturn Color A new Color object. -@function Color -*/ +/// @int R red component +// @int G green component +// @int B blue component +// @treturn Color A new Color object. +// @function Color ScriptColor::ScriptColor(byte r, byte g, byte b) : -m_color(r, g, b) +_color(r, g, b) { } -/*** -@int R red component -@int G green component -@int B blue component -@int A alpha component (255 is opaque, 0 is invisible) -@treturn Color A new Color object. -@function Color -*/ -ScriptColor::ScriptColor(byte r, byte g, byte b, byte a) : ScriptColor(r, g, b) +// @function Color() +// @int R Red component. +// @int G Green component. +// @int B Blue component. +// @int A Alpha component (0 = invisible, 255 = opaque). +// @treturn Color A new Color object. +ScriptColor::ScriptColor(byte r, byte g, byte b, byte a) : + ScriptColor(r, g, b) { SetA(a); } ScriptColor::ScriptColor(const Vector3& color) : - m_color(color) + _color(color) { } ScriptColor::ScriptColor(const Vector4& color) : - m_color(color) + _color(color) { } ScriptColor::ScriptColor(D3DCOLOR color) : - m_color(color) + _color(color) { } -ScriptColor::operator Vector3() const -{ - return m_color; -} - -ScriptColor::operator Vector4() const -{ - return m_color; -} - -// D3DCOLOR is 32 bits and is laid out as ARGB. -ScriptColor::operator D3DCOLOR() const -{ - return m_color; -} - -ScriptColor::operator RGBAColor8Byte() const -{ - return m_color; -} - byte ScriptColor::GetR() const { - return m_color.GetR(); -} - -void ScriptColor::SetR(byte value) -{ - m_color.SetR(value); + return _color.GetR(); } byte ScriptColor::GetG() const { - return m_color.GetG(); -} - -void ScriptColor::SetG(byte value) -{ - m_color.SetG(value); + return _color.GetG(); } byte ScriptColor::GetB() const { - return m_color.GetB(); -} - -void ScriptColor::SetB(byte value) -{ - m_color.SetB(value); + return _color.GetB(); } byte ScriptColor::GetA() const { - return m_color.GetA(); + return _color.GetA(); +} + +void ScriptColor::SetR(byte value) +{ + _color.SetR(value); +} + +void ScriptColor::SetG(byte value) +{ + _color.SetG(value); +} + +void ScriptColor::SetB(byte value) +{ + _color.SetB(value); } void ScriptColor::SetA(byte value) { - m_color.SetA(value); + _color.SetA(value); } -/*** -@tparam Color color this color -@treturn string A string showing the r, g, b, and a values of the color -@function __tostring -*/ +/// @tparam Color color This color. +// @treturn string A string representing the r, g, b, and a values of the color. +// @function __tostring std::string ScriptColor::ToString() const { - return "{" + std::to_string(GetR()) + ", " + std::to_string(GetG()) + ", " + std::to_string(GetB()) + ", " + std::to_string(GetA()) + "}"; + return "{ " + std::to_string(GetR()) + ", " + std::to_string(GetG()) + ", " + std::to_string(GetB()) + ", " + std::to_string(GetA()) + " }"; +} + +ScriptColor::operator Color() const +{ + return _color; +} + +ScriptColor::operator Vector3() const +{ + return _color; +} + +ScriptColor::operator Vector4() const +{ + return _color; +} + +// NOTE: D3DCOLOR is 32 bits and is laid out as ARGB. +ScriptColor::operator D3DCOLOR() const +{ + return _color; +} + +ScriptColor::operator RGBAColor8Byte() const +{ + return _color; } diff --git a/TombEngine/Scripting/Internal/TEN/Color/Color.h b/TombEngine/Scripting/Internal/TEN/Color/Color.h index 03f75630d..701d133d5 100644 --- a/TombEngine/Scripting/Internal/TEN/Color/Color.h +++ b/TombEngine/Scripting/Internal/TEN/Color/Color.h @@ -11,32 +11,39 @@ namespace sol class ScriptColor { +private: + // Members + RGBAColor8Byte _color; + public: + static void Register(sol::table& parent); + + // Constructors ScriptColor(byte r, byte g, byte b); ScriptColor(byte r, byte g, byte b, byte a); ScriptColor(const Vector3& color); ScriptColor(const Vector4& color); ScriptColor(D3DCOLOR); + // Getters byte GetR() const; byte GetG() const; byte GetB() const; byte GetA() const; + // Setters void SetR(byte value); void SetG(byte value); void SetB(byte value); void SetA(byte value); + // Converters std::string ToString() const; + // Operators + operator Color() const; operator Vector3() const; operator Vector4() const; operator D3DCOLOR() const; operator RGBAColor8Byte() const; - - static void Register(sol::table& parent); - -private: - RGBAColor8Byte m_color; }; diff --git a/TombEngine/Specific/RGBAColor8Byte.cpp b/TombEngine/Specific/RGBAColor8Byte.cpp index b627b21e4..7ec856d3e 100644 --- a/TombEngine/Specific/RGBAColor8Byte.cpp +++ b/TombEngine/Specific/RGBAColor8Byte.cpp @@ -1,46 +1,57 @@ #include "framework.h" -#include "RGBAColor8Byte.h" +#include "Specific/RGBAColor8Byte.h" -static byte FloatComponentToByte(float v) +static byte FloatComponentToByte(float value) { - //todo look into what these actually do AND TEST THEM - //todo like, see if these are actually not undefined or some shit - auto lval = std::lroundf((v / 2.0f) * 255.0f); - return static_cast(lval); + // TODO: Look into what these actually do and test them to see if they are actually not undefined. + long byteValue = std::lroundf((value / 2.0f) * 255.0f); + return (byte)byteValue; } static float ByteComponentToFloat(byte b) { - //todo look into what these actually do AND TEST THEM - //todo like, see if these are actually not undefined or some shit - float f = b; - f = (f / 255.0f) * 2.0f; - return f; + // TODO: Look into what these actually do and test them to see if they are actually not undefined. + float value = (b / 255.0f) * 2; + return value; } - -RGBAColor8Byte::RGBAColor8Byte(D3DCOLOR col) +RGBAColor8Byte::RGBAColor8Byte(D3DCOLOR color) { - b = col & 0xFF; - col >>= 8; - g = col & 0xFF; - col >>= 8; - r = col & 0xFF; - col >>= 8; - a = col & 0xFF; + b = color & 0xFF; + color >>= 8; + g = color & 0xFF; + color >>= 8; + r = color & 0xFF; + color >>= 8; + a = color & 0xFF; } -RGBAColor8Byte::operator D3DCOLOR() const +RGBAColor8Byte::RGBAColor8Byte(byte r, byte g, byte b) { - D3DCOLOR col = a; - col <<= 8; - col += r; - col <<= 8; - col += g; - col <<= 8; - col += b; + SetR(r); + SetG(g); + SetB(b); +} - return col; +RGBAColor8Byte::RGBAColor8Byte(byte r, byte g, byte b, byte a) : + RGBAColor8Byte(r, g, b) +{ + SetA(a); +} + +RGBAColor8Byte::RGBAColor8Byte(const Vector3& color) +{ + r = FloatComponentToByte(color.x); + g = FloatComponentToByte(color.y); + b = FloatComponentToByte(color.z); +} + +RGBAColor8Byte::RGBAColor8Byte(const Vector4& color) +{ + r = FloatComponentToByte(color.x); + g = FloatComponentToByte(color.y); + b = FloatComponentToByte(color.z); + a = FloatComponentToByte(color.w); } byte RGBAColor8Byte::GetR() const @@ -83,40 +94,30 @@ void RGBAColor8Byte::SetA(byte v) a = std::clamp(v, 0, 255); } -RGBAColor8Byte::RGBAColor8Byte(Vector3 const& col) : - r(FloatComponentToByte(col.x)), - g(FloatComponentToByte(col.y)), - b(FloatComponentToByte(col.z)) -{ -} - -RGBAColor8Byte::RGBAColor8Byte(Vector4 const& col) : - r(FloatComponentToByte(col.x)), - g(FloatComponentToByte(col.y)), - b(FloatComponentToByte(col.z)), - a(FloatComponentToByte(col.w)) +RGBAColor8Byte::operator Color() const { + return Color(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b)); } RGBAColor8Byte::operator Vector3() const { - return Vector3{ ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b) }; + return Vector3(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b)); } RGBAColor8Byte::operator Vector4() const { - return Vector4{ ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b), ByteComponentToFloat(a) }; + return Vector4(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b), ByteComponentToFloat(a)); } -RGBAColor8Byte::RGBAColor8Byte(byte r, byte g, byte b) +RGBAColor8Byte::operator D3DCOLOR() const { - SetR(r); - SetG(g); - SetB(b); -} + D3DCOLOR color = a; + color <<= 8; + color += r; + color <<= 8; + color += g; + color <<= 8; + color += b; -RGBAColor8Byte::RGBAColor8Byte(byte r, byte g, byte b, byte a) : RGBAColor8Byte(r, g, b) -{ - SetA(a); + return color; } - diff --git a/TombEngine/Specific/RGBAColor8Byte.h b/TombEngine/Specific/RGBAColor8Byte.h index e89eb7cd3..8566b00b0 100644 --- a/TombEngine/Specific/RGBAColor8Byte.h +++ b/TombEngine/Specific/RGBAColor8Byte.h @@ -4,32 +4,36 @@ typedef DWORD D3DCOLOR; class RGBAColor8Byte { -public: - RGBAColor8Byte(D3DCOLOR); +private: + // Members + byte r = 0; + byte g = 0; + byte b = 0; + byte a = 255; +public: + // Constructors + RGBAColor8Byte(D3DCOLOR color); RGBAColor8Byte(byte r, byte g, byte b); RGBAColor8Byte(byte r, byte g, byte b, byte a); - RGBAColor8Byte(Vector3 const &); - RGBAColor8Byte(Vector4 const &); + RGBAColor8Byte(const Vector3& color); + RGBAColor8Byte(const Vector4& color); + // Getters + byte GetR() const; + byte GetG() const; + byte GetB() const; + byte GetA() const; + + // Setters + void SetR(byte value); + void SetG(byte value); + void SetB(byte value); + void SetA(byte value); + + // Operators + operator Color() const; operator Vector3() const; operator Vector4() const; operator D3DCOLOR() const; - - byte GetR() const; - void SetR(byte v); - byte GetG() const; - void SetG(byte v); - byte GetB() const; - void SetB(byte v); - byte GetA() const; - void SetA(byte v); - -private: - byte r{ 0 }; - byte g{ 0 }; - byte b{ 0 }; - byte a{ 255 }; - }; - From 3ff70b29153791ae81fe7744f9e7416bee4b3da6 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 14:38:00 +1000 Subject: [PATCH 146/410] Remove unnecessary string constants --- .../Scripting/Internal/ReservedScriptNames.h | 16 ----------- .../TEN/DisplaySprite/ScriptDisplaySprite.cpp | 28 +++++++++---------- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 8d0e58181..ba1134907 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -37,22 +37,6 @@ static constexpr char ScriptReserved_MoveableStatus[] = "MoveableStatus"; static constexpr char ScriptReserved_Lara[] = "Lara"; static constexpr char ScriptReserved_GetPlayerInteractedMoveable[] = "GetInteractedMoveable"; -// DisplaySprite object -static constexpr char ScriptReserved_DisplaySprite[] = "DisplaySprite"; -static constexpr char ScriptReserved_DisplayStringGetObjectID[] = "GetObjectID"; -static constexpr char ScriptReserved_DisplayStringGetSpriteID[] = "GetSpriteID"; -static constexpr char ScriptReserved_DisplayStringGetPosition[] = "GetPosition"; -static constexpr char ScriptReserved_DisplayStringGetRotation[] = "GetRotation"; -static constexpr char ScriptReserved_DisplayStringGetScale[] = "GetScale"; -static constexpr char ScriptReserved_DisplayStringGetColor[] = "GetColor"; -static constexpr char ScriptReserved_DisplayStringSetObjectID[] = "SetObjectID"; -static constexpr char ScriptReserved_DisplayStringSetSpriteID[] = "SetSpriteID"; -static constexpr char ScriptReserved_DisplayStringSetPosition[] = "SetPosition"; -static constexpr char ScriptReserved_DisplayStringSetRotation[] = "SetRotation"; -static constexpr char ScriptReserved_DisplayStringSetScale[] = "SetScale"; -static constexpr char ScriptReserved_DisplayStringSetColor[] = "SetColor"; -static constexpr char ScriptReserved_DisplaySpriteDraw[] = "Draw"; - static constexpr char ScriptReserved_EndReasonExitToTitle[] = "EXITTOTITLE"; static constexpr char ScriptReserved_EndReasonLevelComplete[] = "LEVELCOMPLETE"; static constexpr char ScriptReserved_EndReasonLoadGame[] = "LOADGAME"; diff --git a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp index 12529806d..aed2f4908 100644 --- a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp +++ b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp @@ -30,23 +30,23 @@ namespace TEN::Scripting::DisplaySprite // Register type. parent.new_usertype( - ScriptReserved_DisplaySprite, + "DisplaySprite", ctors(), sol::call_constructor, ctors(), - ScriptReserved_DisplayStringGetObjectID, &ScriptDisplaySprite::GetObjectID, - ScriptReserved_DisplayStringGetSpriteID, &ScriptDisplaySprite::GetSpriteID, - ScriptReserved_DisplayStringGetPosition, &ScriptDisplaySprite::GetPosition, - ScriptReserved_DisplayStringGetRotation, &ScriptDisplaySprite::GetRotation, - ScriptReserved_DisplayStringGetScale, &ScriptDisplaySprite::GetScale, - ScriptReserved_DisplayStringGetColor, &ScriptDisplaySprite::GetColor, - ScriptReserved_DisplayStringSetObjectID, &ScriptDisplaySprite::SetObjectID, - ScriptReserved_DisplayStringSetSpriteID, &ScriptDisplaySprite::SetSpriteID, - ScriptReserved_DisplayStringSetPosition, &ScriptDisplaySprite::SetPosition, - ScriptReserved_DisplayStringSetRotation, &ScriptDisplaySprite::SetRotation, - ScriptReserved_DisplayStringSetScale, &ScriptDisplaySprite::SetScale, - ScriptReserved_DisplayStringSetColor, &ScriptDisplaySprite::SetColor, - ScriptReserved_DisplaySpriteDraw, &ScriptDisplaySprite::Draw); + "GetObjectID", & ScriptDisplaySprite::GetObjectID, + "GetSpriteID", &ScriptDisplaySprite::GetSpriteID, + "GetPosition", &ScriptDisplaySprite::GetPosition, + "GetRotation", &ScriptDisplaySprite::GetRotation, + "GetScale", &ScriptDisplaySprite::GetScale, + "GetColor", &ScriptDisplaySprite::GetColor, + "SetObjectID", &ScriptDisplaySprite::SetObjectID, + "SetSpriteID", &ScriptDisplaySprite::SetSpriteID, + "SetPosition", &ScriptDisplaySprite::SetPosition, + "SetRotation", &ScriptDisplaySprite::SetRotation, + "SetScale", &ScriptDisplaySprite::SetScale, + "SetColor", &ScriptDisplaySprite::SetColor, + "Draw", &ScriptDisplaySprite::Draw); } /// Create a DisplaySprite object. From 59e74212adee129be69715d8461fc86411e63124 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 18:47:10 +1000 Subject: [PATCH 147/410] Clean up effect and HUD objects --- TombEngine/Game/Hud/Speedometer.cpp | 4 +- TombEngine/Game/Hud/TargetHighlighter.cpp | 9 +- TombEngine/Game/Lara/lara.cpp | 6 +- TombEngine/Game/Lara/lara.h | 2 +- TombEngine/Game/effects/Blood.h | 20 +- TombEngine/Game/effects/DisplaySprite.cpp | 13 +- TombEngine/Game/effects/DisplaySprite.h | 10 +- TombEngine/Game/effects/Electricity.h | 80 ++--- TombEngine/Game/effects/Ripple.h | 12 +- TombEngine/Game/effects/Streamer.cpp | 7 - TombEngine/Game/effects/Streamer.h | 12 +- TombEngine/Game/effects/bubble.h | 16 +- TombEngine/Game/effects/weather.cpp | 319 ++++++++++-------- TombEngine/Game/effects/weather.h | 108 +++--- TombEngine/Game/items.h | 13 +- TombEngine/Renderer/RendererDrawEffect.cpp | 108 +++--- .../TEN/DisplaySprite/ScriptDisplaySprite.cpp | 2 +- TombEngine/Specific/RGBAColor8Byte.cpp | 5 - 18 files changed, 389 insertions(+), 357 deletions(-) diff --git a/TombEngine/Game/Hud/Speedometer.cpp b/TombEngine/Game/Hud/Speedometer.cpp index edd22a230..dbfa3044d 100644 --- a/TombEngine/Game/Hud/Speedometer.cpp +++ b/TombEngine/Game/Hud/Speedometer.cpp @@ -65,14 +65,14 @@ namespace TEN::Hud ID_SPEEDOMETER, DIAL_ELEMENT_SPRITE_ID, POS, 0, SCALE, color, DIAL_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend, - DisplaySpriteSource::DrawPhase); + DisplaySpritePhase::Draw); // Draw pointer. AddDisplaySprite( ID_SPEEDOMETER, POINTER_ELEMENT_SPRITE_ID, POS, _pointerAngle + ORIENT_OFFSET, SCALE, color, POINTER_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend, - DisplaySpriteSource::DrawPhase); + DisplaySpritePhase::Draw); } void SpeedometerController::Clear() diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 8ad619221..166dc66a8 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -133,9 +133,6 @@ namespace TEN::Hud constexpr auto STATIC_ELEMENT_SPRITE_ID = 0; constexpr auto SEGMENT_ELEMENT_SPRITE_ID = 1; constexpr auto PRIORITY = 0; // TODO: Check later. May interfere with Lua display sprites. -- Sezz 2023.10.06 - constexpr auto ALIGN_MODE = DisplaySpriteAlignMode::Center; - constexpr auto SCALE_MODE = DisplaySpriteScaleMode::Fill; - constexpr auto BLEND_MODE = BlendMode::Additive; if (!Position.has_value()) return; @@ -144,7 +141,8 @@ namespace TEN::Hud AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, STATIC_ELEMENT_SPRITE_ID, *Position, Orientation, Vector2(Scale), Color, - PRIORITY, ALIGN_MODE, SCALE_MODE, BLEND_MODE, DisplaySpriteSource::DrawPhase); + PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fill, + BlendMode::Additive, DisplaySpritePhase::Draw); // Draw animated outer segment elements. for (const auto& segment : Segments) @@ -156,7 +154,8 @@ namespace TEN::Hud AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, SEGMENT_ELEMENT_SPRITE_ID, pos, orient, scale, Color, - PRIORITY, ALIGN_MODE, SCALE_MODE, BLEND_MODE, DisplaySpriteSource::DrawPhase); + PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fill, + BlendMode::Additive, DisplaySpritePhase::Draw); } } diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 87632d5dc..b39f9c246 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -59,9 +59,9 @@ using namespace TEN::Gui; using TEN::Renderer::g_Renderer; -LaraInfo Lara = {}; -LaraInfo OldLara = {}; -ItemInfo* LaraItem; +LaraInfo Lara = {}; +LaraInfo PrevLara = {}; +ItemInfo* LaraItem = nullptr; CollisionInfo LaraCollision = {}; void LaraControl(ItemInfo* item, CollisionInfo* coll) diff --git a/TombEngine/Game/Lara/lara.h b/TombEngine/Game/Lara/lara.h index b2562147b..223f47f77 100644 --- a/TombEngine/Game/Lara/lara.h +++ b/TombEngine/Game/Lara/lara.h @@ -94,7 +94,7 @@ constexpr auto SWIM_WATER_DEPTH = CLICK(2.75f); constexpr auto SLOPE_DIFFERENCE = 60; extern LaraInfo Lara; -extern LaraInfo OldLara; +extern LaraInfo PrevLara; extern ItemInfo* LaraItem; extern CollisionInfo LaraCollision; diff --git a/TombEngine/Game/effects/Blood.h b/TombEngine/Game/effects/Blood.h index 37939810b..b30e60761 100644 --- a/TombEngine/Game/effects/Blood.h +++ b/TombEngine/Game/effects/Blood.h @@ -15,19 +15,19 @@ namespace TEN::Effects::Blood float Size = 0.0f; float Opacity = 0.0f; - Vector3 OldPosition = Vector3::Zero; - Vector4 OldColor = Vector4::Zero; - float OldSize = 0.0f; - float OldOpacity = 0.0f; - float OldLife = 0.0f; + Vector3 PrevPosition = Vector3::Zero; + Vector4 PrevColor = Vector4::Zero; + float PrevLife = 0.0f; + float PrevSize = 0.0f; + float PrevOpacity = 0.0f; void StoreInterpolationData() { - OldPosition = Position; - OldColor = Color; - OldSize = Size; - OldOpacity = Opacity; - OldLife = Life; + PrevPosition = Position; + PrevColor = Color; + PrevLife = Life; + PrevSize = Size; + PrevOpacity = Opacity; } }; diff --git a/TombEngine/Game/effects/DisplaySprite.cpp b/TombEngine/Game/effects/DisplaySprite.cpp index efcfb1236..dd3713d6b 100644 --- a/TombEngine/Game/effects/DisplaySprite.cpp +++ b/TombEngine/Game/effects/DisplaySprite.cpp @@ -15,7 +15,7 @@ namespace TEN::Effects::DisplaySprite void AddDisplaySprite(GAME_OBJECT_ID objectID, int spriteID, const Vector2& pos, short orient, const Vector2& scale, const Vector4& color, int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode, - BlendMode blendMode, DisplaySpriteSource source) + BlendMode blendMode, DisplaySpritePhase source) { auto displaySprite = DisplaySprite{}; displaySprite.ObjectID = objectID; @@ -40,8 +40,13 @@ namespace TEN::Effects::DisplaySprite void ClearDrawPhaseDisplaySprites() { - DisplaySprites.erase(std::remove_if(DisplaySprites.begin(), DisplaySprites.end(), - [](const DisplaySprite& displaySprite) { return displaySprite.Source == DisplaySpriteSource::DrawPhase; }), - DisplaySprites.end()); + DisplaySprites.erase( + std::remove_if( + DisplaySprites.begin(), DisplaySprites.end(), + [](const DisplaySprite& displaySprite) + { + return (displaySprite.Source == DisplaySpritePhase::Draw); + }), + DisplaySprites.end()); } } diff --git a/TombEngine/Game/effects/DisplaySprite.h b/TombEngine/Game/effects/DisplaySprite.h index 26947e796..f8928f10a 100644 --- a/TombEngine/Game/effects/DisplaySprite.h +++ b/TombEngine/Game/effects/DisplaySprite.h @@ -24,10 +24,10 @@ namespace TEN::Effects::DisplaySprite Stretch }; - enum class DisplaySpriteSource + enum class DisplaySpritePhase { - ControlPhase, - DrawPhase + Control, + Draw }; struct DisplaySprite @@ -45,14 +45,14 @@ namespace TEN::Effects::DisplaySprite DisplaySpriteScaleMode ScaleMode = DisplaySpriteScaleMode::Fit; BlendMode BlendMode = BlendMode::AlphaBlend; - DisplaySpriteSource Source = DisplaySpriteSource::ControlPhase; + DisplaySpritePhase Source = DisplaySpritePhase::Control; }; extern std::vector DisplaySprites; void AddDisplaySprite(GAME_OBJECT_ID objectID, int spriteID, const Vector2& pos, short orient, const Vector2& scale, const Vector4& color, int priority, DisplaySpriteAlignMode alignMode, DisplaySpriteScaleMode scaleMode, - BlendMode blendMode, DisplaySpriteSource source); + BlendMode blendMode, DisplaySpritePhase source); void ClearAllDisplaySprites(); void ClearDrawPhaseDisplaySprites(); } diff --git a/TombEngine/Game/effects/Electricity.h b/TombEngine/Game/effects/Electricity.h index 0aa4fa764..98be1f93d 100644 --- a/TombEngine/Game/effects/Electricity.h +++ b/TombEngine/Game/effects/Electricity.h @@ -40,25 +40,25 @@ namespace TEN::Effects::Electricity int type; int flags; - Vector3 oldPos1; - Vector3 oldPos2; - Vector3 oldPos3; - Vector3 oldPos4; - byte oldR; - byte oldG; - byte oldB; - float oldLife; + Vector3 PrevPos1 = Vector3::Zero; + Vector3 PrevPos2 = Vector3::Zero; + Vector3 PrevPos3 = Vector3::Zero; + Vector3 PrevPos4 = Vector3::Zero; + byte PrevR = 0; + byte PrevG = 0; + byte PrevB = 0; + float PrevLife = 0.0f; void StoreInterpolationData() { - oldPos1 = pos1; - oldPos2 = pos2; - oldPos3 = pos3; - oldPos4 = pos4; - oldR = r; - oldG = g; - oldB = b; - oldLife = life; + PrevPos1 = pos1; + PrevPos2 = pos2; + PrevPos3 = pos3; + PrevPos4 = pos4; + PrevR = r; + PrevG = g; + PrevB = b; + PrevLife = life; } }; @@ -66,38 +66,38 @@ namespace TEN::Effects::Electricity { unsigned int NumSegments = 0; - Vector3 Origin = Vector3::Zero; - Vector3 Target = Vector3::Zero; + Vector3 Origin = Vector3::Zero; + Vector3 Target = Vector3::Zero; short Orientation2D = 0; Vector3 LightPosition = Vector3::Zero; // TODO: Use light cone instead? - Vector4 Color = Vector4::Zero; + Vector4 Color = Vector4::Zero; - float Life = 0.0f; - float Radius = 0.0f; - float Length = 0.0f; + float Life = 0.0f; + float Radius = 0.0f; + float Length = 0.0f; float LengthEnd = 0.0f; - float Opacity = 0.0f; - short Rotation = 0; + float Opacity = 0.0f; + short Rotation = 0; - Vector3 OldOrigin = Vector3::Zero; - Vector3 OldTarget = Vector3::Zero; - float OldLife = 0.0f; - float OldRadius = 0.0f; - float OldLength = 0.0f; - float OldOpacity = 0.0f; - Vector4 OldColor = Vector4::Zero; - short OldOrientation2D = 0; + Vector3 PrevOrigin = Vector3::Zero; + Vector3 PrevTarget = Vector3::Zero; + short PrevOrientation2D = 0; + Vector4 PrevColor = Vector4::Zero; + float PrevLife = 0.0f; + float PrevRadius = 0.0f; + float PrevLength = 0.0f; + float PrevOpacity = 0.0f; void StoreInterpolationData() { - OldOrigin = Origin; - OldTarget = Target; - OldLife = Life; - OldRadius = Radius; - OldLength = Length; - OldOpacity = Opacity; - OldColor = Color; - OldOrientation2D = Orientation2D; + PrevOrigin = Origin; + PrevTarget = Target; + PrevOrientation2D = Orientation2D; + PrevColor = Color; + PrevLife = Life; + PrevRadius = Radius; + PrevLength = Length; + PrevOpacity = Opacity; } }; diff --git a/TombEngine/Game/effects/Ripple.h b/TombEngine/Game/effects/Ripple.h index 031301911..261b647d3 100644 --- a/TombEngine/Game/effects/Ripple.h +++ b/TombEngine/Game/effects/Ripple.h @@ -24,15 +24,15 @@ namespace TEN::Effects::Ripple float FadeDuration = 0.0f; int Flags = 0; - Vector3 OldPosition; - Vector4 OldColor; - float OldSize; + Vector3 PrevPosition = Vector3::Zero; + Vector4 PrevColor = Vector4::Zero; + float PrevSize = 0.0f; void StoreInterpolationData() { - OldPosition = Position; - OldColor = Color; - OldSize = Size; + PrevPosition = Position; + PrevColor = Color; + PrevSize = Size; } }; diff --git a/TombEngine/Game/effects/Streamer.cpp b/TombEngine/Game/effects/Streamer.cpp index 48ffb14f8..8e346db3d 100644 --- a/TombEngine/Game/effects/Streamer.cpp +++ b/TombEngine/Game/effects/Streamer.cpp @@ -38,13 +38,6 @@ namespace TEN::Effects::Streamer Life -= 1.0f; } - void Streamer::StreamerSegment::StoreInterpolationData() - { - OldVertices[0] = Vertices[0]; - OldVertices[1] = Vertices[1]; - OldColor = Color; - } - void Streamer::StreamerSegment::TransformVertices(float vel, float scaleRate) { // Apply expansion. diff --git a/TombEngine/Game/effects/Streamer.h b/TombEngine/Game/effects/Streamer.h index 5a189d83d..39db32d22 100644 --- a/TombEngine/Game/effects/Streamer.h +++ b/TombEngine/Game/effects/Streamer.h @@ -39,15 +39,21 @@ namespace TEN::Effects::Streamer std::array Vertices = {}; - std::array OldVertices = {}; - Vector4 OldColor = Vector4::Zero; + std::array PrevVertices = {}; + Vector4 PrevColor = Vector4::Zero; void InitializeVertices(const Vector3& pos, float width); void Update(); private: void TransformVertices(float vel, float scaleRate); - void StoreInterpolationData(); + + void StoreInterpolationData() + { + PrevVertices[0] = Vertices[0]; + PrevVertices[1] = Vertices[1]; + PrevColor = Color; + } }; // Members diff --git a/TombEngine/Game/effects/bubble.h b/TombEngine/Game/effects/bubble.h index e410842a9..dff0c523a 100644 --- a/TombEngine/Game/effects/bubble.h +++ b/TombEngine/Game/effects/bubble.h @@ -31,17 +31,17 @@ namespace TEN::Effects::Bubble float OscillationPeriod = 0.0f; float OscillationVelocity = 0.0f; - Vector3 OldPosition = Vector3::Zero; - Vector4 OldColor = Vector4::Zero; - Vector2 OldSize = Vector2::Zero; - float OldLife = 0.0f; + Vector3 PrevPosition = Vector3::Zero; + Vector4 PrevColor = Vector4::Zero; + Vector2 PrevSize = Vector2::Zero; + float PrevLife = 0.0f; void StoreInterpolationData() { - OldPosition = Position; - OldColor = Color; - OldSize = Size; - OldLife = Life; + PrevPosition = Position; + PrevColor = Color; + PrevSize = Size; + PrevLife = Life; } }; diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index e91a0f546..f8ad60ac7 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -25,8 +25,8 @@ namespace TEN::Effects::Environment float WeatherParticle::Transparency() const { - float result = WEATHER_PARTICLES_TRANSPARENCY; - float fade = WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE; + float result = WEATHER_PARTICLE_OPACITY; + float fade = WEATHER_PARTICLE_NEAR_DEATH_LIFE; if (Life <= fade) result *= Life / fade; @@ -42,12 +42,12 @@ namespace TEN::Effects::Environment EnvironmentController::EnvironmentController() { - Particles.reserve(WEATHER_PARTICLES_MAX_COUNT); + Particles.reserve(WEATHER_PARTICLE_COUNT_MAX); } void EnvironmentController::Update() { - ScriptInterfaceLevel* level = g_GameFlow->GetLevel(CurrentLevel); + const auto& level = *g_GameFlow->GetLevel(CurrentLevel); UpdateSky(level); UpdateStorm(level); @@ -63,20 +63,23 @@ namespace TEN::Effects::Environment void EnvironmentController::Clear() { - // Clear storm vars + // Clear storm variables. StormTimer = 0; StormSkyColor = 1; StormSkyColor2 = 1; - // Clear wind vars - WindCurrent = WindX = WindZ = 0; - WindAngle = WindDAngle = 2048; + // Clear wind variables. + WindCurrent = + WindX = + WindZ = 0; + WindAngle = + WindDAngle = 2048; - // Clear flash vars + // Clear flash variables. FlashProgress = 0.0f; FlashColorBase = Vector3::Zero; - // Clear weather + // Clear weather. Particles.clear(); // Clear starfield. @@ -93,27 +96,31 @@ namespace TEN::Effects::Environment std::clamp(b, 0, UCHAR_MAX) / (float)UCHAR_MAX); } - void EnvironmentController::UpdateSky(ScriptInterfaceLevel* level) + void EnvironmentController::UpdateSky(const ScriptInterfaceLevel& level) { for (int i = 0; i < 2; i++) { - if (!level->GetSkyLayerEnabled(i)) + if (!level.GetSkyLayerEnabled(i)) continue; - SkyCurrentPosition[i] += level->GetSkyLayerSpeed(i); - if (SkyCurrentPosition[i] <= SKY_SIZE) + auto& skyPos = SkyCurrentPosition[i]; + + skyPos += level.GetSkyLayerSpeed(i); + if (skyPos <= SKY_SIZE) { - if (SkyCurrentPosition[i] < 0) - SkyCurrentPosition[i] += SKY_SIZE; + if (skyPos < 0) + skyPos += SKY_SIZE; } else - SkyCurrentPosition[i] -= SKY_SIZE; + { + skyPos -= SKY_SIZE; + } } } - void EnvironmentController::UpdateStorm(ScriptInterfaceLevel* level) + void EnvironmentController::UpdateStorm(const ScriptInterfaceLevel& level) { - if (level->GetStormEnabled()) + if (level.GetStormEnabled()) { if (StormCount || StormRand) { @@ -121,7 +128,7 @@ namespace TEN::Effects::Environment if (StormTimer > -1) StormTimer--; if (!StormTimer) - SoundEffect(SFX_TR4_THUNDER_RUMBLE, NULL); + SoundEffect(SFX_TR4_THUNDER_RUMBLE, nullptr); } else if (!(rand() & 0x7F)) { @@ -132,11 +139,13 @@ namespace TEN::Effects::Environment for (int i = 0; i < 2; i++) { - auto color = Vector4(level->GetSkyLayerColor(i).GetR() / 255.0f, - level->GetSkyLayerColor(i).GetG() / 255.0f, - level->GetSkyLayerColor(i).GetB() / 255.0f, 1.0f); + auto color = Color( + level.GetSkyLayerColor(i).GetR() / 255.0f, + level.GetSkyLayerColor(i).GetG() / 255.0f, + level.GetSkyLayerColor(i).GetB() / 255.0f, + 1.0f); - if (level->GetStormEnabled()) + if (level.GetStormEnabled()) { auto flashBrightness = StormSkyColor / 255.0f; auto r = std::clamp(color.x + flashBrightness, 0.0f, 1.0f); @@ -146,7 +155,9 @@ namespace TEN::Effects::Environment SkyCurrentColor[i] = Vector4(r, g, b, color.w); } else + { SkyCurrentColor[i] = color; + } } } @@ -161,7 +172,7 @@ namespace TEN::Effects::Environment } else if (StormCount < 5 && StormSkyColor < 50) { - auto newColor = StormSkyColor - StormCount * 2; + auto newColor = StormSkyColor - (StormCount * 2); if (newColor < 0) newColor = 0; StormSkyColor = newColor; @@ -176,20 +187,28 @@ namespace TEN::Effects::Environment } } - void EnvironmentController::UpdateWind(ScriptInterfaceLevel* level) + void EnvironmentController::UpdateWind(const ScriptInterfaceLevel& level) { WindCurrent += (GetRandomControl() & 7) - 3; if (WindCurrent <= -2) + { WindCurrent++; + } else if (WindCurrent >= 9) + { WindCurrent--; + } WindDAngle = (WindDAngle + 2 * (GetRandomControl() & 63) - 64) & 0x1FFE; if (WindDAngle < 1024) + { WindDAngle = 2048 - WindDAngle; + } else if (WindDAngle > 3072) + { WindDAngle += 6144 - 2 * WindDAngle; + } WindAngle = (WindAngle + ((WindDAngle - WindAngle) >> 3)) & 0x1FFE; @@ -197,7 +216,7 @@ namespace TEN::Effects::Environment WindZ = WindCurrent * phd_cos(WindAngle << 3); } - void EnvironmentController::UpdateFlash(ScriptInterfaceLevel* level) + void EnvironmentController::UpdateFlash(const ScriptInterfaceLevel& level) { if (FlashProgress > 0.0f) { @@ -210,14 +229,14 @@ namespace TEN::Effects::Environment FlashColorBase = Vector3::Zero; } - void EnvironmentController::UpdateStarfield(ScriptInterfaceLevel* level) + void EnvironmentController::UpdateStarfield(const ScriptInterfaceLevel& level) { - if (!level->GetStarfieldStarsEnabled()) + if (!level.GetStarfieldStarsEnabled()) return; if (ResetStarField) { - int starCount = level->GetStarfieldStarCount(); + int starCount = level.GetStarfieldStarCount(); Stars.clear(); Stars.reserve(starCount); @@ -257,7 +276,7 @@ namespace TEN::Effects::Environment for (auto& star : Stars) star.Blinking = Random::GenerateFloat(0.5f, 1.0f); - if (level->GetStarfieldMeteorsEnabled()) + if (level.GetStarfieldMeteorsEnabled()) { for (auto& meteor : Meteors) { @@ -284,159 +303,158 @@ namespace TEN::Effects::Environment meteor.Fade = 1.0f; } - meteor.Position += meteor.Direction * level->GetStarfieldMeteorVelocity(); + meteor.Position += meteor.Direction * level.GetStarfieldMeteorVelocity(); } } } - void EnvironmentController::UpdateWeather(ScriptInterfaceLevel* level) + void EnvironmentController::UpdateWeather(const ScriptInterfaceLevel& level) { - for (auto& p : Particles) + for (auto& part : Particles) { - p.StoreInterpolationData(); + part.StoreInterpolationData(); - p.Life -= 2; + part.Life -= 2; - // Disable particle if it is dead. It will be cleaned on next call of - // SpawnWeatherParticles(). - - if (p.Life <= 0) + // Disable particle if dead. Will be cleaned on next call of SpawnWeatherParticles(). + if (part.Life <= 0) { - p.Enabled = false; + part.Enabled = false; continue; } - // Check if particle got out of collision check radius, and fade it out if it did. - - if (abs(Camera.pos.x - p.Position.x) > COLLISION_CHECK_DISTANCE || - abs(Camera.pos.z - p.Position.z) > COLLISION_CHECK_DISTANCE) + // Check if particle got out of collision check radius and fade out if it did. + if (abs(Camera.pos.x - part.Position.x) > COLLISION_CHECK_DISTANCE || + abs(Camera.pos.z - part.Position.z) > COLLISION_CHECK_DISTANCE) { - p.Life = std::clamp(p.Life, 0.0f, WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE); + part.Life = std::clamp(part.Life, 0.0f, WEATHER_PARTICLE_NEAR_DEATH_LIFE); } // If particle was locked (after landing or stucking in substance such as water or swamp), - // fade it out and bypass any collision checks and movement updates. - - if (p.Stopped) + // fade out and bypass collision checks and movement updates. + if (part.Stopped) { - if (p.Type == WeatherType::Snow) - p.Size *= WEATHER_PARTICLES_NEAR_DEATH_MELT_FACTOR; + if (part.Type == WeatherType::Snow) + part.Size *= WEATHER_PARTICLE_NEAR_DEATH_MELT_FACTOR; continue; } - // Backup old position and progress new position according to velocity. + // Backup previous position and progress new position according to velocity. + auto prevPos = part.Position; + part.Position.x += part.Velocity.x; + part.Position.z += part.Velocity.z; - auto oldPos = p.Position; - p.Position.x += p.Velocity.x; - p.Position.z += p.Velocity.z; - - switch (p.Type) + switch (part.Type) { case WeatherType::None: - p.Position.y += p.Velocity.y; + part.Position.y += part.Velocity.y; break; case WeatherType::Rain: case WeatherType::Snow: - p.Position.y += (p.Velocity.y / 2.0f); + part.Position.y += (part.Velocity.y / 2.0f); break; } - // Particle is inert, don't check collisions. - - if (p.Type == WeatherType::None) + // Particle is inert; don't check collisions. + if (part.Type == WeatherType::None) continue; - auto pointColl = GetPointCollision(p.Position, p.Room); + auto pointColl = GetPointCollision(part.Position, part.RoomNumber); bool collisionCalculated = false; - if (p.CollisionCheckDelay <= 0) + if (part.CollisionCheckDelay <= 0) { - pointColl = GetPointCollision(p.Position, p.Room); + pointColl = GetPointCollision(part.Position, part.RoomNumber); // Determine collision checking frequency based on nearest floor/ceiling surface position. - // If floor and ceiling is too far, don't do precise collision checks, instead doing it + // If floor and ceiling are too far, don't do precise collision checks, instead doing it // every 5th frame. If particle approaches floor or ceiling, make checks more frequent. - // This allows to avoid unnecessary thousands of calls to GetCollisionResult for every particle. + // This avoids calls to GetPointCollision() for every particle. - auto coeff = std::min(std::max(0.0f, (pointColl.GetFloorHeight() - p.Position.y)), std::max(0.0f, (p.Position.y - pointColl.GetCeilingHeight()))); - p.CollisionCheckDelay = std::min(floor(coeff / std::max(std::numeric_limits::denorm_min(), p.Velocity.y)), WEATHER_PARTICLES_MAX_COLL_CHECK_DELAY); + auto coeff = std::min(std::max(0.0f, (pointColl.GetFloorHeight() - part.Position.y)), std::max(0.0f, (part.Position.y - pointColl.GetCeilingHeight()))); + part.CollisionCheckDelay = std::min(floor(coeff / std::max(std::numeric_limits::denorm_min(), part.Velocity.y)), WEATHER_PARTICLE_COLL_CHECK_DELAY_MAX); collisionCalculated = true; } else { - p.CollisionCheckDelay--; + part.CollisionCheckDelay--; } - // Check if particle got out of room bounds - - if (!IsPointInRoom(p.Position, p.Room)) + // Check if particle is beyond room bounds. + if (!IsPointInRoom(part.Position, part.RoomNumber)) { if (!collisionCalculated) { - pointColl = GetPointCollision(p.Position, p.Room); + pointColl = GetPointCollision(part.Position, part.RoomNumber); collisionCalculated = true; } - if (pointColl.GetRoomNumber() == p.Room) + if (pointColl.GetRoomNumber() == part.RoomNumber) { - p.Enabled = false; // Not landed on door, so out of room bounds - delete + // Not landed on door, so out of room bounds - delete. + part.Enabled = false; continue; } else { - p.Room = pointColl.GetRoomNumber(); + part.RoomNumber = pointColl.GetRoomNumber(); } } // If collision was updated, process with position checks. - if (collisionCalculated) { // If particle is inside water or swamp, count it as "inSubstance". // If particle got below floor or above ceiling, count it as "landed". - bool inSubstance = g_Level.Rooms[pointColl.GetRoomNumber()].flags & (ENV_FLAG_WATER | ENV_FLAG_SWAMP); - bool landed = (pointColl.GetFloorHeight() <= p.Position.y) || (pointColl.GetCeilingHeight() >= p.Position.y); + bool landed = (pointColl.GetFloorHeight() <= part.Position.y) || (pointColl.GetCeilingHeight() >= part.Position.y); if (inSubstance || landed) { - p.Stopped = true; - p.Position = oldPos; - p.Life = std::clamp(p.Life, 0.0f, WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE); + part.Stopped = true; + part.Position = prevPos; + part.Life = std::clamp(part.Life, 0.0f, WEATHER_PARTICLE_NEAR_DEATH_LIFE); // Produce ripples if particle got into substance (water or swamp). if (inSubstance) - SpawnRipple(p.Position, p.Room, Random::GenerateFloat(16.0f, 24.0f), (int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity); + SpawnRipple(part.Position, part.RoomNumber, Random::GenerateFloat(16.0f, 24.0f), (int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity); // Immediately disable rain particle because it doesn't need fading out. - if (p.Type == WeatherType::Rain) + if (part.Type == WeatherType::Rain) { - p.Enabled = false; - AddWaterSparks(oldPos.x, oldPos.y, oldPos.z, 6); + part.Enabled = false; + AddWaterSparks(prevPos.x, prevPos.y, prevPos.z, 6); } } } // Update velocities for every particle type. - - switch (p.Type) + switch (part.Type) { case WeatherType::Snow: - if (p.Velocity.x < (WindX << 2)) - p.Velocity.x += Random::GenerateFloat(0.5f, 2.5f); - else if (p.Velocity.x > (WindX << 2)) - p.Velocity.x -= Random::GenerateFloat(0.5f, 2.5f); + if (part.Velocity.x < (WindX << 2)) + { + part.Velocity.x += Random::GenerateFloat(0.5f, 2.5f); + } + else if (part.Velocity.x > (WindX << 2)) + { + part.Velocity.x -= Random::GenerateFloat(0.5f, 2.5f); + } - if (p.Velocity.z < (WindZ << 2)) - p.Velocity.z += Random::GenerateFloat(0.5f, 2.5f); - else if (p.Velocity.z > (WindZ << 2)) - p.Velocity.z -= Random::GenerateFloat(0.5f, 2.5f); + if (part.Velocity.z < (WindZ << 2)) + { + part.Velocity.z += Random::GenerateFloat(0.5f, 2.5f); + } + else if (part.Velocity.z > (WindZ << 2)) + { + part.Velocity.z -= Random::GenerateFloat(0.5f, 2.5f); + } - if (p.Velocity.y < p.Size / 2) - p.Velocity.y += p.Size / 5.0f; + if (part.Velocity.y < part.Size / 2) + part.Velocity.y += part.Size / 5.0f; break; @@ -445,32 +463,40 @@ namespace TEN::Effects::Environment auto random = Random::GenerateInt(); if ((random & 3) != 3) { - p.Velocity.x += (float)((random & 3) - 1); - if (p.Velocity.x < -4) - p.Velocity.x = -4; - else if (p.Velocity.x > 4) - p.Velocity.x = 4; + part.Velocity.x += (float)((random & 3) - 1); + if (part.Velocity.x < -4) + { + part.Velocity.x = -4; + } + else if (part.Velocity.x > 4) + { + part.Velocity.x = 4; + } } random = (random >> 2) & 3; if (random != 3) { - p.Velocity.z += random - 1; - if (p.Velocity.z < -4) - p.Velocity.z = -4; - else if (p.Velocity.z > 4) - p.Velocity.z = 4; + part.Velocity.z += random - 1; + if (part.Velocity.z < -4) + { + part.Velocity.z = -4; + } + else if (part.Velocity.z > 4) + { + part.Velocity.z = 4; + } } - if (p.Velocity.y < p.Size * 2 * std::clamp(level->GetWeatherStrength(), 0.6f, 1.0f)) - p.Velocity.y += p.Size / 5.0f; + if (part.Velocity.y < part.Size * 2 * std::clamp(level.GetWeatherStrength(), 0.6f, 1.0f)) + part.Velocity.y += part.Size / 5.0f; break; } } } - void EnvironmentController::SpawnDustParticles(ScriptInterfaceLevel* level) + void EnvironmentController::SpawnDustParticles(const ScriptInterfaceLevel& level) { for (int i = 0; i < DUST_SPAWN_DENSITY; i++) { @@ -478,7 +504,7 @@ namespace TEN::Effects::Environment int yPos = Camera.pos.y + rand() % DUST_SPAWN_RADIUS - DUST_SPAWN_RADIUS / 2.0f; int zPos = Camera.pos.z + rand() % DUST_SPAWN_RADIUS - DUST_SPAWN_RADIUS / 2.0f; - // Use fast GetFloor instead of GetCollision as we spawn a lot of dust. + // Use more memory-efficient GetFloor() instead of GetPointCollision() as a lot of dust may spawn at a time. short roomNumber = Camera.pos.RoomNumber; auto* floor = GetFloor(xPos, yPos, zPos, &roomNumber); @@ -491,13 +517,13 @@ namespace TEN::Effects::Environment auto part = WeatherParticle(); - part.Velocity = Random::GenerateDirection() * MAX_DUST_SPEED; + part.Velocity = Random::GenerateDirection() * DUST_VELOCITY_MAX; - part.Size = Random::GenerateFloat(MAX_DUST_SIZE / 2, MAX_DUST_SIZE); + part.Size = Random::GenerateFloat(DUST_SIZE_MAX / 2, DUST_SIZE_MAX); part.Type = WeatherType::None; part.Life = DUST_LIFE + Random::GenerateInt(-10, 10); - part.Room = roomNumber; + part.RoomNumber = roomNumber; part.Position.x = xPos; part.Position.y = yPos; part.Position.z = zPos; @@ -509,33 +535,42 @@ namespace TEN::Effects::Environment } } - void EnvironmentController::SpawnWeatherParticles(ScriptInterfaceLevel* level) + void EnvironmentController::SpawnWeatherParticles(const ScriptInterfaceLevel& level) { - // Clean up dead particles + // Clean up dead particles. if (Particles.size() > 0) - Particles.erase(std::remove_if(Particles.begin(), Particles.end(), [](const WeatherParticle& part) { return !part.Enabled; }), Particles.end()); + { + Particles.erase( + std::remove_if( + Particles.begin(), Particles.end(), + [](const WeatherParticle& part) + { + return !part.Enabled; + }), + Particles.end()); + } - if (level->GetWeatherType() == WeatherType::None || level->GetWeatherStrength() == 0.0f) + if (level.GetWeatherType() == WeatherType::None || level.GetWeatherStrength() == 0.0f) return; int newParticlesCount = 0; - int density = WEATHER_PARTICLES_SPAWN_DENSITY * level->GetWeatherStrength(); + int density = WEATHER_PARTICLE_SPAWN_DENSITY * level.GetWeatherStrength(); - // Snow is falling twice as fast, and must be spawned accordingly fast - if (level->GetWeatherType() == WeatherType::Snow) + // Snow is falling twice as fast and must be spawned accordingly fast. + if (level.GetWeatherType() == WeatherType::Snow) density *= 2; - if (density > 0.0f && level->GetWeatherType() != WeatherType::None) + if (density > 0.0f && level.GetWeatherType() != WeatherType::None) { - while (Particles.size() < WEATHER_PARTICLES_MAX_COUNT) + while (Particles.size() < WEATHER_PARTICLE_COUNT_MAX) { if (newParticlesCount > density) break; newParticlesCount++; - auto distance = level->GetWeatherType() == WeatherType::Snow ? COLLISION_CHECK_DISTANCE : COLLISION_CHECK_DISTANCE / 2; - auto radius = Random::GenerateInt(0, distance); + float dist = (level.GetWeatherType() == WeatherType::Snow) ? COLLISION_CHECK_DISTANCE : (COLLISION_CHECK_DISTANCE / 2); + float radius = Random::GenerateInt(0, dist); short angle = Random::GenerateInt(ANGLE(0), ANGLE(180)); auto xPos = Camera.pos.x + ((int)(phd_cos(angle) * radius)); @@ -557,26 +592,26 @@ namespace TEN::Effects::Environment auto part = WeatherParticle(); - switch (level->GetWeatherType()) + switch (level.GetWeatherType()) { case WeatherType::Snow: - part.Size = Random::GenerateFloat(MAX_SNOW_SIZE / 3, MAX_SNOW_SIZE); - part.Velocity.y = Random::GenerateFloat(MAX_SNOW_SPEED / 4, MAX_SNOW_SPEED) * (part.Size / MAX_SNOW_SIZE); - part.Life = (MAX_SNOW_SPEED / 3) + ((MAX_SNOW_SPEED / 2) - ((int)part.Velocity.y >> 2)); + part.Size = Random::GenerateFloat(SNOW_SIZE_MAX / 3, SNOW_SIZE_MAX); + part.Velocity.y = Random::GenerateFloat(SNOW_VELOCITY_MAX / 4, SNOW_VELOCITY_MAX) * (part.Size / SNOW_SIZE_MAX); + part.Life = (SNOW_VELOCITY_MAX / 3) + ((SNOW_VELOCITY_MAX / 2) - ((int)part.Velocity.y >> 2)); break; case WeatherType::Rain: - part.Size = Random::GenerateFloat(MAX_RAIN_SIZE / 2, MAX_RAIN_SIZE); - part.Velocity.y = Random::GenerateFloat(MAX_RAIN_SPEED / 2, MAX_RAIN_SPEED) * (part.Size / MAX_RAIN_SIZE) * std::clamp(level->GetWeatherStrength(), 0.6f, 1.0f); - part.Life = (MAX_RAIN_SPEED * 2) - part.Velocity.y; + part.Size = Random::GenerateFloat(RAIN_SIZE_MAX / 2, RAIN_SIZE_MAX); + part.Velocity.y = Random::GenerateFloat(RAIN_VELOCITY_MAX / 2, RAIN_VELOCITY_MAX) * (part.Size / RAIN_SIZE_MAX) * std::clamp(level.GetWeatherStrength(), 0.6f, 1.0f); + part.Life = (RAIN_VELOCITY_MAX * 2) - part.Velocity.y; break; } - part.Velocity.x = Random::GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_SPEED / 2, WEATHER_PARTICLE_HORIZONTAL_SPEED); - part.Velocity.z = Random::GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_SPEED / 2, WEATHER_PARTICLE_HORIZONTAL_SPEED); + part.Velocity.x = Random::GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_VELOCITY / 2, WEATHER_PARTICLE_HORIZONTAL_VELOCITY); + part.Velocity.z = Random::GenerateFloat(WEATHER_PARTICLE_HORIZONTAL_VELOCITY / 2, WEATHER_PARTICLE_HORIZONTAL_VELOCITY); - part.Type = level->GetWeatherType(); - part.Room = outsideRoom; + part.Type = level.GetWeatherType(); + part.RoomNumber = outsideRoom; part.Position.x = xPos; part.Position.y = yPos; part.Position.z = zPos; @@ -590,7 +625,7 @@ namespace TEN::Effects::Environment } } - void EnvironmentController::SpawnMeteorParticles(ScriptInterfaceLevel* level) + void EnvironmentController::SpawnMeteorParticles(const ScriptInterfaceLevel& level) { // Clean up dead particles. if (!Meteors.empty()) @@ -605,13 +640,13 @@ namespace TEN::Effects::Environment Meteors.end()); } - if (!level->GetStarfieldMeteorsEnabled()) + if (!level.GetStarfieldMeteorsEnabled()) return; - int density = level->GetStarfieldMeteorSpawnDensity(); + int density = level.GetStarfieldMeteorSpawnDensity(); if (density > 0) { - for (int i = 0; i < level->GetStarfieldMeteorCount(); i++) + for (int i = 0; i < level.GetStarfieldMeteorCount(); i++) { if (i > density) break; diff --git a/TombEngine/Game/effects/weather.h b/TombEngine/Game/effects/weather.h index 15ff5452f..ad06bbc9b 100644 --- a/TombEngine/Game/effects/weather.h +++ b/TombEngine/Game/effects/weather.h @@ -7,32 +7,32 @@ using namespace TEN::Entities::Effects; namespace TEN::Effects::Environment { - constexpr auto WEATHER_PARTICLES_SPAWN_DENSITY = 32; - constexpr auto WEATHER_PARTICLES_MAX_COUNT = 2048; - constexpr auto WEATHER_PARTICLES_MAX_COLL_CHECK_DELAY = 5.0f; + constexpr auto WEATHER_PARTICLE_SPAWN_DENSITY = 32; + constexpr auto WEATHER_PARTICLE_COUNT_MAX = 2048; + constexpr auto WEATHER_PARTICLE_COLL_CHECK_DELAY_MAX = 5.0f; - constexpr auto MAX_DUST_SIZE = 25.0f; - constexpr auto MAX_SNOW_SIZE = 32.0f; - constexpr auto MAX_RAIN_SIZE = 128.0f; + constexpr auto DUST_SIZE_MAX = 25.0f; + constexpr auto SNOW_SIZE_MAX = 32.0f; + constexpr auto RAIN_SIZE_MAX = 128.0f; - constexpr auto WEATHER_PARTICLE_HORIZONTAL_SPEED = 8.0f; - constexpr auto MAX_SNOW_SPEED = 128.0f; - constexpr auto MAX_RAIN_SPEED = 256.0f; - constexpr auto MAX_DUST_SPEED = 1.0f; + constexpr auto WEATHER_PARTICLE_HORIZONTAL_VELOCITY = 8.0f; + constexpr auto SNOW_VELOCITY_MAX = 128.0f; + constexpr auto RAIN_VELOCITY_MAX = 256.0f; + constexpr auto DUST_VELOCITY_MAX = 1.0f; - constexpr auto WEATHER_PARTICLES_TRANSPARENCY = 0.8f; - constexpr auto WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE = 20.0f; - constexpr auto WEATHER_PARTICLES_NEAR_DEATH_MELT_FACTOR = 1.0f - (1.0f / (WEATHER_PARTICLES_NEAR_DEATH_LIFE_VALUE * 2)); + constexpr auto WEATHER_PARTICLE_OPACITY = 0.8f; + constexpr auto WEATHER_PARTICLE_NEAR_DEATH_LIFE = 20.0f; + constexpr auto WEATHER_PARTICLE_NEAR_DEATH_MELT_FACTOR = 1.0f - (1.0f / (WEATHER_PARTICLE_NEAR_DEATH_LIFE * 2)); constexpr auto DUST_SPAWN_DENSITY = 300; - constexpr auto DUST_LIFE = 40; - constexpr auto DUST_SPAWN_RADIUS = (10 * 1024); + constexpr auto DUST_LIFE = 40; + constexpr auto DUST_SPAWN_RADIUS = BLOCK(10); - constexpr auto METEOR_PARTICLE_COUNT_MAX = 10; - constexpr auto METEOR_PARTICLE_LIFE_MAX = 150; - constexpr auto METEOR_PARTICLE_VELOCITY = 32.0f; + constexpr auto METEOR_PARTICLE_COUNT_MAX = 10; + constexpr auto METEOR_PARTICLE_LIFE_MAX = 150; + constexpr auto METEOR_PARTICLE_VELOCITY = 32.0f; constexpr auto METEOR_PARTICLE_SPAWN_DENSITY = 4; - constexpr auto METEOR_PARTICLE_FADE_TIME = 30.0f; + constexpr auto METEOR_PARTICLE_FADE_TIME = 30.0f; struct StarParticle { @@ -70,31 +70,31 @@ namespace TEN::Effects::Environment { WeatherType Type = WeatherType::None; - int Room = NO_VALUE; - Vector3 Position = Vector3::Zero; - Vector3 Velocity = Vector3::Zero; + Vector3 Position = Vector3::Zero; + int RoomNumber = NO_VALUE; + Vector3 Velocity = Vector3::Zero; - float StartLife = 0.0f; - float Life = 0.0f; + float StartLife = 0.0f; + float Life = 0.0f; float CollisionCheckDelay = 0.0f; - float Size = 0.0f; + float Size = 0.0f; bool Enabled = false; bool Stopped = false; float Transparency() const; - Vector3 OldPosition = Vector3::Zero; - Vector3 OldVelocity = Vector3::Zero; - float OldSize = 0.0f; - float OldLife = 0.0f; + Vector3 PrevPosition = Vector3::Zero; + Vector3 PrevVelocity = Vector3::Zero; + float PrevSize = 0.0f; + float PrevLife = 0.0f; void StoreInterpolationData() { - OldPosition = Position; - OldVelocity = Velocity; - OldSize = Size; - OldLife = Life; + PrevPosition = Position; + PrevVelocity = Velocity; + PrevSize = Size; + PrevLife = Life; } }; @@ -104,7 +104,7 @@ namespace TEN::Effects::Environment EnvironmentController(); Vector3 Wind() { return Vector3(WindX / 2.0f, 0, WindZ / 2.0f); } - Vector3 FlashColor() { return FlashColorBase * sin(FlashProgress * PI / 2.0f); } + Vector3 FlashColor() { return FlashColorBase * sin((FlashProgress * PI) / 2.0f); } Vector4 SkyColor(int index) { return SkyCurrentColor[std::clamp(index, 0, 1)]; } short SkyPosition(int index) { return SkyCurrentPosition[std::clamp(index, 0, 1)]; } @@ -113,16 +113,16 @@ namespace TEN::Effects::Environment void Clear(); const std::vector& GetParticles() const { return Particles; } - const std::vector& GetStars() const { return Stars; } - const std::vector& GetMeteors() { return Meteors; } + const std::vector& GetStars() const { return Stars; } + const std::vector& GetMeteors() const { return Meteors; } private: // Weather - std::vector Particles; + std::vector Particles = {}; // Sky - Vector4 SkyCurrentColor[2] = {}; - short SkyCurrentPosition[2] = {}; + Vector4 SkyCurrentColor[2] = {}; + short SkyCurrentPosition[2] = {}; // Wind int WindX = 0; @@ -133,14 +133,14 @@ namespace TEN::Effects::Environment // Flash fader Vector3 FlashColorBase = Vector3::Zero; - float FlashSpeed = 1.0f; - float FlashProgress = 0.0f; + float FlashSpeed = 1.0f; + float FlashProgress = 0.0f; // Lightning - int StormCount = 0; - int StormRand = 0; - int StormTimer = 0; - byte StormSkyColor = 1; + int StormCount = 0; + int StormRand = 0; + int StormTimer = 0; + byte StormSkyColor = 1; byte StormSkyColor2 = 1; // Starfield @@ -151,17 +151,17 @@ namespace TEN::Effects::Environment // Lens flare LensFlare GlobalLensFlare = {}; - void UpdateStarfield(ScriptInterfaceLevel* level); - void UpdateSky(ScriptInterfaceLevel* level); - void UpdateStorm(ScriptInterfaceLevel* level); - void UpdateWind(ScriptInterfaceLevel* level); - void UpdateFlash(ScriptInterfaceLevel* level); - void UpdateWeather(ScriptInterfaceLevel* level); + void UpdateStarfield(const ScriptInterfaceLevel& level); + void UpdateSky(const ScriptInterfaceLevel& level); + void UpdateStorm(const ScriptInterfaceLevel& level); + void UpdateWind(const ScriptInterfaceLevel& level); + void UpdateFlash(const ScriptInterfaceLevel& level); + void UpdateWeather(const ScriptInterfaceLevel& level); void UpdateLightning(); - void SpawnDustParticles(ScriptInterfaceLevel* level); - void SpawnWeatherParticles(ScriptInterfaceLevel* level); - void SpawnMeteorParticles(ScriptInterfaceLevel* level); + void SpawnDustParticles(const ScriptInterfaceLevel& level); + void SpawnWeatherParticles(const ScriptInterfaceLevel& level); + void SpawnMeteorParticles(const ScriptInterfaceLevel& level); }; extern EnvironmentController Weather; diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index f5ea6aa21..e630fbf29 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -128,11 +128,12 @@ struct ItemInfo short RoomNumber = 0; // TODO: Make int. int Floor = 0; - int HitPoints = 0; - bool HitStatus = false; - bool LookedAt = false; - bool Collidable = false; - bool InDrawRoom = false; + int HitPoints = 0; + bool HitStatus = false; + bool LookedAt = false; + bool Collidable = false; + bool InDrawRoom = false; + bool DisableInterpolation = false; int BoxNumber = 0; int Timer = 0; @@ -172,8 +173,6 @@ struct ItemInfo bool IsLara() const; bool IsCreature() const; bool IsBridge() const; - - bool DisableInterpolation = false; }; bool TestState(int refState, const std::vector& stateList); diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 8b4dfe37a..1d49791a7 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -144,13 +144,13 @@ namespace TEN::Renderer if (segment.Flags & (int)StreamerFlags::FadeLeft) { AddColoredQuad( - Vector3::Lerp(segment.OldVertices[0], segment.Vertices[0], _interpolationFactor), - Vector3::Lerp(segment.OldVertices[1], segment.Vertices[1], _interpolationFactor), - Vector3::Lerp(prevSegment.OldVertices[1], prevSegment.Vertices[1], _interpolationFactor), - Vector3::Lerp(prevSegment.OldVertices[0], prevSegment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.PrevVertices[0], segment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.PrevVertices[1], segment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.PrevVertices[1], prevSegment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.PrevVertices[0], prevSegment.Vertices[0], _interpolationFactor), Vector4::Zero, - Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), - Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + Vector4::Lerp(segment.PrevColor, segment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), Vector4::Zero, blendMode, view); @@ -158,28 +158,28 @@ namespace TEN::Renderer else if (segment.Flags & (int)StreamerFlags::FadeRight) { AddColoredQuad( - Vector3::Lerp(segment.OldVertices[0], segment.Vertices[0], _interpolationFactor), - Vector3::Lerp(segment.OldVertices[1], segment.Vertices[1], _interpolationFactor), - Vector3::Lerp(prevSegment.OldVertices[1], prevSegment.Vertices[1], _interpolationFactor), - Vector3::Lerp(prevSegment.OldVertices[0], prevSegment.Vertices[0], _interpolationFactor), - Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), + Vector3::Lerp(segment.PrevVertices[0], segment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.PrevVertices[1], segment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.PrevVertices[1], prevSegment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.PrevVertices[0], prevSegment.Vertices[0], _interpolationFactor), + Vector4::Lerp(segment.PrevColor, segment.Color, _interpolationFactor), Vector4::Zero, Vector4::Zero, - Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), blendMode, view); } else { AddColoredQuad( - Vector3::Lerp(segment.OldVertices[0], segment.Vertices[0], _interpolationFactor), - Vector3::Lerp(segment.OldVertices[1], segment.Vertices[1], _interpolationFactor), - Vector3::Lerp(prevSegment.OldVertices[1], prevSegment.Vertices[1], _interpolationFactor), - Vector3::Lerp(prevSegment.OldVertices[0], prevSegment.Vertices[0], _interpolationFactor), - Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), - Vector4::Lerp(segment.OldColor, segment.Color, _interpolationFactor), - Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), - Vector4::Lerp(prevSegment.OldColor, prevSegment.Color, _interpolationFactor), + Vector3::Lerp(segment.PrevVertices[0], segment.Vertices[0], _interpolationFactor), + Vector3::Lerp(segment.PrevVertices[1], segment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.PrevVertices[1], prevSegment.Vertices[1], _interpolationFactor), + Vector3::Lerp(prevSegment.PrevVertices[0], prevSegment.Vertices[0], _interpolationFactor), + Vector4::Lerp(segment.PrevColor, segment.Color, _interpolationFactor), + Vector4::Lerp(segment.PrevColor, segment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), + Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), blendMode, view); } @@ -202,13 +202,13 @@ namespace TEN::Renderer if (laser.Life <= 0.0f) continue; - auto color = Vector4::Lerp(laser.OldColor, laser.Color, _interpolationFactor); - color.w = Lerp(laser.OldOpacity, laser.Opacity, _interpolationFactor); + auto color = Vector4::Lerp(laser.PrevColor, laser.Color, _interpolationFactor); + color.w = Lerp(laser.PrevOpacity, laser.Opacity, _interpolationFactor); - Vector3 laserTarget = Vector3::Lerp(laser.OldTarget, laser.Target, _interpolationFactor); + Vector3 laserTarget = Vector3::Lerp(laser.PrevTarget, laser.Target, _interpolationFactor); ElectricityKnots[0] = laserTarget; - ElectricityKnots[1] = Vector3::Lerp(laser.OldOrigin, laser.Origin, _interpolationFactor); + ElectricityKnots[1] = Vector3::Lerp(laser.PrevOrigin, laser.Origin, _interpolationFactor); for (int j = 0; j < 2; j++) ElectricityKnots[j] -= laserTarget; @@ -261,12 +261,12 @@ namespace TEN::Renderer if (arc.life <= 0) continue; - ElectricityKnots[0] = Vector3::Lerp(arc.oldPos1, arc.pos1, _interpolationFactor); - ElectricityKnots[1] = Vector3::Lerp(arc.oldPos1, arc.pos1, _interpolationFactor); - ElectricityKnots[2] = Vector3::Lerp(arc.oldPos2, arc.pos2, _interpolationFactor); - ElectricityKnots[3] = Vector3::Lerp(arc.oldPos3, arc.pos3, _interpolationFactor); - ElectricityKnots[4] = Vector3::Lerp(arc.oldPos4, arc.pos4, _interpolationFactor); - ElectricityKnots[5] = Vector3::Lerp(arc.oldPos4, arc.pos4, _interpolationFactor); + ElectricityKnots[0] = Vector3::Lerp(arc.PrevPos1, arc.pos1, _interpolationFactor); + ElectricityKnots[1] = Vector3::Lerp(arc.PrevPos1, arc.pos1, _interpolationFactor); + ElectricityKnots[2] = Vector3::Lerp(arc.PrevPos2, arc.pos2, _interpolationFactor); + ElectricityKnots[3] = Vector3::Lerp(arc.PrevPos3, arc.pos3, _interpolationFactor); + ElectricityKnots[4] = Vector3::Lerp(arc.PrevPos4, arc.pos4, _interpolationFactor); + ElectricityKnots[5] = Vector3::Lerp(arc.PrevPos4, arc.pos4, _interpolationFactor); for (int j = 0; j < ElectricityKnots.size(); j++) ElectricityKnots[j] -= LaraItem->Pose.Position.ToVector3(); @@ -307,17 +307,17 @@ namespace TEN::Renderer byte oldR, oldG, oldB; - if (arc.oldLife >= 16) + if (arc.PrevLife >= 16) { - oldR = arc.oldR; - oldG = arc.oldG; - oldB = arc.oldB; + oldR = arc.PrevR; + oldG = arc.PrevG; + oldB = arc.PrevB; } else { - oldR = (arc.oldLife * arc.oldR) / 16; - oldG = (arc.oldLife * arc.oldG) / 16; - oldB = (arc.oldLife * arc.oldB) / 16; + oldR = (arc.PrevLife * arc.PrevR) / 16; + oldG = (arc.PrevLife * arc.PrevG) / 16; + oldB = (arc.PrevLife * arc.PrevB) / 16; } r = (byte)Lerp(oldR, r, _interpolationFactor); @@ -640,11 +640,11 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + bubble.SpriteIndex], - Vector3::Lerp(bubble.OldPosition, bubble.Position, _interpolationFactor), - Vector4::Lerp(bubble.OldColor, bubble.Color, _interpolationFactor), + Vector3::Lerp(bubble.PrevPosition, bubble.Position, _interpolationFactor), + Vector4::Lerp(bubble.PrevColor, bubble.Color, _interpolationFactor), 0.0f, 1.0f, - Vector2::Lerp(bubble.OldSize, bubble.Size, _interpolationFactor) / 2, + Vector2::Lerp(bubble.PrevSize, bubble.Size, _interpolationFactor) / 2, BlendMode::Additive, true, view); @@ -698,17 +698,17 @@ namespace TEN::Renderer auto color = ripple.Color; color.w = opacity; - float oldOpacity = ripple.OldColor.w * ((ripple.Flags & (int)RippleFlags::LowOpacity) ? 0.5f : 1.0f); - auto oldColor = ripple.OldColor; + float oldOpacity = ripple.PrevColor.w * ((ripple.Flags & (int)RippleFlags::LowOpacity) ? 0.5f : 1.0f); + auto oldColor = ripple.PrevColor; oldColor.w = oldOpacity; AddSpriteBillboardConstrainedLookAt( &_sprites[ripple.SpriteIndex], - Vector3::Lerp(ripple.OldPosition, ripple.Position, _interpolationFactor), + Vector3::Lerp(ripple.PrevPosition, ripple.Position, _interpolationFactor), Vector4::Lerp(oldColor, color, _interpolationFactor), 0.0f, 1.0f, - Vector2(Lerp(ripple.OldSize, ripple.Size, _interpolationFactor) * 2), + Vector2(Lerp(ripple.PrevSize, ripple.Size, _interpolationFactor) * 2), BlendMode::Additive, ripple.Normal, true, @@ -741,7 +741,7 @@ namespace TEN::Renderer if (uwBlood.Init) oldColor = Vector4(uwBlood.Init / 2, 0, uwBlood.Init / 16, UCHAR_MAX); else - oldColor = Vector4(uwBlood.OldLife / 2, 0, uwBlood.OldLife / 16, UCHAR_MAX); + oldColor = Vector4(uwBlood.PrevLife / 2, 0, uwBlood.PrevLife / 16, UCHAR_MAX); oldColor.x = (int)std::clamp((int)oldColor.x, 0, UCHAR_MAX); oldColor.y = (int)std::clamp((int)oldColor.y, 0, UCHAR_MAX); @@ -750,13 +750,13 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[uwBlood.SpriteIndex], - Vector3::Lerp(uwBlood.OldPosition, uwBlood.Position, _interpolationFactor), + Vector3::Lerp(uwBlood.PrevPosition, uwBlood.Position, _interpolationFactor), Vector4::Lerp(oldColor, color, _interpolationFactor), 0.0f, 1.0f, Vector2( - Lerp(uwBlood.OldSize, uwBlood.Size, _interpolationFactor), - Lerp(uwBlood.OldSize, uwBlood.Size, _interpolationFactor) + Lerp(uwBlood.PrevSize, uwBlood.Size, _interpolationFactor), + Lerp(uwBlood.PrevSize, uwBlood.Size, _interpolationFactor) ) * 2, BlendMode::Additive, true, @@ -994,11 +994,11 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], - Vector3::Lerp(p.OldPosition, p.Position, _interpolationFactor), + Vector3::Lerp(p.PrevPosition, p.Position, _interpolationFactor), Vector4(1.0f, 1.0f, 1.0f, p.Transparency()), 0.0f, 1.0f, - Vector2(Lerp(p.OldSize, p.Size, _interpolationFactor)), + Vector2(Lerp(p.PrevSize, p.Size, _interpolationFactor)), BlendMode::Additive, true, view); @@ -1012,11 +1012,11 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], - Vector3::Lerp(p.OldPosition, p.Position, _interpolationFactor), + Vector3::Lerp(p.PrevPosition, p.Position, _interpolationFactor), Vector4(1.0f, 1.0f, 1.0f, p.Transparency()), 0.0f, 1.0f, - Vector2(Lerp(p.OldSize, p.Size, _interpolationFactor)), + Vector2(Lerp(p.PrevSize, p.Size, _interpolationFactor)), BlendMode::Additive, true, view); @@ -1033,11 +1033,11 @@ namespace TEN::Renderer AddSpriteBillboardConstrained( &_sprites[Objects[ID_DRIP_SPRITE].meshIndex], - Vector3::Lerp(p.OldPosition, p.Position, _interpolationFactor), + Vector3::Lerp(p.PrevPosition, p.Position, _interpolationFactor), Vector4(0.8f, 1.0f, 1.0f, p.Transparency()), 0.0f, 1.0f, - Vector2(RAIN_WIDTH, Lerp(p.OldSize, p.Size, _interpolationFactor)), + Vector2(RAIN_WIDTH, Lerp(p.PrevSize, p.Size, _interpolationFactor)), BlendMode::Additive, -v, true, diff --git a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp index 3ea31cf12..7478bafa9 100644 --- a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp +++ b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp @@ -219,6 +219,6 @@ namespace TEN::Scripting::DisplaySprite alignMode.value_or(DEFAULT_ALIGN_MODE), scaleMode.value_or(DEFAULT_SCALE_MODE), blendMode.value_or(DEFAULT_BLEND_MODE), - DisplaySpriteSource::ControlPhase); + DisplaySpritePhase::Control); } } diff --git a/TombEngine/Specific/RGBAColor8Byte.cpp b/TombEngine/Specific/RGBAColor8Byte.cpp index 57f1568fb..7ec856d3e 100644 --- a/TombEngine/Specific/RGBAColor8Byte.cpp +++ b/TombEngine/Specific/RGBAColor8Byte.cpp @@ -99,11 +99,6 @@ RGBAColor8Byte::operator Color() const return Color(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b)); } -RGBAColor8Byte::operator Color() const -{ - return Color(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b)); -} - RGBAColor8Byte::operator Vector3() const { return Vector3(ByteComponentToFloat(r), ByteComponentToFloat(g), ByteComponentToFloat(b)); From 6240cce4e832c5bbf4efd6126db39a7179b61f40 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 19:21:29 +1000 Subject: [PATCH 148/410] Clean up effect rendering --- TombEngine/Renderer/RendererDrawEffect.cpp | 395 ++++++++------------- TombEngine/Renderer/RendererSprites.cpp | 4 +- 2 files changed, 158 insertions(+), 241 deletions(-) diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 1d49791a7..34bbb36c5 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -88,13 +88,10 @@ namespace TEN::Renderer { bool isLastSubdivision = (i == (LaserBeamEffect::SUBDIVISION_COUNT - 1)); - Vector4 color = Vector4::Lerp(beam.OldColor, beam.Color, _interpolationFactor); + auto color = Color::Lerp(beam.OldColor, beam.Color, _interpolationFactor); AddColoredQuad( - Vector3::Lerp( - beam.OldVertices[i], - beam.Vertices[i], - _interpolationFactor), + Vector3::Lerp(beam.OldVertices[i], beam.Vertices[i], _interpolationFactor), Vector3::Lerp( beam.OldVertices[isLastSubdivision ? 0 : (i + 1)], beam.Vertices[isLastSubdivision ? 0 : (i + 1)], @@ -107,13 +104,8 @@ namespace TEN::Renderer beam.OldVertices[LaserBeamEffect::SUBDIVISION_COUNT + i], beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + i], _interpolationFactor), - color, - color, - color, - color, - BlendMode::Additive, - view, - SpriteRenderType::LaserBeam); + color, color, color, color, + BlendMode::Additive, view, SpriteRenderType::LaserBeam); } } } @@ -152,8 +144,7 @@ namespace TEN::Renderer Vector4::Lerp(segment.PrevColor, segment.Color, _interpolationFactor), Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), Vector4::Zero, - blendMode, - view); + blendMode, view); } else if (segment.Flags & (int)StreamerFlags::FadeRight) { @@ -166,8 +157,7 @@ namespace TEN::Renderer Vector4::Zero, Vector4::Zero, Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), - blendMode, - view); + blendMode, view); } else { @@ -180,8 +170,7 @@ namespace TEN::Renderer Vector4::Lerp(segment.PrevColor, segment.Color, _interpolationFactor), Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), Vector4::Lerp(prevSegment.PrevColor, prevSegment.Color, _interpolationFactor), - blendMode, - view); + blendMode, view); } } } @@ -205,7 +194,7 @@ namespace TEN::Renderer auto color = Vector4::Lerp(laser.PrevColor, laser.Color, _interpolationFactor); color.w = Lerp(laser.PrevOpacity, laser.Opacity, _interpolationFactor); - Vector3 laserTarget = Vector3::Lerp(laser.PrevTarget, laser.Target, _interpolationFactor); + auto laserTarget = Vector3::Lerp(laser.PrevTarget, laser.Target, _interpolationFactor); ElectricityKnots[0] = laserTarget; ElectricityKnots[1] = Vector3::Lerp(laser.PrevOrigin, laser.Origin, _interpolationFactor); @@ -229,22 +218,15 @@ namespace TEN::Renderer auto target = laserTarget + interpPosArray[bufferIndex]; auto center = (origin + target) / 2; - auto direction = target - origin; - direction.Normalize(); + auto dir = target - origin; + dir.Normalize(); AddSpriteBillboardConstrained( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LIGHTHING], - center, - color, - PI_DIV_2, - 1.0f, - Vector2(5 * 8.0f, Vector3::Distance(origin, target)), - BlendMode::Additive, - direction, - true, - view); + center, color, PI_DIV_2, 1.0f, Vector2(5 * 8.0f, Vector3::Distance(origin, target)), + BlendMode::Additive, dir, true, view); } - } + } } } @@ -288,8 +270,8 @@ namespace TEN::Renderer auto target = (LaraItem->Pose.Position + interpPosArray[bufferIndex]).ToVector3(); auto center = (origin + target) / 2; - auto direction = target - origin; - direction.Normalize(); + auto dir = target - origin; + dir.Normalize(); byte r, g, b; if (arc.life >= 16) @@ -326,15 +308,9 @@ namespace TEN::Renderer AddSpriteBillboardConstrained( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LIGHTHING], - center, - Vector4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f), - PI_DIV_2, - 1.0f, + center, Vector4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f), PI_DIV_2, 1.0f, Vector2(arc.width * 8, Vector3::Distance(origin, target)), - BlendMode::Additive, - direction, - true, - view); + BlendMode::Additive, dir, true, view); } } } @@ -342,36 +318,31 @@ namespace TEN::Renderer void Renderer::PrepareSmokes(RenderView& view) { - for (int i = 0; i < 32; i++) + for (const auto& smoke : SmokeSparks) { - SMOKE_SPARKS* spark = &SmokeSparks[i]; + if (!smoke.on) + continue; - if (spark->on) - { - AddSpriteBillboard( - &_sprites[spark->def], - Vector3::Lerp( - Vector3(spark->oldPosition.x, spark->oldPosition.y, spark->oldPosition.z), - Vector3(spark->position.x, spark->position.y, spark->position.z), - _interpolationFactor), - Vector4::Lerp( - Vector4(spark->oldShade / 255.0f, spark->oldShade / 255.0f, spark->oldShade / 255.0f, 1.0f), - Vector4(spark->shade / 255.0f, spark->shade / 255.0f, spark->shade / 255.0f, 1.0f), - _interpolationFactor), - TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), - Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), - { - Lerp(spark->oldSize, spark->size, _interpolationFactor) * 4.0f, - Lerp(spark->oldSize, spark->size, _interpolationFactor) * 4.0f - }, - BlendMode::Additive, - true, - view); - } + AddSpriteBillboard( + &_sprites[smoke.def], + Vector3::Lerp( + Vector3(smoke.oldPosition.x, smoke.oldPosition.y, smoke.oldPosition.z), + Vector3(smoke.position.x, smoke.position.y, smoke.position.z), + _interpolationFactor), + Vector4::Lerp( + Vector4(smoke.oldShade / 255.0f, smoke.oldShade / 255.0f, smoke.oldShade / 255.0f, 1.0f), + Vector4(smoke.shade / 255.0f, smoke.shade / 255.0f, smoke.shade / 255.0f, 1.0f), + _interpolationFactor), + TO_RAD(Lerp(smoke.oldRotAng << 4, smoke.rotAng << 4, _interpolationFactor)), + Lerp(smoke.oldScalar, smoke.scalar, _interpolationFactor), + { + Lerp(smoke.oldSize, smoke.size, _interpolationFactor) * 4.0f, + Lerp(smoke.oldSize, smoke.size, _interpolationFactor) * 4.0f + }, + BlendMode::Additive, true, view); } } - void Renderer::PrepareFires(RenderView& view) { for (int k = 0; k < MAX_FIRE_LIST; k++) @@ -385,43 +356,41 @@ namespace TEN::Renderer for (int i = 0; i < MAX_SPARKS_FIRE; i++) { - auto* spark = &FireSparks[i]; + auto* fire = &FireSparks[i]; - if (spark->on) + if (fire->on) { AddSpriteBillboard( - &_sprites[spark->def], + &_sprites[fire->def], Vector3::Lerp( Vector3( - fire->oldPosition.x + spark->oldPosition.x * fire->oldSize / 2, - fire->oldPosition.y + spark->oldPosition.y * fire->oldSize / 2, - fire->oldPosition.z + spark->oldPosition.z * fire->oldSize / 2), + fire->oldPosition.x + fire->oldPosition.x * fire->oldSize / 2, + fire->oldPosition.y + fire->oldPosition.y * fire->oldSize / 2, + fire->oldPosition.z + fire->oldPosition.z * fire->oldSize / 2), Vector3( - fire->position.x + spark->position.x * fire->size / 2, - fire->position.y + spark->position.y * fire->size / 2, - fire->position.z + spark->position.z * fire->size / 2), + fire->position.x + fire->position.x * fire->size / 2, + fire->position.y + fire->position.y * fire->size / 2, + fire->position.z + fire->position.z * fire->size / 2), _interpolationFactor), Vector4::Lerp( Vector4( - spark->oldColor.x / 255.0f * fade, - spark->oldColor.y / 255.0f * fade, - spark->oldColor.z / 255.0f * fade, + fire->oldColor.x / 255.0f * fade, + fire->oldColor.y / 255.0f * fade, + fire->oldColor.z / 255.0f * fade, 1.0f), Vector4( - spark->color.x / 255.0f * fade, - spark->color.y / 255.0f * fade, - spark->color.z / 255.0f * fade, + fire->color.x / 255.0f * fade, + fire->color.y / 255.0f * fade, + fire->color.z / 255.0f * fade, 1.0f), _interpolationFactor), - TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), - Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), + TO_RAD(Lerp(fire->oldRotAng << 4, fire->rotAng << 4, _interpolationFactor)), + Lerp(fire->oldScalar, fire->scalar, _interpolationFactor), Vector2::Lerp( - Vector2(spark->oldSize * fire->oldSize, spark->oldSize * fire->oldSize), - Vector2(spark->size * fire->size, spark->size * fire->size), + Vector2(fire->oldSize * fire->oldSize, fire->oldSize * fire->oldSize), + Vector2(fire->size * fire->size, fire->size * fire->size), _interpolationFactor), - BlendMode::Additive, - true, - view); + BlendMode::Additive, true, view); } } } @@ -481,9 +450,13 @@ namespace TEN::Renderer int meshIndex = NodeOffsets[particle.nodeNumber].meshNum; if (meshIndex >= 0) + { nodePos = GetJointPosition(item, meshIndex, nodePos); + } else + { nodePos = GetJointPosition(LaraItem, -meshIndex, nodePos); + } NodeOffsets[particle.nodeNumber].gotIt = true; NodeVectors[particle.nodeNumber] = nodePos; @@ -511,7 +484,7 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[spriteIndex], pos, - Vector4(particle.r / (float)UCHAR_MAX, particle.g / (float)UCHAR_MAX, particle.b / (float)UCHAR_MAX, 1.0f), + Color(particle.r / (float)UCHAR_MAX, particle.g / (float)UCHAR_MAX, particle.b / (float)UCHAR_MAX, 1.0f), TO_RAD(particle.rotAng << 4), particle.scalar, Vector2(particle.size, particle.size), particle.blendMode, true, view); @@ -562,18 +535,18 @@ namespace TEN::Renderer } } - byte oldColor = (splash.oldLife >= 32 ? 128 : (byte)((splash.oldLife / 32.0f) * 128)); + byte prevColor = (splash.oldLife >= 32 ? 128 : (byte)((splash.oldLife / 32.0f) * 128)); if (!splash.isRipple) { if (splash.oldHeightSpeed < 0 && splash.oldHeight < 1024) { float multiplier = splash.oldHeight / 1024.0f; - oldColor = (float)oldColor * multiplier; + prevColor = (float)prevColor * multiplier; } } - color = (byte)Lerp(oldColor, color, _interpolationFactor); + color = (byte)Lerp(prevColor, color, _interpolationFactor); float xInner; float zInner; @@ -610,17 +583,13 @@ namespace TEN::Renderer z2Outer += splash.z; AddQuad(&_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + splash.spriteSequenceStart + (int)splash.animationPhase], - Vector3(xOuter, yOuter, zOuter), - Vector3(x2Outer, yOuter, z2Outer), - Vector3(x2Inner, yInner, z2Inner), - Vector3(xInner, yInner, zInner), - Vector4(color / 255.0f, color / 255.0f, color / 255.0f, 1.0f), - 0, - 1, - { 0, 0 }, - BlendMode::Additive, - false, - view); + Vector3(xOuter, yOuter, zOuter), + Vector3(x2Outer, yOuter, z2Outer), + Vector3(x2Inner, yInner, z2Inner), + Vector3(xInner, yInner, zInner), + Vector4(color / 255.0f, color / 255.0f, color / 255.0f, 1.0f), + 0, 1, Vector2::Zero, + BlendMode::Additive, false, view); } } } @@ -643,11 +612,9 @@ namespace TEN::Renderer Vector3::Lerp(bubble.PrevPosition, bubble.Position, _interpolationFactor), Vector4::Lerp(bubble.PrevColor, bubble.Color, _interpolationFactor), 0.0f, - 1.0f, + 1.0f, Vector2::Lerp(bubble.PrevSize, bubble.Size, _interpolationFactor) / 2, - BlendMode::Additive, - true, - view); + BlendMode::Additive, true, view); } } @@ -667,20 +634,15 @@ namespace TEN::Renderer auto axis = drip.Velocity; drip.Velocity.Normalize(axis); - auto oldAxis = drip.OldVelocity; - drip.OldVelocity.Normalize(oldAxis); + auto prevAxis = drip.OldVelocity; + drip.OldVelocity.Normalize(prevAxis); AddSpriteBillboardConstrained( &_sprites[Objects[ID_DRIP_SPRITE].meshIndex], Vector3::Lerp(drip.OldPosition, drip.Position, _interpolationFactor), Vector4::Lerp(drip.OldColor, drip.Color, _interpolationFactor), - 0.0f, - 1.0f, - Vector2::Lerp(drip.OldSize, drip.Size, _interpolationFactor), - BlendMode::Additive, - -Vector3::Lerp(oldAxis, axis, _interpolationFactor), - false, - view); + 0.0f, 1.0f, Vector2::Lerp(drip.OldSize, drip.Size, _interpolationFactor), + BlendMode::Additive, -Vector3::Lerp(prevAxis, axis, _interpolationFactor), false, view); } } @@ -706,13 +668,8 @@ namespace TEN::Renderer &_sprites[ripple.SpriteIndex], Vector3::Lerp(ripple.PrevPosition, ripple.Position, _interpolationFactor), Vector4::Lerp(oldColor, color, _interpolationFactor), - 0.0f, - 1.0f, - Vector2(Lerp(ripple.PrevSize, ripple.Size, _interpolationFactor) * 2), - BlendMode::Additive, - ripple.Normal, - true, - view); + 0.0f, 1.0f, Vector2(Lerp(ripple.PrevSize, ripple.Size, _interpolationFactor) * 2), + BlendMode::Additive, ripple.Normal, true, view); } } @@ -728,9 +685,13 @@ namespace TEN::Renderer auto color = Vector4::Zero; if (uwBlood.Init) + { color = Vector4(uwBlood.Init / 2, 0, uwBlood.Init / 16, UCHAR_MAX); + } else + { color = Vector4(uwBlood.Life / 2, 0, uwBlood.Life / 16, UCHAR_MAX); + } color.x = (int)std::clamp((int)color.x, 0, UCHAR_MAX); color.y = (int)std::clamp((int)color.y, 0, UCHAR_MAX); @@ -752,15 +713,11 @@ namespace TEN::Renderer &_sprites[uwBlood.SpriteIndex], Vector3::Lerp(uwBlood.PrevPosition, uwBlood.Position, _interpolationFactor), Vector4::Lerp(oldColor, color, _interpolationFactor), - 0.0f, - 1.0f, + 0.0f, 1.0f, Vector2( Lerp(uwBlood.PrevSize, uwBlood.Size, _interpolationFactor), - Lerp(uwBlood.PrevSize, uwBlood.Size, _interpolationFactor) - ) * 2, - BlendMode::Additive, - true, - view); + Lerp(uwBlood.PrevSize, uwBlood.Size, _interpolationFactor)) * 2, + BlendMode::Additive, true, view); } } @@ -775,7 +732,7 @@ namespace TEN::Renderer for (int i = 0; i < MAX_SHOCKWAVE; i++) { - SHOCKWAVE_STRUCT* shockwave = &ShockWaves[i]; + auto* shockwave = &ShockWaves[i]; if (!shockwave->life) continue; @@ -836,7 +793,6 @@ namespace TEN::Renderer r = shockwave->r * shockwave->life / 255.0f; } - if (shockwave->sg < shockwave->g) { shockwave->sg += shockwave->g / 18; @@ -847,7 +803,6 @@ namespace TEN::Renderer g = shockwave->g * shockwave->life / 255.0f; } - if (shockwave->sb < shockwave->b) { shockwave->sb += shockwave->b / 18; @@ -916,7 +871,7 @@ namespace TEN::Renderer g / 16.0f, b / 16.0f, 1.0f), - 0, 1, { 0,0 }, BlendMode::Additive, true, view); + 0, 1, Vector2::Zero, BlendMode::Additive, true, view); } else if (shockwave->style == (int)ShockwaveStyle::Knockback) @@ -933,7 +888,7 @@ namespace TEN::Renderer g / 16.0f, b / 16.0f, 1.0f), - 0, 1, { 0,0 }, BlendMode::Additive, true, view); + 0, 1, Vector2::Zero, BlendMode::Additive, true, view); } p1 = p2; @@ -946,7 +901,7 @@ namespace TEN::Renderer { for (int i = 0; i < 32; i++) { - BLOOD_STRUCT* blood = &Blood[i]; + auto* blood = &Blood[i]; if (blood->on) { @@ -962,16 +917,13 @@ namespace TEN::Renderer Vector4::Lerp( Vector4(blood->oldShade / 255.0f, blood->oldShade * 0, blood->oldShade * 0, 1.0f), Vector4(blood->shade / 255.0f, blood->shade * 0, blood->shade * 0, 1.0f), - _interpolationFactor - ), - TO_RAD(Lerp(blood->oldRotAng << 4, blood->rotAng << 4, _interpolationFactor)), - 1.0f, - { - Lerp(blood->oldSize, blood->size, _interpolationFactor) * 8.0f, - Lerp(blood->oldSize, blood->size, _interpolationFactor) * 8.0f }, - BlendMode::Additive, - true, - view); + _interpolationFactor), + TO_RAD(Lerp(blood->oldRotAng << 4, blood->rotAng << 4, _interpolationFactor)), + 1.0f, + Vector2( + Lerp(blood->oldSize, blood->size, _interpolationFactor) * 8.0f, + Lerp(blood->oldSize, blood->size, _interpolationFactor) * 8.0f), + BlendMode::Additive, true, view); } } } @@ -980,12 +932,12 @@ namespace TEN::Renderer { constexpr auto RAIN_WIDTH = 4.0f; - for (auto& p : Weather.GetParticles()) + for (const auto& part : Weather.GetParticles()) { - if (!p.Enabled) + if (!part.Enabled) continue; - switch (p.Type) + switch (part.Type) { case WeatherType::None: @@ -994,14 +946,10 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], - Vector3::Lerp(p.PrevPosition, p.Position, _interpolationFactor), - Vector4(1.0f, 1.0f, 1.0f, p.Transparency()), - 0.0f, - 1.0f, - Vector2(Lerp(p.PrevSize, p.Size, _interpolationFactor)), - BlendMode::Additive, - true, - view); + Vector3::Lerp(part.PrevPosition, part.Position, _interpolationFactor), + Color(1.0f, 1.0f, 1.0f, part.Transparency()), + 0.0f, 1.0f, Vector2(Lerp(part.PrevSize, part.Size, _interpolationFactor)), + BlendMode::Additive, true, view); break; @@ -1012,14 +960,10 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_UNDERWATERDUST], - Vector3::Lerp(p.PrevPosition, p.Position, _interpolationFactor), - Vector4(1.0f, 1.0f, 1.0f, p.Transparency()), - 0.0f, - 1.0f, - Vector2(Lerp(p.PrevSize, p.Size, _interpolationFactor)), - BlendMode::Additive, - true, - view); + Vector3::Lerp(part.PrevPosition, part.Position, _interpolationFactor), + Color(1.0f, 1.0f, 1.0f, part.Transparency()), + 0.0f, 1.0f, Vector2(Lerp(part.PrevSize, part.Size, _interpolationFactor)), + BlendMode::Additive, true, view); break; @@ -1029,19 +973,15 @@ namespace TEN::Renderer return; Vector3 v; - p.Velocity.Normalize(v); + part.Velocity.Normalize(v); AddSpriteBillboardConstrained( &_sprites[Objects[ID_DRIP_SPRITE].meshIndex], - Vector3::Lerp(p.PrevPosition, p.Position, _interpolationFactor), - Vector4(0.8f, 1.0f, 1.0f, p.Transparency()), - 0.0f, - 1.0f, - Vector2(RAIN_WIDTH, Lerp(p.PrevSize, p.Size, _interpolationFactor)), - BlendMode::Additive, - -v, - true, - view); + Vector3::Lerp(part.PrevPosition, part.Position, _interpolationFactor), + Color(0.8f, 1.0f, 1.0f, part.Transparency()), + 0.0f, 1.0f, + Vector2(RAIN_WIDTH, Lerp(part.PrevSize, part.Size, _interpolationFactor)), + BlendMode::Additive, -v, true, view); break; } @@ -1053,8 +993,8 @@ namespace TEN::Renderer _context->VSSetShader(_vsStatics.Get(), nullptr, 0); _context->PSSetShader(_psStatics.Get(), nullptr, 0); - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); @@ -1178,8 +1118,8 @@ namespace TEN::Renderer _context->VSSetShader(_vsStatics.Get(), nullptr, 0); _context->PSSetShader(_psStatics.Get(), nullptr, 0); - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); @@ -1291,7 +1231,7 @@ namespace TEN::Renderer Texture2D Renderer::CreateDefaultNormalTexture() { - std::vector data = { 128, 128, 255, 1 }; + auto data = std::vector{ 128, 128, 255, 1 }; return Texture2D(_device.Get(), 1, 1, data.data()); } @@ -1375,9 +1315,7 @@ namespace TEN::Renderer for (int p = 0; p < passes; p++) { if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) - { continue; - } BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); @@ -1394,8 +1332,8 @@ namespace TEN::Renderer _context->VSSetShader(_vsStatics.Get(), nullptr, 0); _context->PSSetShader(_psStatics.Get(), nullptr, 0); - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); @@ -1415,8 +1353,6 @@ namespace TEN::Renderer void Renderer::DrawDebris(RenderView& view, RendererPass rendererPass) { - std::vector vertices; - bool activeDebrisExist = false; for (auto& deb : DebrisFragments) { @@ -1439,9 +1375,7 @@ namespace TEN::Renderer if (deb.active) { if (!SetupBlendModeAndAlphaTest(deb.mesh.blendMode, rendererPass, 0)) - { continue; - } if (deb.isStatic) { @@ -1513,15 +1447,12 @@ namespace TEN::Renderer &_sprites[Objects[ID_SMOKE_SPRITES].meshIndex + smoke.sprite], Vector3::Lerp(smoke.oldPosition, smoke.position, _interpolationFactor), Vector4::Lerp(smoke.oldColor, smoke.color, _interpolationFactor), - Lerp(smoke.oldRotation, smoke.rotation, _interpolationFactor), - 1.0f, - { + Lerp(smoke.oldRotation, smoke.rotation, _interpolationFactor), + 1.0f, + Vector2( Lerp(smoke.oldSize, smoke.size, _interpolationFactor), - Lerp(smoke.oldSize, smoke.size, _interpolationFactor) - }, - BlendMode::AlphaBlend, - true, - view); + Lerp(smoke.oldSize, smoke.size, _interpolationFactor)), + BlendMode::AlphaBlend, true, view); } } @@ -1534,20 +1465,18 @@ namespace TEN::Renderer for (int i = 0; i < SparkParticles.size(); i++) { - SparkParticle& s = SparkParticles[i]; + auto& s = SparkParticles[i]; if (!s.active) continue; if (!CheckIfSlotExists(ID_SPARK_SPRITE, "Spark particle rendering")) - { return; - } - Vector3 oldVelocity; + Vector3 prevVelocity; Vector3 velocity; - s.oldVelocity.Normalize(oldVelocity); + s.oldVelocity.Normalize(prevVelocity); s.velocity.Normalize(velocity); - velocity = Vector3::Lerp(oldVelocity, velocity, _interpolationFactor); + velocity = Vector3::Lerp(prevVelocity, velocity, _interpolationFactor); velocity.Normalize(); float normalizedLife = s.age / s.life; @@ -1558,16 +1487,11 @@ namespace TEN::Renderer &_sprites[Objects[ID_SPARK_SPRITE].meshIndex], Vector3::Lerp(s.oldPos, s.pos, _interpolationFactor), color, - 0, - 1, - { + 0, 1, + Vector2( s.width, - s.height * height - }, - BlendMode::Additive, - -velocity, - false, - view); + s.height * height), + BlendMode::Additive, -velocity, false, view); } } @@ -1578,25 +1502,22 @@ namespace TEN::Renderer for (int i = 0; i < explosionParticles.size(); i++) { - ExplosionParticle& e = explosionParticles[i]; - if (!e.active) continue; + auto& exp = explosionParticles[i]; + if (!exp.active) continue; if (!CheckIfSlotExists(ID_EXPLOSION_SPRITES, "Explosion particles rendering")) return; AddSpriteBillboard( - &_sprites[Objects[ID_EXPLOSION_SPRITES].meshIndex + e.sprite], - Vector3::Lerp(e.oldPos, e.pos, _interpolationFactor), - Vector4::Lerp(e.oldTint, e.tint, _interpolationFactor), - Lerp(e.oldRotation, e.rotation, _interpolationFactor), + &_sprites[Objects[ID_EXPLOSION_SPRITES].meshIndex + exp.sprite], + Vector3::Lerp(exp.oldPos, exp.pos, _interpolationFactor), + Vector4::Lerp(exp.oldTint, exp.tint, _interpolationFactor), + Lerp(exp.oldRotation, exp.rotation, _interpolationFactor), 1.0f, - { - Lerp(e.oldSize, e.size, _interpolationFactor), - Lerp(e.oldSize, e.size, _interpolationFactor) - }, - BlendMode::Additive, - true, - view); + Vector2( + Lerp(exp.oldSize, exp.size, _interpolationFactor), + Lerp(exp.oldSize, exp.size, _interpolationFactor)), + BlendMode::Additive, true, view); } } @@ -1604,26 +1525,22 @@ namespace TEN::Renderer { using namespace TEN::Effects; - for (SimpleParticle& s : simpleParticles) + for (const auto& part : simpleParticles) { - if (!s.active) continue; + if (!part.active) + continue; - if (!CheckIfSlotExists(s.sequence, "Particle rendering")) + if (!CheckIfSlotExists(part.sequence, "Particle rendering")) continue; AddSpriteBillboard( - &_sprites[Objects[s.sequence].meshIndex + s.sprite], - Vector3::Lerp(s.oldWorldPosition, s.worldPosition, _interpolationFactor), - Vector4(1.0f), - 0, - 1.0f, - { - Lerp(s.oldSize, s.size, _interpolationFactor), - Lerp(s.oldSize, s.size, _interpolationFactor) / 2 - }, - BlendMode::AlphaBlend, - true, - view); + &_sprites[Objects[part.sequence].meshIndex + part.sprite], + Vector3::Lerp(part.oldWorldPosition, part.worldPosition, _interpolationFactor), + Color(1.0f, 1.0f, 1.0f), 0, 1.0f, + Vector2( + Lerp(part.oldSize, part.size, _interpolationFactor), + Lerp(part.oldSize, part.size, _interpolationFactor) / 2), + BlendMode::AlphaBlend, true, view); } } } diff --git a/TombEngine/Renderer/RendererSprites.cpp b/TombEngine/Renderer/RendererSprites.cpp index 28d3cc8ad..272b06884 100644 --- a/TombEngine/Renderer/RendererSprites.cpp +++ b/TombEngine/Renderer/RendererSprites.cpp @@ -39,7 +39,7 @@ namespace TEN::Renderer void Renderer::AddSpriteBillboardConstrained(RendererSprite* sprite, const Vector3& pos, const Vector4& color, float orient2D, float scale, Vector2 size, BlendMode blendMode, const Vector3& constrainAxis, - bool softParticles, RenderView& view, SpriteRenderType renderType) + bool isSoft, RenderView& view, SpriteRenderType renderType) { if (scale <= 0.0f) scale = 1.0f; @@ -58,7 +58,7 @@ namespace TEN::Renderer spr.Height = size.y; spr.BlendMode = blendMode; spr.ConstrainAxis = constrainAxis; - spr.SoftParticle = softParticles; + spr.SoftParticle = isSoft; spr.c1 = color; spr.c2 = color; spr.c3 = color; From 460d2d9edbe96518084190b200395a25546291b4 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 19:49:52 +1000 Subject: [PATCH 149/410] Add interpolation for pickup summary; more clean up --- TombEngine/Game/Hud/PickupSummary.cpp | 2 ++ TombEngine/Game/Hud/PickupSummary.h | 13 +++++++++ TombEngine/Renderer/RendererDraw.cpp | 33 ++++++++++------------ TombEngine/Renderer/RendererDrawEffect.cpp | 10 ++----- TombEngine/Renderer/RendererDrawMenu.cpp | 7 ++++- TombEngine/Renderer/RendererSprites.cpp | 23 ++++----------- 6 files changed, 45 insertions(+), 43 deletions(-) diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index bc816aafc..137d54233 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -39,6 +39,8 @@ namespace TEN::Hud constexpr auto ROT_RATE = ANGLE(360.0f / (LIFE_MAX * FPS)); constexpr auto ROT = EulerAngles(0, ROT_RATE, 0); + StoreInterpolationData(); + // Move offscreen. if (Life <= 0.0f && isHead) { diff --git a/TombEngine/Game/Hud/PickupSummary.h b/TombEngine/Game/Hud/PickupSummary.h index a1c0b012f..6a68d50b5 100644 --- a/TombEngine/Game/Hud/PickupSummary.h +++ b/TombEngine/Game/Hud/PickupSummary.h @@ -25,8 +25,21 @@ namespace TEN::Hud float StringScale = 0.0f; float StringScalar = 0.0f; + Vector2 PrevPosition = Vector2::Zero; + EulerAngles PrevOrientation = EulerAngles::Identity; + float PrevScale = 0.0f; + float PrevOpacity = 0.0f; + bool IsOffscreen() const; void Update(bool isHead); + + void StoreInterpolationData() + { + PrevPosition = Position; + PrevOrientation = Orientation; + PrevScale = Scale; + PrevOpacity = Opacity; + } }; class PickupSummaryController diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 2af4157dd..2ce60496a 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1714,7 +1714,7 @@ namespace TEN::Renderer PrepareLaserBarriers(view); PrepareSingleLaserBeam(view); - // Sprites grouped in buckets for instancing. Non-commutative sprites are collected for a later stage. + // Sprites grouped in buckets for instancing. Non-commutative sprites are collected at a later stage. SortAndPrepareSprites(view); auto time2 = std::chrono::high_resolution_clock::now(); @@ -1726,7 +1726,7 @@ namespace TEN::Renderer SetDepthState(DepthState::Write, true); SetCullMode(CullMode::CounterClockwise, true); - // Bind constant buffers + // Bind constant buffers. BindConstantBufferVS(ConstantBufferRegister::Camera, _cbCameraMatrices.get()); BindConstantBufferVS(ConstantBufferRegister::Item, _cbItem.get()); BindConstantBufferVS(ConstantBufferRegister::InstancedStatics, _cbInstancedStaticMeshBuffer.get()); @@ -1763,7 +1763,7 @@ namespace TEN::Renderer _context->ClearRenderTargetView(_renderTarget.RenderTargetView.Get(), _debugPage == RendererDebugPage::WireframeMode ? Colors::White : Colors::Black); _context->ClearDepthStencilView(_renderTarget.DepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); - // Reset viewport and scissor + // Reset viewport and scissor. _context->RSSetViewports(1, &view.Viewport); ResetScissor(); @@ -1812,7 +1812,7 @@ namespace TEN::Renderer // Draw horizon and sky. DrawHorizonAndSky(view, _renderTarget.DepthStencilView.Get()); - // Build G-Buffer (Normals + Depth). + // Build G-Buffer (normals + depth). _context->ClearRenderTargetView(_normalsRenderTarget.RenderTargetView.Get(), Colors::Black); _context->ClearRenderTargetView(_depthRenderTarget.RenderTargetView.Get(), Colors::White); @@ -1831,7 +1831,7 @@ namespace TEN::Renderer DrawRats(view, RendererPass::GBuffer); DrawLocusts(view, RendererPass::GBuffer); - // Calculate ambient occlusion + // Calculate ambient occlusion. if (g_Configuration.EnableAmbientOcclusion) { _doingFullscreenPass = true; @@ -1849,8 +1849,7 @@ namespace TEN::Renderer _context->RSSetViewports(1, &view.Viewport); ResetScissor(); - // Bind main render target again. - // At this point, main depth buffer is already filled and avoids overdraw in following steps. + // Bind main render target again. Main depth buffer is already filled and avoids overdraw in following steps. _context->OMSetRenderTargets(1, _renderTarget.RenderTargetView.GetAddressOf(), _renderTarget.DepthStencilView.Get()); // Draw opaque, alpha test, and fast alpha blend faces. @@ -1883,7 +1882,7 @@ namespace TEN::Renderer DrawFishSwarm(view, RendererPass::Additive); // Collect all non-commutative transparent faces. - // NOTE: Sorted sprites are already collected at the beginning of the frame. + // NOTE: Sorted sprites already collected at beginning of frame. DrawRooms(view, RendererPass::CollectTransparentFaces); DrawItems(view, RendererPass::CollectTransparentFaces); DrawStatics(view, RendererPass::CollectTransparentFaces); @@ -1896,11 +1895,11 @@ namespace TEN::Renderer // Draw sorted faces. DrawSortedFaces(view); - // HACK: Draw gunflashes after everything because they are very near the camera. + // HACK: Gunflashes drawn after everything because they are very near the camera. DrawGunFlashes(view); DrawBaddyGunflashes(view); - // Draw 3D debug lines and trianges. + // Draw 3D debug lines and triangles. DrawLines3D(view); DrawTriangles3D(view); @@ -2000,7 +1999,7 @@ namespace TEN::Renderer SetCullMode(CullMode::Clockwise); } - RenderView view = RenderView(&Camera, 0, PI / 2.0f, 32, DEFAULT_FAR_VIEW, ROOM_AMBIENT_MAP_SIZE, ROOM_AMBIENT_MAP_SIZE); + auto view = RenderView(&Camera, 0, PI / 2.0f, 32, DEFAULT_FAR_VIEW, ROOM_AMBIENT_MAP_SIZE, ROOM_AMBIENT_MAP_SIZE); CCameraMatrixBuffer cameraConstantBuffer; cameraConstantBuffer.DualParaboloidView = Matrix::CreateLookAt(position, position + Vector3(0, 0, 1024), -Vector3::UnitY); @@ -2016,12 +2015,10 @@ namespace TEN::Renderer _context->VSSetShader(_vsRoomAmbientSky.Get(), nullptr, 0); if (Lara.Control.Look.OpticRange != 0) - { AlterFOV(ANGLE(DEFAULT_FOV) - Lara.Control.Look.OpticRange, false); - } - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; // Draw sky. auto rotation = Matrix::CreateRotationX(PI); @@ -2220,13 +2217,13 @@ namespace TEN::Renderer void Renderer::DrawItems(RenderView& view, RendererPass rendererPass) { - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); - // Set shaders + // Set shaders. if (rendererPass == RendererPass::GBuffer) { _context->VSSetShader(_vsGBufferItems.Get(), nullptr, 0); diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 34bbb36c5..6cbcbd011 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -1300,17 +1300,13 @@ namespace TEN::Renderer BindStaticLights(effect->LightsToDraw); _cbStatic.UpdateData(_stStatic, _context.Get()); - auto* meshPtr = effect->Mesh; - auto m_lastBlendMode = BlendMode::Unknown; - - for (auto& bucket : meshPtr->Buckets) + auto& mesh = *effect->Mesh; + for (auto& bucket : mesh.Buckets) { if (bucket.NumVertices == 0) - { continue; - } - int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; + int passes = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest) ? 2 : 1; for (int p = 0; p < passes; p++) { diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index f38ba9add..69dfe4271 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -718,8 +718,13 @@ namespace TEN::Renderer constexpr auto COUNT_STRING_INF = "Inf"; constexpr auto COUNT_STRING_OFFSET = Vector2(DISPLAY_SPACE_RES.x / 40, 0.0f); + auto pos = Vector2::Lerp(pickup.PrevPosition, pickup.Position, _interpolationFactor); + auto orient = EulerAngles::Lerp(pickup.PrevOrientation, pickup.Orientation, _interpolationFactor); + float scale = Lerp(pickup.PrevScale, pickup.Scale, _interpolationFactor); + float opacity = Lerp(pickup.PrevOpacity, pickup.Opacity, _interpolationFactor); + // Draw display pickup. - DrawObjectIn2DSpace(pickup.ObjectID, pickup.Position, pickup.Orientation, pickup.Scale); + DrawObjectIn2DSpace(pickup.ObjectID, pos, orient, scale); // Draw count string. if (pickup.Count != 1) diff --git a/TombEngine/Renderer/RendererSprites.cpp b/TombEngine/Renderer/RendererSprites.cpp index 272b06884..417155097 100644 --- a/TombEngine/Renderer/RendererSprites.cpp +++ b/TombEngine/Renderer/RendererSprites.cpp @@ -39,7 +39,7 @@ namespace TEN::Renderer void Renderer::AddSpriteBillboardConstrained(RendererSprite* sprite, const Vector3& pos, const Vector4& color, float orient2D, float scale, Vector2 size, BlendMode blendMode, const Vector3& constrainAxis, - bool isSoft, RenderView& view, SpriteRenderType renderType) + bool isSoftParticle, RenderView& view, SpriteRenderType renderType) { if (scale <= 0.0f) scale = 1.0f; @@ -58,7 +58,7 @@ namespace TEN::Renderer spr.Height = size.y; spr.BlendMode = blendMode; spr.ConstrainAxis = constrainAxis; - spr.SoftParticle = isSoft; + spr.SoftParticle = isSoftParticle; spr.c1 = color; spr.c2 = color; spr.c3 = color; @@ -259,24 +259,17 @@ namespace TEN::Renderer void Renderer::DrawSprites(RenderView& view, RendererPass rendererPass) { if (view.SpritesToDraw.empty()) - { return; - } - // Draw instanced sprites + // Draw instanced sprites. bool wasGPUSet = false; - for (auto& spriteBucket : _spriteBuckets) { if (spriteBucket.SpritesToDraw.size() == 0 || !spriteBucket.IsBillboard) - { continue; - } if (!SetupBlendModeAndAlphaTest(spriteBucket.BlendMode, rendererPass, 0)) - { continue; - } if (!wasGPUSet) { @@ -291,8 +284,8 @@ namespace TEN::Renderer _context->PSSetShader(_psInstancedSprites.Get(), nullptr, 0); // Set up vertex buffer and parameters. - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); wasGPUSet = true; @@ -329,20 +322,16 @@ namespace TEN::Renderer _numInstancedSpritesDrawCalls++; } - // Draw 3D non instanced sprites + // Draw 3D non-instanced sprites. wasGPUSet = false; for (auto& spriteBucket : _spriteBuckets) { if (spriteBucket.SpritesToDraw.empty() || spriteBucket.IsBillboard) - { continue; - } if (!SetupBlendModeAndAlphaTest(spriteBucket.BlendMode, rendererPass, 0)) - { continue; - } if (!wasGPUSet) { From 272db667727614c906e396931774b4e7cb0c63ca Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 20:37:41 +1000 Subject: [PATCH 150/410] Interpolate crosshairs (partial solution) --- TombEngine/Game/Hud/PickupSummary.cpp | 5 ++++- TombEngine/Game/Hud/TargetHighlighter.cpp | 22 ++++++++++++++++------ TombEngine/Game/Hud/TargetHighlighter.h | 15 +++++++++++++++ TombEngine/Game/gui.cpp | 2 +- TombEngine/Renderer/Renderer.h | 14 ++++++++------ TombEngine/Renderer/RendererDraw.cpp | 12 ++++++------ TombEngine/Renderer/RendererDrawMenu.cpp | 14 +++++++------- TombEngine/Renderer/RendererHelper.cpp | 5 +++++ 8 files changed, 62 insertions(+), 27 deletions(-) diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index 137d54233..810226208 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -215,7 +215,10 @@ namespace TEN::Hud _displayPickups.erase( std::remove_if( _displayPickups.begin(), _displayPickups.end(), - [](const DisplayPickup& pickup) { return ((pickup.Life <= 0.0f) && pickup.IsOffscreen()); }), + [](const DisplayPickup& pickup) + { + return ((pickup.Life <= 0.0f) && pickup.IsOffscreen()); + }), _displayPickups.end()); } diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 166dc66a8..cd52b5825 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -74,6 +74,9 @@ namespace TEN::Hud constexpr auto ORIENT_LERP_ALPHA = 0.1f; constexpr auto RADIUS_LERP_ALPHA = 0.2f; + if (Position.has_value()) + StoreInterpolationData(); + // Update active status. IsActive = isActive; @@ -137,23 +140,30 @@ namespace TEN::Hud if (!Position.has_value()) return; + auto pos0 = Vector2::Lerp(*Position, PrevPosition, g_Renderer.GetInterpolationFactor()); + short orient0 = (short)Lerp(PrevOrientation, Orientation, g_Renderer.GetInterpolationFactor()); // TODO: use Geometry::GetShortestAngle() + float scale = Lerp(PrevScale, Scale, g_Renderer.GetInterpolationFactor()); + auto color = Color::Lerp(PrevColor, Color, g_Renderer.GetInterpolationFactor()); + // Draw main static element. AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, STATIC_ELEMENT_SPRITE_ID, - *Position, Orientation, Vector2(Scale), Color, + pos0, orient0, Vector2(scale), color, PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fill, BlendMode::Additive, DisplaySpritePhase::Draw); // Draw animated outer segment elements. - for (const auto& segment : Segments) + for (int i = 0; i < Segments.size(); i++) { - auto pos = *Position + segment.PosOffset; - short orient = Orientation + segment.OrientOffset; - auto scale = Vector2(Scale / 2); + const auto& segment = Segments[i]; + const auto& prevSegment = PrevSegments[i]; + + auto pos1 = pos0 + Vector2::Lerp(prevSegment.PosOffset, segment.PosOffset, g_Renderer.GetInterpolationFactor()); + short orient1 = orient0 + (short)Lerp(prevSegment.OrientOffset, segment.OrientOffset, g_Renderer.GetInterpolationFactor()); // TODO: use Geometry::GetShortestAngle() AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, SEGMENT_ELEMENT_SPRITE_ID, - pos, orient, scale, Color, + pos1, orient1, Vector2(scale / 2), color, PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fill, BlendMode::Additive, DisplaySpritePhase::Draw); } diff --git a/TombEngine/Game/Hud/TargetHighlighter.h b/TombEngine/Game/Hud/TargetHighlighter.h index b62c5b3df..9108137b4 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.h +++ b/TombEngine/Game/Hud/TargetHighlighter.h @@ -46,6 +46,21 @@ namespace TEN::Hud // Utilities void Update(const Vector3& targetPos, bool isActive, bool doPulse); void Draw() const; + + Vector2 PrevPosition = Vector2::Zero; + short PrevOrientation = 0; + float PrevScale = 0.0f; + Vector4 PrevColor = Vector4::Zero; + std::array PrevSegments = {}; + + void StoreInterpolationData() + { + PrevPosition = *Position; + PrevOrientation = Orientation; + PrevScale = Scale; + PrevColor = Color; + PrevSegments = Segments; + } }; class TargetHighlighterController diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 7767da684..45162341c 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3448,7 +3448,7 @@ namespace TEN::Gui needleOrient.Lerp(EulerAngles(0, item->Pose.Orientation.y, 0), LERP_ALPHA); float wibble = std::sin(((float)(GameTimer & 0x3F) / (float)0x3F) * PI_MUL_2); - this->CompassNeedleAngle = needleOrient.y + ANGLE(wibble); + CompassNeedleAngle = needleOrient.y + ANGLE(wibble); // HACK: Needle is rotated in the draw function. const auto& invObject = InventoryObjectTable[INV_OBJECT_COMPASS]; diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 527c7a33d..6890825d0 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -377,7 +377,7 @@ namespace TEN::Renderer VertexBuffer _sortedPolygonsVertexBuffer; IndexBuffer _sortedPolygonsIndexBuffer; - // Used for variable framerate + // Variable framerate. float _interpolationFactor = 0.0f; // Private functions @@ -587,8 +587,8 @@ namespace TEN::Renderer void DrawBar(float percent, const RendererHudBar& bar, GAME_OBJECT_ID textureSlot, int frame, bool poison); void Create(); void Initialize(int w, int h, bool windowed, HWND handle); - void Render(float interpolationFactor); - void RenderTitle(float interpolationFactor); + void Render(float interpFactor); + void RenderTitle(float interpFactor); void Lock(); bool PrepareDataForTheRenderer(); void UpdateCameraMatrices(CAMERA_INFO* cam, float roll, float fov, float farView); @@ -641,9 +641,11 @@ namespace TEN::Renderer void SetTextureOrDefault(Texture2D& texture, std::wstring path); std::string GetDefaultAdapterName(); void SaveOldState(); - Vector2i GetScreenResolution() const; - std::optional Get2DPosition(const Vector3& pos) const; - Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero); + + float GetInterpolationFactor() const; + Vector2i GetScreenResolution() const; + std::optional Get2DPosition(const Vector3& pos) const; + Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero); std::pair GetRay(const Vector2& pos) const; void AddDisplaySprite(const RendererSprite& sprite, const Vector2& pos2D, short orient, const Vector2& size, const Vector4& color, diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 2ce60496a..8b131c80e 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3074,15 +3074,15 @@ namespace TEN::Renderer SetCullMode(CullMode::CounterClockwise); } - void Renderer::Render(float interpolationFactor) + void Renderer::Render(float interpFactor) { //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); // Interpolate camera. - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolationFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolationFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolationFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpolationFactor); + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum=_currentGameCamera.Camera.Frustum; @@ -3091,7 +3091,7 @@ namespace TEN::Renderer _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - _interpolationFactor = interpolationFactor; + _interpolationFactor = interpFactor; RenderScene(&_backBuffer, true, _gameCamera); diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 69dfe4271..8ac86c306 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -729,7 +729,7 @@ namespace TEN::Renderer // Draw count string. if (pickup.Count != 1) { - auto countString = (pickup.Count != -1) ? std::to_string(pickup.Count) : COUNT_STRING_INF; + auto countString = (pickup.Count != NO_VALUE) ? std::to_string(pickup.Count) : COUNT_STRING_INF; auto countStringPos = pickup.Position + COUNT_STRING_OFFSET; AddString(countString, countStringPos, Color(PRINTSTRING_COLOR_WHITE), pickup.StringScale, SF()); @@ -1118,12 +1118,12 @@ namespace TEN::Renderer _swapChain->Present(1, 0); } - void Renderer::RenderTitle(float interpolationFactor) + void Renderer::RenderTitle(float interpFactor) { - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpolationFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpolationFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpolationFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpolationFactor); + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; @@ -1132,7 +1132,7 @@ namespace TEN::Renderer _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - _interpolationFactor = interpolationFactor; + _interpolationFactor = interpFactor; RenderScene(&_dumpScreenRenderTarget, false, _gameCamera); diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 4ef1310fc..7a0ae86c7 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -519,6 +519,11 @@ namespace TEN::Renderer return s; } + float Renderer::GetInterpolationFactor() const + { + return _interpolationFactor; + } + Vector2i Renderer::GetScreenResolution() const { return Vector2i(_screenWidth, _screenHeight); From c398f4ae58c34a3b743c023e404c593afaa8798d Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 20:46:17 +1000 Subject: [PATCH 151/410] Prepare interpolation data for speedometer --- TombEngine/Game/Hud/Speedometer.cpp | 4 ++++ TombEngine/Game/Hud/Speedometer.h | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/TombEngine/Game/Hud/Speedometer.cpp b/TombEngine/Game/Hud/Speedometer.cpp index dbfa3044d..cc3d0fe69 100644 --- a/TombEngine/Game/Hud/Speedometer.cpp +++ b/TombEngine/Game/Hud/Speedometer.cpp @@ -30,6 +30,8 @@ namespace TEN::Hud return; } + StoreInterpolationData(); + // Update life and updated value status. _life = std::clamp(_life + (_hasValueUpdated ? 1.0f : -1.0f), 0.0f, LIFE_MAX * FPS); _hasValueUpdated = false; @@ -58,6 +60,8 @@ namespace TEN::Hud if (_life <= 0.0f) return; + // TODO: Interpolation. + auto color = Color(1.0f, 1.0f, 1.0f, _opacity); // Draw dial. diff --git a/TombEngine/Game/Hud/Speedometer.h b/TombEngine/Game/Hud/Speedometer.h index 164d652a2..bcc770234 100644 --- a/TombEngine/Game/Hud/Speedometer.h +++ b/TombEngine/Game/Hud/Speedometer.h @@ -16,6 +16,15 @@ namespace TEN::Hud float _opacity = 0.0f; float _life = 0.0f; + short _prevPointerAngle = 0; + float _prevOpacity = 0.0f; + + void StoreInterpolationData() + { + _prevPointerAngle = _pointerAngle; + _prevOpacity = _opacity; + } + public: // Utilities void UpdateValue(float value); From ce723b5a7eaa18b8a0ab479df9f88d6c354f2ede Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 8 May 2024 22:59:14 +1000 Subject: [PATCH 152/410] Clean up more effects --- TombEngine/Game/effects/Streamer.cpp | 5 +- TombEngine/Game/effects/Streamer.h | 11 ++-- TombEngine/Game/effects/debris.h | 5 +- TombEngine/Game/effects/drip.h | 20 +++--- TombEngine/Game/effects/hair.cpp | 6 +- TombEngine/Game/effects/hair.h | 8 +-- TombEngine/Game/effects/simple_particle.cpp | 70 +++++++++++---------- TombEngine/Game/effects/simple_particle.h | 8 +-- TombEngine/Game/effects/smoke.h | 16 ++--- TombEngine/Game/effects/spark.h | 8 +-- TombEngine/Renderer/RendererDrawEffect.cpp | 32 +++++----- TombEngine/Renderer/RendererLara.cpp | 4 +- 12 files changed, 99 insertions(+), 94 deletions(-) diff --git a/TombEngine/Game/effects/Streamer.cpp b/TombEngine/Game/effects/Streamer.cpp index 8e346db3d..0a77723b6 100644 --- a/TombEngine/Game/effects/Streamer.cpp +++ b/TombEngine/Game/effects/Streamer.cpp @@ -192,7 +192,10 @@ namespace TEN::Effects::Streamer pool.erase( std::remove_if( pool.begin(), pool.end(), - [](const auto& streamer) { return streamer.Segments.empty(); }), + [](const auto& streamer) + { + return streamer.Segments.empty(); + }), pool.end()); } diff --git a/TombEngine/Game/effects/Streamer.h b/TombEngine/Game/effects/Streamer.h index 39db32d22..57df932d2 100644 --- a/TombEngine/Game/effects/Streamer.h +++ b/TombEngine/Game/effects/Streamer.h @@ -9,10 +9,9 @@ namespace TEN::Effects::Streamer { enum class StreamerFlags { - FadeLeft = (1 << 0), - FadeRight = (1 << 1), - - BlendModeAdditive = (1 << 2) + FadeLeft = 1 << 0, + FadeRight = 1 << 1, + BlendModeAdditive = 1 << 2 }; class Streamer @@ -39,8 +38,8 @@ namespace TEN::Effects::Streamer std::array Vertices = {}; - std::array PrevVertices = {}; Vector4 PrevColor = Vector4::Zero; + std::array PrevVertices = {}; void InitializeVertices(const Vector3& pos, float width); void Update(); @@ -50,9 +49,9 @@ namespace TEN::Effects::Streamer void StoreInterpolationData() { + PrevColor = Color; PrevVertices[0] = Vertices[0]; PrevVertices[1] = Vertices[1]; - PrevColor = Color; } }; diff --git a/TombEngine/Game/effects/debris.h b/TombEngine/Game/effects/debris.h index 513d096ed..bffb68871 100644 --- a/TombEngine/Game/effects/debris.h +++ b/TombEngine/Game/effects/debris.h @@ -71,11 +71,12 @@ struct DebrisFragment bool active; bool isStatic; Matrix Transform; - Matrix OldTransform; + + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Game/effects/drip.h b/TombEngine/Game/effects/drip.h index bb6946ab1..31c428a74 100644 --- a/TombEngine/Game/effects/drip.h +++ b/TombEngine/Game/effects/drip.h @@ -16,19 +16,19 @@ namespace TEN::Effects::Drip float LifeMax = 0.0f; float Gravity = 0.0f; - Vector3 OldPosition = Vector3::Zero; - Vector4 OldColor = Vector4::Zero; - Vector2 OldSize = Vector2::Zero; - float OldLife = 0.0f; - Vector3 OldVelocity = Vector3::Zero; + Vector3 PrevPosition = Vector3::Zero; + Vector3 PrevVelocity = Vector3::Zero; + Vector2 PrevSize = Vector2::Zero; + Vector4 PrevColor = Vector4::Zero; + float PrevLife = 0.0f; void StoreInterpolationData() { - OldPosition = Position; - OldColor = Color; - OldSize = Size; - OldLife = Life; - OldVelocity = Velocity; + PrevPosition = Position; + PrevColor = Color; + PrevSize = Size; + PrevLife = Life; + PrevVelocity = Velocity; } }; diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 20576a9fd..1d633a849 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -25,10 +25,8 @@ namespace TEN::Effects::Hair void HairUnit::Update(const ItemInfo& item, int hairUnitIndex) { - for (int i = 0; i < Segments.size(); i++) - { - Segments[i].StoreInterpolationData(); - } + for (auto& segment : Segments) + segment.StoreInterpolationData(); const auto& player = GetLaraInfo(item); diff --git a/TombEngine/Game/effects/hair.h b/TombEngine/Game/effects/hair.h index dde5d3b3c..1e89aa3b3 100644 --- a/TombEngine/Game/effects/hair.h +++ b/TombEngine/Game/effects/hair.h @@ -16,13 +16,13 @@ namespace TEN::Effects::Hair Vector3 Velocity = Vector3::Zero; Quaternion Orientation = Quaternion::Identity; - Vector3 OldPosition = Vector3::Zero; - Quaternion OldOrientation = Quaternion::Identity; + Vector3 PrevPosition = Vector3::Zero; + Quaternion PrevOrientation = Quaternion::Identity; void StoreInterpolationData() { - OldPosition = Position; - OldOrientation = Orientation; + PrevPosition = Position; + PrevOrientation = Orientation; } }; diff --git a/TombEngine/Game/effects/simple_particle.cpp b/TombEngine/Game/effects/simple_particle.cpp index 867f0da63..850c1b98b 100644 --- a/TombEngine/Game/effects/simple_particle.cpp +++ b/TombEngine/Game/effects/simple_particle.cpp @@ -13,9 +13,11 @@ namespace TEN::Effects SimpleParticle& GetFreeSimpleParticle() { - for (auto& p : simpleParticles) - if (!p.active) - return p; + for (auto& part : simpleParticles) + { + if (!part.active) + return part; + } return simpleParticles[0]; } @@ -28,17 +30,18 @@ namespace TEN::Effects float z = std::cos(angle + angleVariation); x = x* -500 + snowMobile->Pose.Position.x; z = z* -500 + snowMobile->Pose.Position.z; - SimpleParticle& p = GetFreeSimpleParticle(); - p = {}; - p.active = true; - p.life = Random::GenerateFloat(8, 14); - p.room = snowMobile->RoomNumber; - p.ageRate = Random::GenerateFloat(0.9f, 1.3f); + + SimpleParticle& part = GetFreeSimpleParticle(); + part = {}; + part.active = true; + part.life = Random::GenerateFloat(8, 14); + part.room = snowMobile->RoomNumber; + part.ageRate = Random::GenerateFloat(0.9f, 1.3f); float size = Random::GenerateFloat(96, 128); - p.worldPosition = {x, float(snowMobile->Pose.Position.y) - size / 2 , z}; - p.sequence = ID_SKIDOO_SNOW_TRAIL_SPRITES; - p.size = Random::GenerateFloat(256, 512); - p.blendMode = BlendMode::AlphaBlend; + part.worldPosition = {x, float(snowMobile->Pose.Position.y) - size / 2 , z}; + part.sequence = ID_SKIDOO_SNOW_TRAIL_SPRITES; + part.size = Random::GenerateFloat(256, 512); + part.blendMode = BlendMode::AlphaBlend; } void TriggerSpeedboatFoam(ItemInfo* boat, Vector3 offset) @@ -47,41 +50,42 @@ namespace TEN::Effects { float size = Random::GenerateFloat(96, 128); float angle = TO_RAD(boat->Pose.Orientation.y); - float angleVariation = i*2*10 * RADIAN; + float angleVariation = i * 2 * 10 * RADIAN; float y = float(boat->Pose.Position.y) - size / 2 + offset.y; float x = std::sin(angle + angleVariation); float z = std::cos(angle + angleVariation); x = x * offset.z + z * offset.x + boat->Pose.Position.x; z = z * offset.z + x * offset.x + boat->Pose.Position.z; - SimpleParticle& p = GetFreeSimpleParticle(); - p = {}; - p.active = true; - p.life = Random::GenerateFloat(5, 9); - p.room = boat->RoomNumber; - p.ageRate = Random::GenerateFloat(0.9f, 1.3f); - p.worldPosition = { x, y, z }; - p.sequence = ID_MOTORBOAT_FOAM_SPRITES; - p.size = Random::GenerateFloat(256, 512); - p.blendMode = BlendMode::Additive; + + auto& part = GetFreeSimpleParticle(); + part = {}; + part.active = true; + part.life = Random::GenerateFloat(5, 9); + part.room = boat->RoomNumber; + part.ageRate = Random::GenerateFloat(0.9f, 1.3f); + part.worldPosition = { x, y, z }; + part.sequence = ID_MOTORBOAT_FOAM_SPRITES; + part.size = Random::GenerateFloat(256, 512); + part.blendMode = BlendMode::Additive; } } void UpdateSimpleParticles() { - for (auto& p : simpleParticles) + for (auto& part : simpleParticles) { - if (!p.active) + if (!part.active) continue; - p.StoreInterpolationData(); + part.StoreInterpolationData(); - p.age+= p.ageRate; - if (p.life < p.age) - p.active = false; + part.age+= part.ageRate; + if (part.life < part.age) + part.active = false; - int numSprites = -Objects[p.sequence].nmeshes - 1; - float normalizedAge = p.age / p.life; - p.sprite = Lerp(0.0f, numSprites, normalizedAge); + int spriteCount = -Objects[part.sequence].nmeshes - 1; + float normalizedAge = part.age / part.life; + part.sprite = Lerp(0.0f, spriteCount, normalizedAge); } } } diff --git a/TombEngine/Game/effects/simple_particle.h b/TombEngine/Game/effects/simple_particle.h index 592c23154..42811cf23 100644 --- a/TombEngine/Game/effects/simple_particle.h +++ b/TombEngine/Game/effects/simple_particle.h @@ -22,13 +22,13 @@ namespace TEN::Effects bool active; BlendMode blendMode; - Vector3 oldWorldPosition; - float oldSize; + Vector3 PrevWorldPosition = Vector3::Zero; + float PrevSize = 0.0f; void StoreInterpolationData() { - oldWorldPosition = worldPosition; - oldSize = size; + PrevWorldPosition = worldPosition; + PrevSize = size; } }; extern std::array simpleParticles; diff --git a/TombEngine/Game/effects/smoke.h b/TombEngine/Game/effects/smoke.h index fb0dfb7ab..5386fe12e 100644 --- a/TombEngine/Game/effects/smoke.h +++ b/TombEngine/Game/effects/smoke.h @@ -28,17 +28,17 @@ namespace TEN::Effects::Smoke bool affectedByWind; bool active; - Vector4 oldColor; - Vector3 oldPosition; - float oldRotation; - float oldSize; + Vector3 PrevPosition = Vector3::Zero; + float PrevRotation = 0.0f; + Vector4 PrevColor = Vector4::Zero; + float PrevSize = 0.0f; void StoreInterpolationData() { - oldColor = color; - oldPosition = position; - oldRotation = rotation; - oldSize = size; + PrevPosition = position; + PrevRotation = rotation; + PrevColor = color; + PrevSize = size; } }; extern std::array SmokeParticles; diff --git a/TombEngine/Game/effects/spark.h b/TombEngine/Game/effects/spark.h index 34fe6b386..d925ae26e 100644 --- a/TombEngine/Game/effects/spark.h +++ b/TombEngine/Game/effects/spark.h @@ -23,13 +23,13 @@ namespace TEN::Effects::Spark float height; bool active; - Vector3 oldPos; - Vector3 oldVelocity; + Vector3 PrevPosition = Vector3::Zero; + Vector3 PrevVelocity = Vector3::Zero; void StoreInterpolationData() { - oldPos = pos; - oldVelocity = velocity; + PrevPosition = pos; + PrevVelocity = velocity; } }; extern std::array SparkParticles; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 6cbcbd011..1b9d8d069 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -634,14 +634,14 @@ namespace TEN::Renderer auto axis = drip.Velocity; drip.Velocity.Normalize(axis); - auto prevAxis = drip.OldVelocity; - drip.OldVelocity.Normalize(prevAxis); + auto prevAxis = drip.PrevVelocity; + drip.PrevVelocity.Normalize(prevAxis); AddSpriteBillboardConstrained( &_sprites[Objects[ID_DRIP_SPRITE].meshIndex], - Vector3::Lerp(drip.OldPosition, drip.Position, _interpolationFactor), - Vector4::Lerp(drip.OldColor, drip.Color, _interpolationFactor), - 0.0f, 1.0f, Vector2::Lerp(drip.OldSize, drip.Size, _interpolationFactor), + Vector3::Lerp(drip.PrevPosition, drip.Position, _interpolationFactor), + Vector4::Lerp(drip.PrevColor, drip.Color, _interpolationFactor), + 0.0f, 1.0f, Vector2::Lerp(drip.PrevSize, drip.Size, _interpolationFactor), BlendMode::Additive, -Vector3::Lerp(prevAxis, axis, _interpolationFactor), false, view); } } @@ -1382,7 +1382,7 @@ namespace TEN::Renderer BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[deb.mesh.tex]), SamplerStateRegister::LinearClamp); } - _stStatic.World = Matrix::Lerp(deb.OldTransform, deb.Transform, _interpolationFactor); + _stStatic.World = Matrix::Lerp(deb.PrevTransform, deb.Transform, _interpolationFactor); _stStatic.Color = deb.color; _stStatic.AmbientLight = _rooms[deb.roomNumber].AmbientLight; _stStatic.LightMode = (int)deb.lightMode; @@ -1441,13 +1441,13 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[ID_SMOKE_SPRITES].meshIndex + smoke.sprite], - Vector3::Lerp(smoke.oldPosition, smoke.position, _interpolationFactor), - Vector4::Lerp(smoke.oldColor, smoke.color, _interpolationFactor), - Lerp(smoke.oldRotation, smoke.rotation, _interpolationFactor), + Vector3::Lerp(smoke.PrevPosition, smoke.position, _interpolationFactor), + Vector4::Lerp(smoke.PrevColor, smoke.color, _interpolationFactor), + Lerp(smoke.PrevRotation, smoke.rotation, _interpolationFactor), 1.0f, Vector2( - Lerp(smoke.oldSize, smoke.size, _interpolationFactor), - Lerp(smoke.oldSize, smoke.size, _interpolationFactor)), + Lerp(smoke.PrevSize, smoke.size, _interpolationFactor), + Lerp(smoke.PrevSize, smoke.size, _interpolationFactor)), BlendMode::AlphaBlend, true, view); } } @@ -1469,7 +1469,7 @@ namespace TEN::Renderer Vector3 prevVelocity; Vector3 velocity; - s.oldVelocity.Normalize(prevVelocity); + s.PrevVelocity.Normalize(prevVelocity); s.velocity.Normalize(velocity); velocity = Vector3::Lerp(prevVelocity, velocity, _interpolationFactor); @@ -1481,7 +1481,7 @@ namespace TEN::Renderer AddSpriteBillboardConstrained( &_sprites[Objects[ID_SPARK_SPRITE].meshIndex], - Vector3::Lerp(s.oldPos, s.pos, _interpolationFactor), + Vector3::Lerp(s.PrevPosition, s.pos, _interpolationFactor), color, 0, 1, Vector2( @@ -1531,11 +1531,11 @@ namespace TEN::Renderer AddSpriteBillboard( &_sprites[Objects[part.sequence].meshIndex + part.sprite], - Vector3::Lerp(part.oldWorldPosition, part.worldPosition, _interpolationFactor), + Vector3::Lerp(part.PrevWorldPosition, part.worldPosition, _interpolationFactor), Color(1.0f, 1.0f, 1.0f), 0, 1.0f, Vector2( - Lerp(part.oldSize, part.size, _interpolationFactor), - Lerp(part.oldSize, part.size, _interpolationFactor) / 2), + Lerp(part.PrevSize, part.size, _interpolationFactor), + Lerp(part.PrevSize, part.size, _interpolationFactor) / 2), BlendMode::AlphaBlend, true, view); } } diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index 2685390bc..f12ab25f0 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -352,9 +352,9 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render const auto& segment = unit.Segments[i]; auto worldMatrix = Matrix::CreateFromQuaternion( - Quaternion::Lerp(segment.OldOrientation, segment.Orientation, _interpolationFactor)) * + Quaternion::Lerp(segment.PrevOrientation, segment.Orientation, _interpolationFactor)) * Matrix::CreateTranslation( - Vector3::Lerp(segment.OldPosition, segment.Position, _interpolationFactor)); + Vector3::Lerp(segment.PrevPosition, segment.Position, _interpolationFactor)); _stItem.BonesMatrices[i + 1] = worldMatrix; _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; From 367cb777588eb9a5b4f48e0a021a92442a70cbba Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 9 May 2024 01:43:20 +1000 Subject: [PATCH 153/410] Fix doc comments --- .../Internal/TEN/Flow/LensFlare/LensFlare.cpp | 15 ++++++--------- .../Internal/TEN/Flow/Starfield/Starfield.cpp | 5 +---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp index aab754268..138c5eced 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp @@ -19,10 +19,7 @@ namespace TEN::Scripting // Register type. parent.new_usertype( - "LensFlare", - ctors(), - sol::call_constructor, ctors(), - + "LensFlare", ctors(), sol::call_constructor, ctors(), "GetEnabled", &LensFlare::GetEnabled, "GetSunSpriteID", &LensFlare::GetSunSpriteID, "GetRotation", &LensFlare::GetRotation, @@ -60,7 +57,7 @@ namespace TEN::Scripting return _sunSpriteID; } - // Get the lens flare's euler rotation. + /// Get the lens flare's euler rotation. // @function LensFlare:GetRotation() // @treturn Rotation Rotation. Rotation LensFlare::GetRotation() const @@ -68,14 +65,14 @@ namespace TEN::Scripting return _rotation; } - // Get the lens flare's color. + /// Get the lens flare's color. // @function LensFlare:SetColor() ScriptColor LensFlare::GetColor() const { return _color; } - // Set the lens flare's sun sprite ID. + /// Set the lens flare's sun sprite ID. // @function LensFlare:SetSunbjectID() // @tparam int New sprite ID. void LensFlare::SetSunSpriteID(int spriteID) @@ -90,7 +87,7 @@ namespace TEN::Scripting _sunSpriteID = spriteID; } - // Set the lens flare's euler rotation. + /// Set the lens flare's euler rotation. // @function LensFlare:SetRotation(Rotation) // @tparam Rotation New euler rotation. void LensFlare::SetRotation(const Rotation& rot) @@ -98,7 +95,7 @@ namespace TEN::Scripting _rotation = rot; } - // Set the lens flare's color. + /// Set the lens flare's color. // @function LensFlare:SetColor(Color) // @tparam Color New color. void LensFlare::SetColor(const ScriptColor& color) diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp index a2f030a6e..b37703135 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp @@ -21,10 +21,7 @@ namespace TEN::Scripting // Register type. parent.new_usertype( - "Starfield", - ctors(), - sol::call_constructor, ctors(), - + "Starfield", ctors(), sol::call_constructor, ctors(), "GetStarsEnabled", &Starfield::GetStarsEnabled, "GetMeteorsEnabled", &Starfield::GetMeteorsEnabled, "GetStarCount", &Starfield::GetStarCount, From caa13a659c9459e38d841b296a667396d935757c Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 9 May 2024 03:33:11 +1000 Subject: [PATCH 154/410] Update TombEngine.vcxproj --- TombEngine/TombEngine.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 24ff002ab..48697de84 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -300,6 +300,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" /Zc:__cplusplus /experimental:external /external:anglebrackets 4018;4244;4996;%(DisableSpecificWarnings) true + $(IntDir)/%(RelativeDir)/ Console From 1bd183203748d3c2357f7d8afd373ac6da408056 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 9 May 2024 05:42:36 +0200 Subject: [PATCH 155/410] WIP solution for variable monitor refresh rates --- .../doc/2 classes/Flow.LensFlare.html | 122 ++++++++++++++++++ TombEngine/Game/gui.cpp | 2 +- TombEngine/Renderer/Renderer.h | 2 + TombEngine/Renderer/RendererDrawMenu.cpp | 13 +- TombEngine/Renderer/RendererHelper.cpp | 5 + TombEngine/Renderer/RendererInit.cpp | 10 +- TombEngine/Specific/winmain.cpp | 16 +++ TombEngine/Specific/winmain.h | 3 +- 8 files changed, 164 insertions(+), 9 deletions(-) diff --git a/Documentation/doc/2 classes/Flow.LensFlare.html b/Documentation/doc/2 classes/Flow.LensFlare.html index 574b42065..5ce8350f1 100644 --- a/Documentation/doc/2 classes/Flow.LensFlare.html +++ b/Documentation/doc/2 classes/Flow.LensFlare.html @@ -122,6 +122,26 @@ + + + + + + + + + + + + + + + + + + + +
    ColorAn RGBA or RGB color.Represents an RGBA or RGB color.
    RotationLensFlare:GetObjectID() Get the sun's sprite ID.
    LensFlare:GetRotation()Get the lens flare's euler rotation.
    LensFlare:SetColor()Get the lens flare's color.
    LensFlare:SetSunbjectID(New)Set the lens flare's sun sprite ID.
    LensFlare:SetRotation(New)Set the lens flare's euler rotation.
    LensFlare:SetColor(New)Set the lens flare's color.

    @@ -208,6 +228,108 @@ +
    +
    + + LensFlare:GetRotation() +
    +
    + Get the lens flare's euler rotation. () + + + + +

    Returns:

    +
      + + Rotation + Rotation. +
    + + + + +
    +
    + + LensFlare:SetColor() +
    +
    + Get the lens flare's color. () + + + + + + + + +
    +
    + + LensFlare:SetSunbjectID(New) +
    +
    + Set the lens flare's sun sprite ID. () + + + +

    Parameters:

    +
      +
    • New + int + sprite ID. +
    • +
    + + + + + +
    +
    + + LensFlare:SetRotation(New) +
    +
    + Set the lens flare's euler rotation. (Rotation) + + + +

    Parameters:

    +
      +
    • New + Rotation + euler rotation. +
    • +
    + + + + + +
    +
    + + LensFlare:SetColor(New) +
    +
    + Set the lens flare's color. (Color) + + + +

    Parameters:

    +
      +
    • New + Color + color. +
    • +
    + + + + +
    diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 45162341c..6b8ce4bf5 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -2806,7 +2806,7 @@ namespace TEN::Gui const auto& player = GetLaraInfo(*item); auto& ring = Rings[(int)ringType]; - float multiplier = g_Configuration.EnableVariableFramerate ? 2.0f : 1.0f; + float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; if (ring.CurrentObjectList <= 0) return; diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 6890825d0..8d058514d 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -305,6 +305,7 @@ namespace TEN::Renderer // Screen settings int _screenWidth; int _screenHeight; + int _refreshRate; bool _isWindowed; float _farView = DEFAULT_FAR_VIEW; @@ -644,6 +645,7 @@ namespace TEN::Renderer float GetInterpolationFactor() const; Vector2i GetScreenResolution() const; + int GetScreenRefreshRate() const; std::optional Get2DPosition(const Vector3& pos) const; Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero); std::pair GetRay(const Vector2& pos) const; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 8ac86c306..d27af4d35 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -892,28 +892,29 @@ namespace TEN::Renderer static EulerAngles orient = EulerAngles::Identity; static float scaler = 1.2f; + float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; short invItem = g_Gui.GetRing(RingTypes::Inventory).CurrentObjectList[g_Gui.GetRing(RingTypes::Inventory).CurrentObjectInList].InventoryItem; auto& object = InventoryObjectTable[invItem]; if (IsHeld(In::Forward)) - orient.x += ANGLE(3.0f); + orient.x += ANGLE(3.0f / multiplier); if (IsHeld(In::Back)) - orient.x -= ANGLE(3.0f); + orient.x -= ANGLE(3.0f / multiplier); if (IsHeld(In::Left)) - orient.y += ANGLE(3.0f); + orient.y += ANGLE(3.0f / multiplier); if (IsHeld(In::Right)) - orient.y -= ANGLE(3.0f); + orient.y -= ANGLE(3.0f / multiplier); if (IsHeld(In::Sprint)) - scaler += 0.03f; + scaler += 0.03f / multiplier; if (IsHeld(In::Crouch)) - scaler -= 0.03f; + scaler -= 0.03f / multiplier; if (scaler > 1.6f) scaler = 1.6f; diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 7a0ae86c7..7c69bf102 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -529,6 +529,11 @@ namespace TEN::Renderer return Vector2i(_screenWidth, _screenHeight); } + int Renderer::GetScreenRefreshRate() const + { + return _refreshRate; + } + std::optional Renderer::Get2DPosition(const Vector3& pos) const { auto point = Vector4(pos.x, pos.y, pos.z, 1.0f); diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp index 9eb926176..d382d191d 100644 --- a/TombEngine/Renderer/RendererInit.cpp +++ b/TombEngine/Renderer/RendererInit.cpp @@ -465,12 +465,20 @@ namespace TEN::Renderer sd.BufferDesc.Height = h; if (!g_Configuration.EnableVariableFramerate) { + _refreshRate = 30; + sd.BufferDesc.RefreshRate.Numerator = 0; sd.BufferDesc.RefreshRate.Denominator = 0; } else { - sd.BufferDesc.RefreshRate.Numerator = 60; + _refreshRate = GetCurrentScreenRefreshRate(); + if (_refreshRate == 0) + { + _refreshRate = 60; + } + + sd.BufferDesc.RefreshRate.Numerator = _refreshRate; sd.BufferDesc.RefreshRate.Denominator = 1; } sd.BufferDesc.RefreshRate.Numerator = 60; diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp index 3a3d7438b..3e2e7ed5b 100644 --- a/TombEngine/Specific/winmain.cpp +++ b/TombEngine/Specific/winmain.cpp @@ -60,6 +60,22 @@ Vector2i GetScreenResolution() return resolution; } +int GetCurrentScreenRefreshRate() +{ + DEVMODE devmode; + memset(&devmode, 0, sizeof(devmode)); + devmode.dmSize = sizeof(devmode); + + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode)) + { + return devmode.dmDisplayFrequency; + } + else + { + return 0; + } +} + std::vector GetAllSupportedScreenResolutions() { auto resList = std::vector{}; diff --git a/TombEngine/Specific/winmain.h b/TombEngine/Specific/winmain.h index 80427898b..14158adb5 100644 --- a/TombEngine/Specific/winmain.h +++ b/TombEngine/Specific/winmain.h @@ -39,4 +39,5 @@ void WinClose(); LRESULT CALLBACK WinAppProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); void CALLBACK HandleWmCommand(unsigned short wParam); Vector2i GetScreenResolution(); -std::vector GetAllSupportedScreenResolutions(); \ No newline at end of file +std::vector GetAllSupportedScreenResolutions(); +int GetCurrentScreenRefreshRate(); \ No newline at end of file From afab268a133e2765216024d5621426b6e13f47c0 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 9 May 2024 13:38:08 +0200 Subject: [PATCH 156/410] Fixed ammos ring speed --- TombEngine/Game/gui.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 6b8ce4bf5..a6a48b75c 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -2028,6 +2028,8 @@ namespace TEN::Gui void GuiController::FadeAmmoSelector() { + float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; + if (Rings[(int)RingTypes::Inventory].RingActive) { AmmoSelectorFadeVal = 0; @@ -2035,7 +2037,7 @@ namespace TEN::Gui else if (AmmoSelectorFadeDir == 1) { if (AmmoSelectorFadeVal < 128) - AmmoSelectorFadeVal += 32; + AmmoSelectorFadeVal += 32 / multiplier; if (AmmoSelectorFadeVal > 128) { @@ -2046,7 +2048,7 @@ namespace TEN::Gui else if (AmmoSelectorFadeDir == 2) { if (AmmoSelectorFadeVal > 0) - AmmoSelectorFadeVal -= 32; + AmmoSelectorFadeVal -= 32 / multiplier; if (AmmoSelectorFadeVal < 0) { @@ -2737,6 +2739,8 @@ namespace TEN::Gui { if (!AmmoSelectorFlag) return; + + float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; int xPos = (2 * PHD_CENTER_X - OBJLIST_SPACING) / 2; if (NumAmmoSlots == 2) @@ -2753,13 +2757,13 @@ namespace TEN::Gui if (n == *CurrentAmmoType) { if (invObject->RotFlags & INV_ROT_X) - AmmoObjectList[n].Orientation.x += ANGLE(5.0f); + AmmoObjectList[n].Orientation.x += ANGLE(5.0f / multiplier); if (invObject->RotFlags & INV_ROT_Y) - AmmoObjectList[n].Orientation.y += ANGLE(5.0f); + AmmoObjectList[n].Orientation.y += ANGLE(5.0f / multiplier); if (invObject->RotFlags & INV_ROT_Z) - AmmoObjectList[n].Orientation.z += ANGLE(5.0f); + AmmoObjectList[n].Orientation.z += ANGLE(5.0f / multiplier); } else SpinBack(AmmoObjectList[n].Orientation); From fa697cc26e7e3bd0ad92e093e6aff1ee91389cb8 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 10 May 2024 22:19:36 +1000 Subject: [PATCH 157/410] Update lens flare Lua API --- .../doc/2 classes/Flow.LensFlare.html | 107 +++++++++++++----- .../doc/3 primitive classes/Rotation.html | 2 +- TombEngine/Game/control/control.cpp | 2 +- .../Scripting/Include/ScriptInterfaceLevel.h | 9 +- .../Internal/TEN/Flow/LensFlare/LensFlare.cpp | 57 ++++++---- .../Internal/TEN/Flow/LensFlare/LensFlare.h | 8 +- .../Internal/TEN/Flow/Level/FlowLevel.cpp | 9 +- .../Internal/TEN/Flow/Level/FlowLevel.h | 9 +- .../Internal/TEN/Rotation/Rotation.cpp | 35 +++--- 9 files changed, 157 insertions(+), 81 deletions(-) diff --git a/Documentation/doc/2 classes/Flow.LensFlare.html b/Documentation/doc/2 classes/Flow.LensFlare.html index 5ce8350f1..825fe070e 100644 --- a/Documentation/doc/2 classes/Flow.LensFlare.html +++ b/Documentation/doc/2 classes/Flow.LensFlare.html @@ -111,7 +111,7 @@

    Functions

    - + @@ -119,24 +119,32 @@ - + - - + + + + + + - + - - + + + + + + @@ -153,7 +161,7 @@
    - LensFlare(Rotation., Color.) + LensFlare(Pitch, Yaw, Color.)
    Create a LensFlare object. () @@ -162,11 +170,13 @@

    Parameters:

      -
    • Rotation. - Rotation - - - +
    • Pitch + float + angle. +
    • +
    • Yaw + float + angle.
    • Color. Color @@ -209,8 +219,8 @@
    - - LensFlare:GetObjectID() + + LensFlare:GetSunSpriteID()
    Get the sun's sprite ID. () @@ -230,11 +240,11 @@
    - - LensFlare:GetRotation() + + LensFlare:GetPitch()
    - Get the lens flare's euler rotation. () + Get the lens flare's pitch angle in degrees. () @@ -242,8 +252,29 @@

    Returns:

      - Rotation - Rotation. + float + Pitch angle in degrees. +
    + + + + +
    +
    + + LensFlare:GetYaw() +
    +
    + Get the lens flare's yaw angle in degrees. () + + + + +

    Returns:

    +
      + + float + Yaw angle in degrees.
    @@ -266,8 +297,8 @@
    - - LensFlare:SetSunbjectID(New) + + LensFlare:SetSunSpriteID(New)
    Set the lens flare's sun sprite ID. () @@ -288,19 +319,41 @@
    - - LensFlare:SetRotation(New) + + LensFlare:SetPitch(New)
    - Set the lens flare's euler rotation. (Rotation) + Set the lens flare's pitch angle. (float)

    Parameters:

    • New - Rotation - euler rotation. + float + pitch angle in degrees. +
    • +
    + + + + + +
    +
    + + LensFlare:SetYaw(New) +
    +
    + Set the lens flare's yaw angle. (float) + + + +

    Parameters:

    +
      +
    • New + float + yaw angle in degrees.
    diff --git a/Documentation/doc/3 primitive classes/Rotation.html b/Documentation/doc/3 primitive classes/Rotation.html index 81269805f..b163bc9de 100644 --- a/Documentation/doc/3 primitive classes/Rotation.html +++ b/Documentation/doc/3 primitive classes/Rotation.html @@ -103,7 +103,7 @@

    Primitive Class Rotation

    Represents a degree-based 3D rotation.

    -

    All values are clamped to the range [0.0, 360.0].

    +

    All values are clamped to the range [0.0, 360.0].

    Members

    diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 23f028319..f8666c90f 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -247,7 +247,7 @@ GameStatus ControlPhase() if (g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareEnabled()) { SetupGlobalLensFlare( - g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareRotation(), + EulerAngles(g_GameFlow->GetLevel(CurrentLevel)->GetLensFlarePitch(), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareYaw(), 0), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareColor(), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSunSpriteID()); } diff --git a/TombEngine/Scripting/Include/ScriptInterfaceLevel.h b/TombEngine/Scripting/Include/ScriptInterfaceLevel.h index b96635db7..f1c442cca 100644 --- a/TombEngine/Scripting/Include/ScriptInterfaceLevel.h +++ b/TombEngine/Scripting/Include/ScriptInterfaceLevel.h @@ -50,10 +50,11 @@ public: virtual bool GetResetHubEnabled() const = 0; // Lens flare getters - virtual bool GetLensFlareEnabled() const = 0; - virtual int GetLensFlareSunSpriteID() const = 0; - virtual EulerAngles GetLensFlareRotation() const = 0; - virtual Color GetLensFlareColor() const = 0; + virtual bool GetLensFlareEnabled() const = 0; + virtual int GetLensFlareSunSpriteID() const = 0; + virtual short GetLensFlarePitch() const = 0; + virtual short GetLensFlareYaw() const = 0; + virtual Color GetLensFlareColor() const = 0; // Starfield getters virtual bool GetStarfieldStarsEnabled() const = 0; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp index 138c5eced..8b9664593 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp @@ -15,30 +15,33 @@ namespace TEN::Scripting void LensFlare::Register(sol::table& parent) { using ctors = sol::constructors< - LensFlare(const Rotation& rot, const ScriptColor& color)>; + LensFlare(float pitch, float yaw, const ScriptColor& color)>; // Register type. parent.new_usertype( "LensFlare", ctors(), sol::call_constructor, ctors(), "GetEnabled", &LensFlare::GetEnabled, "GetSunSpriteID", &LensFlare::GetSunSpriteID, - "GetRotation", &LensFlare::GetRotation, + "GetPitch", &LensFlare::GetPitch, + "GetYaw", &LensFlare::GetYaw, "GetColor", &LensFlare::GetColor, "SetSunSpriteID", &LensFlare::SetSunSpriteID, - "SetRotation", &LensFlare::SetRotation, + "SetPitch", &LensFlare::SetPitch, + "SetYaw", &LensFlare::SetYaw, "SetColor", &LensFlare::SetColor); } /// Create a LensFlare object. // @function LensFlare() - // @tparam Rotation Rotation. + // @tparam float Pitch angle in degrees. + // @tparam float Yaw angle in degrees. // @tparam Color Color. // @treturn LensFlare A new LensFlare object. - LensFlare::LensFlare(const Rotation& rot, const ScriptColor& color) + LensFlare::LensFlare(float pitch, float yaw, const ScriptColor& color) { _isEnabled = true; _color = color; - _rotation = rot; + _rotation = Rotation(pitch, yaw, 0.0f); } /// Get the lens flare's enabled status. @@ -50,19 +53,27 @@ namespace TEN::Scripting } /// Get the sun's sprite ID. - // @function LensFlare:GetObjectID() + // @function LensFlare:GetSunSpriteID() // @treturn int Sprite ID. int LensFlare::GetSunSpriteID() const { return _sunSpriteID; } - /// Get the lens flare's euler rotation. - // @function LensFlare:GetRotation() - // @treturn Rotation Rotation. - Rotation LensFlare::GetRotation() const + /// Get the lens flare's pitch angle in degrees. + // @function LensFlare:GetPitch() + // @treturn float Pitch angle in degrees. + float LensFlare::GetPitch() const { - return _rotation; + return _rotation.x; + } + + /// Get the lens flare's yaw angle in degrees. + // @function LensFlare:GetYaw() + // @treturn float Yaw angle in degrees. + float LensFlare::GetYaw() const + { + return _rotation.y; } /// Get the lens flare's color. @@ -73,28 +84,36 @@ namespace TEN::Scripting } /// Set the lens flare's sun sprite ID. - // @function LensFlare:SetSunbjectID() + // @function LensFlare:SetSunSpriteID() // @tparam int New sprite ID. void LensFlare::SetSunSpriteID(int spriteID) { // Sprite ID out of range; return early. if (spriteID < 0 || g_Level.Sprites.size() > spriteID) { - TENLog("Sub sprite ID out of range."); + TENLog("Sun sprite ID out of range."); return; } _sunSpriteID = spriteID; } - /// Set the lens flare's euler rotation. - // @function LensFlare:SetRotation(Rotation) - // @tparam Rotation New euler rotation. - void LensFlare::SetRotation(const Rotation& rot) + /// Set the lens flare's pitch angle. + // @function LensFlare:SetPitch(float) + // @tparam float New pitch angle in degrees. + void LensFlare::SetPitch(float pitch) { - _rotation = rot; + _rotation.x = pitch; } + /// Set the lens flare's yaw angle. + // @function LensFlare:SetYaw(float) + // @tparam float New yaw angle in degrees. + void LensFlare::SetYaw(float yaw) + { + _rotation.y = yaw; + } + /// Set the lens flare's color. // @function LensFlare:SetColor(Color) // @tparam Color New color. diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h index 8b034b9f0..e13f97d40 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h @@ -23,17 +23,19 @@ namespace TEN::Scripting // Constructors LensFlare() = default; - LensFlare(const Rotation& rot, const ScriptColor& color); + LensFlare(float pitch, float yaw, const ScriptColor& color); // Getters bool GetEnabled() const; int GetSunSpriteID() const; - Rotation GetRotation() const; + float GetPitch() const; + float GetYaw() const; ScriptColor GetColor() const; // Setters void SetSunSpriteID(int spriteID); - void SetRotation(const Rotation& rot); + void SetPitch(float pitch); + void SetYaw(float yaw); void SetColor(const ScriptColor& color); }; } diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp index 2f419cf1d..f9c92fc6f 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp @@ -301,9 +301,14 @@ int Level::GetLensFlareSunSpriteID() const return LensFlare.GetSunSpriteID(); } -EulerAngles Level::GetLensFlareRotation() const +short Level::GetLensFlarePitch() const { - return LensFlare.GetRotation().ToEulerAngles(); + return ANGLE(LensFlare.GetPitch()); +} + +short Level::GetLensFlareYaw() const +{ + return ANGLE(LensFlare.GetYaw()); } Color Level::GetLensFlareColor() const diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h index 4b8610f5c..18d52df5b 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.h @@ -72,10 +72,11 @@ struct Level : public ScriptInterfaceLevel bool GetResetHubEnabled() const override; // Lens flare getters - bool GetLensFlareEnabled() const override; - int GetLensFlareSunSpriteID() const override; - EulerAngles GetLensFlareRotation() const override; - Color GetLensFlareColor() const override; + bool GetLensFlareEnabled() const override; + int GetLensFlareSunSpriteID() const override; + short GetLensFlarePitch() const override; + short GetLensFlareYaw() const override; + Color GetLensFlareColor() const override; // Starfield getters bool GetStarfieldStarsEnabled() const override; diff --git a/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp b/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp index 1fad9a411..3a2cdf881 100644 --- a/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp +++ b/TombEngine/Scripting/Internal/TEN/Rotation/Rotation.cpp @@ -6,11 +6,10 @@ using namespace TEN::Math; -/*** Represents a degree-based 3D rotation. -All values are clamped to the range [0.0, 360.0]. -@tenprimitive Rotation -@pragma nostrip -*/ +/// Represents a degree-based 3D rotation. +// All values are clamped to the range [0.0, 360.0]. +// @tenprimitive Rotation +// @pragma nostrip void Rotation::Register(sol::table& parent) { @@ -21,25 +20,23 @@ void Rotation::Register(sol::table& parent) sol::meta_function::to_string, &Rotation::ToString, /// (float) X angle component. - //@mem x + // @mem x "x", &Rotation::x, /// (float) Y angle component. - //@mem y + // @mem y "y", &Rotation::y, /// (float) Z angle component. - //@mem z + // @mem z "z", &Rotation::z); } -/*** -@tparam float x X angle component. -@tparam float y Y angle component. -@tparam float z Z angle component. -@treturn Rotation A Rotation. -@function Rotation -*/ +/// @tparam float x X angle component. +// @tparam float y Y angle component. +// @tparam float z Z angle component. +// @treturn Rotation A Rotation. +// @function Rotation Rotation::Rotation(float x, float y, float z) { this->x = x; @@ -80,11 +77,9 @@ Rotation::operator Vector3() const return Vector3(x, y, z); }; -/*** -@tparam Rotation rotation this Rotation. -@treturn string A string showing the X, Y, and Z angle components of the Rotation. -@function __tostring -*/ +/// @tparam Rotation rotation this Rotation. +// @treturn string A string showing the X, Y, and Z angle components of the Rotation. +// @function __tostring std::string Rotation::ToString() const { return ("{ " + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + " }"); From 52398927439ea3b361a46f5e4be68d51ce8c4beb Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 10 May 2024 23:33:55 +1000 Subject: [PATCH 158/410] Update starfield error handling --- TombEngine/Objects/Effects/LensFlare.cpp | 22 ++++++++--------- TombEngine/Objects/Effects/LensFlare.h | 3 ++- .../Internal/TEN/Flow/LensFlare/LensFlare.h | 4 ++-- .../Internal/TEN/Flow/Starfield/Starfield.cpp | 24 ++++++++----------- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/TombEngine/Objects/Effects/LensFlare.cpp b/TombEngine/Objects/Effects/LensFlare.cpp index 080605a63..6e0677fe0 100644 --- a/TombEngine/Objects/Effects/LensFlare.cpp +++ b/TombEngine/Objects/Effects/LensFlare.cpp @@ -75,6 +75,17 @@ namespace TEN::Entities::Effects LensFlares.push_back(lensFlare); } + void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID) + { + constexpr auto BASE_POS = Vector3(0.0f, 0.0f, BLOCK(256)); + + auto pos = Camera.pos.ToVector3(); + auto rotMatrix = orient.ToRotationMatrix(); + + pos += Vector3::Transform(BASE_POS, rotMatrix); + SetupLensFlare(pos, NO_VALUE, color, true, spriteID); + } + void ControlLensFlare(int itemNumber) { auto& item = g_Level.Items[itemNumber]; @@ -87,15 +98,4 @@ namespace TEN::Entities::Effects { LensFlares.clear(); } - - void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID) - { - constexpr auto BASE_POS = Vector3(0.0f, 0.0f, BLOCK(256)); - - auto pos = Camera.pos.ToVector3(); - auto rotMatrix = orient.ToRotationMatrix(); - - pos += Vector3::Transform(BASE_POS, rotMatrix); - SetupLensFlare(pos, NO_VALUE, color, true, spriteID); - } } diff --git a/TombEngine/Objects/Effects/LensFlare.h b/TombEngine/Objects/Effects/LensFlare.h index be1e88f8f..3440e5ad8 100644 --- a/TombEngine/Objects/Effects/LensFlare.h +++ b/TombEngine/Objects/Effects/LensFlare.h @@ -17,7 +17,8 @@ namespace TEN::Entities::Effects extern std::vector LensFlares; + void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID); + void ControlLensFlare(int itemNumber); void ClearLensFlares(); - void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID); } diff --git a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h index e13f97d40..ab450b6e1 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/LensFlare/LensFlare.h @@ -12,8 +12,8 @@ namespace TEN::Scripting { private: // Members - int _sunSpriteID = SPRITE_TYPES::SPR_LENS_FLARE_3; - bool _isEnabled; + int _sunSpriteID = SPRITE_TYPES::SPR_LENS_FLARE_3; + bool _isEnabled = false; Rotation _rotation = {}; ScriptColor _color = 0; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp index b37703135..15cfde18b 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp @@ -50,8 +50,14 @@ namespace TEN::Scripting // @treturn Starfield A new Starfield object. Starfield::Starfield(int starCount, int meteorCount, int meteorSpawnDensity, float meteorVel) { - _starCount = starCount; - _meteorCount = meteorCount; + if (starCount < 0 || starCount > STAR_COUNT_MAX) + TENLog("Star count must be in range [0, " + std::to_string(STAR_COUNT_MAX) + "].", LogLevel::Warning); + + if (meteorCount < 0 || meteorCount > METEOR_COUNT_MAX) + TENLog("Meteor count must be in range [0, " + std::to_string(METEOR_COUNT_MAX) + "].", LogLevel::Warning); + + _starCount = std::clamp(starCount, 0, STAR_COUNT_MAX); + _meteorCount = std::clamp(meteorCount, 0, METEOR_COUNT_MAX); _meteorSpawnDensity = meteorSpawnDensity; _meteorVelocity = meteorVel; } @@ -109,15 +115,10 @@ namespace TEN::Scripting // @tparam int New count. void Starfield::SetStarCount(int count) { - // Star count out of range; set max. if (count < 0 || count > STAR_COUNT_MAX) - { TENLog("Star count must be in range [0, " + std::to_string(STAR_COUNT_MAX) + "].", LogLevel::Warning); - _starCount = STAR_COUNT_MAX; - return; - } - _starCount = count; + _starCount = std::clamp(count, 0, STAR_COUNT_MAX); } /// Set the starfield's number of meteors. @@ -125,15 +126,10 @@ namespace TEN::Scripting // @tparam int New count. void Starfield::SetMeteorCount(int count) { - // Meteor count out of range; set max. if (count < 0 || count > METEOR_COUNT_MAX) - { TENLog("Meteor count must be in range [0, " + std::to_string(METEOR_COUNT_MAX) + "].", LogLevel::Warning); - _meteorCount = METEOR_COUNT_MAX; - return; - } - _meteorCount = count; + _meteorCount = std::clamp(count, 0, METEOR_COUNT_MAX); } /// Set the starfield's meteor spawn density. From af5bce3cf85ce142adb48d81319d967af7aec07c Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 11 May 2024 00:29:21 +1000 Subject: [PATCH 159/410] Update TargetHighlighter.h --- TombEngine/Game/Hud/TargetHighlighter.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/Hud/TargetHighlighter.h b/TombEngine/Game/Hud/TargetHighlighter.h index 9108137b4..f3be870a5 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.h +++ b/TombEngine/Game/Hud/TargetHighlighter.h @@ -34,6 +34,12 @@ namespace TEN::Hud std::array Segments = {}; + Vector2 PrevPosition = Vector2::Zero; + short PrevOrientation = 0; + float PrevScale = 0.0f; + Vector4 PrevColor = Vector4::Zero; + std::array PrevSegments = {}; + // Getters float GetScale(float cameraDist) const; float GetRadius() const; @@ -47,12 +53,6 @@ namespace TEN::Hud void Update(const Vector3& targetPos, bool isActive, bool doPulse); void Draw() const; - Vector2 PrevPosition = Vector2::Zero; - short PrevOrientation = 0; - float PrevScale = 0.0f; - Vector4 PrevColor = Vector4::Zero; - std::array PrevSegments = {}; - void StoreInterpolationData() { PrevPosition = *Position; From 715df20e1faab1cb86c0a9bbf568cb28c9ebc2e2 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 11 May 2024 01:51:48 +1000 Subject: [PATCH 160/410] Fix crosshair angle interpolation --- Documentation/doc/2 classes/Flow.LensFlare.html | 4 ++-- TombEngine/Game/Hud/TargetHighlighter.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/doc/2 classes/Flow.LensFlare.html b/Documentation/doc/2 classes/Flow.LensFlare.html index 825fe070e..4f972ab32 100644 --- a/Documentation/doc/2 classes/Flow.LensFlare.html +++ b/Documentation/doc/2 classes/Flow.LensFlare.html @@ -172,11 +172,11 @@
    • Pitch float - angle. + angle in degrees.
    • Yaw float - angle. + angle in degrees.
    • Color. Color diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index cd52b5825..7cd768ba4 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -141,7 +141,7 @@ namespace TEN::Hud return; auto pos0 = Vector2::Lerp(*Position, PrevPosition, g_Renderer.GetInterpolationFactor()); - short orient0 = (short)Lerp(PrevOrientation, Orientation, g_Renderer.GetInterpolationFactor()); // TODO: use Geometry::GetShortestAngle() + short orient0 = PrevOrientation + (Geometry::GetShortestAngle(PrevOrientation, Orientation) * g_Renderer.GetInterpolationFactor()); float scale = Lerp(PrevScale, Scale, g_Renderer.GetInterpolationFactor()); auto color = Color::Lerp(PrevColor, Color, g_Renderer.GetInterpolationFactor()); @@ -159,7 +159,7 @@ namespace TEN::Hud const auto& prevSegment = PrevSegments[i]; auto pos1 = pos0 + Vector2::Lerp(prevSegment.PosOffset, segment.PosOffset, g_Renderer.GetInterpolationFactor()); - short orient1 = orient0 + (short)Lerp(prevSegment.OrientOffset, segment.OrientOffset, g_Renderer.GetInterpolationFactor()); // TODO: use Geometry::GetShortestAngle() + short orient1 = orient0 + (prevSegment.OrientOffset + (Geometry::GetShortestAngle(prevSegment.OrientOffset, segment.OrientOffset) * g_Renderer.GetInterpolationFactor())); AddDisplaySprite( SPRITE_SEQUENCE_OBJECT_ID, SEGMENT_ELEMENT_SPRITE_ID, From 895660fe5a2df006b0a0eb92fffd2acbecf268d0 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 11 May 2024 05:54:25 +0200 Subject: [PATCH 161/410] Fixed look at camera; --- TombEngine/Game/camera.cpp | 2 +- TombEngine/Renderer/ConstantBuffers/CameraMatrixBuffer.h | 3 ++- TombEngine/Renderer/RendererDraw.cpp | 3 +++ TombEngine/Renderer/RendererHelper.cpp | 3 --- TombEngine/Shaders/AnimatedTextures.hlsli | 2 +- TombEngine/Shaders/CBCamera.hlsli | 3 ++- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index e0863e650..722d1db91 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -202,7 +202,7 @@ void LookAt(CAMERA_INFO* cam, short roll) float levelFarView = g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * float(BLOCK(1)); - g_Renderer.UpdateCameraMatrices(cam, r, fov, levelFarView); + g_Renderer.UpdateCameraMatrices(cam, r, fov, levelFarView); } void AlterFOV(short value, bool store) diff --git a/TombEngine/Renderer/ConstantBuffers/CameraMatrixBuffer.h b/TombEngine/Renderer/ConstantBuffers/CameraMatrixBuffer.h index ed29faa40..9be9b953b 100644 --- a/TombEngine/Renderer/ConstantBuffers/CameraMatrixBuffer.h +++ b/TombEngine/Renderer/ConstantBuffers/CameraMatrixBuffer.h @@ -42,8 +42,9 @@ namespace TEN::Renderer::ConstantBuffers float NearPlane; float FarPlane; //-- + int RefreshRate; int NumFogBulbs; - Vector3 Padding2; + Vector2 Padding2; //-- ShaderFogBulb FogBulbs[MAX_FOG_BULBS_DRAW]; }; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 8b131c80e..9d0c992a4 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1652,6 +1652,8 @@ namespace TEN::Renderer if (_blinkTime > PI_MUL_2) _blinkTime -= PI_MUL_2; + _oldGameCamera = _currentGameCamera; + _isLocked = false; } @@ -1771,6 +1773,7 @@ namespace TEN::Renderer CCameraMatrixBuffer cameraConstantBuffer; view.FillConstantBuffer(cameraConstantBuffer); cameraConstantBuffer.Frame = GlobalCounter; + cameraConstantBuffer.RefreshRate = _refreshRate; cameraConstantBuffer.CameraUnderwater = g_Level.Rooms[cameraConstantBuffer.RoomNumber].flags & ENV_FLAG_WATER; cameraConstantBuffer.DualParaboloidView = Matrix::CreateLookAt(LaraItem->Pose.Position.ToVector3(), LaraItem->Pose.Position.ToVector3() + Vector3(0, 0, 1024), -Vector3::UnitY); diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 7c69bf102..8dd9814bb 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -361,9 +361,6 @@ namespace TEN::Renderer if (farView < MIN_FAR_VIEW) farView = DEFAULT_FAR_VIEW; - farView = farView; - - _oldGameCamera = _currentGameCamera; _currentGameCamera = RenderView(cam, roll, fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); _gameCamera = RenderView(cam, roll, fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); } diff --git a/TombEngine/Shaders/AnimatedTextures.hlsli b/TombEngine/Shaders/AnimatedTextures.hlsli index bf733d74a..f43de521b 100644 --- a/TombEngine/Shaders/AnimatedTextures.hlsli +++ b/TombEngine/Shaders/AnimatedTextures.hlsli @@ -36,7 +36,7 @@ float2 CalculateUVRotate(float2 uv, unsigned int frame) float2 GetFrame(unsigned int index, unsigned int offset) { - float speed = FPS / 30.0f; + float speed = (float)FPS / 30.0f; int frame = int(Frame * speed + offset) % NumAnimFrames; float2 result = 0; diff --git a/TombEngine/Shaders/CBCamera.hlsli b/TombEngine/Shaders/CBCamera.hlsli index 85dc4ac3d..2c627acb5 100644 --- a/TombEngine/Shaders/CBCamera.hlsli +++ b/TombEngine/Shaders/CBCamera.hlsli @@ -33,8 +33,9 @@ cbuffer CBCamera : register(b0) float NearPlane; float FarPlane; //-- + int RefreshRate; int NumFogBulbs; - float3 Padding2; + float2 Padding2; //-- ShaderFogBulb FogBulbs[MAX_FOG_BULBS]; }; From 48d1c9ca10062e907528dc8aa039d46564a2437f Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 11 May 2024 06:02:24 +0200 Subject: [PATCH 162/410] Better handling of legacy 30 fps --- TombEngine/Game/control/control.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index f8666c90f..eae248add 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -598,6 +598,8 @@ GameStatus DoGameLoop(int levelIndex) controlLag += frameTime; } + bool legacy30FPSdoneDraw = false; + while (controlLag >= controlFrameTime) { #if _DEBUG @@ -615,22 +617,27 @@ GameStatus DoGameLoop(int levelIndex) controlLag -= controlFrameTime; controlCalls++; - if (!g_Configuration.EnableVariableFramerate) - { - DrawPhase(!levelIndex, 0.0f); - drawCalls++; - } + legacy30FPSdoneDraw = false; } if (status != GameStatus::Normal) break; if (!g_Configuration.EnableVariableFramerate) - continue; - - float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); - DrawPhase(!levelIndex, interpolationFactor); - drawCalls++; + { + if (!legacy30FPSdoneDraw) + { + DrawPhase(!levelIndex, 0.0f); + drawCalls++; + legacy30FPSdoneDraw = true; + } + } + else + { + float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + DrawPhase(!levelIndex, interpolationFactor); + drawCalls++; + } } EndGameLoop(levelIndex, status); From 8aa34857e045db30cf351efaf17304d67a54c015 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 11 May 2024 10:12:42 +0200 Subject: [PATCH 163/410] Fix inventory spinback --- TombEngine/Game/gui.cpp | 37 ++++++++++++++++++------------------- TombEngine/Game/gui.h | 3 +++ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index a6a48b75c..953a9961b 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -193,6 +193,11 @@ namespace TEN::Gui return false; } + float GuiController::GetSpinSpeed() + { + return g_Configuration.EnableVariableFramerate ? (g_Renderer.GetScreenRefreshRate() / 30.0f) : 1.0f; + } + bool GuiController::CanDeselect() const { return !(IsHeld(In::Select) || IsHeld(In::Action)); @@ -2028,8 +2033,6 @@ namespace TEN::Gui void GuiController::FadeAmmoSelector() { - float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; - if (Rings[(int)RingTypes::Inventory].RingActive) { AmmoSelectorFadeVal = 0; @@ -2037,7 +2040,7 @@ namespace TEN::Gui else if (AmmoSelectorFadeDir == 1) { if (AmmoSelectorFadeVal < 128) - AmmoSelectorFadeVal += 32 / multiplier; + AmmoSelectorFadeVal += 32 / GetSpinSpeed(); if (AmmoSelectorFadeVal > 128) { @@ -2048,7 +2051,7 @@ namespace TEN::Gui else if (AmmoSelectorFadeDir == 2) { if (AmmoSelectorFadeVal > 0) - AmmoSelectorFadeVal -= 32 / multiplier; + AmmoSelectorFadeVal -= 32 / GetSpinSpeed(); if (AmmoSelectorFadeVal < 0) { @@ -2732,15 +2735,13 @@ namespace TEN::Gui void GuiController::SpinBack(EulerAngles& orient) { - orient.Lerp(EulerAngles::Identity, 1.0f / 8); + orient.Lerp(EulerAngles::Identity, 1.0f / (8.0f * GetSpinSpeed())); } void GuiController::DrawAmmoSelector() { if (!AmmoSelectorFlag) return; - - float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; int xPos = (2 * PHD_CENTER_X - OBJLIST_SPACING) / 2; if (NumAmmoSlots == 2) @@ -2757,13 +2758,13 @@ namespace TEN::Gui if (n == *CurrentAmmoType) { if (invObject->RotFlags & INV_ROT_X) - AmmoObjectList[n].Orientation.x += ANGLE(5.0f / multiplier); + AmmoObjectList[n].Orientation.x += ANGLE(5.0f / GetSpinSpeed()); if (invObject->RotFlags & INV_ROT_Y) - AmmoObjectList[n].Orientation.y += ANGLE(5.0f / multiplier); + AmmoObjectList[n].Orientation.y += ANGLE(5.0f / GetSpinSpeed()); if (invObject->RotFlags & INV_ROT_Z) - AmmoObjectList[n].Orientation.z += ANGLE(5.0f / multiplier); + AmmoObjectList[n].Orientation.z += ANGLE(5.0f / GetSpinSpeed()); } else SpinBack(AmmoObjectList[n].Orientation); @@ -2810,8 +2811,6 @@ namespace TEN::Gui const auto& player = GetLaraInfo(*item); auto& ring = Rings[(int)ringType]; - float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; - if (ring.CurrentObjectList <= 0) return; @@ -3137,13 +3136,13 @@ namespace TEN::Gui if (!i && !ring.ObjectListMovement) { if (invObject.RotFlags & INV_ROT_X) - listObject.Orientation.x += ANGLE(5.0f / multiplier); + listObject.Orientation.x += ANGLE(5.0f / GetSpinSpeed()); if (invObject.RotFlags & INV_ROT_Y) - listObject.Orientation.y += ANGLE(5.0f / multiplier); + listObject.Orientation.y += ANGLE(5.0f / GetSpinSpeed()); if (invObject.RotFlags & INV_ROT_Z) - listObject.Orientation.z += ANGLE(5.0f / multiplier); + listObject.Orientation.z += ANGLE(5.0f / GetSpinSpeed()); } else { @@ -3199,17 +3198,17 @@ namespace TEN::Gui if (ring.NumObjectsInList != 1 && (ringType != RingTypes::Ammo || CombineRingFadeVal == 128)) { if (ring.ObjectListMovement > 0) - ring.ObjectListMovement += ANGLE(45.0f / multiplier); + ring.ObjectListMovement += ANGLE(45.0f / GetSpinSpeed()); if (ring.ObjectListMovement < 0) - ring.ObjectListMovement -= ANGLE(45.0f / multiplier); + ring.ObjectListMovement -= ANGLE(45.0f / GetSpinSpeed()); if (IsHeld(In::Left)) { if (!ring.ObjectListMovement) { SoundEffect(SFX_TR4_MENU_ROTATE, nullptr, SoundEnvironment::Always); - ring.ObjectListMovement += ANGLE(45.0f / multiplier); + ring.ObjectListMovement += ANGLE(45.0f / GetSpinSpeed()); if (AmmoSelectorFlag) AmmoSelectorFadeDir = 2; @@ -3221,7 +3220,7 @@ namespace TEN::Gui if (!ring.ObjectListMovement) { SoundEffect(SFX_TR4_MENU_ROTATE, nullptr, SoundEnvironment::Always); - ring.ObjectListMovement -= ANGLE(45.0f / multiplier); + ring.ObjectListMovement -= ANGLE(45.0f / GetSpinSpeed()); if (AmmoSelectorFlag) AmmoSelectorFadeDir = 2; diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h index bf4a4baea..f63e35b0e 100644 --- a/TombEngine/Game/gui.h +++ b/TombEngine/Game/gui.h @@ -127,6 +127,9 @@ namespace TEN::Gui bool CanSelect() const; bool CanDeselect() const; + // Variable FPS + float GetSpinSpeed(); + // GUI variables Menu MenuToDisplay = Menu::Title; int SelectedOption; From 09d756a75f6c13f03ec7042bcc632842c5e1dbe8 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 11 May 2024 10:38:35 +0200 Subject: [PATCH 164/410] Only disable interpolation in scripting method if difference is big enough --- .../TEN/Objects/Moveable/MoveableObject.cpp | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 4e5a62952..90ca4bdd7 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -580,8 +580,10 @@ Vec3 Moveable::GetPos() const // @bool[opt] updateRoom Will room changes be automatically detected? Set to false if you are using overlapping rooms (default: true) void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) { - auto prevPos = m_item->Pose.Position.ToVector3(); - m_item->Pose.Position = pos.ToVector3i(); + auto newPos = pos.ToVector3i(); + bool bigDistance = Vector3i::Distance(newPos, m_item->Pose.Position) > CLICK(1); + + m_item->Pose.Position = newPos; bool willUpdate = !updateRoom.has_value() || updateRoom.value(); @@ -590,8 +592,7 @@ void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) bool isRoomUpdated = m_item->IsLara() ? UpdateLaraRoom(m_item, pos.y) : UpdateItemRoom(m_item->Index); // In case direct portal room update didn't happen and distance between old and new points is significant, do predictive room update. - if (!isRoomUpdated && - (willUpdate || Vector3::Distance(prevPos, m_item->Pose.Position.ToVector3()) > BLOCK(1))) + if (!isRoomUpdated && (willUpdate || bigDistance)) { int potentialNewRoom = FindRoomNumber(m_item->Pose.Position, m_item->RoomNumber); if (potentialNewRoom != m_item->RoomNumber) @@ -602,7 +603,8 @@ void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) if (m_item->IsBridge()) UpdateBridgeItem(*m_item); - m_item->DisableInterpolation = true; + if (bigDistance) + m_item->DisableInterpolation = true; } Vec3 Moveable::GetJointPos(int jointIndex) const @@ -627,14 +629,16 @@ Rotation Moveable::GetRot() const void Moveable::SetRot(const Rotation& rot) { - m_item->Pose.Orientation.x = ANGLE(rot.x); - m_item->Pose.Orientation.y = ANGLE(rot.y); - m_item->Pose.Orientation.z = ANGLE(rot.z); + auto newRot = rot.ToEulerAngles(); + bool bigRotation = EulerAngles::Compare(newRot, m_item->Pose.Orientation, ANGLE(30.0f)); + + m_item->Pose.Orientation = newRot; if (m_item->IsBridge()) UpdateBridgeItem(*m_item); - m_item->DisableInterpolation = true; + if (bigRotation) + m_item->DisableInterpolation = true; } short Moveable::GetHP() const From 796354e67af3aff4cdcb7dcdf9171193dabe562e Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 11 May 2024 10:59:07 +0200 Subject: [PATCH 165/410] Invert SetRot interpolation condition --- .../Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 90ca4bdd7..7987d2366 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -630,7 +630,7 @@ Rotation Moveable::GetRot() const void Moveable::SetRot(const Rotation& rot) { auto newRot = rot.ToEulerAngles(); - bool bigRotation = EulerAngles::Compare(newRot, m_item->Pose.Orientation, ANGLE(30.0f)); + bool bigRotation = !EulerAngles::Compare(newRot, m_item->Pose.Orientation, ANGLE(30.0f)); m_item->Pose.Orientation = newRot; From 98f4caec8045226c1c2ac82c8a775e03f0cba2f3 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 12 May 2024 05:42:08 +0200 Subject: [PATCH 166/410] Fixed missing strings in inventory --- TombEngine/Game/gui.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 953a9961b..42411c31d 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -279,7 +279,6 @@ namespace TEN::Gui void GuiController::DrawInventory() { - g_Renderer.PrepareScene(); g_Renderer.RenderInventory(); g_Renderer.Lock(); // TODO: When inventory is converted to 60 FPS, move this lock call outside of render loop. } @@ -3273,8 +3272,13 @@ namespace TEN::Gui while (g_Gui.GetInventoryMode() == InventoryMode::Pause) { - g_Gui.DrawInventory(); - g_Renderer.Synchronize(); + g_Renderer.PrepareScene(); + g_Renderer.RenderInventory(); + g_Renderer.Lock(); + if (!g_Configuration.EnableVariableFramerate) + { + g_Renderer.Synchronize(); + } if (g_Gui.DoPauseMenu(LaraItem) == InventoryResult::ExitToTitle) { @@ -3329,7 +3333,7 @@ namespace TEN::Gui exitLoop = true; } - DrawInventory(); + g_Renderer.PrepareScene(); switch (InvMode) { @@ -3387,6 +3391,8 @@ namespace TEN::Gui SetEnterInventory(NO_VALUE); + g_Renderer.RenderInventory(); + g_Renderer.Lock(); if (!g_Configuration.EnableVariableFramerate) { g_Renderer.Synchronize(); From 5bd68efc108f2ea23fc3d64c2919629a52b8d24c Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 12 May 2024 06:02:09 +0200 Subject: [PATCH 167/410] WIP better inventory game loop --- TombEngine/Game/gui.cpp | 154 ++++++++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 54 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 42411c31d..b86f1de38 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3313,6 +3313,19 @@ namespace TEN::Gui InitializeInventory(item); Camera.numberFrames = 2; + LARGE_INTEGER lastTime; + LARGE_INTEGER currentTime; + double controlLag = 0; + double frameTime = 0; + constexpr auto controlFrameTime = 1000.0f / 30.0f; + + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&lastTime); + + int controlCalls = 0; + int drawCalls = 0; + bool exitLoop = false; while (!exitLoop) { @@ -3322,81 +3335,114 @@ namespace TEN::Gui return false; } - TimeInMenu++; - GameTimer++; - - UpdateInputActions(item); - - if (GuiIsDeselected() || IsClicked(In::Inventory)) + if (App.ResetClock) { - SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); - exitLoop = true; + App.ResetClock = false; + QueryPerformanceCounter(&lastTime); + currentTime = lastTime; + controlLag = 0; + frameTime = 0; + } + else + { + QueryPerformanceCounter(¤tTime); + frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; + lastTime = currentTime; + controlLag += frameTime; } - g_Renderer.PrepareScene(); - - switch (InvMode) + while (controlLag >= controlFrameTime) { - case InventoryMode::InGame: - DoInventory(item); - break; +#if _DEBUG + constexpr auto DEBUG_SKIP_FRAMES = 10; - case InventoryMode::Statistics: - DoStatisticsMode(); - break; - - case InventoryMode::Examine: - DoExamineMode(); - break; - - case InventoryMode::Diary: - DoDiary(item); - break; - - case InventoryMode::Load: - switch (DoLoad()) + if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) { - case LoadResult::Load: - doLoad = true; + TENLog("Game loop is running too slow!", LogLevel::Warning); + App.ResetClock = true; + break; + } +#endif + TimeInMenu++; + GameTimer++; + + UpdateInputActions(item); + + if (GuiIsDeselected() || IsClicked(In::Inventory)) + { + SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); exitLoop = true; - break; - - case LoadResult::Cancel: - exitLoop = !resetMode; - - if (resetMode) - SetInventoryMode(InventoryMode::InGame); - - break; - - case LoadResult::None: - break; } - break; + g_Renderer.PrepareScene(); - case InventoryMode::Save: - if (DoSave()) + switch (InvMode) { - exitLoop = !resetMode; - if (resetMode) - SetInventoryMode(InventoryMode::InGame); + case InventoryMode::InGame: + DoInventory(item); + break; + + case InventoryMode::Statistics: + DoStatisticsMode(); + break; + + case InventoryMode::Examine: + DoExamineMode(); + break; + + case InventoryMode::Diary: + DoDiary(item); + break; + + case InventoryMode::Load: + switch (DoLoad()) + { + case LoadResult::Load: + doLoad = true; + exitLoop = true; + break; + + case LoadResult::Cancel: + exitLoop = !resetMode; + + if (resetMode) + SetInventoryMode(InventoryMode::InGame); + + break; + + case LoadResult::None: + break; + } + + break; + + case InventoryMode::Save: + if (DoSave()) + { + exitLoop = !resetMode; + if (resetMode) + SetInventoryMode(InventoryMode::InGame); + } + + break; } - break; + if (ItemUsed && NoAction()) + exitLoop = true; + + SetEnterInventory(NO_VALUE); + controlLag -= controlFrameTime; + controlCalls++; } - if (ItemUsed && NoAction()) - exitLoop = true; - - SetEnterInventory(NO_VALUE); - g_Renderer.RenderInventory(); g_Renderer.Lock(); if (!g_Configuration.EnableVariableFramerate) { g_Renderer.Synchronize(); } + + drawCalls++; } LastInvItem = Rings[(int)RingTypes::Inventory].CurrentObjectList[Rings[(int)RingTypes::Inventory].CurrentObjectInList].InventoryItem; From bb4e64812122d3420c9156aa69e3db08e341084a Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 12 May 2024 15:45:44 +0200 Subject: [PATCH 168/410] WIP fixes for other menus --- TombEngine/Game/gui.cpp | 113 +++++++++++++++++++++++---- TombEngine/Renderer/Renderer.h | 1 + TombEngine/Renderer/RendererDraw.cpp | 2 +- 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index b86f1de38..5f1afb82d 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -1191,7 +1191,6 @@ namespace TEN::Gui case Menu::Display: HandleDisplaySettingsInput(true); - App.ResetClock = true; return InventoryResult::None; case Menu::GeneralActions: @@ -1199,12 +1198,10 @@ namespace TEN::Gui case Menu::QuickActions: case Menu::MenuActions: HandleControlSettingsInput(item, true); - App.ResetClock = true; return InventoryResult::None; case Menu::OtherSettings: HandleOtherSettingsInput(true); - App.ResetClock = true; return InventoryResult::None; } @@ -1288,7 +1285,6 @@ namespace TEN::Gui } } - App.ResetClock = true; return InventoryResult::None; } @@ -3270,21 +3266,93 @@ namespace TEN::Gui bool doExitToTitle = false; + LARGE_INTEGER lastTime; + LARGE_INTEGER currentTime; + double controlLag = 0; + double frameTime = 0; + constexpr auto controlFrameTime = 1000.0f / 30.0f; + + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&lastTime); + + int controlCalls = 0; + int drawCalls = 0; + while (g_Gui.GetInventoryMode() == InventoryMode::Pause) { - g_Renderer.PrepareScene(); - g_Renderer.RenderInventory(); - g_Renderer.Lock(); - if (!g_Configuration.EnableVariableFramerate) + if (ThreadEnded) { - g_Renderer.Synchronize(); + App.ResetClock = true; + return false; } - if (g_Gui.DoPauseMenu(LaraItem) == InventoryResult::ExitToTitle) + if (App.ResetClock) + { + App.ResetClock = false; + QueryPerformanceCounter(&lastTime); + currentTime = lastTime; + controlLag = 0; + frameTime = 0; + } + else + { + QueryPerformanceCounter(¤tTime); + frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; + lastTime = currentTime; + controlLag += frameTime; + } + + bool legacy30FPSdoneDraw = false; + + while (controlLag >= controlFrameTime) + { +#if _DEBUG + constexpr auto DEBUG_SKIP_FRAMES = 10; + + if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) + { + TENLog("Game loop is running too slow!", LogLevel::Warning); + App.ResetClock = true; + break; + } +#endif + g_Renderer.PrepareScene(); + + if (g_Gui.DoPauseMenu(LaraItem) == InventoryResult::ExitToTitle) + { + doExitToTitle = true; + break; + } + + controlLag -= controlFrameTime; + controlCalls++; + + legacy30FPSdoneDraw = false; + } + + if (doExitToTitle) { - doExitToTitle = true; break; } + + if (!g_Configuration.EnableVariableFramerate) + { + if (!legacy30FPSdoneDraw) + { + g_Renderer.RenderInventory(); + g_Renderer.Lock(); + g_Renderer.Synchronize(); + drawCalls++; + legacy30FPSdoneDraw = true; + } + } + else + { + g_Renderer.RenderInventory(); + g_Renderer.Lock(); + drawCalls++; + } } if (doExitToTitle) @@ -3351,6 +3419,8 @@ namespace TEN::Gui controlLag += frameTime; } + bool legacy30FPSdoneDraw = false; + while (controlLag >= controlFrameTime) { #if _DEBUG @@ -3433,16 +3503,27 @@ namespace TEN::Gui SetEnterInventory(NO_VALUE); controlLag -= controlFrameTime; controlCalls++; + + legacy30FPSdoneDraw = false; } - g_Renderer.RenderInventory(); - g_Renderer.Lock(); if (!g_Configuration.EnableVariableFramerate) { - g_Renderer.Synchronize(); + if (!legacy30FPSdoneDraw) + { + g_Renderer.RenderInventory(); + g_Renderer.Lock(); + g_Renderer.Synchronize(); + drawCalls++; + legacy30FPSdoneDraw = true; + } + } + else + { + g_Renderer.RenderInventory(); + g_Renderer.Lock(); + drawCalls++; } - - drawCalls++; } LastInvItem = Rings[(int)RingTypes::Inventory].CurrentObjectList[Rings[(int)RingTypes::Inventory].CurrentObjectInList].InventoryItem; diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 8d058514d..41ed018ce 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -202,6 +202,7 @@ namespace TEN::Renderer std::vector _stringsToDraw; float _blinkColorValue = 0.0f; float _blinkTime = 0.0f; + float _oldBlinkTime = 0.0f; // Graphics resources Texture2D _logo; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 9d0c992a4..78cb5ef4e 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1648,7 +1648,7 @@ namespace TEN::Renderer _blinkColorValue = ((sin(_blinkTime) + BLINK_VALUE_MAX) * 0.5f) + BLINK_VALUE_MIN; // Update blink time. - _blinkTime += BLINK_TIME_STEP; + _blinkTime += BLINK_TIME_STEP / (g_Configuration.EnableVariableFramerate ? (g_Renderer.GetScreenRefreshRate() / 30.0f) : 1.0f); if (_blinkTime > PI_MUL_2) _blinkTime -= PI_MUL_2; From a7b697e75640c96e50055b507eb93015249c30f3 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 13 May 2024 00:16:07 +1000 Subject: [PATCH 169/410] Minor formatting --- TombEngine/Game/gui.cpp | 46 ++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 5f1afb82d..628e799a6 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3256,6 +3256,8 @@ namespace TEN::Gui bool GuiController::CallPause() { + constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; + g_Renderer.DumpGameScene(); PauseAllSounds(SoundPauseMode::Pause); SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); @@ -3270,7 +3272,6 @@ namespace TEN::Gui LARGE_INTEGER currentTime; double controlLag = 0; double frameTime = 0; - constexpr auto controlFrameTime = 1000.0f / 30.0f; LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); @@ -3303,16 +3304,16 @@ namespace TEN::Gui controlLag += frameTime; } - bool legacy30FPSdoneDraw = false; + bool legacy30FpsDoneDraw = false; - while (controlLag >= controlFrameTime) + while (controlLag >= CONTROL_FRAME_TIME) { #if _DEBUG constexpr auto DEBUG_SKIP_FRAMES = 10; - if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) + if (controlLag >= (DEBUG_SKIP_FRAMES * CONTROL_FRAME_TIME)) { - TENLog("Game loop is running too slow!", LogLevel::Warning); + TENLog("Game loop is running too slow.", LogLevel::Warning); App.ResetClock = true; break; } @@ -3325,26 +3326,24 @@ namespace TEN::Gui break; } - controlLag -= controlFrameTime; + controlLag -= CONTROL_FRAME_TIME; controlCalls++; - legacy30FPSdoneDraw = false; + legacy30FpsDoneDraw = false; } if (doExitToTitle) - { break; - } if (!g_Configuration.EnableVariableFramerate) { - if (!legacy30FPSdoneDraw) + if (!legacy30FpsDoneDraw) { g_Renderer.RenderInventory(); g_Renderer.Lock(); g_Renderer.Synchronize(); drawCalls++; - legacy30FPSdoneDraw = true; + legacy30FpsDoneDraw = true; } } else @@ -3356,15 +3355,21 @@ namespace TEN::Gui } if (doExitToTitle) + { StopAllSounds(); + } else + { ResumeAllSounds(SoundPauseMode::Pause); + } return doExitToTitle; } bool GuiController::CallInventory(ItemInfo* item, bool resetMode) { + constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; + auto* lara = GetLaraInfo(item); bool doLoad = false; @@ -3385,7 +3390,6 @@ namespace TEN::Gui LARGE_INTEGER currentTime; double controlLag = 0; double frameTime = 0; - constexpr auto controlFrameTime = 1000.0f / 30.0f; LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); @@ -3419,16 +3423,16 @@ namespace TEN::Gui controlLag += frameTime; } - bool legacy30FPSdoneDraw = false; + bool legacy30FpsDoneDraw = false; - while (controlLag >= controlFrameTime) + while (controlLag >= CONTROL_FRAME_TIME) { #if _DEBUG - constexpr auto DEBUG_SKIP_FRAMES = 10; + constexpr auto DEBUG_SKIP_FRAME_COUNT = 10; - if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) + if (controlLag >= (DEBUG_SKIP_FRAME_COUNT * CONTROL_FRAME_TIME)) { - TENLog("Game loop is running too slow!", LogLevel::Warning); + TENLog("Game loop is running too slow.", LogLevel::Warning); App.ResetClock = true; break; } @@ -3501,21 +3505,21 @@ namespace TEN::Gui exitLoop = true; SetEnterInventory(NO_VALUE); - controlLag -= controlFrameTime; + controlLag -= CONTROL_FRAME_TIME; controlCalls++; - legacy30FPSdoneDraw = false; + legacy30FpsDoneDraw = false; } if (!g_Configuration.EnableVariableFramerate) { - if (!legacy30FPSdoneDraw) + if (!legacy30FpsDoneDraw) { g_Renderer.RenderInventory(); g_Renderer.Lock(); g_Renderer.Synchronize(); drawCalls++; - legacy30FPSdoneDraw = true; + legacy30FpsDoneDraw = true; } } else From 24a8dd3b47b0ec7c79738f1a3b350c614bea89a8 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 13 May 2024 06:06:17 +0200 Subject: [PATCH 170/410] Fix occasional freeze after calling pause menu --- TombEngine/Game/gui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 5f1afb82d..ea88f039f 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3360,6 +3360,8 @@ namespace TEN::Gui else ResumeAllSounds(SoundPauseMode::Pause); + App.ResetClock = true; + return doExitToTitle; } From 46b3b383a63514d73f8ff5e0a10859ab9ea3a00f Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 14 May 2024 11:53:54 +0200 Subject: [PATCH 171/410] Added animated textures support in G-Buffer creation for rooms --- TombEngine/Renderer/Renderer.h | 1 + TombEngine/Renderer/RendererDraw.cpp | 12 +++++++++++- TombEngine/Renderer/RendererInit.cpp | 1 + TombEngine/Shaders/GBuffer.fx | 12 +++++++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 41ed018ce..7bc8a35a0 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -151,6 +151,7 @@ namespace TEN::Renderer ComPtr _psHUDTexture; ComPtr _psHUDBarColor; ComPtr _vsGBufferRooms; + ComPtr _vsGBufferRoomsAnimated; ComPtr _vsGBufferItems; ComPtr _vsGBufferStatics; ComPtr _vsGBufferInstancedStatics; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 78cb5ef4e..401b1ec0d 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2630,7 +2630,6 @@ namespace TEN::Renderer { if (rendererPass == RendererPass::GBuffer) { - _context->VSSetShader(_vsGBufferRooms.Get(), nullptr, 0); _context->PSSetShader(_psGBuffer.Get(), nullptr, 0); } else @@ -2709,6 +2708,17 @@ namespace TEN::Renderer _context->VSSetShader(_vsRoomsAnimatedTextures.Get(), nullptr, 0); } } + else + { + if (animated == 0) + { + _context->VSSetShader(_vsGBufferRooms.Get(), nullptr, 0); + } + else + { + _context->VSSetShader(_vsGBufferRoomsAnimated.Get(), nullptr, 0); + } + } for (auto& bucket : room->Buckets) { diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp index d382d191d..78f714ed0 100644 --- a/TombEngine/Renderer/RendererInit.cpp +++ b/TombEngine/Renderer/RendererInit.cpp @@ -86,6 +86,7 @@ namespace TEN::Renderer _vsInstancedSprites = Utils::compileVertexShader(_device.Get(), GetAssetPath(L"Shaders\\InstancedSprites.fx"), "VS", "vs_5_0", nullptr, blob); _psInstancedSprites = Utils::compilePixelShader(_device.Get(), GetAssetPath(L"Shaders\\InstancedSprites.fx"), "PS", "ps_5_0", nullptr, blob); _vsGBufferRooms = Utils::compileVertexShader(_device.Get(), GetAssetPath(L"Shaders\\GBuffer.fx"), "VSRooms", "vs_5_0", nullptr, blob); + _vsGBufferRoomsAnimated = Utils::compileVertexShader(_device.Get(), GetAssetPath(L"Shaders\\GBuffer.fx"), "VSRooms", "vs_5_0", &roomDefinesAnimated[0], blob); _vsGBufferItems = Utils::compileVertexShader(_device.Get(), GetAssetPath(L"Shaders\\GBuffer.fx"), "VSItems", "vs_5_0", nullptr, blob); _vsGBufferStatics = Utils::compileVertexShader(_device.Get(), GetAssetPath(L"Shaders\\GBuffer.fx"), "VSStatics", "vs_5_0", nullptr, blob); _vsGBufferInstancedStatics = Utils::compileVertexShader(_device.Get(), GetAssetPath(L"Shaders\\GBuffer.fx"), "VSInstancedStatics", "vs_5_0", nullptr, blob); diff --git a/TombEngine/Shaders/GBuffer.fx b/TombEngine/Shaders/GBuffer.fx index 830ed1c33..566ca6518 100644 --- a/TombEngine/Shaders/GBuffer.fx +++ b/TombEngine/Shaders/GBuffer.fx @@ -1,6 +1,7 @@ #include "./CBCamera.hlsli" #include "./VertexInput.hlsli" #include "./VertexEffects.hlsli" +#include "./AnimatedTextures.hlsli" #include "./Blending.hlsli" #include "./Math.hlsli" @@ -102,7 +103,16 @@ PixelShaderInput VSRooms(VertexShaderInput input) output.Tangent = input.Tangent; output.Binormal = input.Binormal; output.PositionCopy = screenPos; - output.UV = input.UV; + +#ifdef ANIMATED + + if (Type == 0) + output.UV = GetFrame(input.PolyIndex, input.AnimationFrameOffset); + else + output.UV = input.UV; // TODO: true UVRotate in future? +#else + output.UV = input.UV; +#endif return output; } From 2a0f01824765bc9096371027a430111975aa15e3 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 14 May 2024 12:15:06 +0200 Subject: [PATCH 172/410] Fixed flickering transparent sorted faces; Fixed variable framerate always on even if disabled in settings; --- TombEngine/Game/control/control.cpp | 4 ++-- TombEngine/Game/gui.cpp | 8 ++++---- TombEngine/Renderer/RenderView.cpp | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index eae248add..813d29b12 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -579,6 +579,8 @@ GameStatus DoGameLoop(int levelIndex) int controlCalls = 0; int drawCalls = 0; + + bool legacy30FPSdoneDraw = false; while (DoTheGame) { @@ -598,8 +600,6 @@ GameStatus DoGameLoop(int levelIndex) controlLag += frameTime; } - bool legacy30FPSdoneDraw = false; - while (controlLag >= controlFrameTime) { #if _DEBUG diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 83e875041..31efc000f 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3280,6 +3280,8 @@ namespace TEN::Gui int controlCalls = 0; int drawCalls = 0; + bool legacy30FpsDoneDraw = false; + while (g_Gui.GetInventoryMode() == InventoryMode::Pause) { if (ThreadEnded) @@ -3304,8 +3306,6 @@ namespace TEN::Gui controlLag += frameTime; } - bool legacy30FpsDoneDraw = false; - while (controlLag >= CONTROL_FRAME_TIME) { #if _DEBUG @@ -3400,7 +3400,9 @@ namespace TEN::Gui int controlCalls = 0; int drawCalls = 0; + bool legacy30FpsDoneDraw = false; bool exitLoop = false; + while (!exitLoop) { if (ThreadEnded) @@ -3425,8 +3427,6 @@ namespace TEN::Gui controlLag += frameTime; } - bool legacy30FpsDoneDraw = false; - while (controlLag >= CONTROL_FRAME_TIME) { #if _DEBUG diff --git a/TombEngine/Renderer/RenderView.cpp b/TombEngine/Renderer/RenderView.cpp index 6558d062c..1f02db401 100644 --- a/TombEngine/Renderer/RenderView.cpp +++ b/TombEngine/Renderer/RenderView.cpp @@ -52,6 +52,7 @@ namespace TEN::Renderer SortedStaticsToDraw.clear(); FogBulbsToDraw.clear(); LensFlaresToDraw.clear(); + TransparentObjectsToDraw.clear(); } RenderViewCamera::RenderViewCamera(CAMERA_INFO* cam, float roll, float fov, float n, float f, int w, int h) From f9963f7940804910d20a834ae3a33afdb7463d9e Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Tue, 14 May 2024 22:51:47 +0200 Subject: [PATCH 173/410] Fix slow text fade --- TombEngine/Renderer/RendererDraw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 401b1ec0d..a1c0966b7 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1648,7 +1648,7 @@ namespace TEN::Renderer _blinkColorValue = ((sin(_blinkTime) + BLINK_VALUE_MAX) * 0.5f) + BLINK_VALUE_MIN; // Update blink time. - _blinkTime += BLINK_TIME_STEP / (g_Configuration.EnableVariableFramerate ? (g_Renderer.GetScreenRefreshRate() / 30.0f) : 1.0f); + _blinkTime += BLINK_TIME_STEP; if (_blinkTime > PI_MUL_2) _blinkTime -= PI_MUL_2; From 15da2fcc874b5b7e06420f87dc780e806a307abf Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 15 May 2024 09:01:03 +0200 Subject: [PATCH 174/410] Removed old numberFrames field from camera --- TombEngine/Game/camera.cpp | 1 - TombEngine/Game/camera.h | 1 - TombEngine/Game/gui.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 722d1db91..b3733f0d1 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -248,7 +248,6 @@ void InitializeCamera() Camera.targetDistance = BLOCK(1.5f); Camera.item = nullptr; - Camera.numberFrames = 1; Camera.type = CameraType::Chase; Camera.speed = 1; Camera.flags = CF_NONE; diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 504a59ed4..969dec236 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -28,7 +28,6 @@ struct CAMERA_INFO int flags; bool fixedCamera; bool underwater; - int numberFrames; int bounce; int targetDistance; short targetAngle; diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 31efc000f..6af798543 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3386,7 +3386,6 @@ namespace TEN::Gui SetInventoryMode(InventoryMode::InGame); InitializeInventory(item); - Camera.numberFrames = 2; LARGE_INTEGER lastTime; LARGE_INTEGER currentTime; From 359df969e1e6748607d81012ffbc898275b5c13e Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 16 May 2024 06:58:21 +1000 Subject: [PATCH 175/410] Update doc comments; minor formatting --- TombEngine/Game/control/control.cpp | 8 +-- TombEngine/Renderer/RendererDraw.cpp | 53 ++++++------------- .../Internal/TEN/Flow/Starfield/Starfield.cpp | 8 +-- 3 files changed, 25 insertions(+), 44 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 813d29b12..504a55a9f 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -580,7 +580,7 @@ GameStatus DoGameLoop(int levelIndex) int controlCalls = 0; int drawCalls = 0; - bool legacy30FPSdoneDraw = false; + bool legacy30FpsDoneDraw = false; while (DoTheGame) { @@ -617,7 +617,7 @@ GameStatus DoGameLoop(int levelIndex) controlLag -= controlFrameTime; controlCalls++; - legacy30FPSdoneDraw = false; + legacy30FpsDoneDraw = false; } if (status != GameStatus::Normal) @@ -625,11 +625,11 @@ GameStatus DoGameLoop(int levelIndex) if (!g_Configuration.EnableVariableFramerate) { - if (!legacy30FPSdoneDraw) + if (!legacy30FpsDoneDraw) { DrawPhase(!levelIndex, 0.0f); drawCalls++; - legacy30FPSdoneDraw = true; + legacy30FpsDoneDraw = true; } } else diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index a1c0966b7..ebf7a04b3 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2679,69 +2679,48 @@ namespace TEN::Renderer for (int i = (int)view.RoomsToDraw.size() - 1; i >= 0; i--) { - int index = i; - RendererRoom* room = view.RoomsToDraw[index]; - ROOM_INFO* nativeRoom = &g_Level.Rooms[room->RoomNumber]; + const auto& room = *view.RoomsToDraw[i]; + const auto& nativeRoom = g_Level.Rooms[room.RoomNumber]; if (rendererPass != RendererPass::GBuffer) { - _stRoom.Caustics = (int)(g_Configuration.EnableCaustics && (nativeRoom->flags & ENV_FLAG_WATER)); - _stRoom.AmbientColor = room->AmbientLight; + _stRoom.Caustics = int(g_Configuration.EnableCaustics && (nativeRoom.flags & ENV_FLAG_WATER)); + _stRoom.AmbientColor = room.AmbientLight; BindRoomLights(view.LightsToDraw); } - _stRoom.Water = (nativeRoom->flags & ENV_FLAG_WATER) != 0 ? 1 : 0; + _stRoom.Water = (nativeRoom.flags & ENV_FLAG_WATER) != 0 ? 1 : 0; _cbRoom.UpdateData(_stRoom, _context.Get()); - SetScissor(room->ClipBounds); + SetScissor(room.ClipBounds); for (int animated = 0; animated < 2; animated++) { if (rendererPass != RendererPass::GBuffer) { - if (animated == 0) - { - _context->VSSetShader(_vsRooms.Get(), nullptr, 0); - } - else - { - _context->VSSetShader(_vsRoomsAnimatedTextures.Get(), nullptr, 0); - } + _context->VSSetShader((animated == 0) ? _vsRooms.Get() : _vsRoomsAnimatedTextures.Get(), nullptr, 0); } else { - if (animated == 0) - { - _context->VSSetShader(_vsGBufferRooms.Get(), nullptr, 0); - } - else - { - _context->VSSetShader(_vsGBufferRoomsAnimated.Get(), nullptr, 0); - } + _context->VSSetShader((animated == 0) ? _vsGBufferRooms.Get() : _vsGBufferRoomsAnimated.Get(), nullptr, 0); } - for (auto& bucket : room->Buckets) + for (const auto& bucket : room.Buckets) { if ((animated == 1) ^ bucket.Animated) - { continue; - } if (bucket.NumVertices == 0) - { continue; - } int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; for (int p = 0; p < passes; p++) { if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) - { continue; - } - // Draw geometry + // Draw geometry. if (animated) { BindTexture(TextureRegister::ColorMap, @@ -2750,7 +2729,7 @@ namespace TEN::Renderer BindTexture(TextureRegister::NormalMap, &std::get<1>(_animatedTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - RendererAnimatedTextureSet& set = _animatedTextureSets[bucket.Texture]; + const auto& set = _animatedTextureSets[bucket.Texture]; _stAnimated.NumFrames = set.NumTextures; _stAnimated.Type = 0; _stAnimated.Fps = set.Fps; @@ -2759,7 +2738,7 @@ namespace TEN::Renderer { if (j >= _stAnimated.Textures.size()) { - TENLog("Animated frame " + std::to_string(j) + " is out of bounds, too many frames in sequence."); + TENLog("Animated frame " + std::to_string(j) + " out of bounds. Too many frames in sequence."); break; } @@ -2772,10 +2751,12 @@ namespace TEN::Renderer } else { - BindTexture(TextureRegister::ColorMap, &std::get<0>(_roomTextures[bucket.Texture]), + BindTexture( + TextureRegister::ColorMap, &std::get<0>(_roomTextures[bucket.Texture]), + SamplerStateRegister::AnisotropicClamp); + BindTexture( + TextureRegister::NormalMap, &std::get<1>(_roomTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - BindTexture(TextureRegister::NormalMap, - &std::get<1>(_roomTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); } DrawIndexedTriangles(bucket.NumIndices, bucket.StartIndex, 0); diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp index 15cfde18b..60d277a17 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Starfield/Starfield.cpp @@ -45,8 +45,8 @@ namespace TEN::Scripting /// Create a starfield object with stars and meteors. // @function Starfield() - // @tparam int starCount Star count. - // @tparam int meteorCount Meteor count. + // @tparam int starCount Star count (6000 max). + // @tparam int meteorCount Meteor count (100 max). // @treturn Starfield A new Starfield object. Starfield::Starfield(int starCount, int meteorCount, int meteorSpawnDensity, float meteorVel) { @@ -110,7 +110,7 @@ namespace TEN::Scripting return _meteorVelocity; } - /// Set the starfield's number of stars. + /// Set the starfield's number of stars (6000 max). // @function Starfield:SetStarCount(int) // @tparam int New count. void Starfield::SetStarCount(int count) @@ -121,7 +121,7 @@ namespace TEN::Scripting _starCount = std::clamp(count, 0, STAR_COUNT_MAX); } - /// Set the starfield's number of meteors. + /// Set the starfield's number of meteors (100 max). // @function Starfield:SetMeteorCount(int) // @tparam int New count. void Starfield::SetMeteorCount(int count) From 93549b7b07a3ec59dc4abebb75cf3e27ccb9e326 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 16 May 2024 07:02:38 +1000 Subject: [PATCH 176/410] Revert "Remove unnecessary string constants" This reverts commit 3ff70b29153791ae81fe7744f9e7416bee4b3da6. --- .../Scripting/Internal/ReservedScriptNames.h | 16 +++++++++++ .../TEN/DisplaySprite/ScriptDisplaySprite.cpp | 28 +++++++++---------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index ba1134907..8d0e58181 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -37,6 +37,22 @@ static constexpr char ScriptReserved_MoveableStatus[] = "MoveableStatus"; static constexpr char ScriptReserved_Lara[] = "Lara"; static constexpr char ScriptReserved_GetPlayerInteractedMoveable[] = "GetInteractedMoveable"; +// DisplaySprite object +static constexpr char ScriptReserved_DisplaySprite[] = "DisplaySprite"; +static constexpr char ScriptReserved_DisplayStringGetObjectID[] = "GetObjectID"; +static constexpr char ScriptReserved_DisplayStringGetSpriteID[] = "GetSpriteID"; +static constexpr char ScriptReserved_DisplayStringGetPosition[] = "GetPosition"; +static constexpr char ScriptReserved_DisplayStringGetRotation[] = "GetRotation"; +static constexpr char ScriptReserved_DisplayStringGetScale[] = "GetScale"; +static constexpr char ScriptReserved_DisplayStringGetColor[] = "GetColor"; +static constexpr char ScriptReserved_DisplayStringSetObjectID[] = "SetObjectID"; +static constexpr char ScriptReserved_DisplayStringSetSpriteID[] = "SetSpriteID"; +static constexpr char ScriptReserved_DisplayStringSetPosition[] = "SetPosition"; +static constexpr char ScriptReserved_DisplayStringSetRotation[] = "SetRotation"; +static constexpr char ScriptReserved_DisplayStringSetScale[] = "SetScale"; +static constexpr char ScriptReserved_DisplayStringSetColor[] = "SetColor"; +static constexpr char ScriptReserved_DisplaySpriteDraw[] = "Draw"; + static constexpr char ScriptReserved_EndReasonExitToTitle[] = "EXITTOTITLE"; static constexpr char ScriptReserved_EndReasonLevelComplete[] = "LEVELCOMPLETE"; static constexpr char ScriptReserved_EndReasonLoadGame[] = "LOADGAME"; diff --git a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp index aed2f4908..12529806d 100644 --- a/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp +++ b/TombEngine/Scripting/Internal/TEN/DisplaySprite/ScriptDisplaySprite.cpp @@ -30,23 +30,23 @@ namespace TEN::Scripting::DisplaySprite // Register type. parent.new_usertype( - "DisplaySprite", + ScriptReserved_DisplaySprite, ctors(), sol::call_constructor, ctors(), - "GetObjectID", & ScriptDisplaySprite::GetObjectID, - "GetSpriteID", &ScriptDisplaySprite::GetSpriteID, - "GetPosition", &ScriptDisplaySprite::GetPosition, - "GetRotation", &ScriptDisplaySprite::GetRotation, - "GetScale", &ScriptDisplaySprite::GetScale, - "GetColor", &ScriptDisplaySprite::GetColor, - "SetObjectID", &ScriptDisplaySprite::SetObjectID, - "SetSpriteID", &ScriptDisplaySprite::SetSpriteID, - "SetPosition", &ScriptDisplaySprite::SetPosition, - "SetRotation", &ScriptDisplaySprite::SetRotation, - "SetScale", &ScriptDisplaySprite::SetScale, - "SetColor", &ScriptDisplaySprite::SetColor, - "Draw", &ScriptDisplaySprite::Draw); + ScriptReserved_DisplayStringGetObjectID, &ScriptDisplaySprite::GetObjectID, + ScriptReserved_DisplayStringGetSpriteID, &ScriptDisplaySprite::GetSpriteID, + ScriptReserved_DisplayStringGetPosition, &ScriptDisplaySprite::GetPosition, + ScriptReserved_DisplayStringGetRotation, &ScriptDisplaySprite::GetRotation, + ScriptReserved_DisplayStringGetScale, &ScriptDisplaySprite::GetScale, + ScriptReserved_DisplayStringGetColor, &ScriptDisplaySprite::GetColor, + ScriptReserved_DisplayStringSetObjectID, &ScriptDisplaySprite::SetObjectID, + ScriptReserved_DisplayStringSetSpriteID, &ScriptDisplaySprite::SetSpriteID, + ScriptReserved_DisplayStringSetPosition, &ScriptDisplaySprite::SetPosition, + ScriptReserved_DisplayStringSetRotation, &ScriptDisplaySprite::SetRotation, + ScriptReserved_DisplayStringSetScale, &ScriptDisplaySprite::SetScale, + ScriptReserved_DisplayStringSetColor, &ScriptDisplaySprite::SetColor, + ScriptReserved_DisplaySpriteDraw, &ScriptDisplaySprite::Draw); } /// Create a DisplaySprite object. From eb7163a4729ff753e0b959937d6b32d80516f536 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 16 May 2024 05:43:54 +0200 Subject: [PATCH 177/410] Fixed meteors drawing --- TombEngine/Game/effects/weather.cpp | 12 ++-- TombEngine/Renderer/RendererDraw.cpp | 89 ++++++++++++++++------------ 2 files changed, 59 insertions(+), 42 deletions(-) diff --git a/TombEngine/Game/effects/weather.cpp b/TombEngine/Game/effects/weather.cpp index f8ad60ac7..e4e2c95f6 100644 --- a/TombEngine/Game/effects/weather.cpp +++ b/TombEngine/Game/effects/weather.cpp @@ -645,10 +645,12 @@ namespace TEN::Effects::Environment int density = level.GetStarfieldMeteorSpawnDensity(); if (density > 0) - { - for (int i = 0; i < level.GetStarfieldMeteorCount(); i++) + { + int newParticlesCount = 0; + + while (Meteors.size() < level.GetStarfieldMeteorCount()) { - if (i > density) + if (newParticlesCount > density) break; auto horizontalDir = Random::GenerateDirection2D(); @@ -658,7 +660,7 @@ namespace TEN::Effects::Environment part.Active = true; part.Life = METEOR_PARTICLE_LIFE_MAX; part.StartPosition = - part.Position = Random::GenerateDirectionInCone(-Vector3::UnitY, 40.0f) * BLOCK(1.5f); + part.Position = Random::GenerateDirectionInCone(-Vector3::UnitY, 40.0f) * BLOCK(1.5f); part.Fade = 0.0f; part.Color = Vector3( Random::GenerateFloat(0.6f, 1.0f), @@ -670,6 +672,8 @@ namespace TEN::Effects::Environment part.Direction.y = -part.Direction.y; Meteors.push_back(part); + + newParticlesCount++; } } } diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index a1c0966b7..b1adaed7c 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2878,7 +2878,10 @@ namespace TEN::Renderer while (drawnStars < starCount) { - int starsToDraw = (starCount - drawnStars) > 100 ? 100 : (starCount - drawnStars); + int starsToDraw = + (starCount - drawnStars) > INSTANCED_SPRITES_BUCKET_SIZE ? + INSTANCED_SPRITES_BUCKET_SIZE : + (starCount - drawnStars); int i = 0; for (int i = 0; i < starsToDraw; i++) @@ -2930,51 +2933,61 @@ namespace TEN::Renderer rDrawSprite.Sprite = &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_LENS_FLARE_3]; BindTexture(TextureRegister::ColorMap, rDrawSprite.Sprite->Texture, SamplerStateRegister::LinearClamp); - int meteorCount = 0; + int drawnMeteors = 0; + int meteorsCount = (int)Weather.GetMeteors().size(); - for (int i = 0; i < Weather.GetMeteors().size(); i++) + while (drawnMeteors < meteorsCount) { - auto meteor = Weather.GetMeteors()[i]; + int meteorsToDraw = + (meteorsCount - drawnMeteors) > INSTANCED_SPRITES_BUCKET_SIZE ? + INSTANCED_SPRITES_BUCKET_SIZE : + (meteorsCount - drawnMeteors); + int i = 0; - if (meteor.Active == false) - continue; + for (int i = 0; i < meteorsToDraw; i++) + { + auto meteor = Weather.GetMeteors()[drawnMeteors + i]; - rDrawSprite.Type = SpriteType::CustomBillboard; - rDrawSprite.pos = - renderView.Camera.WorldPosition + - Vector3::Lerp(meteor.PrevPosition, meteor.Position, _interpolationFactor); - rDrawSprite.Rotation = 0; - rDrawSprite.Scale = 1; - rDrawSprite.Width = 2; - rDrawSprite.Height = 192; - rDrawSprite.ConstrainAxis = meteor.Direction; + if (meteor.Active == false) + continue; - _stInstancedSpriteBuffer.Sprites[meteorCount].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); - _stInstancedSpriteBuffer.Sprites[meteorCount].Color = Vector4( - meteor.Color.x, - meteor.Color.y, - meteor.Color.z, - Lerp(meteor.PrevFade, meteor.Fade, _interpolationFactor)); - _stInstancedSpriteBuffer.Sprites[meteorCount].IsBillboard = 1; - _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; + rDrawSprite.Type = SpriteType::CustomBillboard; + rDrawSprite.pos = + renderView.Camera.WorldPosition + + Vector3::Lerp(meteor.PrevPosition, meteor.Position, _interpolationFactor); + rDrawSprite.Rotation = 0; + rDrawSprite.Scale = 1; + rDrawSprite.Width = 2; + rDrawSprite.Height = 192; + rDrawSprite.ConstrainAxis = meteor.Direction; - // NOTE: Strange packing due to particular HLSL 16 byte alignment requirements. - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].x = rDrawSprite.Sprite->UV[0].x; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].y = rDrawSprite.Sprite->UV[1].x; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].z = rDrawSprite.Sprite->UV[2].x; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[0].w = rDrawSprite.Sprite->UV[3].x; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].x = rDrawSprite.Sprite->UV[0].y; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].y = rDrawSprite.Sprite->UV[1].y; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].z = rDrawSprite.Sprite->UV[2].y; - _stInstancedSpriteBuffer.Sprites[meteorCount].UV[1].w = rDrawSprite.Sprite->UV[3].y; + _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); + _stInstancedSpriteBuffer.Sprites[i].Color = Vector4( + meteor.Color.x, + meteor.Color.y, + meteor.Color.z, + Lerp(meteor.PrevFade, meteor.Fade, _interpolationFactor)); + _stInstancedSpriteBuffer.Sprites[i].IsBillboard = 1; + _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = 0; - meteorCount++; + // NOTE: Strange packing due to particular HLSL 16 byte alignment requirements. + _stInstancedSpriteBuffer.Sprites[i].UV[0].x = rDrawSprite.Sprite->UV[0].x; + _stInstancedSpriteBuffer.Sprites[i].UV[0].y = rDrawSprite.Sprite->UV[1].x; + _stInstancedSpriteBuffer.Sprites[i].UV[0].z = rDrawSprite.Sprite->UV[2].x; + _stInstancedSpriteBuffer.Sprites[i].UV[0].w = rDrawSprite.Sprite->UV[3].x; + _stInstancedSpriteBuffer.Sprites[i].UV[1].x = rDrawSprite.Sprite->UV[0].y; + _stInstancedSpriteBuffer.Sprites[i].UV[1].y = rDrawSprite.Sprite->UV[1].y; + _stInstancedSpriteBuffer.Sprites[i].UV[1].z = rDrawSprite.Sprite->UV[2].y; + _stInstancedSpriteBuffer.Sprites[i].UV[1].w = rDrawSprite.Sprite->UV[3].y; + } + + _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); + + // Draw sprites with instancing. + DrawInstancedTriangles(4, meteorsToDraw, 0); + + drawnMeteors += meteorsToDraw; } - - _cbInstancedSpriteBuffer.UpdateData(_stInstancedSpriteBuffer, _context.Get()); - - // Draw sprites with instancing. - DrawInstancedTriangles(4, meteorCount, 0); } _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); From 20d591b74fd46a7ea09ccee8fb404ff1c0193fc4 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 15 May 2024 21:53:40 +0200 Subject: [PATCH 178/410] Increase maximum interpolated distance change --- .../Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 7987d2366..2f1dd3e2b 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -581,7 +581,7 @@ Vec3 Moveable::GetPos() const void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) { auto newPos = pos.ToVector3i(); - bool bigDistance = Vector3i::Distance(newPos, m_item->Pose.Position) > CLICK(1); + bool bigDistance = Vector3i::Distance(newPos, m_item->Pose.Position) > BLOCK(1); m_item->Pose.Position = newPos; From 09445ad0ba554fdbd107713a40b52b2db4445f08 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 16 May 2024 09:13:36 +0300 Subject: [PATCH 179/410] Update README.md --- README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 58288e125..c5799ecab 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,7 @@ ![Logo](https://github.com/MontyTRC89/TombEngine/assets/80340234/f22c9ca9-7159-467f-b8ad-7bb32274a278) -In the year 2000, Core Design granted us a great gift: their TR4-based Level Editor, which allowed people to create custom levels. It was, unfortunately, quite limited, hence why over the decades it was upgraded massively with fan projects such as Tomb Raider Engine Patcher (TREP) and Tomb Raider Next Generation (TRNG). -- TREP was a tool which allowed modification of the executable to expand certain limits and implement new features. -- TRNG built upon TREP and provided many new tools, including a scripting language, expanding even more limits with its own .DLL. - -Unfortunately, TRNG's toolset is poorly documented and not user-friendly; the program remains closed-source to this day and is in all practicality an abandonware. As a direct consequence, no one is able to fix the countless well-known bugs and issues extant in TRNG, rendering implementation of new features is impossible without an in-depth knowledge of C++ plugin creation and a solid understanding of the classic Tomb Raider engine's many idiosyncrasies. - -TombEngine (TEN) is a new, open-source engine which aims to abolish all limits, fix bugs from the original games, introduce new features while refining old ones, and provide for a refined, user-friendly level creation process. Current support includes: +In the year 2000, Core Design granted us a great gift: their TR4-based Level Editor, which allowed people to create custom levels. It was, unfortunately, quite limited, hence why over the decades it was upgraded massively with fan patcher projects such as Tomb Raider Engine Patcher (TREP) and Tomb Raider Next Generation (TRNG). TombEngine (TEN) is a new, open-source engine which aims to abolish all limits, fix bugs from the original games, introduce new features while refining old ones, and provide for a refined, user-friendly level creation process. Current support includes: - Lua (as the native scripting language) - All objects from the classic series (1-5) - Many more exciting gameplay functionalities such as diagonal shimmying and expanded crawlspace flexibility @@ -22,7 +16,7 @@ Tomb Engine should be used in conjuction with Tomb Editor. Tomb Editor is also o # Compiling TombEngine To compile TEN, ensure you have installed: - Microsoft Visual Studio -- TombEditor (if you would like to create and test levels) +- Tomb Editor (if you would like to create and test levels) Steps: 1) Clone the repository to your GitHub Desktop From 0b59e4f7241f7a9c4b5032cbda7ed4799e4e1da6 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 16 May 2024 09:14:09 +0300 Subject: [PATCH 180/410] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c5799ecab..fd3834ff5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ ![Logo](https://github.com/MontyTRC89/TombEngine/assets/80340234/f22c9ca9-7159-467f-b8ad-7bb32274a278) -In the year 2000, Core Design granted us a great gift: their TR4-based Level Editor, which allowed people to create custom levels. It was, unfortunately, quite limited, hence why over the decades it was upgraded massively with fan patcher projects such as Tomb Raider Engine Patcher (TREP) and Tomb Raider Next Generation (TRNG). TombEngine (TEN) is a new, open-source engine which aims to abolish all limits, fix bugs from the original games, introduce new features while refining old ones, and provide for a refined, user-friendly level creation process. Current support includes: +In the year 2000, Core Design granted us a great gift: their TR4-based Level Editor, which allowed people to create custom levels. It was, unfortunately, quite limited, hence why over the decades it was upgraded massively with fan patcher projects such as Tomb Raider Engine Patcher (TREP) and Tomb Raider Next Generation (TRNG). + +TombEngine (TEN) is a new, open-source engine which aims to abolish all limits, fix bugs from the original games, introduce new features while refining old ones, and provide for a refined, user-friendly level creation process. Current support includes: - Lua (as the native scripting language) - All objects from the classic series (1-5) - Many more exciting gameplay functionalities such as diagonal shimmying and expanded crawlspace flexibility From 9124b3129ec468d64f38abec745163efe5d221a9 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 16 May 2024 18:26:20 +1000 Subject: [PATCH 181/410] Squishy blocks aren't bridges --- TombEngine/Specific/level.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index d3e4e1fbc..88596ddc4 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -38,8 +38,6 @@ using namespace TEN::Utils; const std::vector BRIDGE_OBJECT_IDS = { ID_EXPANDING_PLATFORM, - ID_SQUISHY_BLOCK_HORIZONTAL, - ID_SQUISHY_BLOCK_VERTICAL, ID_FALLING_BLOCK, ID_FALLING_BLOCK2, From cec6e744757768a2b584fef712eac53e450c7428 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Thu, 16 May 2024 09:30:23 +0100 Subject: [PATCH 182/410] Update CHANGELOG.md --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 287a40f15..aac358b80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,21 @@ Here you will find the full changelog of TEN's releases from Version 1.0 and up The dates are in European standard format where date is presented as **YYYY-MM-DD** +## Version 1.5 - xxxx-xx-xx + +### Bug fixes +* Fixed original issue with classic switch off trigger wrongly activating some trigger actions. +* Fixed incorrect diving animation when swandiving from a high place. +* Fixed camera rotating with Lara's hips when climbing out of water. +* Fixed AI for skidoo driver and worker with shotgun TR2 enemies. +* Fixed Ember emitter crashing when ocb is between -1 and -10 +* Fixed Electric cleaner and Squishy block not detecting collision with certain block heights. + +### Features/Amendments + +### Lua API changes +* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. + ## Version 1.4 - 2024-04-21 ### Bug Fixes From 654e3a0381a953cd0de6af9dbe4de261df6928a7 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 16 May 2024 09:31:38 +0100 Subject: [PATCH 183/410] remove changes.txt (changelog is now in CHANGELOG.md) --- Documentation/Changes.txt | 707 -------------------------------------- 1 file changed, 707 deletions(-) delete mode 100644 Documentation/Changes.txt diff --git a/Documentation/Changes.txt b/Documentation/Changes.txt deleted file mode 100644 index 61d2938c7..000000000 --- a/Documentation/Changes.txt +++ /dev/null @@ -1,707 +0,0 @@ -Version 1.5 -=========== - -* Fixed original issue with classic switch off trigger wrongly activating some trigger actions. -* Fixed incorrect diving animation when swandiving from a high place. -* Fixed camera rotating with Lara's hips when climbing out of water. -* Fixed AI for skidoo driver and worker with shotgun TR2 enemies. -* Fixed Ember emitter crashing when ocb is between -1 and -10 -* Fixed Electric cleaner and Squishy block not detecting collision with certain block heights. - -Lua API changes: -* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. - -Version 1.4 -=========== - -* Fixed drawing of display sprites in title level. -* Fixed drawing of smoke sprites and various other sprites. -* Fixed drawing of transparent surfaces when debris are present in scene. -* Fixed player holster state and current vehicle not preserved correctly on level jump. -* Fixed diving when swimming over sinks. -* Fixed fire item effect not extinguishing in water. -* Fixed fade-in and fade-out effects not canceling correctly when next level is loaded. -* Fixed shadows still being visible after shattering a moveable. -* Fixed FOV interpolation at the end of the flyby sequence. -* Fixed sounds resuming in pause mode while switching between apps. -* Fixed slide directions. -* Fixed occasional collision warnings in a log when teeth spikes object was activated. -* Fixed climbable pushables collision during continuous pulling action. -* Fixed collision for solid static meshes with zero collision box. -* Fixed bottom collision for solid static meshes. -* Fixed T-Rex's head rotation. -* Auto-switch to a crawl state if player start position is in a crawlspace. -* Allow directional flame emitter (negative OCBs) to be rotated at any angle. -* Revise wall spikes: - - Wall spikes now stop when they touch a pushable, another spike wall or a normal wall. - - Wall spikes will shatter any shatter in its path. - - Wall spikes can be stopped by normal antitrigger or with a volume. -* Added hub system to preserve level state on level jumps. -* Added ember emitter. -* Added fish emitter. -* Added laser beam object. -* Added TR2 dragon. -* Added TR3 Winston (requires updated TEN .wad2 on TombEngine.com). -* Added TR4 squishy blocks (requires updated TEN .wad2 on TombEngine.com). - -Lua API changes: -* Added resetHub flag to Flow.Level, which allows to reset hub data. -* Added Flow.GetFlipMapStatus() function to get current flipmap status. -* Added Moveable:GetMeshCount() function to get number of moveable meshes. -* Added timeout parameter for Moveable:Enable() function. -* Added Static:GetHP() and Static:SetHP() functions to change shatterable static mesh hit points. -* Fixed Moveable:SetOnCollidedWithObject() callback. - -Version 1.3 -=========== - -* Fixed crash if title logo is removed from Textures folder. -* Fixed crash if unknown player state ID is encountered. -* Fixed bug with OCB 2 on pushables, and some other pushable bugs. -* Fixed pushable camera bug during edge slip. -* Fixed lever switch turn off alignment animation. -* Fixed lack of water splash in certain scenarios. -* Fixed hydra flame not showing when charging. -* Fixed shockwave light for hammer god. -* Fixed camera shaking in some cases when the player is in quicksand room. -* Fixed certain flame emitter OCBs emitting fire in wrong directions. -* Fixed player not being able to pick up a torch when crouching. -* Fixed jittery camera when performing crawl-to-hang. -* Fixed several issues with limited pistol ammo. -* Fixed player not being able to crawl if two-handed weapon is currently equipped. -* Fixed playback issues with audio tracks placed in subfolders. -* Fixed thin caustics outline on the edge of the blocks. -* Fixed big static objects affected wrongly by dynamic lights. -* Fixed legacy trigger leveljumps ignoring provided level index. -* Fixed incorrect light collection in some cases. -* Fixed normal mapping for rooms, items, and statics. -* Added ambient occlusion (SSAO). -* Added new post-process workflow (monochrome, negative, exclusion) with tinting. -* Added SMAA antialiasing instead of MSAA. -* Added previously missing player start position object functionality. -* Added fast speed for fly cheat by holding Sprint input action. -* Added speedometer to vehicles. -* Added global node events. -* Totally revised transparency handling. -* Increased the maximum frames for animated sequences from 128 to 256. -* Optimized the renderer. -* Separate underwater wall and ceiling switch objects into two slots each. -* Accurately rotate display sprites around the pivot defined by the align mode. -* Allow walking on slopes when wading in water (similar to quicksand). -* Allow player to pull certain levers with both hands when holding a flare. -* Ported twin auto gun from TR3. -* Revised keyhole OCBs to account for keeping or losing keys: - - OCB 0: Play default animation and lose key. - - Positive OCB: Play anim number and keep key. - - Negative OCB: Play anim number and lose key. -* Revised Wolf OCBs: - - OCB 0: Wolf starts in walking animation, ready to chase Lara. - - OCB 1: Wolf starts in sleeping animation. - -Lua API changes: -* Added Lara:GetInteractedMoveable() which returns currently interacted moveable by Lara. -* Added Moveable:SetStatus() to set the current status of the moveable. -* Added Room:GetColor() to get room's ambient light color. -* Added Util.PickMoveableByDisplayPosition() and Util.PickStaticByDisplayPosition() functions. -* Added View.GetCameraPosition(), View.GetCameraTarget() and View.GetCameraRoom() functions. -* Added View.SetPostProcessMode(), View.SetPostProcessStrength() and View.SetPostProcessTint() functions. - -Version 1.2 -=========== - -* Fix burning torch not working properly if there are more than 256 objects in a level. -* Fix grenade and rocket projectiles smoke offset in certain directions. -* Fix projectiles flying through animating objects. -* Fix harpoon gun doing enormous damage on enemies. -* Fix train death animation. -* Fix various camera issues with unique death animations. -* Fix zipline not following correct trajectory. -* Fix TR1 wolf damage value inflicted on a close bite attack. -* Fix TR1 bear various original AI issues. -* Fix TR2 knife thrower AI. -* Fix TR2 doberman crashing the game when killed by explosive weapons. -* Fix random crashes when killing exploding enemies. -* Fix random crashes in battle with more than 8 enemies. -* Fix volume change in settings not affecting voice track. -* Fix several lighting bugs. -* Fix double drawing additive faces. -* Fix savegame count not properly increasing. -* Fix regeneration of non-ammo pickups with OCB 128. -* Fix vault bug preventing the player from climbing onto ledges out of deeper sections of wade-depth water. -* Fix cold exposure status not recovering in non-cold wade-depth water. -* Fix non-elevated combat camera. -* Fix camera snap when disengaging the look-around mode. -* Fix TR4 mapper not being visible. -* Improve head-on wall collision. -* Overhaul pushables: - - Separate climbable and non-climbable pushable object slots. - - Add new pushable OCB to manipulate pushable properties. - - Add new animations for pushing pushables off edgees (TR1-3 and TR4-5 versions). - - Fix pushables not working with raising blocks. - - Fix miscellaneous pushable bugs. -* Overhaul look-around feature: - - Allow for more consistent and wider viewing angles while crawling, crouching, and hanging. - - Improve look camera movement and control. - - Re-enable looking while performing up jump, backward jump, or backward crawl. - - Add functionality to rotate slowly when holding Walk while using binoculars or lasersight. -* Add target highlighter system with toggle in Sound and Gameplay settings. -* Add sprint slide state 191. -* Add swinging blade. -* Add crumbling platform and add new OCBs for behaviour: - - OCB 0: Default behaviour. When the player steps on the platform, it will shake and crumble after 1.2 seconds. - - OCB > 0: When the player steps on the platform, it will crumble after the number of frames set in the OCB. - - A positive value results in activation via player collision. - - A negative value requires a trigger to activate. -* Add basic mouse input handling. Allows for binding of mouse inputs in control settings. -* Add settings for Mouse Sensitivity and Mouse Smoothing (not used in-game yet). - -Lua API changes: -* Split and organize functions in `Misc` namespace to appropriate new namespaces. -* Make Vec2 and Vec3 objects float-based instead of integer-based. -* Add DisplaySprite object. -* Add Flow.EnableLoadSave() function to disable savegames. -* Add Flow.EnablePointFilter() function to disable bilinear filtering. -* Add View.GetAspectRatio() function to get the screen resolution's aspect ratio. -* Add Logic.HandleEvent() function to call node events. -* Add Input.GetCursorDisplayPosition() function to get the cursor's position. -* Add functions to load, save, delete and check existence of savegames. -* Add Lara:GetAmmoType() function to read the ammo that player is using. -* Add Moveable:GetEndFrame() function to get the end frame number of a moveable's current animation. -* Add extra parameter to GiveItem() function to optionally display an inventory item given to the player in the pickup summary. -* Add DisplayStringOption.RIGHT and DisplayStringOption.BLINK flags for DisplayString. -* Add log messages warnings to functions AddCallback and RemoveCallback. -* Add Vec2 and Vec3 arithmetic for division with a number and multiplication with another Vec2 or Vec3. -* Add various Vec2 and Vec3 operators and methods, such as Normalize() and Lerp(). -* Fix InventoryItem constructor, now it will accept compound values in Item Action parameter. -* Fix Moveable constructor forcing initial animation to 0 and hit points to 10, even if not specified. -* Fix activation of a flipped room when using SetPos() script command or position change node. -* Fix Sound:PlaySoundEffect() function when used without optional position argument. -* Update DisplayString constructor to take a "scale" parameter, allowing for the resizing of text. -* Make DisplayString constructor's "color" parameter optional. -* Add DisplayString::SetScale() function to resize text. -* Add DisplayString::GetScale() function to get text scale. - -Version 1.1.0 -============== - -* Fix enemies shooting Lara through static meshes and moveables. -* Fix skeletons and mummies not being affected by explosive weapons. -* Fix crash on loading if static meshes with IDs above maximum are present. -* Fix various crashes specific to 64-bit build. -* Fix random crashes when playing audio tracks with names longer than 15 symbols. -* Fix crashes when trying to play .wav audio tracks on some Windows 11 systems. -* Fix last selected gun type not preserved after level jump. -* Fix incorrect vertical position after reloading a savegame made while standing on a bridge. -* Fix sprint value going below zero. -* Fix fog bulb density formula. -* Fix clockwork beetle activation crashing the game. -* Fix corrupted vehicle positions after savegame reload. -* Fix default ambience overlapping current one when loading a savegame. -* Fix doppelganger being limited to a single room. -* Fix bat AI, damage value, and incorrect collision after death. -* Fix regeneration for pickups with OCB 128. -* Fix raising blocks still shaking without OCB. -* Fix spiky ceiling, improve collision, and allow setting velocity via OCB. -* Fix TR1 winged mutant pathfinding and damage issues and add new OCBs. -* Fix TR1 Natla facing angle, bomb and shard projectiles, shooting anim in the second phase. -* Fix last inventory item position not being saved. -* Fix some puzzle hole objects crashing the game on item insertion. -* Fix incorrect harpoon bolt speed and angle when shooting vertically. -* Fix black shatter debris. -* Fix Lara's shadow projecting only her joints on some occasions. -* Fix sun and spot bulbs direction and sheen casts. -* Fix room collector freezing game on some occasions. -* Fix incorrect culling for scaled static meshes. -* Fix normal mapping. -* Add ability to save screenshot in the "Screenshots" subfolder by pressing the "Print screen" key. -* Implement separate audio track channel for playing voiceovers with subtitles in .srt format. -* Don't stop ambience when Lara dies. -* Pause all sounds when entering inventory or pause menu. -* Preserve hit points on level jump. -* Improve deflection against slopes. -* Move and rotate Lara and activated pickups together with dynamic bridge objects. -* Reduce camera bounce. -* Improve spiky wall collision accuracy. -* Expand control settings page. -* Allow key bindings for previously hardcoded actions (weapon hotkeys, vehicle controls). -* Add input actions for weapon scroll. -* Add splash effect to rockets and grenades when they enter water. -* Allow multiple doppelgangers by using the same OCB for the origin nullmesh and doppelganger. -* Add TR1 skateboard kid. -* Add TR1 Kold. - -Lua API changes: -* Add soundtrack functions: - - Misc::GetAudioTrackLoudness() for getting current loudness of a given track type. - - Misc::IsAudioTrackPlaying() for checking if a given track type is playing. - - Misc::GetCurrentSubtitle() for getting current subtitle string for the voice track. - -Version 1.0.9 -============= - -* Fix cold bar triggered in non-water rooms. -* Fix spiky wall speed value and change it via OCB number or Lua (Moveable::SetItemFlags[0]). -* Fix bats emitter crashing the game if little beetle object does not exist in wad. -* Fix gunflash rendering and position for entities. -* Fix snowmobile driver crashing the game. -* Fix knifethrower not throwing knife. -* Fix classic rollingball rolling in place into some closed doors. -* Fix zipline not working properly. -* Fix missing heavytrigger checks for node events activated from classic triggers. -* Fix death flag burning enemies underwater. -* Fix pickups and object collision not working properly in flipped rooms without portals. -* Fix footprints not being cleared after level change. -* Fix thumbstick camera option sometimes producing jerky camera movements during object interaction. -* Fix soundtrack position not restoring if same track is already playing. -* Fix inventory input interference when entering inventory via puzzle. -* Fix gamepad still vibrating if Lara was poisoned prior to death. -* Fix flare brightness. -* Fix grenade firing angle. -* Fix rendering for static meshes with custom blending modes and alpha transparency. -* Fix inconsistent multiline string spacing on different display modes. -* Remove search object 4 hardcoded meshswap activated with a flipmap. -* Add TR1 cowboy. -* Add TR3 wall mounted blade. -* Add TR3 claw mutant. -* Add TR5 lasers: - - Choose colour for the lasers via tint menu. - - Laser OCB means width of the laser in sectors. - - Negative OCB laser will trigger heavy trigger. - - Positive OCB kills Lara. -* Add removable puzzles from puzzle holes and puzzle dones: - - Employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done. - - Can be mixed with puzzle done and puzzle holes of the same or different type. -* Add reusable keys for key holes: - - Employed by setting the trigger type as "Switch" for key hole. -* Allow key hole animation to be played via OCB number: - - Default OCB 0 will play Lara use key animation. - - Any positive OCB number will play the animation according to the OCB number. -* Reimplement fog bulbs. -* Add missing gunflash for some entities, also include dynamic light and smoke to all gunflashes. -* Add ability to pick up a single inactive flare as an inventory item. -* Add log reports if title level or other levels don't exist. -* Add better error handling for missing font, sprites or shaders. -* Add "Reset to defaults" entry to controls menu and automatically bind XBOX gamepad profile if connected. -* Add 64-bit executable and place both 32-bit and 64-bit versions into /Bin subdirectory. - -Lua API changes: -* Add Vec2 class. -* Add function String::SetTranslated(). -* Add function Misc::IsStringDisplaying(). -* Add the following for use in AddCallback and RemoveCallback: - - PRESTART, POSTSTART - - PREEND, POSTEND - - PRESAVE, POSTSAVE - - PRELOAD, POSTLOAD - -Version 1.0.8 -============= - -* Fix bubbles phasing through ceilings. -* Fix object camera not clearing at level end. -* Fix double breath sound effect when coming up for air. -* Fix flickering hair. -* Fix harpoon gun triggering water and dry sounds when shooting and reholstering. -* Fix Z-fighting in inventory rendering. -* Fix transparent objects not displaying correctly in the Inventory. -* Fix dozy cheat always giving uzi weapons even if not present in WAD. -* Fix player getting launched when landing close to an edge. -* Fix player going through trapdoor/bridge while climbing up a climbable wall. -* Fix TR3 Sophia's charge ring drawing below floor. -* Fix TR5 imp collision handling and animations: - - OCB 1: Climbs up to player when triggered. - - OCB 2: Starts rolling on the floor when triggered. - - OCB 3: Will throw stones at player. - - Imp is also scared of of the player if holding a lit torch. - - Please note you must use the patched version found here: https://github.com/TombEngine/Resources/blob/main/Wad2%20Objects/tr5_Imp.wad2 -* Fix and improve wraith tails. -* Add dedicated WRAITH_TRAP object with enhanced effects. - - OCB 0: Effect disabled. - - OCB 1: Effect enabled. -* Add TR1 slamming doors. -* Add TR3 mutant wasp (AI_MODIFY object won't allow it to land, the wasp will always fly). -* Add TR3 Corpse - - OCB 0: used for coprses targeted by the compsognathus dinosaur. - - OCB 1: used for corpses hung in the air to be used as piranha bait. Will fall when shot. - - Please note you must use the patched version found here: https://github.com/TombEngine/Resources/blob/main/Wad2%20Objects/tr3_Compsognathus_Cadavar.wad2 -* Add cold exposure bar (employed by setting the "cold" flag in water rooms in Tomb Editor). -* Add water wakes for vehicles. -* Restored light effect nullmeshes (color, electrical, pulse, and strobe): - - Select the light color as object tint in the OCB menu in Tomb Editor. - - ELECTRICAL_LIGHT: - - Can have multiple meshes. Add mesh number to OCB to be renderd with the light. - - OCB + (mesh number): Light behaves like a neon light. - - OCB – (mesh number): Light flickers. -* Restored inventory compass. -* Allow dynamic segment count for hair object. - -Lua API changes: -* Add function Misc::IsSoundPlaying() -* Add function DisplayString::SetFlags() - -Version 1.0.7 -============= - -* Fix spark particles not being cleared on level reload. -* Fix visible but inactive enemies (e.g. Shiva or Xian guardians) taking damage. -* Fix blockable LOT type enemies (e.g. T-Rex and Shiva) not being able to step up 1 click or drop 2 clicks. -* Fix valve switch unable to untrigger objects. -* Fix valve and wall hole switches (OCB 5 and 6) not working as a timed switches. -* Fix incorrect Lara alignment on monkeyswing autojump. -* Fix silent crash if hair object or skin joints are missing. -* Fix holster meshes not displaying for Lara's shadow. -* Use Lara object's own meshes if Lara skin object does not exist in level file. -* Fix TR3 Shiva not taking explosive damage (should still block it with the sword). -* Fix TR3 Puna boss not blocking projectiles (grenade, rocket, harpoon, bolt) with the shield. -* Fix TR3 Puna boss and TR5 Roman statue taking fire when shot by explosive ammo. -* Fix TR2 sword and spear guardian: - - Not doing transition from alive to stone and stone to alive. - - Taking damage in stone mode. - - Wrong joint index for rotating the head and torso. - - Spear guardian not using left and right spear attack when walking (had wrong state ID set as target). - - Killing move for spear used wrong value. -* Fix TR3 big gun spawning rocket with 0 life which caused an immediate explosion. -* Fix TR3 Tony and add boss effect for him. -* Add TR3 civvy. -* Add TR3 electric cleaner. -* Add TR3 Sophia Leigh with following OCBs: - - 0 – Normal mode. Sophia behaves like a regular enemy. - - 1 – Tower mode. Behaviour matched from Tomb Raider III. - - 2 – Tower mode with volumes. Same as tower mode, but Sophia's ascent can be controlled using volumes in Tomb Editor. -* Add airlock switch object. Achieved by putting valve switch trigger and door trigger on the same sector (TR5 submarine door setup). -* Add OCB 7 for switches to be used with SetItemFlags Lua commands for customizing on/off animations and reachable distance. -* Add instant headshot to guards. -* Polish the distance position between Lara and switch objects. -* Adjust rocket ammo pickup from 10 to 1. -* Improve behaviour of tiger and lion enemies. -* Implement more realistic water bubble effects. -* Implement a new stacked pickup display inspired by OpenLara. -* Prevent Lara from drawing weapons during parallel bar swinging. -* Further renderer performance optimizations and bugfixes. - -Lua API changes: -* Fix Camera:SetPosition not updating camera position when it is played simultaneously. -* Add Moveable:GetAirborne and Moveable:SetAirborne. -* Add Moveable:GetLocationAI and Moveable:SetLocationAI. - -Version 1.0.6 -============= - -* Fix major pathfinding bug which could have caused lots of issues with enemy behaviour. -* Fix potential random crashes due to incorrect rendering behaviour. -* Fix savegame crash for disabled enemies with partially set activation mask. -* Fix certain enemies not damaging Lara if binoculars or lasersight mode is active. -* Fix invisible Lara after starting a new game from title flyby with hidden Lara. -* Fix backholster weapons not updating their sound position together with player. -* Fix black screen bug when there was an obstacle between the fixed camera and the target. -* Fix underwater caustics not appearing without visiting options menu beforehand. -* Fix TR1 ape climbing. -* Fix TR1 rat which crashed the game when it was killed. -* Fix TR2 small spider climbing and pathfinding. -* Fix TR3 Shiva and TR4 baddy 2 not blocking bullets. -* Fix TR4 harpy's sting attack which was neither hurting nor poisoning Lara. -* Fix TR4 SAS teleporting over the blocks he walks by. -* Fix TR4 seth blades that were doing a double activation when used an OCB different than 0. -* Fix TR4 skeleton spawn when used with OCB 3. -* Fix TR4 sphinx solving his bugged behaviour that happened if it received a lot of damage. -* Fix TR5 Roman statue and its meshswap. -* Fix TR5 twogun laser guard. -* Fix enemy projectile effect colours. -* Fix enemy shadow position. -* Fix sound positions not updated during flybys. -* Fix grenade launcher super ammo emitting too many fragments. -* Fix grenade and rocket launcher lighting. -* Fix ceiling trapdoor and floor trapdoor that Lara couldn't open manually. -* Make enemies drop pickups at first available bounding box corner point, not centerpoint. -* Restore original volumetric explosion effects. -* Add TR3 lizard and Puna. -* Add TR3 boss effects in ID_BOSS_SHIELD and ID_BOSS_SHOCKWAVE_EXPLOSION slots. -* Add an option to activate Lua or node events from legacy triggers. -* Add more warnings in logs to enemies which animation or required slot is missing. -* Antitriggering an enemy will now cause it to vanish and pause. -* Re-triggering an enemy will cause it to reappear and unpause. -* Lua Moveable functions Enable and Disable now correctly trigger and antitrigger the moveable. -* Improve level loading speed a lot. - -Lua API changes: -* Moveable:SetVisible has been added. MakeInvisible is now an alias for SetVisible(false). -* Moveable:MeshIsVisible is now GetMeshVisible. -* Moveable:SetMeshVisible has been added to replace ShowMesh/HideMesh. -* Moveable:MeshIsSwapped is now GetMeshSwapped -* Camera:SetPosition now updates the position if it's called while it's being played. -* Primitive Classes (Color, Rotation, Vec3) can now be saved via Levelvars and Gamevars variables. -* OnSave function now gets called just before data is saved, rather than just after. -* Add new function CameraObject::PlayCamera() -* Add new function Misc::GetCameraType() -* Add new functions Moveable:GetAirborne() and Moveable:SetAirborne(bool input) - -Version 1.0.5 -============= - -* Fix combined items not existing in inventory upon game reload. -* Fix classic rollingball not behaving properly in rooms beyond the distance of 32 blocks. -* Fix rollingball not killing Lara under certain movement angles. -* Fix savegame crashes when rooms with static meshes are flipped. -* Fix discrepancies between statistics and save / load game time units. -* Fix draw key incorrectly working in binoculars / lasersight mode. -* Fix incorrect picking up from plinths concealed by raising blocks. -* Fix reversed grenade rotation. -* Fix flame emitter 3 not burning player. -* Fix TR2 yeti, TR3 civvy and MP with stick vault bugs. -* Fix TR2 worker with flamethrower and TR3 flamethrower baddy attack ranges and aiming issues. -* Fix TR3 tribeman with axe not attacking Lara. -* Fix TR3 tribeman with dart not shooting at Lara's direction. -* Fix TR3 crow and TR4 harpy death animations not performing correctly. -* Fix TR4 crocodile attack range and joint rotation speed. -* Fix TR4 Von Croy not using animation for 2 and 3 step down vaults. -* Fix TR4 baddies not using animation for 3 step down vaults. -* Fix TR5 laserhead guardian. -* Fix crash, water death and meshswap issues for TR5 cyborg. -* Fix pathfinding problems for first initialized enemy of every slot. -* Fix pathfinding of flying and water creatures (partial). -* Fix rare crash when smash item is inside a wall and add warning log for the scenario. -* Fix bone rotations of some entities. -* Fix Lara's animation for cog switch release. -* Added new OCB to cog switch object: - - Use OCB 0 to have the traditional behaviour. - - Use any other OCB to can use the Cog Switch without need of any door linked. -* Allow to freely rotate dart emitter in all directions. -* Customize dart emitter damage with OCB. Negative number will additionally poison Lara. -* Draw real mesh for darts. -* Added warning log when one slot requires another slot which is missing. - -Lua API changes: -* Add new Room class and several methods for it. - -Version 1.0.4 -============= - -* Add generic assignable effects for moveables - fire, sparks, smoke and laser / electric ignite. -* Add ability to burn enemies with FLAME_EMITTER_1 and death blocks. -* Add wireframe mode and other visual debug information (switch by F10/F11 debug page scroll hotkeys). -* Activate Lara-bound volume triggers with mounted vehicles. -* Allow multiple individual activators for the same volume at the same time. -* Remove TRC remnant which added HK to inventory if pistols weren't available. -* Change default shatter sound to TR4_SMASH_ROCK (tomb4 default). -* Reduce idle pose time from 30 to 20 seconds. -* Automatically align pickups to floor surface. -* Minecart enhancements: - - Add landing / jump sound. - - Add falldamage. - - Explode in water below 2 click surface. - - Fix jump. -* Templar Knight enhancements: - - Restored spark effects. - - Can destroy statics in shatter slots. - - Fix crash when attacking. -* SAS enhancements: - - Fix grenade shooting. - - Fix AI_MODIFY and AI_GUARD behaviour. -* Fix choppy camera movement in several cases. -* Fix Lara's vertical position when shimmying around steep slope corners. -* Fix legacy pickup triggers not working in certain cases. -* Fix crawl pickup not actually doing any pickups. -* Fix demigod and harpy shooting in incorrect directions. -* Fix particle effects for seth and harpy magic attacks. -* Fix lasersight always displaying with HK, revolver and crossbow. -* Fix rapid ammo spending in HK lasersight mode. -* Fix incorrect string IDs for item combine, HK and revolver with lasersight. -* Fix puzzle holes not swapping to puzzle done objects. -* Fix several collision and sound source issues in flipped rooms. -* Fix several pushable sound and object collision bugs. -* Fix original bug with incorrect climb up behaviour on ladders under sloped ceilings. -* Fix original bug with reassigned control keys still triggering default events. -* Fix TR1 centaur bubble targeting. -* Fix TR5 autogun rotation. -* Fix occasional wrong rollingball collision in narrow pits. -* Fix classic rollingball and big rollingball not behaving properly. -* Fix caustics not turning off in display settings. -* Fix windowed mode not using real resolution when DPI scaling is active. -* Fix control lock not working in flyby sequences. -* Fix empty inventory when using build and play feature in TE. -* Fix non-pickupable thrown flares. -* Fix throwing flare without drawing any weapons if there are no weapons present. -* Fix several incorrect FOV reset issues. -* Fix current soundtrack fading into silence if incoming one doesn't exist. -* Fix crash if there is an attempt to display a string with missing characters. - -Lua API changes: -* Add new Volume class and several methods for it. -* Add new Moveable functions: GetEffect, SetEffect and SetCustomEffect (for colored fire). -* Add new Lara functions: GetTarget, GetVehicle and TorchIsLit. -* Remove Lara functions: SetOnFire and GetOnFire (replaced with GetEffect and SetEffect). -* Add Gameflow.lua options: - - Flow.EnableMassPickup for mass pickup functionality. - - Flow.EnableLaraInTitle for displaying Lara in title flyby. - - Flow.EnableLevelSelect for title flyby level selection. - - level.secrets for level-specific secret count. - -* Fix level.ambientTrack property not working for title flyby. -* Fix action key script functions not fully working in some cases. -* Fix mounted vehicles ignoring Disable, Shatter and Explode script commands. -* Fix SetPosition command not updating room number correctly. -* Fix Rotation class using integers under the hood which prevented using fractional rotation values. -* Fix distance tests failing on a very high distances. - -Version 1.0.3 -============= - -* Add ledge jumps (Lara object must be updated with new animations to make it work). -* Allow any object slot to be used as a meshswap. -* Add OCB 1 for rollingball to make it silent. -* Customize waterfall mist colour and OCB (XXYY, where XX is width, and YY is size). -* Implement HK shooting modes from TR5. -* Implement sprite instancing to speed up rendering. -* Enable dynamic lights for swarm enemies (beetles, rats and bats). -* Re-enable underwater caustics. -* Increase amount of maximum secrets per level from 8 to 32. -* Improve game and inventory input handling. -* Adjust sprint jump timing. -* Backport DAMOCLES_SWORD from TR1. -* Fix going into inventory and load/save dialogs during fade-ins and fade-outs. -* Fix savegames not preserving save number and game timer. -* Fix dodgy weapon lock angle constraints. -* Fix wrong shotgun ammo pickup amount. -* Fix shotgun using 6 units of ammo with each shot. -* Fix rocket explosions near statics. -* Fix explosive crossbow bolts not damaging player. -* Fix poisoned crossbow bolts not damaging enemies. -* Fix TR3 monkey level crash. -* Fix occasional ejections when landing on a slope. -* Fix occasional ejections when climbing up on a ledge under a slope. -* Fix pushables not being pushable on top of bridges and other pushables. -* Fix pushables having incorrect collision when bounding box is bigger than 1 sector. -* Fix grabbing narrow ledges below ceilings. -* Fix slow centaur projectile velocity. -* Fix search animations - allow chest and shelf animations to play properly. -* Fix sarcophagus and its item pickup. -* Fix underwater door and double doors continuing to be interactable after opening. -* Fix underwater door being interactable when underwater switch is on the same square. -* Fix ability to turn when aligning to an object while standing. -* Fix left arm lock while picking up an item with a flare in hand. -* Fix potential crashes when exiting game. -* Fix secret soundtrack (which filename number should be the last) not playing. -* Fix distance fog not applying properly to additive and subtractive surfaces. -* Fix swarm enemies and projectiles occasionally drawn using incorrect meshes. -* Fix single-hand weapons not having a sound on draw and undraw. -* Fix waterfall mist - it can now be disabled with antitrigger. -* Fix underwater lever pull animation playing after interacting with underwater ceiling switch. -* Fix SAS_DRAG_BLOKE object interaction. -* Fix KILLER_STATUE not triggering. - -Lua API changes: -* A new class has been added, LaraObject, for Lara-specific functions. The built-in "Lara" variable now uses this class. -* Add functions for Lara object: - - GetPoison / SetPoison - - GetAir / SetAir - - GetOnFire / SetOnFire - - GetSprintEnergy / SetSprintEnergy - - GetWet / SetWet - - GetWeaponType / SetWeaponType - - UndrawWeapon - - GetAmmoCount - - GetHandStatus - - ThrowAwayTorch - -* Add FlipMap and PlayFlyBy script commands and node functions. -* Add GetMoveablesBySlot and GetStaticsBySlot script commands to select groups of items. -* Add FlyCheat option to gameflow script for disabling dozy mode. -* Add SetTotalSecretCount option to gameflow script to set overall amount of secrets. -* Raised the maximum value on Moveable.SetHP to 32767 (its internal numeric maximum). - -Version 1.0.2 -============= - -* Fix removing Pistols with TakeItem and SetItemCount. -* Allow saving and loading of Vec3s in LevelVars and GameVars. -* Support volume triggers made with node editor. -* Adjust max turn rate of idle state. -* Align Lara on slopes when crouching, crawling, and dying. -* Better slope alignment for large, flat enemies (i.e. big scorpion and crocodile). -* Lock turn rate when automatically aligning Lara to objects. -* Don't play Lara alignment animations if the interacted object is too close. -* Allow vertical pole mounts only when facing one directly. -* Allow vertical pole mounts while turning, walking, or running. -* Update monkey swing 180 turn animation. -* Update backward monkey swing animations. -* Added standing 180 turn. Activated with WALK+ROLL on dry ground, automatic when in wade-height water or swamp. -* Added crouch turn and crawl turn animations. -* Added new switch OCBs: - - 0 for wall switch - - 1 for small wall switch - - 2 for small button - - 3 for big button - - 4 for giant button (sequence switch) - - 5 for valve turn - - 6 for hole switch - - any other OCBs play corresponding switch on anim or OCB+1 switch off anim. - -* Fix incorrect pole mounting. -* Fix zeroed forward velocity upon landing. -* Fix incorrect behaviour when falling on statics from the top after monkeyswing. -* Fix missing animcommand calls on first animation frame. -* Fix 1-frame turn rate delays. -* Fix occasional leave event calls when moving closer to volumes. -* Fix incorrect viewport size in windowed mode. -* Fix late landing animation dispatch in rare cases. -* Fix incorrect velocity calculations for death animations. -* Fix horseman's axe attack using his left foot as the damaging joint. -* Fix stargate blades needlessly pushing the player around while hardly doing any damage. -* Fix weapon hotkeys and add missing crossbow hotkey. - -Lua API changes: -* Util.ShortenTENCalls no longer needs to be called; it is now automatic for both level scripts and Gameflow.lua. -* Flow.InvID has been removed; any function taking a pickup (e.g. GiveItem) now takes an Objects.ObjID instead. -* Add Enable, Disable, GetActive, Get/SetSolid functions for static meshes. -* Add FadeOutComplete, StopAudioTrack and StopAudioTracks functions. -* Account for objects in HasLineOfSight tests. -* Move Timer.lua, EventSequence.lua and Util.lua to a subfolder named "Engine". -* LevelFuncs can now contain tables as well as functions. These tables can contain functions and other tables, and so forth. -* Moveable functions SetOnHit, SetOnKilled, SetOnCollidedWithObject and SetOnCollidedWithRoom no longer take strings, and instead take function objects themselves. -* Don't require EventSequence and Timer to call Timer.UpdateAll in OnControlPhase. -* Add TEN.Logic.AddCallback and TEN.Logic.RemoveCallback. -* Rework GiveItem, TakeItem, and SetItemCount (e.g. SetItemCount with a value of -1 can give infinite ammo/consumables). - - -Version 1.0.1 -============= - -* Added antialiasing support. -* Added static mesh scaling support. -* Added free rotation for teeth spikes instead of using OCB codes. -* Fix some issues with shimmying between diagonal ledges and walls. -* Fix rope transparency. -* Fix objects disappearing under certain angles at the edges of the screen. -* Fix incorrect polerope and jumpswitch grabbing. -* Fix camera behaviour with pushable blocks. -* Fix minecart unduck on inclines. -* Fix quadbike dismount with jump key and allow to shoot big gun with action key. -* Fix static meshes having wrong colors on savegame reload. -* Fix rollingball incorrectly killing Lara in water and in jump. -* Fix resurfacing on underwater death. -* Fix water to ladder animation not activating in all cases. -* Fix ripples not appearing on water connections higher than room bottom. -* Fix several problems with ropes (stumbling, rope length, etc). -* Fix several problems with teeth spikes. -* Fix falling through twoblock platform on room number change. -* Fix falling block breaking too early if placed on a vertical portal. -* Fix crashes when loading image files are missing. -* Disable trigger check for puzzle holes. -* Clear locusts and other swarm enemies on level reload. -* Enhance cobra AI and fix targeting. -* Fully decompile HAMMER object from TR4. -* Prevent title music audio from starting in a random place. -* Update harpoon speed on room change. -* Enable second sky layer rendering. -* Preserve inventory and flare on level jumps. -* Timer.Create now lets you choose the units to display remaining time. -* Fatal script errors now boot you to the title (it will crash if the title itself has these errors). -* SetFarView has been removed, and Flow.Level.farView is now uncapped. -* DisplayString text will now be cleared when a level is exited or reloaded. -* EventSequence.lua has been added and documented. - - -Version 1.0 -=========== - -First beta release. From 2d670175b48a2f1187e4dcd96ff3d0049a524144 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Thu, 16 May 2024 09:41:48 +0100 Subject: [PATCH 184/410] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aac358b80..f511bfbe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Here you will find the full changelog of TEN's releases from Version 1.0 and up The dates are in European standard format where date is presented as **YYYY-MM-DD** +TombEngine releases are located in this repository (alongside with Tomb Editor): https://github.com/TombEngine/TombEditorReleases + ## Version 1.5 - xxxx-xx-xx ### Bug fixes From 23254c87eaeeb0a0a224ed2bbc918ab95d8cf1e4 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Thu, 16 May 2024 10:14:26 +0100 Subject: [PATCH 185/410] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f511bfbe0..545c4f5e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed AI for skidoo driver and worker with shotgun TR2 enemies. * Fixed Ember emitter crashing when ocb is between -1 and -10 * Fixed Electric cleaner and Squishy block not detecting collision with certain block heights. +* Fixed Squishy blocks crashing the level. ### Features/Amendments From d5ed115d507e8438c136bfa5b83eac3d7a72ef95 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 16 May 2024 11:49:58 +0200 Subject: [PATCH 186/410] Fixed wrong positions for transparent faces in moveable items --- Documentation/doc/2 classes/Flow.Starfield.html | 12 ++++++------ TombEngine/Renderer/RendererDraw.cpp | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/doc/2 classes/Flow.Starfield.html b/Documentation/doc/2 classes/Flow.Starfield.html index 07749c388..a0d3880c4 100644 --- a/Documentation/doc/2 classes/Flow.Starfield.html +++ b/Documentation/doc/2 classes/Flow.Starfield.html @@ -144,11 +144,11 @@
    - + - + @@ -208,11 +208,11 @@
    • starCount int - Star count. + Star count (6000 max).
    • meteorCount int - Meteor count. + Meteor count (100 max).
    @@ -358,7 +358,7 @@ Starfield:SetStarCount(New)
    - Set the starfield's number of stars. (int) + Set the starfield's number of stars (6000 max). (int) @@ -380,7 +380,7 @@ Starfield:SetMeteorCount(New)
    - Set the starfield's number of meteors. (int) + Set the starfield's number of meteors (100 max). (int) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index cede3ccbf..137143413 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3123,7 +3123,7 @@ namespace TEN::Renderer for (int p = 0; p < bucket.Polygons.size(); p++) { auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, itemToDraw->AnimationTransforms[boneIndex] * itemToDraw->World); + bucket.Polygons[p].Centre, itemToDraw->InterpolatedAnimationTransforms[boneIndex] * itemToDraw->InterpolatedWorld); int distance = (centre - cameraPos).Length(); RendererSortableObject object; @@ -3566,10 +3566,10 @@ namespace TEN::Renderer RendererObject& moveableObj = *_moveableObjects[objectInfo->Item->ObjectNumber]; // Bind item main properties - _stItem.World = objectInfo->Item->World; + _stItem.World = objectInfo->Item->InterpolatedWorld; _stItem.Color = objectInfo->Item->Color; _stItem.AmbientLight = objectInfo->Item->AmbientLight; - memcpy(_stItem.BonesMatrices, objectInfo->Item->AnimationTransforms, sizeof(Matrix) * MAX_BONES); + memcpy(_stItem.BonesMatrices, objectInfo->Item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) _stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode; From a39f7ccd2c3e9a9f2ea4266a5dc9a8436e6b3298 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 16 May 2024 12:01:33 +0200 Subject: [PATCH 187/410] Disabled interpolation on PuzzleDone --- TombEngine/Objects/Generic/puzzles_keys.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TombEngine/Objects/Generic/puzzles_keys.cpp b/TombEngine/Objects/Generic/puzzles_keys.cpp index 811896ad1..31733b631 100644 --- a/TombEngine/Objects/Generic/puzzles_keys.cpp +++ b/TombEngine/Objects/Generic/puzzles_keys.cpp @@ -339,6 +339,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber) item->ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 }; item->ItemFlags[5] = (int)ReusableReceptacleState::Done; SetAnimation(item, 0); + item->DisableInterpolation = true; item->ResetModelToDefault(); } else @@ -349,6 +350,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber) item->Animation.ActiveState = GetAnimData(item).ActiveState; item->Animation.TargetState = GetAnimData(item).ActiveState; item->Animation.RequiredState = NO_VALUE; + item->DisableInterpolation = true; item->ResetModelToDefault(); AddActiveItem(itemNumber); From 411c397027f9d6f30ffe2d40fe538491f6aa6ba4 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 17 May 2024 18:52:26 +1000 Subject: [PATCH 188/410] Minor formatting --- Scripts/SystemStrings.lua | 2 +- TombEngine/Renderer/RendererDraw.cpp | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Scripts/SystemStrings.lua b/Scripts/SystemStrings.lua index 69009d8eb..73caa9386 100644 --- a/Scripts/SystemStrings.lua +++ b/Scripts/SystemStrings.lua @@ -110,10 +110,10 @@ local strings = total_secrets_found = { "Secrets Found Total" }, use = { "Use" }, used_medipacks = { "Medipacks Used" }, + variable_framerate = { "Variable Framerate" }, vehicle_actions = { "Vehicle Actions" }, view = { "View" }, volumetric_fog = { "Volumetric Fog" }, - variable_framerate = { "Variable Framerate" }, waiting_for_input = { "Waiting For Input" }, window_title = { "TombEngine" }, windowed = { "Windowed" }, diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 137143413..364ad3156 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3547,8 +3547,8 @@ namespace TEN::Renderer void Renderer::DrawItemSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view) { - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); _context->IASetInputLayout(_inputLayout.Get()); @@ -3561,25 +3561,24 @@ namespace TEN::Renderer _context->VSSetShader(_vsItems.Get(), nullptr, 0); _context->PSSetShader(_psItems.Get(), nullptr, 0); - ItemInfo* nativeItem = &g_Level.Items[objectInfo->Item->ItemNumber]; - RendererRoom* room = &_rooms[objectInfo->Item->RoomNumber]; - RendererObject& moveableObj = *_moveableObjects[objectInfo->Item->ObjectNumber]; - - // Bind item main properties + // Bind main item properties. _stItem.World = objectInfo->Item->InterpolatedWorld; _stItem.Color = objectInfo->Item->Color; _stItem.AmbientLight = objectInfo->Item->AmbientLight; memcpy(_stItem.BonesMatrices, objectInfo->Item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); + const auto& moveableObj = *_moveableObjects[objectInfo->Item->ObjectNumber]; for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) _stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode; BindMoveableLights(objectInfo->Item->LightsToDraw, objectInfo->Item->RoomNumber, objectInfo->Item->PrevRoomNumber, objectInfo->Item->LightFade); _cbItem.UpdateData(_stItem, _context.Get()); - BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[objectInfo->Bucket->Texture]), + BindTexture( + TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[objectInfo->Bucket->Texture]), SamplerStateRegister::AnisotropicClamp); - BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[objectInfo->Bucket->Texture]), + BindTexture( + TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[objectInfo->Bucket->Texture]), SamplerStateRegister::AnisotropicClamp); _sortedPolygonsIndexBuffer.Update(_context.Get(), _sortedPolygonsIndices, 0, (int)_sortedPolygonsIndices.size()); From 206fd59e55fbcef30069feee2d4ff8cebc588463 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 17 May 2024 18:57:22 +1000 Subject: [PATCH 189/410] Interpolate speedometer --- TombEngine/Game/Hud/Speedometer.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/Hud/Speedometer.cpp b/TombEngine/Game/Hud/Speedometer.cpp index cc3d0fe69..9689c6d73 100644 --- a/TombEngine/Game/Hud/Speedometer.cpp +++ b/TombEngine/Game/Hud/Speedometer.cpp @@ -48,7 +48,7 @@ namespace TEN::Hud void SpeedometerController::Draw() const { constexpr auto POS = Vector2(DISPLAY_SPACE_RES.x - (DISPLAY_SPACE_RES.x / 6), DISPLAY_SPACE_RES.y - (DISPLAY_SPACE_RES.y / 10)); - constexpr auto ORIENT_OFFSET = ANGLE(90.0f); + constexpr auto POINTER_ANGLE_OFFSET = ANGLE(90.0f); constexpr auto SCALE = Vector2(0.35f); constexpr auto DIAL_ELEMENT_SPRITE_ID = 0; constexpr auto POINTER_ELEMENT_SPRITE_ID = 1; @@ -60,9 +60,8 @@ namespace TEN::Hud if (_life <= 0.0f) return; - // TODO: Interpolation. - - auto color = Color(1.0f, 1.0f, 1.0f, _opacity); + short pointerAngle = (short)Lerp(_prevPointerAngle, _pointerAngle, g_Renderer.GetInterpolationFactor()); + auto color = Color(1.0f, 1.0f, 1.0f, Lerp(_prevOpacity, _opacity, g_Renderer.GetInterpolationFactor())); // Draw dial. AddDisplaySprite( @@ -74,7 +73,7 @@ namespace TEN::Hud // Draw pointer. AddDisplaySprite( ID_SPEEDOMETER, POINTER_ELEMENT_SPRITE_ID, - POS, _pointerAngle + ORIENT_OFFSET, SCALE, color, + POS, pointerAngle + POINTER_ANGLE_OFFSET, SCALE, color, POINTER_PRIORITY, DisplaySpriteAlignMode::Center, DisplaySpriteScaleMode::Fit, BlendMode::AlphaBlend, DisplaySpritePhase::Draw); } From de91720fc9c6857bdaa7b7ac88c919a0155db715 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 17 May 2024 19:40:09 +1000 Subject: [PATCH 190/410] Formatting --- TombEngine/Game/Lara/lara.cpp | 6 -- TombEngine/Game/Lara/lara.h | 6 +- TombEngine/Game/camera.cpp | 2 +- TombEngine/Game/control/control.cpp | 116 +++++++++++++++------------- TombEngine/Game/gui.cpp | 4 +- 5 files changed, 68 insertions(+), 66 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index b39f9c246..bc4465ce6 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -629,12 +629,6 @@ void UpdateLara(ItemInfo* item, bool isTitle) // Control player. InItemControlLoop = true; - - // Copy current state to old state for interpolation - //memcpy(&item->OldPose, &item->Pose, sizeof(Pose)); - //memcpy(&item->OldLocation, &item->Location, sizeof(Vector3i)); - //memcpy(&item->OldAnimation, &item->Animation, sizeof(EntityAnimationData)); - //memcpy(&OldLara, &Lara, sizeof(LaraInfo)); LaraControl(item, &LaraCollision); HandlePlayerFlyCheat(*item); diff --git a/TombEngine/Game/Lara/lara.h b/TombEngine/Game/Lara/lara.h index 223f47f77..fda62282c 100644 --- a/TombEngine/Game/Lara/lara.h +++ b/TombEngine/Game/Lara/lara.h @@ -93,9 +93,9 @@ constexpr auto WADE_WATER_DEPTH = STEPUP_HEIGHT; constexpr auto SWIM_WATER_DEPTH = CLICK(2.75f); constexpr auto SLOPE_DIFFERENCE = 60; -extern LaraInfo Lara; -extern LaraInfo PrevLara; -extern ItemInfo* LaraItem; +extern LaraInfo Lara; +extern LaraInfo PrevLara; +extern ItemInfo* LaraItem; extern CollisionInfo LaraCollision; void LaraControl(ItemInfo* item, CollisionInfo* coll); diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index b3733f0d1..a53123c16 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -202,7 +202,7 @@ void LookAt(CAMERA_INFO* cam, short roll) float levelFarView = g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * float(BLOCK(1)); - g_Renderer.UpdateCameraMatrices(cam, r, fov, levelFarView); + g_Renderer.UpdateCameraMatrices(cam, r, fov, levelFarView); } void AlterFOV(short value, bool store) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 504a55a9f..6fa9b355d 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -153,20 +153,18 @@ GameStatus ControlPhase() SetupInterpolation(); g_Renderer.SaveOldState(); - // Controls are polled before OnLoop, so input data could be - // overwritten by script API methods. + // Controls are polled before OnLoop to allow input data to be overwritten by script API methods. HandleControls(isTitle); // Pre-loop script and event handling. g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index); - // Control lock is processed after handling scripts, because builder may want to - // process input externally, while still locking Lara from input. + // Control lock is processed after handling scripts because builder may want to process input externally while locking player from input. if (!isTitle && Lara.Control.IsLocked) ClearAllActions(); - // Handle inventory / pause / load / save screens. + // Handle inventory, pause, load, save screens. auto result = HandleMenuCalls(isTitle); if (result != GameStatus::Normal) return result; @@ -176,9 +174,8 @@ GameStatus ControlPhase() if (result != GameStatus::Normal) return result; - // Queued input actions are read again and cleared after UI - // interrupts are processed, so first frame after exiting UI - // will still register it. + // Queued input actions are read again and cleared after UI interrupts are processed, + // so first game frame after exiting UI will still register it. ApplyActionQueue(); ClearActionQueue(); @@ -188,14 +185,14 @@ GameStatus ControlPhase() g_GameScriptEntities->TestCollidingObjects(); + // Draw flyby cameras. if (UseSpotCam) { - // Draw flyby cameras. CalculateSpotCameras(); } + // Do standard camera. else { - // Do the standard camera. TrackCameraInit = false; CalculateCamera(LaraCollision); } @@ -206,11 +203,11 @@ GameStatus ControlPhase() // Smash shatters and clear stopper flags under them. UpdateShatters(); - // Clear last selected item in inventory (need to be after on loop event handling, so they can detect that). + // Clear last selected item in inventory (must be after on loop event handling, so they can detect that). g_Gui.CancelInventorySelection(); - // Control lock is processed after handling scripts, because builder may want to - // process input externally, while still locking Lara from input. + // Control lock is processed after handling scripts because builder may want to + // process input externally while locking player from input. if (!isTitle && Lara.Control.IsLocked) ClearAllActions(); @@ -286,22 +283,26 @@ GameStatus ControlPhase() unsigned CALLBACK GameMain(void *) { - TENLog("Starting GameMain...", LogLevel::Info); + TENLog("Starting GameMain()...", LogLevel::Info); TimeInit(); - // Do a fixed time title image. + // Do fixed-time title image. if (g_GameFlow->IntroImagePath.empty()) - TENLog("Intro image path is not set.", LogLevel::Warning); + { + TENLog("Intro image path not set.", LogLevel::Warning); + } else + { g_Renderer.RenderTitleImage(); + } - // Execute the Lua gameflow and play the game. + // Execute Lua gameflow and play game. g_GameFlow->DoFlow(); DoTheGame = false; - // Finish the thread. + // Finish thread. PostMessage(WindowsHandle, WM_CLOSE, NULL, NULL); EndThread(); @@ -317,7 +318,7 @@ GameStatus DoLevel(int levelIndex, bool loadGame) // Load level. Fall back to title if unsuccessful. if (!LoadLevelFile(levelIndex)) - return isTitle ? GameStatus::ExitGame : GameStatus::ExitToTitle; + return (isTitle ? GameStatus::ExitGame : GameStatus::ExitToTitle); // Initialize items, effects, lots, and cameras. HairEffect.Initialize(); @@ -374,11 +375,15 @@ void KillMoveItems() { for (int i = 0; i < ItemNewRoomNo; i++) { - short itemNumber = ItemNewRooms[2 * i]; + int itemNumber = ItemNewRooms[i * 2]; if (itemNumber >= 0) - ItemNewRoom(itemNumber, ItemNewRooms[2 * i + 1]); + { + ItemNewRoom(itemNumber, ItemNewRooms[(i * 2) + 1]); + } else + { KillItem(itemNumber & 0x7FFF); + } } } @@ -391,11 +396,15 @@ void KillMoveEffects() { for (int i = 0; i < ItemNewRoomNo; i++) { - short itemNumber = ItemNewRooms[2 * i]; + int itemNumber = ItemNewRooms[i * 2]; if (itemNumber >= 0) - EffectNewRoom(itemNumber, ItemNewRooms[2 * i + 1]); + { + EffectNewRoom(itemNumber, ItemNewRooms[(i * 2) + 1]); + } else + { KillEffect(itemNumber & 0x7FFF); + } } } @@ -417,13 +426,13 @@ void CleanUp() // Reset oscillator seed. Wibble = 0; - // Needs to be cleared, otherwise controls will lock if user exits to title while playing flyby with locked controls. + // Clear player lock, otherwise controls will lock if user exits to title while playing flyby with locked controls. Lara.Control.IsLocked = false; // Resets lightning and wind parameters to avoid holding over previous weather to new level. Weather.Clear(); - // Needs to be cleared, otherwise a list of active creatures from previous level will spill into new level. + // Clear creatures, otherwise list of active creatures from previous level will spill into new level. ActiveCreatures.clear(); // Clear ropes. @@ -473,26 +482,27 @@ void InitializeScripting(int levelIndex, LevelLoadType type) g_GameStringsHandler->ClearDisplayStrings(); g_GameScript->ResetScripts(!levelIndex || type != LevelLoadType::New); - auto* level = g_GameFlow->GetLevel(levelIndex); + const auto& level = *g_GameFlow->GetLevel(levelIndex); // Run level script if it exists. - if (!level->ScriptFileName.empty()) + if (!level.ScriptFileName.empty()) { - g_GameScript->ExecuteScriptFile(g_GameFlow->GetGameDir() + level->ScriptFileName); + g_GameScript->ExecuteScriptFile(g_GameFlow->GetGameDir() + level.ScriptFileName); g_GameScript->InitCallbacks(); g_GameStringsHandler->SetCallbackDrawString([](const std::string& key, D3DCOLOR color, const Vec2& pos, float scale, int flags) { g_Renderer.AddString( key, - Vector2(((float)pos.x / (float)g_Configuration.ScreenWidth * DISPLAY_SPACE_RES.x), - ((float)pos.y / (float)g_Configuration.ScreenHeight * DISPLAY_SPACE_RES.y)), + Vector2( + (pos.x / g_Configuration.ScreenWidth) * DISPLAY_SPACE_RES.x, + (pos.y / g_Configuration.ScreenHeight) * DISPLAY_SPACE_RES.y), Color(color), scale, flags); }); } // Play default background music. if (type != LevelLoadType::Load) - PlaySoundTrack(level->GetAmbientTrack(), SoundTrackType::BGM); + PlaySoundTrack(level.GetAmbientTrack(), SoundTrackType::BGM); } void DeInitializeScripting(int levelIndex, GameStatus reason) @@ -503,7 +513,7 @@ void DeInitializeScripting(int levelIndex, GameStatus reason) g_GameScript->FreeLevelScripts(); g_GameScriptEntities->FreeEntities(); - if (!levelIndex) + if (levelIndex == 0) g_GameScript->ResetScripts(true); } @@ -512,7 +522,7 @@ void InitializeOrLoadGame(bool loadGame) g_Gui.SetInventoryItemChosen(NO_VALUE); g_Gui.SetEnterInventory(NO_VALUE); - // Restore the game? + // Restore game? if (loadGame) { SaveGame::Load(g_GameFlow->SelectedSaveGame); @@ -533,7 +543,7 @@ void InitializeOrLoadGame(bool loadGame) } else { - // If not loading a savegame, clear all info. + // If not loading savegame, clear all info. SaveGame::Statistics.Level = {}; if (InitializeGame) @@ -559,19 +569,19 @@ void InitializeOrLoadGame(bool loadGame) GameStatus DoGameLoop(int levelIndex) { - int numFrames = LOOP_FRAME_COUNT; + constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; + + int frameCount = LOOP_FRAME_COUNT; auto& status = g_GameFlow->LastGameStatus; - // Before entering actual game loop, ControlPhase must be + // Before entering actual game loop, ControlPhase() must be // called once to sort out various runtime shenanigangs (e.g. hair). - status = ControlPhase(); LARGE_INTEGER lastTime; LARGE_INTEGER currentTime; double controlLag = 0; double frameTime = 0; - constexpr auto controlFrameTime = 1000.0f / 30.0f; LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); @@ -600,21 +610,21 @@ GameStatus DoGameLoop(int levelIndex) controlLag += frameTime; } - while (controlLag >= controlFrameTime) + while (controlLag >= CONTROL_FRAME_TIME) { #if _DEBUG constexpr auto DEBUG_SKIP_FRAMES = 10; - if (controlLag >= DEBUG_SKIP_FRAMES * controlFrameTime) + if (controlLag >= DEBUG_SKIP_FRAMES * CONTROL_FRAME_TIME) { - TENLog("Game loop is running too slow!", LogLevel::Warning); + TENLog("Game loop is running too slow.", LogLevel::Warning); App.ResetClock = true; break; } #endif status = ControlPhase(); - controlLag -= controlFrameTime; + controlLag -= CONTROL_FRAME_TIME; controlCalls++; legacy30FpsDoneDraw = false; @@ -634,7 +644,7 @@ GameStatus DoGameLoop(int levelIndex) } else { - float interpolationFactor = std::min((float)controlLag / (float)controlFrameTime, 1.0f); + float interpolationFactor = std::min((float)controlLag / (float)CONTROL_FRAME_TIME, 1.0f); DrawPhase(!levelIndex, interpolationFactor); drawCalls++; } @@ -658,9 +668,7 @@ void EndGameLoop(int levelIndex, GameStatus reason) void SetupInterpolation() { for (int i = 0; i < g_Level.Items.size(); i++) - { g_Level.Items[i].DisableInterpolation = false; - } } void HandleControls(bool isTitle) @@ -675,10 +683,10 @@ void HandleControls(bool isTitle) GameStatus HandleMenuCalls(bool isTitle) { - auto result = GameStatus::Normal; + auto gameStatus = GameStatus::Normal; if (ScreenFading) - return result; + return gameStatus; if (isTitle) { @@ -697,10 +705,10 @@ GameStatus HandleMenuCalls(bool isTitle) return GameStatus::ExitGame; } - return result; + return gameStatus; } - // Does the player want to enter inventory? + // Handle inventory. if (IsClicked(In::Save) && LaraItem->HitPoints > 0 && g_Gui.GetInventoryMode() != InventoryMode::Save && g_GameFlow->IsLoadSaveEnabled()) @@ -717,28 +725,28 @@ GameStatus HandleMenuCalls(bool isTitle) g_Gui.SetInventoryMode(InventoryMode::Load); if (g_Gui.CallInventory(LaraItem, false)) - result = GameStatus::LoadGame; + gameStatus = GameStatus::LoadGame; } else if (IsClicked(In::Pause) && LaraItem->HitPoints > 0 && g_Gui.GetInventoryMode() != InventoryMode::Pause) { if (g_Gui.CallPause()) - result = GameStatus::ExitToTitle; + gameStatus = GameStatus::ExitToTitle; } else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_VALUE) && LaraItem->HitPoints > 0 && !Lara.Control.Look.IsUsingBinoculars) { if (g_Gui.CallInventory(LaraItem, true)) - result = GameStatus::LoadGame; + gameStatus = GameStatus::LoadGame; } - if (result != GameStatus::Normal) + if (gameStatus != GameStatus::Normal) { StopAllSounds(); StopRumble(); } - return result; + return gameStatus; } GameStatus HandleGlobalInputEvents(bool isTitle) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 6af798543..16ef14da1 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3588,8 +3588,8 @@ namespace TEN::Gui auto needleOrient = EulerAngles(0, CompassNeedleAngle, 0); needleOrient.Lerp(EulerAngles(0, item->Pose.Orientation.y, 0), LERP_ALPHA); - float wibble = std::sin(((float)(GameTimer & 0x3F) / (float)0x3F) * PI_MUL_2); - CompassNeedleAngle = needleOrient.y + ANGLE(wibble); + float wibble = std::sin((float(GameTimer & 0x3F) / (float)0x3F) * PI_MUL_2); + CompassNeedleAngle = needleOrient.y + ANGLE(wibble / 2); // HACK: Needle is rotated in the draw function. const auto& invObject = InventoryObjectTable[INV_OBJECT_COMPASS]; From b9d3f812536a240b77e3bb0bd216d537b1782301 Mon Sep 17 00:00:00 2001 From: Adngel Date: Fri, 17 May 2024 12:30:14 +0200 Subject: [PATCH 191/410] Fix: Electric Cleaner crash When it detected a sector with no box (a tile marked with "set non-walkable sector" editor flag) the game was crashing. Changing the detection order solved the issue. This issue was not happening in previous version (it was originated at some point of the past month) so I'm not registering in the changes.txt --- TombEngine/Game/misc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 7468037c1..29fa3e945 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -131,6 +131,10 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, boo return false; } + // Check for inaccessible sector. + if (pointColl.GetSector().Box == NO_VALUE) + return false; + // Check for blocked grey box. if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKABLE) { @@ -138,10 +142,6 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, boo return false; } - // Check for inaccessible sector. - if (pointColl.GetSector().Box == NO_VALUE) - return false; - // Check for stopper flag. if (pointColl.GetSector().Stopper) return false; From 815598f42528af7b7a34a3b936cb7ea9ffbf5ae3 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Fri, 17 May 2024 13:39:02 +0200 Subject: [PATCH 192/410] Fixed fire emitters --- TombEngine/Renderer/RendererDrawEffect.cpp | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 1b9d8d069..04a28d858 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -356,39 +356,39 @@ namespace TEN::Renderer for (int i = 0; i < MAX_SPARKS_FIRE; i++) { - auto* fire = &FireSparks[i]; + auto* spark = &FireSparks[i]; - if (fire->on) + if (spark->on) { AddSpriteBillboard( - &_sprites[fire->def], + &_sprites[spark->def], Vector3::Lerp( Vector3( - fire->oldPosition.x + fire->oldPosition.x * fire->oldSize / 2, - fire->oldPosition.y + fire->oldPosition.y * fire->oldSize / 2, - fire->oldPosition.z + fire->oldPosition.z * fire->oldSize / 2), + fire->oldPosition.x + spark->oldPosition.x * fire->oldSize / 2, + fire->oldPosition.y + spark->oldPosition.y * fire->oldSize / 2, + fire->oldPosition.z + spark->oldPosition.z * fire->oldSize / 2), Vector3( - fire->position.x + fire->position.x * fire->size / 2, - fire->position.y + fire->position.y * fire->size / 2, - fire->position.z + fire->position.z * fire->size / 2), + fire->position.x + spark->position.x * fire->size / 2, + fire->position.y + spark->position.y * fire->size / 2, + fire->position.z + spark->position.z * fire->size / 2), _interpolationFactor), Vector4::Lerp( Vector4( - fire->oldColor.x / 255.0f * fade, - fire->oldColor.y / 255.0f * fade, - fire->oldColor.z / 255.0f * fade, + spark->oldColor.x / 255.0f * fade, + spark->oldColor.y / 255.0f * fade, + spark->oldColor.z / 255.0f * fade, 1.0f), Vector4( - fire->color.x / 255.0f * fade, - fire->color.y / 255.0f * fade, - fire->color.z / 255.0f * fade, + spark->color.x / 255.0f * fade, + spark->color.y / 255.0f * fade, + spark->color.z / 255.0f * fade, 1.0f), _interpolationFactor), - TO_RAD(Lerp(fire->oldRotAng << 4, fire->rotAng << 4, _interpolationFactor)), - Lerp(fire->oldScalar, fire->scalar, _interpolationFactor), + TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), + Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), Vector2::Lerp( - Vector2(fire->oldSize * fire->oldSize, fire->oldSize * fire->oldSize), - Vector2(fire->size * fire->size, fire->size * fire->size), + Vector2(fire->oldSize * spark->oldSize, fire->oldSize * spark->oldSize), + Vector2(fire->size * spark->size, fire->size * spark->size), _interpolationFactor), BlendMode::Additive, true, view); } From 0b749b0c95c690a6cf58f671c4443048456d676c Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 18 May 2024 01:37:41 +1000 Subject: [PATCH 193/410] Fix bridge push --- TombEngine/Game/collision/collide_item.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 8698d01df..0ae536fb2 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -920,7 +920,8 @@ void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, PointCollisionData& } } // Push item. - else if (Vector2(deltaPose.Position.x, deltaPose.Position.z).Length() <= coll.Setup.Radius && + else if (TestBoundsCollide(&bridgeItem, &item, coll.Setup.Radius) && + Vector2(deltaPose.Position.x, deltaPose.Position.z).Length() <= coll.Setup.Radius && (deltaPos != Vector3i::Zero || deltaOrient != EulerAngles::Identity)) { ItemPushItem(&bridgeItem, &item); From 4fd6cceecd9810ddc150851d6cc4ded699a6feca Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sat, 18 May 2024 05:40:27 +0200 Subject: [PATCH 194/410] Added interpolation for scarabs, locusts, bats, rats, spiders, fishes --- TombEngine/Objects/Effects/tr4_locusts.cpp | 2 ++ TombEngine/Objects/Effects/tr4_locusts.h | 6 ++++ TombEngine/Objects/TR3/Entity/FishSwarm.cpp | 4 +++ TombEngine/Objects/TR3/Entity/FishSwarm.h | 8 +++++ .../Objects/TR4/Entity/tr4_beetle_swarm.cpp | 2 ++ .../Objects/TR4/Entity/tr4_beetle_swarm.h | 6 ++++ .../Objects/TR5/Emitter/tr5_bats_emitter.cpp | 2 ++ .../Objects/TR5/Emitter/tr5_bats_emitter.h | 6 ++++ .../Objects/TR5/Emitter/tr5_rats_emitter.cpp | 2 ++ .../Objects/TR5/Emitter/tr5_rats_emitter.h | 6 ++++ .../TR5/Emitter/tr5_spider_emitter.cpp | 6 ++++ .../Objects/TR5/Emitter/tr5_spider_emitter.h | 8 +++++ TombEngine/Renderer/RendererDraw.cpp | 32 ++++++++++++------- 13 files changed, 79 insertions(+), 11 deletions(-) diff --git a/TombEngine/Objects/Effects/tr4_locusts.cpp b/TombEngine/Objects/Effects/tr4_locusts.cpp index e828ce78b..0b8421507 100644 --- a/TombEngine/Objects/Effects/tr4_locusts.cpp +++ b/TombEngine/Objects/Effects/tr4_locusts.cpp @@ -111,6 +111,8 @@ namespace TEN::Entities::TR4 auto* locust = &Locusts[i]; if (locust->on) { + locust->StoreInterpolationData(); + // NOTE: not present in original TR4 code //if (locust->target == nullptr) // locust->target = LaraItem; diff --git a/TombEngine/Objects/Effects/tr4_locusts.h b/TombEngine/Objects/Effects/tr4_locusts.h index 2f2495a2b..ef1fb58f4 100644 --- a/TombEngine/Objects/Effects/tr4_locusts.h +++ b/TombEngine/Objects/Effects/tr4_locusts.h @@ -15,6 +15,12 @@ struct LOCUST_INFO BYTE counter; Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; namespace TEN::Entities::TR4 diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp index e9d5fedd5..abce85040 100644 --- a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp @@ -262,6 +262,8 @@ namespace TEN::Entities::Creatures::TR3 if (fish.Life <= 0.0f) continue; + fish.StoreInterpolationData(); + // Increase separation distance for each fish. float separationDist = FISH_BASE_SEPARATION_DISTANCE + (fishID * 3); fishID += 1; @@ -417,6 +419,8 @@ namespace TEN::Entities::Creatures::TR3 fish.Undulation += std::clamp(movementValue / 2, 0.3f, 1.0f); if (fish.Undulation > PI_MUL_2) fish.Undulation -= PI_MUL_2; + + fish.Transform = fish.Orientation.ToRotationMatrix() * Matrix::CreateTranslation(fish.Position); } } diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.h b/TombEngine/Objects/TR3/Entity/FishSwarm.h index 1a1dfe471..4f8cde15d 100644 --- a/TombEngine/Objects/TR3/Entity/FishSwarm.h +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.h @@ -25,6 +25,14 @@ namespace TEN::Entities::Creatures::TR3 ItemInfo* TargetItemPtr = nullptr; ItemInfo* LeaderItemPtr = nullptr; + + Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; extern std::vector FishSwarm; diff --git a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp index 9951cd441..910f2dbfb 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp @@ -143,6 +143,8 @@ namespace TEN::Entities::TR4 if (beetle->On) { + beetle->StoreInterpolationData(); + auto oldPos = beetle->Pose.Position; beetle->Pose.Position.x += beetle->Velocity * phd_sin(beetle->Pose.Orientation.y); diff --git a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h index 99f5cb88c..5a09712ff 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h +++ b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h @@ -14,6 +14,12 @@ namespace TEN::Entities::TR4 byte Flags; Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; constexpr auto NUM_BEETLES = 256; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp index a071909d9..865b71bd2 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.cpp @@ -130,6 +130,8 @@ void UpdateBats() if (!bat->On) continue; + bat->StoreInterpolationData(); + if ((LaraItem->Effect.Type != EffectType::None || LaraItem->HitPoints <= 0) && bat->Counter > 90 && !(GetRandomControl() & 7)) diff --git a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h index 9eeee5fb2..a380d0561 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h @@ -18,6 +18,12 @@ struct BatData byte Flags; Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; extern int NextBat; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp index bb1a1403a..ff4abf6e4 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp @@ -141,6 +141,8 @@ void UpdateRats() if (rat->On) { + rat->StoreInterpolationData(); + int oldX = rat->Pose.Position.x; int oldY = rat->Pose.Position.y; int oldZ = rat->Pose.Position.z; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h index 306f5604e..6b5753990 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h @@ -15,6 +15,12 @@ struct RatData byte Flags; Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; extern int NextRat; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp index 8e201afe2..4723ee085 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp @@ -134,6 +134,8 @@ void UpdateSpiders() if (spider->On) { + spider->StoreInterpolationData(); + int x = spider->Pose.Position.x; int y = spider->Pose.Position.y; int z = spider->Pose.Position.z; @@ -241,6 +243,10 @@ void UpdateSpiders() if (!i && !(GetRandomControl() & 4)) SoundEffect(SFX_TR5_INSECTS,&spider->Pose); + + Matrix translation = Matrix::CreateTranslation(spider->Pose.Position.x, spider->Pose.Position.y, spider->Pose.Position.z); + Matrix rotation = spider->Pose.Orientation.ToRotationMatrix(); + spider->Transform = rotation * translation; } } } diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h index d2064d187..0ed0900f4 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h @@ -13,6 +13,14 @@ struct SpiderData short VerticalVelocity; byte Flags; + + Matrix Transform; + Matrix OldTransform; + + void StoreInterpolationData() + { + OldTransform = Transform; + } }; extern int NextSpider; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 364ad3156..c1fa453ec 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -646,7 +646,7 @@ namespace TEN::Renderer for (auto& poly : bucket.Polygons) { - auto worldMatrix = fish.Orientation.ToRotationMatrix() * Matrix::CreateTranslation(fish.Position); + auto worldMatrix = Matrix::Lerp(fish.OldTransform, fish.Transform, _interpolationFactor); auto center = Vector3::Transform(poly.Centre, worldMatrix); float dist = Vector3::Distance(center, view.Camera.WorldPosition); @@ -707,7 +707,7 @@ namespace TEN::Renderer const auto& mesh = *GetMesh(Objects[ID_FISH_EMITTER].meshIndex + fish.MeshIndex); - _stStatic.World = fish.Orientation.ToRotationMatrix() * Matrix::CreateTranslation(fish.Position); + _stStatic.World = Matrix::Lerp(fish.OldTransform, fish.Transform, _interpolationFactor); _stStatic.Color = Vector4::One; _stStatic.AmbientLight = _rooms[fish.RoomNumber].AmbientLight; @@ -763,8 +763,10 @@ namespace TEN::Renderer { for (int p = 0; p < bucket.Polygons.size(); p++) { + Matrix transform = Matrix::Lerp(bat->OldTransform, bat->Transform, _interpolationFactor); + auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, bat->Transform); + bucket.Polygons[p].Centre, transform); int distance = (centre - view.Camera.WorldPosition).Length(); RendererSortableObject object; @@ -774,7 +776,7 @@ namespace TEN::Renderer object.Bucket = &bucket; object.Mesh = mesh; object.Polygon = &bucket.Polygons[p]; - object.World = bat->Transform; + object.World = transform; object.Room = &_rooms[bat->RoomNumber]; view.TransparentObjectsToDraw.push_back(object); @@ -794,9 +796,11 @@ namespace TEN::Renderer if (bat->On) { + Matrix transform = Matrix::Lerp(bat->OldTransform, bat->Transform, _interpolationFactor); + RendererRoom& room = _rooms[bat->RoomNumber]; - _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].World = bat->Transform; + _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].World = transform; _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].Ambient = room.AmbientLight; _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].Color = Vector4::One; _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].LightMode = (int)mesh->LightMode; @@ -879,6 +883,8 @@ namespace TEN::Renderer if (beetle->On) { + Matrix transform = Matrix::Lerp(beetle->OldTransform, beetle->Transform, _interpolationFactor); + for (int j = 0; j < mesh->Buckets.size(); j++) { auto& bucket = mesh->Buckets[j]; @@ -888,7 +894,7 @@ namespace TEN::Renderer for (int p = 0; p < bucket.Polygons.size(); p++) { auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, beetle->Transform); + bucket.Polygons[p].Centre, transform); int distance = (centre - view.Camera.WorldPosition).Length(); RendererSortableObject object; @@ -898,7 +904,7 @@ namespace TEN::Renderer object.Bucket = &bucket; object.Mesh = mesh; object.Polygon = &bucket.Polygons[p]; - object.World = beetle->Transform; + object.World = transform; object.Room = &_rooms[beetle->RoomNumber]; view.TransparentObjectsToDraw.push_back(object); @@ -920,9 +926,11 @@ namespace TEN::Renderer if (beetle.On) { + Matrix transform = Matrix::Lerp(beetle.OldTransform, beetle.Transform, _interpolationFactor); + auto& room = _rooms[beetle.RoomNumber]; - _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].World = beetle.Transform; + _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].World = transform; _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Ambient = room.AmbientLight; _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Color = Vector4::One; _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].LightMode = (int)mesh->LightMode; @@ -1021,8 +1029,10 @@ namespace TEN::Renderer { for (int p = 0; p < bucket.Polygons.size(); p++) { + Matrix transform = Matrix::Lerp(locust->OldTransform, locust->Transform, _interpolationFactor); + auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, locust->Transform); + bucket.Polygons[p].Centre, transform); int distance = (centre - view.Camera.WorldPosition).Length(); RendererSortableObject object; @@ -1032,7 +1042,7 @@ namespace TEN::Renderer object.Bucket = &bucket; object.Mesh = mesh; object.Polygon = &bucket.Polygons[p]; - object.World = locust->Transform; + object.World = transform; object.Room = &_rooms[locust->roomNumber]; view.TransparentObjectsToDraw.push_back(object); @@ -1088,7 +1098,7 @@ namespace TEN::Renderer { RendererMesh* mesh = GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust->counter & 3)); - _stStatic.World = locust->Transform; + _stStatic.World = Matrix::Lerp(locust->OldTransform, locust->Transform, _interpolationFactor); _stStatic.Color = Vector4::One; _stStatic.AmbientLight = _rooms[locust->roomNumber].AmbientLight; _cbStatic.UpdateData(_stStatic, _context.Get()); From e50715bd319505b23a49baa5f23d895c47f1cc33 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 19 May 2024 05:34:53 +0200 Subject: [PATCH 195/410] Fixed bad interpolation of crosshair position --- TombEngine/Game/Hud/TargetHighlighter.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 7cd768ba4..5d0d5b372 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -140,10 +140,25 @@ namespace TEN::Hud if (!Position.has_value()) return; - auto pos0 = Vector2::Lerp(*Position, PrevPosition, g_Renderer.GetInterpolationFactor()); - short orient0 = PrevOrientation + (Geometry::GetShortestAngle(PrevOrientation, Orientation) * g_Renderer.GetInterpolationFactor()); - float scale = Lerp(PrevScale, Scale, g_Renderer.GetInterpolationFactor()); - auto color = Color::Lerp(PrevColor, Color, g_Renderer.GetInterpolationFactor()); + auto pos0 = Vector2::Lerp( + PrevPosition, + *Position, + g_Renderer.GetInterpolationFactor() + ); + + short orient0 = PrevOrientation + Geometry::GetShortestAngle(PrevOrientation, Orientation) * g_Renderer.GetInterpolationFactor(); + + float scale = Lerp( + PrevScale, + Scale, + g_Renderer.GetInterpolationFactor() + ); + + auto color = Color::Lerp( + PrevColor, + Color, + g_Renderer.GetInterpolationFactor() + ); // Draw main static element. AddDisplaySprite( From 978fa30d61dfa9940b28e8d99884720847d753ad Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 19 May 2024 18:09:41 +1000 Subject: [PATCH 196/410] Formatting --- TombEngine/Objects/Effects/tr4_locusts.h | 6 +- TombEngine/Objects/TR3/Entity/FishSwarm.h | 6 +- .../Objects/TR4/Entity/tr4_beetle_swarm.h | 6 +- .../Objects/TR5/Emitter/tr5_bats_emitter.h | 8 +- .../Objects/TR5/Emitter/tr5_rats_emitter.h | 6 +- .../TR5/Emitter/tr5_spider_emitter.cpp | 6 +- .../Objects/TR5/Emitter/tr5_spider_emitter.h | 8 +- TombEngine/Renderer/RendererDraw.cpp | 305 ++++++++---------- 8 files changed, 152 insertions(+), 199 deletions(-) diff --git a/TombEngine/Objects/Effects/tr4_locusts.h b/TombEngine/Objects/Effects/tr4_locusts.h index ef1fb58f4..6fd6530ea 100644 --- a/TombEngine/Objects/Effects/tr4_locusts.h +++ b/TombEngine/Objects/Effects/tr4_locusts.h @@ -14,12 +14,12 @@ struct LOCUST_INFO short escapeZrot; BYTE counter; - Matrix Transform; - Matrix OldTransform; + Matrix Transform = Matrix::Identity; + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.h b/TombEngine/Objects/TR3/Entity/FishSwarm.h index 4f8cde15d..6aa4c6962 100644 --- a/TombEngine/Objects/TR3/Entity/FishSwarm.h +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.h @@ -26,12 +26,12 @@ namespace TEN::Entities::Creatures::TR3 ItemInfo* TargetItemPtr = nullptr; ItemInfo* LeaderItemPtr = nullptr; - Matrix Transform; - Matrix OldTransform; + Matrix Transform = Matrix::Identity; + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h index 5a09712ff..b4bd983e0 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h +++ b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.h @@ -13,12 +13,12 @@ namespace TEN::Entities::TR4 byte Flags; - Matrix Transform; - Matrix OldTransform; + Matrix Transform = Matrix::Identity; + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h index a380d0561..ab0a0b03c 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_bats_emitter.h @@ -16,13 +16,13 @@ struct BatData byte ZTarget; byte Flags; - - Matrix Transform; - Matrix OldTransform; + + Matrix Transform = Matrix::Identity; + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h index 6b5753990..3f57a8f9f 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.h @@ -14,12 +14,12 @@ struct RatData byte Flags; - Matrix Transform; - Matrix OldTransform; + Matrix Transform = Matrix::Identity; + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp index 4723ee085..2828ddaa7 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp @@ -244,9 +244,9 @@ void UpdateSpiders() if (!i && !(GetRandomControl() & 4)) SoundEffect(SFX_TR5_INSECTS,&spider->Pose); - Matrix translation = Matrix::CreateTranslation(spider->Pose.Position.x, spider->Pose.Position.y, spider->Pose.Position.z); - Matrix rotation = spider->Pose.Orientation.ToRotationMatrix(); - spider->Transform = rotation * translation; + auto tMatrix = Matrix::CreateTranslation(spider->Pose.Position.ToVector3()); + auto rotMatrix = spider->Pose.Orientation.ToRotationMatrix(); + spider->Transform = rotMatrix * tMatrix; } } } diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h index 0ed0900f4..636868907 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.h @@ -13,13 +13,13 @@ struct SpiderData short VerticalVelocity; byte Flags; - - Matrix Transform; - Matrix OldTransform; + + Matrix Transform = Matrix::Identity; + Matrix PrevTransform = Matrix::Identity; void StoreInterpolationData() { - OldTransform = Transform; + PrevTransform = Transform; } }; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index c1fa453ec..fdc64e403 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -646,7 +646,7 @@ namespace TEN::Renderer for (auto& poly : bucket.Polygons) { - auto worldMatrix = Matrix::Lerp(fish.OldTransform, fish.Transform, _interpolationFactor); + auto worldMatrix = Matrix::Lerp(fish.PrevTransform, fish.Transform, _interpolationFactor); auto center = Vector3::Transform(poly.Centre, worldMatrix); float dist = Vector3::Distance(center, view.Camera.WorldPosition); @@ -707,7 +707,7 @@ namespace TEN::Renderer const auto& mesh = *GetMesh(Objects[ID_FISH_EMITTER].meshIndex + fish.MeshIndex); - _stStatic.World = Matrix::Lerp(fish.OldTransform, fish.Transform, _interpolationFactor); + _stStatic.World = Matrix::Lerp(fish.PrevTransform, fish.Transform, _interpolationFactor); _stStatic.Color = Vector4::One; _stStatic.AmbientLight = _rooms[fish.RoomNumber].AmbientLight; @@ -745,76 +745,67 @@ namespace TEN::Renderer if (!Objects[ID_BATS_EMITTER].loaded) return; - auto* mesh = GetMesh(Objects[ID_BATS_EMITTER].meshIndex + (GlobalCounter & 3)); + auto& mesh = *GetMesh(Objects[ID_BATS_EMITTER].meshIndex + (GlobalCounter & 3)); if (rendererPass == RendererPass::CollectTransparentFaces) { - for (int i = 0; i < NUM_BATS; i++) + for (const auto& bat : Bats) { - auto* bat = &Bats[i]; + if (!bat.On) + continue; - if (bat->On) + for (auto& bucket : mesh.Buckets) { - for (int j = 0; j < mesh->Buckets.size(); j++) + if (!IsSortedBlendMode(bucket.BlendMode)) + continue; + + for (int p = 0; p < bucket.Polygons.size(); p++) { - auto& bucket = mesh->Buckets[j]; + auto transformMatrix = Matrix::Lerp(bat.PrevTransform, bat.Transform, _interpolationFactor); + auto centre = Vector3::Transform(bucket.Polygons[p].Centre, transformMatrix); + float dist = (centre - view.Camera.WorldPosition).Length(); - if (IsSortedBlendMode(bucket.BlendMode)) - { - for (int p = 0; p < bucket.Polygons.size(); p++) - { - Matrix transform = Matrix::Lerp(bat->OldTransform, bat->Transform, _interpolationFactor); + auto object = RendererSortableObject{}; + object.ObjectType = RendererObjectType::MoveableAsStatic; + object.Centre = centre; + object.Distance = dist; + object.Bucket = &bucket; + object.Mesh = &mesh; + object.Polygon = &bucket.Polygons[p]; + object.World = transformMatrix; + object.Room = &_rooms[bat.RoomNumber]; - auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, transform); - int distance = (centre - view.Camera.WorldPosition).Length(); - - RendererSortableObject object; - object.ObjectType = RendererObjectType::MoveableAsStatic; - object.Centre = centre; - object.Distance = distance; - object.Bucket = &bucket; - object.Mesh = mesh; - object.Polygon = &bucket.Polygons[p]; - object.World = transform; - object.Room = &_rooms[bat->RoomNumber]; - - view.TransparentObjectsToDraw.push_back(object); - } - } + view.TransparentObjectsToDraw.push_back(object); } } } } else { - int batsCount = 0; - + int batCount = 0; for (int i = 0; i < NUM_BATS; i++) { - auto* bat = &Bats[i]; + const auto& bat = Bats[i]; - if (bat->On) + if (bat.On) { - Matrix transform = Matrix::Lerp(bat->OldTransform, bat->Transform, _interpolationFactor); + auto& room = _rooms[bat.RoomNumber]; - RendererRoom& room = _rooms[bat->RoomNumber]; + auto transformMatrix = Matrix::Lerp(bat.PrevTransform, bat.Transform, _interpolationFactor); - _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].World = transform; - _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].Ambient = room.AmbientLight; - _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].Color = Vector4::One; - _stInstancedStaticMeshBuffer.StaticMeshes[batsCount].LightMode = (int)mesh->LightMode; + _stInstancedStaticMeshBuffer.StaticMeshes[batCount].World = transformMatrix; + _stInstancedStaticMeshBuffer.StaticMeshes[batCount].Ambient = room.AmbientLight; + _stInstancedStaticMeshBuffer.StaticMeshes[batCount].Color = Vector4::One; + _stInstancedStaticMeshBuffer.StaticMeshes[batCount].LightMode = (int)mesh.LightMode; if (rendererPass != RendererPass::GBuffer) - { - BindInstancedStaticLights(room.LightsToDraw, batsCount); - } + BindInstancedStaticLights(room.LightsToDraw, batCount); - batsCount++; + batCount++; } - if (batsCount == INSTANCED_STATIC_MESH_BUCKET_SIZE || - (i == NUM_BATS - 1 && batsCount > 0)) + if (batCount == INSTANCED_STATIC_MESH_BUCKET_SIZE || + (i == (NUM_BATS - 1) && batCount > 0)) { if (rendererPass == RendererPass::GBuffer) { @@ -827,40 +818,35 @@ namespace TEN::Renderer _context->PSSetShader(_psInstancedStaticMeshes.Get(), nullptr, 0); } - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get()); - for (auto& bucket : mesh->Buckets) + for (auto& bucket : mesh.Buckets) { if (bucket.NumVertices == 0) - { continue; - } - int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; - - for (int p = 0; p < passes; p++) + int passCount = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest) ? 2 : 1; + for (int p = 0; p < passCount; p++) { if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) - { continue; - } BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - DrawIndexedInstancedTriangles(bucket.NumIndices, batsCount, bucket.StartIndex, 0); + DrawIndexedInstancedTriangles(bucket.NumIndices, batCount, bucket.StartIndex, 0); _numMoveablesDrawCalls++; } } - batsCount = 0; + batCount = 0; } } } @@ -869,79 +855,68 @@ namespace TEN::Renderer void Renderer::DrawScarabs(RenderView& view, RendererPass rendererPass) { if (!Objects[ID_LITTLE_BEETLE].loaded) - { return; - } - RendererMesh* mesh = GetMesh(Objects[ID_LITTLE_BEETLE].meshIndex + ((Wibble >> 2) % 2)); + auto& mesh = *GetMesh(Objects[ID_LITTLE_BEETLE].meshIndex + ((Wibble >> 2) % 2)); if (rendererPass == RendererPass::CollectTransparentFaces) { - for (int i = 0; i < TEN::Entities::TR4::NUM_BEETLES; i++) + for (const auto& beetle : TEN::Entities::TR4::BeetleSwarm) { - auto beetle = &TEN::Entities::TR4::BeetleSwarm[i]; + if (!beetle.On) + continue; - if (beetle->On) + auto transformMatrix = Matrix::Lerp(beetle.PrevTransform, beetle.Transform, _interpolationFactor); + + for (auto& bucket : mesh.Buckets) { - Matrix transform = Matrix::Lerp(beetle->OldTransform, beetle->Transform, _interpolationFactor); + if (!IsSortedBlendMode(bucket.BlendMode)) + continue; - for (int j = 0; j < mesh->Buckets.size(); j++) + for (int p = 0; p < bucket.Polygons.size(); p++) { - auto& bucket = mesh->Buckets[j]; + auto centre = Vector3::Transform(bucket.Polygons[p].Centre, transformMatrix); + float dist = (centre - view.Camera.WorldPosition).Length(); - if (IsSortedBlendMode(bucket.BlendMode)) - { - for (int p = 0; p < bucket.Polygons.size(); p++) - { - auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, transform); - int distance = (centre - view.Camera.WorldPosition).Length(); + auto object = RendererSortableObject{}; + object.ObjectType = RendererObjectType::MoveableAsStatic; + object.Centre = centre; + object.Distance = dist; + object.Bucket = &bucket; + object.Mesh = &mesh; + object.Polygon = &bucket.Polygons[p]; + object.World = transformMatrix; + object.Room = &_rooms[beetle.RoomNumber]; - RendererSortableObject object; - object.ObjectType = RendererObjectType::MoveableAsStatic; - object.Centre = centre; - object.Distance = distance; - object.Bucket = &bucket; - object.Mesh = mesh; - object.Polygon = &bucket.Polygons[p]; - object.World = transform; - object.Room = &_rooms[beetle->RoomNumber]; - - view.TransparentObjectsToDraw.push_back(object); - } - } + view.TransparentObjectsToDraw.push_back(object); } } } } else { - std::vector> beetlesBuckets; - - unsigned int beetleCount = 0; - + int beetleCount = 0; for (int i = 0; i < TEN::Entities::TR4::NUM_BEETLES; i++) { const auto& beetle = TEN::Entities::TR4::BeetleSwarm[i]; if (beetle.On) { - Matrix transform = Matrix::Lerp(beetle.OldTransform, beetle.Transform, _interpolationFactor); - auto& room = _rooms[beetle.RoomNumber]; - _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].World = transform; + auto transformMatrix = Matrix::Lerp(beetle.PrevTransform, beetle.Transform, _interpolationFactor); + + _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].World = transformMatrix; _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Ambient = room.AmbientLight; _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Color = Vector4::One; - _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].LightMode = (int)mesh->LightMode; + _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].LightMode = (int)mesh.LightMode; if (rendererPass != RendererPass::GBuffer) { - std::vector lights; + auto lights = std::vector{}; for (int i = 0; i < std::min((int)room.LightsToDraw.size(), MAX_LIGHTS_PER_ITEM); i++) - { lights.push_back(room.LightsToDraw[i]); - } + BindInstancedStaticLights(lights, beetleCount); } @@ -970,21 +945,16 @@ namespace TEN::Renderer _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get()); - for (const auto& bucket : mesh->Buckets) + for (auto& bucket : mesh.Buckets) { if (bucket.NumVertices == 0) - { continue; - } - int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; - - for (int p = 0; p < passes; p++) + int passCount = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest) ? 2 : 1; + for (int p = 0; p < passCount; p++) { if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) - { continue; - } BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); @@ -1004,50 +974,42 @@ namespace TEN::Renderer void Renderer::DrawLocusts(RenderView& view, RendererPass rendererPass) { if (!Objects[ID_LOCUSTS].loaded) - { return; - } if (rendererPass == RendererPass::CollectTransparentFaces) { - ObjectInfo* obj = &Objects[ID_LOCUSTS]; - RendererObject& moveableObj = *_moveableObjects[ID_LOCUSTS]; + auto* obj = &Objects[ID_LOCUSTS]; + auto& moveableObj = *_moveableObjects[ID_LOCUSTS]; - for (int i = 0; i < TEN::Entities::TR4::MAX_LOCUSTS; i++) + for (const auto& locust : TEN::Entities::TR4::Locusts) { - LOCUST_INFO* locust = &TEN::Entities::TR4::Locusts[i]; + if (!locust.on) + continue; - if (locust->on) + auto& mesh = *GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust.counter & 3)); + + for (auto& bucket : mesh.Buckets) { - RendererMesh* mesh = GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust->counter & 3)); + if (!IsSortedBlendMode(bucket.BlendMode)) + continue; - for (int j = 0; j < mesh->Buckets.size(); j++) + for (int p = 0; p < bucket.Polygons.size(); p++) { - auto& bucket = mesh->Buckets[j]; + auto transformMatrix = Matrix::Lerp(locust.PrevTransform, locust.Transform, _interpolationFactor); + auto centre = Vector3::Transform(bucket.Polygons[p].Centre, transformMatrix); + float dist = (centre - view.Camera.WorldPosition).Length(); - if (IsSortedBlendMode(bucket.BlendMode)) - { - for (int p = 0; p < bucket.Polygons.size(); p++) - { - Matrix transform = Matrix::Lerp(locust->OldTransform, locust->Transform, _interpolationFactor); + auto object = RendererSortableObject{}; + object.ObjectType = RendererObjectType::MoveableAsStatic; + object.Centre = centre; + object.Distance = dist; + object.Bucket = &bucket; + object.Mesh = &mesh; + object.Polygon = &bucket.Polygons[p]; + object.World = transformMatrix; + object.Room = &_rooms[locust.roomNumber]; - auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, transform); - int distance = (centre - view.Camera.WorldPosition).Length(); - - RendererSortableObject object; - object.ObjectType = RendererObjectType::MoveableAsStatic; - object.Centre = centre; - object.Distance = distance; - object.Bucket = &bucket; - object.Mesh = mesh; - object.Polygon = &bucket.Polygons[p]; - object.World = transform; - object.Room = &_rooms[locust->roomNumber]; - - view.TransparentObjectsToDraw.push_back(object); - } - } + view.TransparentObjectsToDraw.push_back(object); } } } @@ -1055,15 +1017,13 @@ namespace TEN::Renderer else { int activeLocustsExist = false; - for (int i = 0; i < TEN::Entities::TR4::MAX_LOCUSTS; i++) + for (const auto& locust : TEN::Entities::TR4::Locusts) { - LOCUST_INFO* locust = &TEN::Entities::TR4::Locusts[i]; + if (!locust.on) + continue; - if (locust->on) - { - activeLocustsExist = true; - break; - } + activeLocustsExist = true; + break; } if (activeLocustsExist) @@ -1079,53 +1039,46 @@ namespace TEN::Renderer _context->PSSetShader(_psStatics.Get(), nullptr, 0); } - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); - ObjectInfo* obj = &Objects[ID_LOCUSTS]; - RendererObject& moveableObj = *_moveableObjects[ID_LOCUSTS]; + auto* obj = &Objects[ID_LOCUSTS]; + auto& moveableObj = *_moveableObjects[ID_LOCUSTS]; _stStatic.LightMode = (int)moveableObj.ObjectMeshes[0]->LightMode; - for (int i = 0; i < TEN::Entities::TR4::MAX_LOCUSTS; i++) + for (const auto& locust : TEN::Entities::TR4::Locusts) { - LOCUST_INFO* locust = &TEN::Entities::TR4::Locusts[i]; + if (!locust.on) + continue; - if (locust->on) + auto& mesh = *GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust.counter & 3)); + + _stStatic.World = Matrix::Lerp(locust.PrevTransform, locust.Transform, _interpolationFactor); + _stStatic.Color = Vector4::One; + _stStatic.AmbientLight = _rooms[locust.roomNumber].AmbientLight; + _cbStatic.UpdateData(_stStatic, _context.Get()); + + for (auto& bucket : mesh.Buckets) { - RendererMesh* mesh = GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust->counter & 3)); + if (bucket.NumVertices == 0) + continue; - _stStatic.World = Matrix::Lerp(locust->OldTransform, locust->Transform, _interpolationFactor); - _stStatic.Color = Vector4::One; - _stStatic.AmbientLight = _rooms[locust->roomNumber].AmbientLight; - _cbStatic.UpdateData(_stStatic, _context.Get()); - - for (auto& bucket : mesh->Buckets) + int passes = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1); + for (int p = 0; p < passes; p++) { - if (bucket.NumVertices == 0) - { + if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) continue; - } - int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; + BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); + BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - for (int p = 0; p < passes; p++) - { - if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) - { - continue; - } + DrawIndexedTriangles(bucket.NumIndices, bucket.StartIndex, 0); - BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - - DrawIndexedTriangles(bucket.NumIndices, bucket.StartIndex, 0); - - _numMoveablesDrawCalls++; - } + _numMoveablesDrawCalls++; } } } From 36133ea5e957fa8cbf2b63415f0ce91fe16b7b52 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 19 May 2024 18:10:45 +1000 Subject: [PATCH 197/410] Use parentheses --- TombEngine/Renderer/RendererDraw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index fdc64e403..75cd73de2 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1067,8 +1067,8 @@ namespace TEN::Renderer if (bucket.NumVertices == 0) continue; - int passes = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1); - for (int p = 0; p < passes; p++) + int passCount = (rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest) ? 2 : 1; + for (int p = 0; p < passCount; p++) { if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) continue; From 210cad57e1ee152409fc0f8d37b3028178d8afbc Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 19 May 2024 18:12:00 +1000 Subject: [PATCH 198/410] Fix formatting --- TombEngine/Game/Hud/TargetHighlighter.cpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 5d0d5b372..ab2fbc398 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -140,25 +140,10 @@ namespace TEN::Hud if (!Position.has_value()) return; - auto pos0 = Vector2::Lerp( - PrevPosition, - *Position, - g_Renderer.GetInterpolationFactor() - ); - + auto pos0 = Vector2::Lerp(PrevPosition, *Position, g_Renderer.GetInterpolationFactor()); short orient0 = PrevOrientation + Geometry::GetShortestAngle(PrevOrientation, Orientation) * g_Renderer.GetInterpolationFactor(); - - float scale = Lerp( - PrevScale, - Scale, - g_Renderer.GetInterpolationFactor() - ); - - auto color = Color::Lerp( - PrevColor, - Color, - g_Renderer.GetInterpolationFactor() - ); + float scale = Lerp(PrevScale, Scale, g_Renderer.GetInterpolationFactor()); + auto color = Color::Lerp(PrevColor, Color, g_Renderer.GetInterpolationFactor()); // Draw main static element. AddDisplaySprite( From be5c525fa2f1f2ae5e3611b4c9526ed635cec92d Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 19 May 2024 18:21:01 +1000 Subject: [PATCH 199/410] Remove Ptr suffix --- TombEngine/Game/Hud/TargetHighlighter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index ab2fbc398..fb863cef9 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -184,23 +184,23 @@ namespace TEN::Hud // Loop over player targets. auto itemNumbers = std::vector{}; - for (const auto* itemPtr : player.TargetList) + for (const auto* item : player.TargetList) { - if (itemPtr == nullptr) + if (item == nullptr) continue; // Collect item number. - if (itemPtr->HitPoints != NOT_TARGETABLE) - itemNumbers.push_back(itemPtr->Index); + if (item->HitPoints != NOT_TARGETABLE) + itemNumbers.push_back(item->Index); // Find crosshair at item number key. - auto it = _crosshairs.find(itemPtr->Index); + auto it = _crosshairs.find(item->Index); if (it == _crosshairs.end()) continue; // Set crosshair as primary or peripheral. auto& crosshair = it->second; - if (player.TargetEntity != nullptr && itemPtr->Index == player.TargetEntity->Index) + if (player.TargetEntity != nullptr && item->Index == player.TargetEntity->Index) { crosshair.SetPrimary(); } From 40966147c9b841f2ee6167903e759813ac40b1d9 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Sun, 19 May 2024 22:42:03 +0100 Subject: [PATCH 200/410] Fix bullet points --- CHANGELOG.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e69120b4..d84194e1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -151,24 +151,24 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Features/Amendments * Improve head-on wall collision. * Overhaul pushables: - - Separate climbable and non-climbable pushable object slots. - - Add new pushable OCB to manipulate pushable properties. - - Add new animations for pushing pushables off edgees (TR1-3 and TR4-5 versions). - - Fix pushables not working with raising blocks. - - Fix miscellaneous pushable bugs. + - Separate climbable and non-climbable pushable object slots. + - Add new pushable OCB to manipulate pushable properties. + - Add new animations for pushing pushables off edgees (TR1-3 and TR4-5 versions). + - Fix pushables not working with raising blocks. + - Fix miscellaneous pushable bugs. * Overhaul look-around feature: - - Allow for more consistent and wider viewing angles while crawling, crouching, and hanging. - - Improve look camera movement and control. - - Re-enable looking while performing up jump, backward jump, or backward crawl. - - Add functionality to rotate slowly when holding Walk while using binoculars or lasersight. + - Allow for more consistent and wider viewing angles while crawling, crouching, and hanging. + - Improve look camera movement and control. + - Re-enable looking while performing up jump, backward jump, or backward crawl. + - Add functionality to rotate slowly when holding Walk while using binoculars or lasersight. * Add target highlighter system with toggle in Sound and Gameplay settings. * Add sprint slide state 191. * Add swinging blade. * Add crumbling platform and add new OCBs for behaviour: - - OCB 0: Default behaviour. When the player steps on the platform, it will shake and crumble after 1.2 seconds. - - OCB > 0: When the player steps on the platform, it will crumble after the number of frames set in the OCB. - - A positive value results in activation via player collision. - - A negative value requires a trigger to activate. + - OCB 0: Default behaviour. When the player steps on the platform, it will shake and crumble after 1.2 seconds. + - OCB > 0: When the player steps on the platform, it will crumble after the number of frames set in the OCB. + - A positive value results in activation via player collision. + - A negative value requires a trigger to activate. * Add basic mouse input handling. Allows for binding of mouse inputs in control settings. * Add settings for Mouse Sensitivity and Mouse Smoothing (not used in-game yet). From dd46927f6286a7c2765bdcca1a6b5407b25ebcad Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 20 May 2024 05:17:31 +0200 Subject: [PATCH 201/410] Fixed fish swarms not drawing --- TombEngine/Game/control/control.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 6fa9b355d..329b8f6be 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -240,6 +240,7 @@ GameStatus ControlPhase() UpdateBeetleSwarm(); UpdateLocusts(); UpdateUnderwaterBloodParticles(); + UpdateFishSwarm(); if (g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareEnabled()) { From 01a4b69168461c33dba7c8447776317dc010f7e8 Mon Sep 17 00:00:00 2001 From: Adngel Date: Mon, 27 May 2024 10:29:09 +0200 Subject: [PATCH 202/410] Fix: Larson and Pierre zone. Human LotType allows enemies to moves up and down of 2 and 4 clicks (like VCI guards) but Larson and Pierre hasn't got climbing animations, so they move over high steps just walking through. That's why I'm changing them to obj->LotType = LotType::Basic; So they will do the correct path through 1 click steps. --- TombEngine/Objects/TR5/tr5_objects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp index 686c9d28c..6a72a81b2 100644 --- a/TombEngine/Objects/TR5/tr5_objects.cpp +++ b/TombEngine/Objects/TR5/tr5_objects.cpp @@ -374,7 +374,7 @@ static void StartEntity(ObjectInfo *obj) obj->pivotLength = 50; obj->radius = 102; obj->intelligent = true; - obj->LotType = LotType::Human; + obj->LotType = LotType::Basic; obj->SetBoneRotationFlags(6, ROT_X | ROT_Y); obj->SetBoneRotationFlags(7, ROT_X | ROT_Y); obj->SetHitEffect(); @@ -391,7 +391,7 @@ static void StartEntity(ObjectInfo *obj) obj->pivotLength = 50; obj->radius = 102; obj->intelligent = true; - obj->LotType = LotType::Human; + obj->LotType = LotType::Basic; obj->SetBoneRotationFlags(6, ROT_X | ROT_Y); obj->SetBoneRotationFlags(7, ROT_X | ROT_Y); obj->SetHitEffect(); From 1f4404d76010c74e76bdcdccd593037c9c27975c Mon Sep 17 00:00:00 2001 From: Adngel Date: Fri, 31 May 2024 20:52:57 +0200 Subject: [PATCH 203/410] Fix: Burning Torch, flame in hand Changing the commands order to switch off the Lara's hand flame in the same frame when she throws or drops the torch. (The command must still be after the torch flare has been created, otherwise the torch flare will be switched off when instantiated). Issue: https://github.com/MontyTRC89/TombEngine/issues/1376 --- TombEngine/Objects/Generic/Object/burning_torch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/burning_torch.cpp b/TombEngine/Objects/Generic/Object/burning_torch.cpp index 7d271b08d..a38b1e3a6 100644 --- a/TombEngine/Objects/Generic/Object/burning_torch.cpp +++ b/TombEngine/Objects/Generic/Object/burning_torch.cpp @@ -127,7 +127,6 @@ namespace TEN::Entities::Generic lara->LeftArm.FrameNumber++; if (lara->LeftArm.FrameNumber == 27) { - lara->Torch.IsLit = false; lara->Flare.ControlLeft = false; lara->LeftArm.Locked = false; lara->Torch.State = TorchState::Holding; @@ -139,6 +138,7 @@ namespace TEN::Entities::Generic { laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND; CreateFlare(*laraItem, ID_BURNING_TORCH_ITEM, true); + lara->Torch.IsLit = false; } } } @@ -147,7 +147,6 @@ namespace TEN::Entities::Generic lara->LeftArm.FrameNumber++; if (lara->LeftArm.FrameNumber == 41) { - lara->Torch.IsLit = false; lara->Flare.ControlLeft = false; lara->LeftArm.Locked = false; lara->Torch.State = TorchState::Holding; @@ -159,6 +158,7 @@ namespace TEN::Entities::Generic { laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND; CreateFlare(*laraItem, ID_BURNING_TORCH_ITEM, false); + lara->Torch.IsLit = false; } } else if (lara->Torch.State == TorchState::JustLit) From 838dab484bc0f55367f6742ad3d19dd20b03bd5c Mon Sep 17 00:00:00 2001 From: Adngel Date: Fri, 31 May 2024 20:59:25 +0200 Subject: [PATCH 204/410] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d84194e1b..f8ffd5f17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed Ember emitter crashing when ocb is between -1 and -10 * Fixed Electric cleaner and Squishy block not detecting collision with certain block heights. * Fixed Squishy blocks crashing the level. +* Fixed the path finding zones of Larson and Pierre. +* Fixed the torch flame delay in disappearing when Lara threw or dropped the torch object. ### Features/Amendments From 47e22abbe92d2a52b79a0df02db7e5eba6b2b584 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 6 Jun 2024 10:52:59 +1000 Subject: [PATCH 205/410] Remove Ptrs suffixes --- TombEngine/Game/Lara/lara_one_gun.cpp | 4 ++-- TombEngine/Game/Lara/lara_tests.cpp | 2 +- TombEngine/Game/collision/collide_item.cpp | 4 ++-- TombEngine/Game/collision/collide_item.h | 6 +++--- TombEngine/Game/pickup/pickup.cpp | 8 ++++---- TombEngine/Objects/Effects/flame_emitters.cpp | 2 +- TombEngine/Objects/Effects/tr5_electricity.cpp | 2 +- .../Generic/Object/Pushable/PushableCollision.cpp | 4 ++-- TombEngine/Objects/Generic/Object/burning_torch.cpp | 12 ++++++------ TombEngine/Objects/TR5/Trap/tr5_explosion.cpp | 2 +- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index a5a55a22f..41f841d9b 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -1563,7 +1563,7 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p break; // Run through statics. - for (auto* staticPtr : collObjects.StaticPtrs) + for (auto* staticPtr : collObjects.Statics) { hasHit = hasHitNotByEmitter = doShatter = true; doExplosion = isExplosive; @@ -1584,7 +1584,7 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p } // Run through items. - for (auto* itemPtr : collObjects.ItemPtrs) + for (auto* itemPtr : collObjects.Items) { // Object was already affected by collision, skip it. if (std::find(affectedObjects.begin(), affectedObjects.end(), itemPtr->Index) != affectedObjects.end()) diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 9d24bc0ea..dc631857c 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -1795,7 +1795,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl //g_Renderer.AddDebugSphere(sphere.Center, 16.0f, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); - for (const auto* itemPtr : collObjects.ItemPtrs) + for (const auto* itemPtr : collObjects.Items) { if (itemPtr->ObjectNumber != ID_POLEROPE) continue; diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 0ae536fb2..b979c66eb 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -204,7 +204,7 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, // Test accurate box intersection. if (box0.Intersects(box1)) - collObjects.ItemPtrs.push_back(&item); + collObjects.Items.push_back(&item); } while (itemNumber != NO_VALUE); } @@ -253,7 +253,7 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, // Test accurate box intersection. if (box0.Intersects(box1)) - collObjects.StaticPtrs.push_back(&staticObj); + collObjects.Statics.push_back(&staticObj); } } } diff --git a/TombEngine/Game/collision/collide_item.h b/TombEngine/Game/collision/collide_item.h index 5bd91e997..6c39f9abb 100644 --- a/TombEngine/Game/collision/collide_item.h +++ b/TombEngine/Game/collision/collide_item.h @@ -30,10 +30,10 @@ struct ObjectCollisionBounds struct CollidedObjectData { - std::vector ItemPtrs = {}; - std::vector StaticPtrs = {}; + std::vector Items = {}; + std::vector Statics = {}; - bool IsEmpty() const { return (ItemPtrs.empty() && StaticPtrs.empty()); }; + bool IsEmpty() const { return (Items.empty() && Statics.empty()); }; }; void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index 0dff72dda..d9d2a3dc0 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -234,8 +234,8 @@ void CollectMultiplePickups(int itemNumber) auto& firstItem = g_Level.Items[itemNumber]; auto collObjects = GetCollidedObjects(firstItem, true, true, LARA_RADIUS, ObjectCollectionMode::Items); - collObjects.ItemPtrs.push_back(&firstItem); - for (auto* itemPtr : collObjects.ItemPtrs) + collObjects.Items.push_back(&firstItem); + for (auto* itemPtr : collObjects.Items) { if (!Objects[itemPtr->ObjectNumber].isPickup) continue; @@ -886,7 +886,7 @@ void DropPickups(ItemInfo* item) // Iterate through all found items and statics around, and determine if dummy sphere // intersects any of those. If so, try other corner. - for (const auto* itemPtr : collObjects.ItemPtrs) + for (const auto* itemPtr : collObjects.Items) { auto box = GameBoundingBox(itemPtr).ToBoundingOrientedBox(itemPtr->Pose); if (box.Intersects(sphere)) @@ -896,7 +896,7 @@ void DropPickups(ItemInfo* item) } } - for (auto* staticPtr : collObjects.StaticPtrs) + for (auto* staticPtr : collObjects.Statics) { auto& object = StaticObjects[staticPtr->staticNumber]; diff --git a/TombEngine/Objects/Effects/flame_emitters.cpp b/TombEngine/Objects/Effects/flame_emitters.cpp index 80fea9e67..d0040a6f7 100644 --- a/TombEngine/Objects/Effects/flame_emitters.cpp +++ b/TombEngine/Objects/Effects/flame_emitters.cpp @@ -65,7 +65,7 @@ namespace TEN::Entities::Effects void BurnNearbyItems(ItemInfo* item, int radius) { auto collObjects = GetCollidedObjects(*item, true, false, radius, ObjectCollectionMode::Items); - for (auto* itemPtr : collObjects.ItemPtrs) + for (auto* itemPtr : collObjects.Items) { if (TestEnvironment(ENV_FLAG_WATER, itemPtr->RoomNumber)) continue; diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index abfd748a3..1e79cb09f 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -180,7 +180,7 @@ void ElectricityWiresControl(short itemNumber) return; auto collObjects = GetCollidedObjects(*item, true, false, BLOCK(2), ObjectCollectionMode::Items); - for (auto* itemPtr : collObjects.ItemPtrs) + for (auto* itemPtr : collObjects.Items) { const auto& object = Objects[itemPtr->ObjectNumber]; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index bf526c49a..4494bc600 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -120,7 +120,7 @@ namespace TEN::Entities::Generic auto collObjects = GetCollidedObjects(pushableItem, true, true); pushableItem.Pose.Position = prevPos; - if (!collObjects.StaticPtrs.empty()) + if (!collObjects.Statics.empty()) return false; for (const auto* itemPtr : collObjects.ItemPtrs) @@ -191,7 +191,7 @@ namespace TEN::Entities::Generic auto collObjects = GetCollidedObjects(*LaraItem, true, true); LaraItem->Pose.Position = prevPos; - if (!collObjects.StaticPtrs.empty()) + if (!collObjects.Statics.empty()) return false; for (const auto* itemPtr : collObjects.ItemPtrs) diff --git a/TombEngine/Objects/Generic/Object/burning_torch.cpp b/TombEngine/Objects/Generic/Object/burning_torch.cpp index a38b1e3a6..4c1da0297 100644 --- a/TombEngine/Objects/Generic/Object/burning_torch.cpp +++ b/TombEngine/Objects/Generic/Object/burning_torch.cpp @@ -261,19 +261,19 @@ namespace TEN::Entities::Generic if (!collObjects.IsEmpty()) { LaraCollision.Setup.EnableObjectPush = true; - if (!collObjects.ItemPtrs.empty()) + if (!collObjects.Items.empty()) { - const auto& object = Objects[collObjects.ItemPtrs.front()->ObjectNumber]; + const auto& object = Objects[collObjects.Items.front()->ObjectNumber]; if (!object.intelligent && - !collObjects.ItemPtrs.front()->IsLara()) + !collObjects.Items.front()->IsLara()) { - ObjectCollision(collObjects.ItemPtrs.front()->Index, item, &LaraCollision); + ObjectCollision(collObjects.Items.front()->Index, item, &LaraCollision); } } - else if (!collObjects.StaticPtrs.empty()) + else if (!collObjects.Statics.empty()) { - ItemPushStatic(item, *collObjects.StaticPtrs.front(), &LaraCollision); + ItemPushStatic(item, *collObjects.Statics.front(), &LaraCollision); } item->Animation.Velocity.z = -int(item->Animation.Velocity.z / 1.5f); diff --git a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp index 8b33196a2..1873979ad 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp @@ -155,7 +155,7 @@ void ExplosionControl(short itemNumber) } } - for (auto* staticPtr : collObjects.StaticPtrs) + for (auto* staticPtr : collObjects.Statics) { if (StaticObjects[staticPtr->staticNumber].shatterType != ShatterType::None) { From d33d1ced19f7488e63ddda96abe3fbacc2990463 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 6 Jun 2024 11:15:43 +1000 Subject: [PATCH 206/410] Manually fix VS search and replace errors --- .../Objects/Generic/Object/Pushable/PushableCollision.cpp | 4 ++-- TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp | 2 +- TombEngine/Objects/TR4/Trap/SpikyWall.cpp | 2 +- TombEngine/Objects/TR5/Trap/tr5_explosion.cpp | 2 +- TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 4494bc600..c1ffac6ce 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -123,7 +123,7 @@ namespace TEN::Entities::Generic if (!collObjects.Statics.empty()) return false; - for (const auto* itemPtr : collObjects.ItemPtrs) + for (const auto* itemPtr : collObjects.Items) { const auto& object = Objects[itemPtr->ObjectNumber]; @@ -194,7 +194,7 @@ namespace TEN::Entities::Generic if (!collObjects.Statics.empty()) return false; - for (const auto* itemPtr : collObjects.ItemPtrs) + for (const auto* itemPtr : collObjects.Items) { const auto& object = Objects[itemPtr->ObjectNumber]; diff --git a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp index f25abbc09..436ade346 100644 --- a/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp +++ b/TombEngine/Objects/TR3/Trap/ElectricCleaner.cpp @@ -114,7 +114,7 @@ namespace TEN::Entities::Traps auto collObjects = GetCollidedObjects(item, true, true); if (!collObjects.IsEmpty()) { - for (auto* itemPtr : collObjects.ItemPtrs) + for (auto* itemPtr : collObjects.Items) { const auto& object = Objects[itemPtr->ObjectNumber]; diff --git a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp index bd1f55d5e..7f707153f 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp @@ -55,7 +55,7 @@ namespace TEN::Entities::Traps auto collObjects = GetCollidedObjects(item, true, true); if (!collObjects.IsEmpty()) { - for (auto* itemPtr : collObjects.ItemPtrs) + for (auto* itemPtr : collObjects.Items) { const auto& object = Objects[itemPtr->ObjectNumber]; diff --git a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp index 1873979ad..70bf86659 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp @@ -132,7 +132,7 @@ void ExplosionControl(short itemNumber) auto collObjects = GetCollidedObjects(*item, true, true, BLOCK(2), ObjectCollectionMode::All); if (!collObjects.IsEmpty()) { - for (auto* itemPtr : collObjects.ItemPtrs) + for (auto* itemPtr : collObjects.Items) { if (itemPtr->ObjectNumber >= ID_SMASH_OBJECT1 && itemPtr->ObjectNumber <= ID_SMASH_OBJECT16) { diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp index 64b74ca70..df52b1c59 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.cpp @@ -184,7 +184,7 @@ void ObjectsHandler::TestCollidingObjects() { // Test against other moveables. auto collObjects = GetCollidedObjects(item, true, false); - for (const auto& collidedItemPtr : collObjects.ItemPtrs) + for (const auto& collidedItemPtr : collObjects.Items) g_GameScript->ExecuteFunction(item.Callbacks.OnObjectCollided, itemNumber0, collidedItemPtr->Index); } From 6fa494b093861fc72620ca538fbde99862e1ab6c Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 6 Jun 2024 11:42:54 +1000 Subject: [PATCH 207/410] Make monkey swing auto jump a player setting; Lua formatting --- Scripts/Settings.lua | 1 - Scripts/SystemStrings.lua | 3 +- TombEngine/Game/Lara/lara_tests.cpp | 6 +-- TombEngine/Game/Lara/lara_tests.h | 2 +- TombEngine/Game/gui.cpp | 15 +++++-- TombEngine/Renderer/RendererDrawMenu.cpp | 33 ++++++++------ .../Include/Flow/ScriptInterfaceFlowHandler.h | 2 +- .../Scripting/Internal/LanguageScript.h | 3 +- TombEngine/Scripting/Internal/LuaHandler.cpp | 16 +++---- TombEngine/Scripting/Internal/LuaHandler.h | 30 ++++++------- .../TEN/Flow/Animations/Animations.cpp | 7 +-- .../Internal/TEN/Flow/Animations/Animations.h | 4 +- .../Internal/TEN/Flow/FlowHandler.cpp | 44 +++++++++---------- .../Scripting/Internal/TEN/Flow/FlowHandler.h | 27 ++++++------ .../Internal/TEN/Strings/StringsHandler.cpp | 2 +- TombEngine/Specific/configuration.cpp | 9 +++- TombEngine/Specific/configuration.h | 2 + 17 files changed, 114 insertions(+), 92 deletions(-) diff --git a/Scripts/Settings.lua b/Scripts/Settings.lua index 4b7a4c226..f50976766 100644 --- a/Scripts/Settings.lua +++ b/Scripts/Settings.lua @@ -11,7 +11,6 @@ local anims = Flow.Animations.new() anims.crawlExtended = true anims.crouchRoll = true anims.crawlspaceSwandive = true -anims.monkeyAutoJump = false anims.overhangClimb = false anims.slideExtended = false anims.sprintJump = false diff --git a/Scripts/SystemStrings.lua b/Scripts/SystemStrings.lua index 2bb0d2e47..23f4c749b 100644 --- a/Scripts/SystemStrings.lua +++ b/Scripts/SystemStrings.lua @@ -51,7 +51,8 @@ local strings = ammo_used = { "Ammo Used" }, antialiasing = { "Antialiasing" }, apply = { "Apply" }, - automatic_targeting = { "Automatic Targeting" }, + auto_monkey_swing_jump = { "Auto Monkey Jump" }, + auto_targeting = { "Auto Targeting" }, back = { "Back" }, cancel = { "Cancel" }, caustics = { "Underwater Caustics" }, diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index dc631857c..97cd5d730 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -1427,7 +1427,7 @@ std::optional TestLaraLadderMount(ItemInfo* item, CollisionInfo return std::nullopt; } -std::optional TestLaraMonkeyAutoJump(ItemInfo* item, CollisionInfo* coll) +std::optional TestLaraAutoMonkeySwingJump(ItemInfo* item, CollisionInfo* coll) { auto* lara = GetLaraInfo(item); @@ -1530,8 +1530,8 @@ std::optional TestLaraVault(ItemInfo* item, CollisionInfo* coll // In this case, they fail due to a reliance on ShiftItem(). @Sezz 2021.02.05 // Auto jump to monkey swing. - vaultResult = TestLaraMonkeyAutoJump(item, coll); - if (vaultResult.has_value() && g_GameFlow->HasMonkeyAutoJump()) + vaultResult = TestLaraAutoMonkeySwingJump(item, coll); + if (vaultResult.has_value() && g_Configuration.EnableAutoMonkeySwingJump) { vaultResult->TargetState = LS_AUTO_JUMP; if (!HasStateDispatch(item, vaultResult->TargetState)) diff --git a/TombEngine/Game/Lara/lara_tests.h b/TombEngine/Game/Lara/lara_tests.h index 1081a1d79..3777783a0 100644 --- a/TombEngine/Game/Lara/lara_tests.h +++ b/TombEngine/Game/Lara/lara_tests.h @@ -56,7 +56,7 @@ std::optional TestLaraVault3StepsToCrouch(ItemInfo* item, Colli std::optional TestLaraLedgeAutoJump(ItemInfo* item, CollisionInfo* coll); std::optional TestLaraLadderAutoJump(ItemInfo* item, CollisionInfo* coll); std::optional TestLaraLadderMount(ItemInfo* item, CollisionInfo* coll); -std::optional TestLaraMonkeyAutoJump(ItemInfo* item, CollisionInfo* coll); +std::optional TestLaraAutoMonkeySwingJump(ItemInfo* item, CollisionInfo* coll); std::optional TestLaraVault(ItemInfo* item, CollisionInfo* coll); bool TestAndDoLaraLadderClimb(ItemInfo* item, CollisionInfo* coll); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 2e2bf148d..baf36f0e6 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -886,7 +886,9 @@ namespace TEN::Gui Reverb, MusicVolume, SfxVolume, + Subtitles, + AutoMonkeySwingJump, AutoTargeting, TargetHighlighter, ToggleRumble, @@ -895,12 +897,12 @@ namespace TEN::Gui MouseSmoothing, Apply, - Cancel + Cancel, + + Count }; - static const auto numOtherSettingsOptions = 11; - - OptionCount = numOtherSettingsOptions; + OptionCount = (int)OtherSettingsOption::Count - 1; if (GuiIsDeselected()) { @@ -923,6 +925,11 @@ namespace TEN::Gui CurrentSettings.Configuration.EnableReverb = !CurrentSettings.Configuration.EnableReverb; break; + case OtherSettingsOption::AutoMonkeySwingJump: + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + CurrentSettings.Configuration.EnableAutoMonkeySwingJump = !CurrentSettings.Configuration.EnableAutoMonkeySwingJump; + break; + case OtherSettingsOption::Subtitles: SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableSubtitles = !CurrentSettings.Configuration.EnableSubtitles; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 8289f1453..4553f5630 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -231,42 +231,47 @@ namespace TEN::Renderer AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableSubtitles), PRINTSTRING_COLOR_WHITE, SF(titleOption == 3)); GetNextLinePosition(&y); + // Auto monkey swing jump + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_AUTO_MONKEY_SWING_JUMP), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 4)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAutoMonkeySwingJump), PRINTSTRING_COLOR_WHITE, SF(titleOption == 4)); + GetNextLinePosition(&y); + // Auto targeting - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_AUTOMATIC_TARGETING), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 4)); - AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAutoTargeting), PRINTSTRING_COLOR_WHITE, SF(titleOption == 4)); + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_AUTO_TARGETING), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 5)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAutoTargeting), PRINTSTRING_COLOR_WHITE, SF(titleOption == 5)); GetNextLinePosition(&y); // Target highlighter - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_TARGET_HIGHLIGHTER), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 5)); - AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableTargetHighlighter), PRINTSTRING_COLOR_WHITE, SF(titleOption == 5)); + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_TARGET_HIGHLIGHTER), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 6)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableTargetHighlighter), PRINTSTRING_COLOR_WHITE, SF(titleOption == 6)); GetNextLinePosition(&y); // Vibration - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_RUMBLE), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 6)); - AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableRumble), PRINTSTRING_COLOR_WHITE, SF(titleOption == 6)); + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_RUMBLE), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 7)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableRumble), PRINTSTRING_COLOR_WHITE, SF(titleOption == 7)); GetNextLinePosition(&y); // Thumbstick camera - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_THUMBSTICK_CAMERA), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 7)); - AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableThumbstickCamera), PRINTSTRING_COLOR_WHITE, SF(titleOption == 7)); + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_THUMBSTICK_CAMERA), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 8)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableThumbstickCamera), PRINTSTRING_COLOR_WHITE, SF(titleOption == 8)); GetNextBlockPosition(&y); // Mouse sensitivity - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MOUSE_SENSITIVITY), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 8)); - AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSensitivity).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 8)); + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MOUSE_SENSITIVITY), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 9)); + AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSensitivity).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 9)); GetNextLinePosition(&y); // Mouse smoothing - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MOUSE_SMOOTHING), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 9)); - AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSmoothing).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 9)); + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MOUSE_SMOOTHING), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 10)); + AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSmoothing).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 10)); GetNextBlockPosition(&y); // Apply - AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_APPLY), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 10)); + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_APPLY), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 11)); GetNextLinePosition(&y); // Cancel - AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_CANCEL), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 11)); + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_CANCEL), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 12)); break; case Menu::GeneralActions: diff --git a/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h b/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h index ac3382e1c..5c679f359 100644 --- a/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h +++ b/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h @@ -39,7 +39,7 @@ public: virtual bool HasCrawlExtended() const = 0; virtual bool HasCrouchRoll() const = 0; virtual bool HasCrawlspaceDive() const = 0; - virtual bool HasMonkeyAutoJump() const = 0; + virtual bool HasAutoMonkeySwingJump() const = 0; virtual bool HasSprintJump() const = 0; virtual bool HasAFKPose() const = 0; virtual bool HasOverhangClimb() const = 0; diff --git a/TombEngine/Scripting/Internal/LanguageScript.h b/TombEngine/Scripting/Internal/LanguageScript.h index a2c04feaf..5eb728917 100644 --- a/TombEngine/Scripting/Internal/LanguageScript.h +++ b/TombEngine/Scripting/Internal/LanguageScript.h @@ -80,7 +80,8 @@ #define STRING_SOUND "sound" #define STRING_ENABLE_SOUND "enable_sound" #define STRING_REVERB "reverb" -#define STRING_AUTOMATIC_TARGETING "automatic_targeting" +#define STRING_AUTO_MONKEY_SWING_JUMP "auto_monkey_swing_jump" +#define STRING_AUTO_TARGETING "auto_targeting" #define STRING_TARGET_HIGHLIGHTER "target_highlighter" #define STRING_RUMBLE "rumble" #define STRING_THUMBSTICK_CAMERA "thumbstick_camera" diff --git a/TombEngine/Scripting/Internal/LuaHandler.cpp b/TombEngine/Scripting/Internal/LuaHandler.cpp index acbb76621..1b3140f9a 100644 --- a/TombEngine/Scripting/Internal/LuaHandler.cpp +++ b/TombEngine/Scripting/Internal/LuaHandler.cpp @@ -4,18 +4,18 @@ #include #include "Scripting/Internal/LuaHandler.h" -LuaHandler::LuaHandler(sol::state* lua) : m_lua{ lua } +LuaHandler::LuaHandler(sol::state* lua) : _lua{ lua } { } void LuaHandler::ResetGlobals() { - auto mt = sol::table{ *m_lua, sol::create }; - m_globals = sol::table{ *m_lua, sol::create }; - mt.set(sol::meta_function::new_index, m_globals); - mt.set(sol::meta_function::index, m_globals); + auto mt = sol::table{ *_lua, sol::create }; + _globals = sol::table{ *_lua, sol::create }; + mt.set(sol::meta_function::new_index, _globals); + mt.set(sol::meta_function::index, _globals); - m_lua->set(sol::metatable_key, mt); + _lua->set(sol::metatable_key, mt); } void LuaHandler::ExecuteScript(const std::string& luaFilename, bool isOptional) @@ -23,7 +23,7 @@ void LuaHandler::ExecuteScript(const std::string& luaFilename, bool isOptional) if (isOptional && !std::filesystem::is_regular_file(luaFilename)) return; - auto result = m_lua->safe_script_file(luaFilename, sol::script_pass_on_error); + auto result = _lua->safe_script_file(luaFilename, sol::script_pass_on_error); if (!result.valid()) { sol::error error = result; @@ -33,7 +33,7 @@ void LuaHandler::ExecuteScript(const std::string& luaFilename, bool isOptional) void LuaHandler::ExecuteString(const std::string& command) { - auto result = m_lua->safe_script(command, sol::environment(m_lua->lua_state(), sol::create, m_lua->globals()), sol::script_pass_on_error); + auto result = _lua->safe_script(command, sol::environment(_lua->lua_state(), sol::create, _lua->globals()), sol::script_pass_on_error); if (!result.valid()) { sol::error error = result; diff --git a/TombEngine/Scripting/Internal/LuaHandler.h b/TombEngine/Scripting/Internal/LuaHandler.h index 050e93dac..53e59eaba 100644 --- a/TombEngine/Scripting/Internal/LuaHandler.h +++ b/TombEngine/Scripting/Internal/LuaHandler.h @@ -6,8 +6,8 @@ class LuaHandler { protected: - sol::state* m_lua; - sol::table m_globals; + sol::state* _lua; + sol::table _globals; public: LuaHandler(sol::state* lua); @@ -22,17 +22,17 @@ public: sol::state* GetState() { - return m_lua; + return _lua; }; template void MakeReadOnlyTable(sol::table parent, const std::string& tableName, const T& container) { // Put all data into metatable. auto metatable = tableName + "Meta"; - m_lua->set(metatable, sol::as_table(container)); + _lua->set(metatable, sol::as_table(container)); auto mtmt = tableName + "MetaMeta"; - auto mtmtTable = m_lua->create_named_table(mtmt); + auto mtmtTable = _lua->create_named_table(mtmt); // Make metatable's metatable's __index fail an assert to generate warning/error when trying to use missing variable. auto lam = [tableName](sol::table tab, std::string const& key) @@ -41,29 +41,29 @@ public: }; mtmtTable[sol::meta_method::index] = lam; - m_lua->safe_script("setmetatable(" + metatable + ", " + mtmt + ")"); + _lua->safe_script("setmetatable(" + metatable + ", " + mtmt + ")"); // Make metatable's __index refer to itself so that requests to main table will go through to metatable // (and thus container's members). - m_lua->safe_script(metatable + ".__index = " + metatable); + _lua->safe_script(metatable + ".__index = " + metatable); - m_lua->safe_script(metatable + ".__type = \"readonly\""); + _lua->safe_script(metatable + ".__type = \"readonly\""); // Don't allow table to have new elements put into it. - m_lua->safe_script(metatable + ".__newindex = function() error('" + tableName + " is read-only') end"); + _lua->safe_script(metatable + ".__newindex = function() error('" + tableName + " is read-only') end"); // Protect metatable. - m_lua->safe_script(metatable + ".__metatable = 'metatable is protected'"); + _lua->safe_script(metatable + ".__metatable = 'metatable is protected'"); - auto tab = m_lua->create_named_table(tableName); + auto tab = _lua->create_named_table(tableName); - m_lua->safe_script("setmetatable(" + tableName + ", " + metatable + ")"); + _lua->safe_script("setmetatable(" + tableName + ", " + metatable + ")"); // Point initial metatable variable away from its contents. This is just for cleanliness. parent.set(tableName, tab); - m_lua->safe_script(tableName + " = nil"); - m_lua->safe_script(metatable + " = nil"); - m_lua->safe_script(mtmt + " = nil"); + _lua->safe_script(tableName + " = nil"); + _lua->safe_script(metatable + " = nil"); + _lua->safe_script(mtmt + " = nil"); } }; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.cpp index 856472784..eb820fb21 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.cpp @@ -15,11 +15,12 @@ void Animations::Register(sol::table& parent) "crawlExtended", &Animations::HasCrawlExtended, "crouchRoll", &Animations::HasCrouchRoll, "crawlspaceSwandive", &Animations::HasCrawlspaceDive, - "monkeyAutoJump", &Animations::HasMonkeyAutoJump, "overhangClimb", &Animations::HasOverhangClimb, "slideExtended", &Animations::HasSlideExtended, "sprintJump", &Animations::HasSprintJump, "pose", &Animations::HasPose, - "ledgeJumps", &Animations::HasLedgeJumps - ); + "ledgeJumps", &Animations::HasLedgeJumps, + + // NOTE: Removed. Keep for now to maintain compatibility. -- Sezz 2024.06.06 + "monkeyAutoJump", & Animations::HasAutoMonkeySwingJump); } diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.h b/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.h index 763fc789c..781f62653 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/Animations/Animations.h @@ -13,12 +13,14 @@ struct Animations bool HasPose; // Crossed arms AFK posing. bool HasSlideExtended; // Extended slope sliding functionality (not ready yet). bool HasSprintJump; // Sprint jump. - bool HasMonkeyAutoJump; // Auto jump to monkey swing when pressing UP + ACTION. TODO: Make this a player setting. bool HasCrawlspaceDive; // Dive into crawlspaces. bool HasCrawlExtended; // Extended crawl moveset. bool HasCrouchRoll; // Crouch roll. bool HasOverhangClimb; // Overhang functionality. bool HasLedgeJumps; // Jump up or back from a ledge. + // NOTE: Removed. Keep for now to maintain compatibility. -- Sezz 2024.06.06 + bool HasAutoMonkeySwingJump; + static void Register(sol::table&); }; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp index 5240789f8..73dfe787c 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp @@ -30,7 +30,7 @@ ScriptInterfaceStringsHandler* g_GameStringsHandler; ScriptInterfaceFlowHandler* g_GameFlow; FlowHandler::FlowHandler(sol::state* lua, sol::table& parent) : - m_handler(lua) + _handler(lua) { /*** gameflow.lua. These functions are called in gameflow.lua, a file loosely equivalent to winroomedit's SCRIPT.DAT. @@ -38,7 +38,7 @@ They handle a game's 'metadata'; i.e., things such as level titles, loading scre ambient tracks. @section Flowlua */ - sol::table tableFlow{ m_handler.GetState()->lua_state(), sol::create }; + sol::table tableFlow{ _handler.GetState()->lua_state(), sol::create }; parent.set(ScriptReserved_Flow, tableFlow); /*** @@ -265,12 +265,12 @@ Specify which translations in the strings table correspond to which languages. Settings::Register(tableFlow); Fog::Register(tableFlow); - m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_WeatherType, WEATHER_TYPES); - m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_LaraType, PLAYER_TYPES); - m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_RotationAxis, ROTATION_AXES); - m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_ItemAction, ITEM_MENU_ACTIONS); - m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_ErrorMode, ERROR_MODES); - m_handler.MakeReadOnlyTable(tableFlow, ScriptReserved_GameStatus, GAME_STATUSES); + _handler.MakeReadOnlyTable(tableFlow, ScriptReserved_WeatherType, WEATHER_TYPES); + _handler.MakeReadOnlyTable(tableFlow, ScriptReserved_LaraType, PLAYER_TYPES); + _handler.MakeReadOnlyTable(tableFlow, ScriptReserved_RotationAxis, ROTATION_AXES); + _handler.MakeReadOnlyTable(tableFlow, ScriptReserved_ItemAction, ITEM_MENU_ACTIONS); + _handler.MakeReadOnlyTable(tableFlow, ScriptReserved_ErrorMode, ERROR_MODES); + _handler.MakeReadOnlyTable(tableFlow, ScriptReserved_GameStatus, GAME_STATUSES); } FlowHandler::~FlowHandler() @@ -281,35 +281,35 @@ FlowHandler::~FlowHandler() std::string FlowHandler::GetGameDir() { - return m_gameDir; + return _gameDir; } void FlowHandler::SetGameDir(const std::string& assetDir) { - m_gameDir = assetDir; + _gameDir = assetDir; } void FlowHandler::SetLanguageNames(sol::as_table_t>&& src) { - m_languageNames = std::move(src); + _languageNames = std::move(src); } void FlowHandler::SetStrings(sol::nested>>&& src) { - if (m_translationsMap.empty()) + if (_translationMap.empty()) { - m_translationsMap = std::move(src); + _translationMap = std::move(src); } else { for (auto& stringPair : src.value()) - m_translationsMap.insert_or_assign(stringPair.first, stringPair.second); + _translationMap.insert_or_assign(stringPair.first, stringPair.second); } } void FlowHandler::SetSettings(Settings const & src) { - m_settings = src; + _settings = src; } void FlowHandler::SetAnimations(Animations const& src) @@ -339,10 +339,10 @@ void FlowHandler::SetTotalSecretCount(int secretsNumber) void FlowHandler::LoadFlowScript() { - m_handler.ExecuteScript(m_gameDir + "Scripts/Gameflow.lua"); - m_handler.ExecuteScript(m_gameDir + "Scripts/SystemStrings.lua", true); - m_handler.ExecuteScript(m_gameDir + "Scripts/Strings.lua", true); - m_handler.ExecuteScript(m_gameDir + "Scripts/Settings.lua", true); + _handler.ExecuteScript(_gameDir + "Scripts/Gameflow.lua"); + _handler.ExecuteScript(_gameDir + "Scripts/SystemStrings.lua", true); + _handler.ExecuteScript(_gameDir + "Scripts/Strings.lua", true); + _handler.ExecuteScript(_gameDir + "Scripts/Settings.lua", true); SetScriptErrorMode(GetSettings()->ErrorMode); @@ -359,19 +359,19 @@ void FlowHandler::LoadFlowScript() char const * FlowHandler::GetString(const char* id) const { - if (!ScriptAssert(m_translationsMap.find(id) != m_translationsMap.end(), std::string{ "Couldn't find string " } + id)) + if (!ScriptAssert(_translationMap.find(id) != _translationMap.end(), std::string{ "Couldn't find string " } + id)) { return id; } else { - return m_translationsMap.at(std::string(id)).at(0).c_str(); + return _translationMap.at(std::string(id)).at(0).c_str(); } } Settings* FlowHandler::GetSettings() { - return &m_settings; + return &_settings; } Level* FlowHandler::GetLevel(int id) diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h index b6aa5a417..84b267d36 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h @@ -1,29 +1,27 @@ #pragma once #include +#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" +#include "Scripting/Include/ScriptInterfaceGame.h" #include "Scripting/Internal/LanguageScript.h" #include "Scripting/Internal/LuaHandler.h" -#include "Scripting/Internal/TEN/Logic/LogicHandler.h" #include "Scripting/Internal/TEN/Color/Color.h" +#include "Scripting/Internal/TEN/Logic/LogicHandler.h" +#include "Scripting/Internal/TEN/Flow/Animations/Animations.h" #include "Scripting/Internal/TEN/Flow/Level/FlowLevel.h" #include "Scripting/Internal/TEN/Flow/Settings/Settings.h" -#include "Scripting/Internal/TEN/Flow/Animations/Animations.h" -#include "Scripting/Include/ScriptInterfaceGame.h" -#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" class FlowHandler : public ScriptInterfaceFlowHandler { private: - Settings m_settings; + LuaHandler _handler; + Settings _settings = {}; + std::string _gameDir = {}; - std::unordered_map> m_translationsMap; - std::vector m_languageNames; + std::map _moveableMap = {}; - std::map m_itemsMap; - - std::string m_gameDir; - - LuaHandler m_handler; + std::unordered_map> _translationMap = {}; + std::vector _languageNames = {}; void PrepareInventoryObjects(); @@ -91,12 +89,13 @@ public: bool HasCrawlExtended() const override { return Anims.HasCrawlExtended; } bool HasCrouchRoll() const override { return Anims.HasCrouchRoll; } bool HasCrawlspaceDive() const override { return Anims.HasCrawlspaceDive; } - bool HasMonkeyAutoJump() const override { return Anims.HasMonkeyAutoJump; } bool HasAFKPose() const override { return Anims.HasPose; } bool HasOverhangClimb() const override { return Anims.HasOverhangClimb; } bool HasSlideExtended() const override { return Anims.HasSlideExtended; } bool HasSprintJump() const override { return Anims.HasSprintJump; } bool HasLedgeJumps() const override { return Anims.HasLedgeJumps; } bool DoFlow() override; -}; + // NOTE: Removed. Keep for now to maintain compatibility. -- Sezz 2024.06.06 + bool HasAutoMonkeySwingJump() const override { return Anims.HasAutoMonkeySwingJump; } +}; diff --git a/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp b/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp index 2f34efd13..e90ea50b6 100644 --- a/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Strings/StringsHandler.cpp @@ -16,7 +16,7 @@ Display strings. StringsHandler::StringsHandler(sol::state* lua, sol::table& parent) : LuaHandler(lua) { - auto table = sol::table(m_lua->lua_state(), sol::create); + auto table = sol::table(_lua->lua_state(), sol::create); parent.set(ScriptReserved_Strings, table); /*** diff --git a/TombEngine/Specific/configuration.cpp b/TombEngine/Specific/configuration.cpp index 6e0b39d26..8d479c44f 100644 --- a/TombEngine/Specific/configuration.cpp +++ b/TombEngine/Specific/configuration.cpp @@ -230,6 +230,7 @@ bool SaveConfiguration() // Set Gameplay keys. if (SetBoolRegKey(gameplayKey, REGKEY_ENABLE_SUBTITLES, g_Configuration.EnableSubtitles) != ERROR_SUCCESS || + SetBoolRegKey(gameplayKey, REGKEY_ENABLE_AUTO_MONKEY_JUMP, g_Configuration.EnableAutoMonkeySwingJump) != ERROR_SUCCESS || SetBoolRegKey(gameplayKey, REGKEY_ENABLE_AUTO_TARGETING, g_Configuration.EnableAutoTargeting) != ERROR_SUCCESS || SetBoolRegKey(gameplayKey, REGKEY_ENABLE_TARGET_HIGHLIGHTER, g_Configuration.EnableTargetHighlighter) != ERROR_SUCCESS || SetBoolRegKey(gameplayKey, REGKEY_ENABLE_RUMBLE, g_Configuration.EnableRumble) != ERROR_SUCCESS || @@ -322,6 +323,7 @@ void InitDefaultConfiguration() g_Configuration.SfxVolume = 100; g_Configuration.EnableSubtitles = true; + g_Configuration.EnableAutoMonkeySwingJump = false; g_Configuration.EnableAutoTargeting = true; g_Configuration.EnableTargetHighlighter = true; g_Configuration.EnableRumble = true; @@ -419,6 +421,7 @@ bool LoadConfiguration() return false; } + bool enableAutoMonkeySwingJump = false; bool enableSubtitles = true; bool enableAutoTargeting = true; bool enableTargetHighlighter = true; @@ -426,7 +429,8 @@ bool LoadConfiguration() bool enableThumbstickCamera = true; // Load Gameplay keys. - if (GetBoolRegKey(gameplayKey, REGKEY_ENABLE_SUBTITLES, &enableSubtitles, true) != ERROR_SUCCESS || + if (GetBoolRegKey(gameplayKey, REGKEY_ENABLE_AUTO_MONKEY_JUMP, &enableAutoMonkeySwingJump, true) != ERROR_SUCCESS || + GetBoolRegKey(gameplayKey, REGKEY_ENABLE_SUBTITLES, &enableSubtitles, true) != ERROR_SUCCESS || GetBoolRegKey(gameplayKey, REGKEY_ENABLE_AUTO_TARGETING, &enableAutoTargeting, true) != ERROR_SUCCESS || GetBoolRegKey(gameplayKey, REGKEY_ENABLE_TARGET_HIGHLIGHTER, &enableTargetHighlighter, true) != ERROR_SUCCESS || GetBoolRegKey(gameplayKey, REGKEY_ENABLE_RUMBLE, &enableRumble, true) != ERROR_SUCCESS || @@ -507,11 +511,12 @@ bool LoadConfiguration() g_Configuration.SfxVolume = sfxVolume; g_Configuration.SoundDevice = soundDevice; + g_Configuration.EnableSubtitles = enableSubtitles; + g_Configuration.EnableAutoMonkeySwingJump = enableAutoMonkeySwingJump; g_Configuration.EnableAutoTargeting = enableAutoTargeting; g_Configuration.EnableTargetHighlighter = enableTargetHighlighter; g_Configuration.EnableRumble = enableRumble; g_Configuration.EnableThumbstickCamera = enableThumbstickCamera; - g_Configuration.EnableSubtitles = enableSubtitles; g_Configuration.MouseSensitivity = mouseSensitivity; g_Configuration.MouseSmoothing = mouseSmoothing; diff --git a/TombEngine/Specific/configuration.h b/TombEngine/Specific/configuration.h index cf10f970c..ab3694e01 100644 --- a/TombEngine/Specific/configuration.h +++ b/TombEngine/Specific/configuration.h @@ -33,6 +33,7 @@ constexpr auto REGKEY_SFX_VOLUME = "SfxVolume"; // Gameplay keys constexpr auto REGKEY_ENABLE_SUBTITLES = "EnableSubtitles"; +constexpr auto REGKEY_ENABLE_AUTO_MONKEY_JUMP = "EnableAutoMonkeySwingJump"; constexpr auto REGKEY_ENABLE_AUTO_TARGETING = "EnableAutoTargeting"; constexpr auto REGKEY_ENABLE_TARGET_HIGHLIGHTER = "EnableTargetHighlighter"; constexpr auto REGKEY_ENABLE_RUMBLE = "EnableRumble"; @@ -69,6 +70,7 @@ struct GameConfiguration // Gameplay bool EnableSubtitles = false; + bool EnableAutoMonkeySwingJump = false; bool EnableAutoTargeting = false; bool EnableTargetHighlighter = false; bool EnableRumble = false; From 22176d05f5f8b33a9f9ab6a03bf291b6f099d6cd Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 6 Jun 2024 11:46:43 +1000 Subject: [PATCH 208/410] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8ffd5f17..3bb3f8a02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. +* Removed anims.monkeyAutoJump. It is now a player menu configuration. ## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21 From a34bfaa89b6d85998c3867e3a36e949e29ce80c5 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 11 Jun 2024 12:07:48 +1000 Subject: [PATCH 209/410] Fix project build paths again --- TombEngine/TombEngine.vcxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 94bbf469b..c4de82af7 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -235,6 +235,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" /Zc:__cplusplus /experimental:external /external:anglebrackets 4018;4244;4996;%(DisableSpecificWarnings) true + $(IntDir)/%(RelativeDir)/ Console @@ -300,6 +301,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" /Zc:__cplusplus /experimental:external /external:anglebrackets 4018;4244;4996;%(DisableSpecificWarnings) true + $(IntDir)/%(RelativeDir)/ Console From 87b5e8390140c5b881613a1ed814525a705b6612 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 19 Jun 2024 15:03:33 +1000 Subject: [PATCH 210/410] Remove unnecessary framework define; add newlines between label comments to avoid inappropriate tooltips --- TombEngine/Game/Hud/PickupSummary.cpp | 5 ++++- TombEngine/Game/Hud/PickupSummary.h | 4 ++++ TombEngine/Game/Hud/Speedometer.h | 3 +++ TombEngine/Game/Hud/StatusBars.h | 4 ++++ TombEngine/Game/Hud/TargetHighlighter.h | 9 +++++++++ TombEngine/Game/Lara/lara_jump.cpp | 20 ++++++++++---------- TombEngine/Game/Lara/lara_tests.cpp | 4 ++-- TombEngine/framework.h | 6 ------ 8 files changed, 36 insertions(+), 19 deletions(-) diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index bc816aafc..8bd2fc4fd 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -213,7 +213,10 @@ namespace TEN::Hud _displayPickups.erase( std::remove_if( _displayPickups.begin(), _displayPickups.end(), - [](const DisplayPickup& pickup) { return ((pickup.Life <= 0.0f) && pickup.IsOffscreen()); }), + [](const DisplayPickup& pickup) + { + return ((pickup.Life <= 0.0f) && pickup.IsOffscreen()); + }), _displayPickups.end()); } diff --git a/TombEngine/Game/Hud/PickupSummary.h b/TombEngine/Game/Hud/PickupSummary.h index a1c0b012f..fc56e09f1 100644 --- a/TombEngine/Game/Hud/PickupSummary.h +++ b/TombEngine/Game/Hud/PickupSummary.h @@ -33,14 +33,17 @@ namespace TEN::Hud { private: // Constants + static constexpr auto DISPLAY_PICKUP_COUNT_MAX = 64; static constexpr auto DISPLAY_PICKUP_COUNT_ARG_DEFAULT = 1; // Members + std::vector _displayPickups = {}; public: // Utilities + void AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector2& origin, unsigned int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT); void AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector3& pos, unsigned int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT); @@ -50,6 +53,7 @@ namespace TEN::Hud private: // Helpers + std::vector GetStackPositions() const; DisplayPickup& GetNewDisplayPickup(); void ClearInactiveDisplayPickups(); diff --git a/TombEngine/Game/Hud/Speedometer.h b/TombEngine/Game/Hud/Speedometer.h index 164d652a2..8795311d0 100644 --- a/TombEngine/Game/Hud/Speedometer.h +++ b/TombEngine/Game/Hud/Speedometer.h @@ -6,9 +6,11 @@ namespace TEN::Hud { private: // Constants + static constexpr auto LIFE_MAX = 0.75f; // Members + bool _hasValueUpdated = false; float _value = 0.0f; @@ -18,6 +20,7 @@ namespace TEN::Hud public: // Utilities + void UpdateValue(float value); void Update(); diff --git a/TombEngine/Game/Hud/StatusBars.h b/TombEngine/Game/Hud/StatusBars.h index 8ba931cb2..783e4648f 100644 --- a/TombEngine/Game/Hud/StatusBars.h +++ b/TombEngine/Game/Hud/StatusBars.h @@ -26,6 +26,7 @@ namespace TEN::Hud { private: // Members + StatusBar _airBar = {}; StatusBar _exposureBar = {}; StatusBar _healthBar = {}; @@ -35,6 +36,7 @@ namespace TEN::Hud public: // Utilities + void Initialize(const ItemInfo& item); void Update(const ItemInfo& item); void Draw(const ItemInfo& item) const; @@ -42,12 +44,14 @@ namespace TEN::Hud private: // Update helpers + void UpdateAirBar(const ItemInfo& item); void UpdateExposureBar(const ItemInfo& item); void UpdateHealthBar(const ItemInfo& item); void UpdateStaminaBar(const ItemInfo& item); // Draw helpers + void DrawStatusBar(float value, float criticalValue, const RendererHudBar& rHudBar, GAME_OBJECT_ID textureID, int frame, bool isPoisoned) const; void DrawAirBar() const; void DrawExposureBar() const; diff --git a/TombEngine/Game/Hud/TargetHighlighter.h b/TombEngine/Game/Hud/TargetHighlighter.h index b62c5b3df..4059d1f5b 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.h +++ b/TombEngine/Game/Hud/TargetHighlighter.h @@ -15,11 +15,13 @@ namespace TEN::Hud public: // Constants + static constexpr auto COLOR_RED = Color(1.0f, 0.2f, 0.2f); static constexpr auto COLOR_GRAY = Color(0.7f, 0.7f, 0.7f, 0.7f); static constexpr auto SEGMENT_COUNT = 4; // Members + bool IsActive = false; bool IsPrimary = false; @@ -35,15 +37,18 @@ namespace TEN::Hud std::array Segments = {}; // Getters + float GetScale(float cameraDist) const; float GetRadius() const; Vector2 GetPositionOffset(short orientOffset) const; // Setters + void SetPrimary(); void SetPeripheral(); // Utilities + void Update(const Vector3& targetPos, bool isActive, bool doPulse); void Draw() const; }; @@ -52,19 +57,23 @@ namespace TEN::Hud { private: // Members + std::unordered_map _crosshairs = {}; // Key = item number. public: // Utilities + void Update(const ItemInfo& playerItem); void Draw() const; void Clear(); private: // Update helpers + void Update(const std::vector& itemNumbers); // Object helpers + CrosshairData& GetNewCrosshair(int itemNumber); void AddCrosshair(int itemNumber, const Vector3& targetPos); void ClearInactiveCrosshairs(); diff --git a/TombEngine/Game/Lara/lara_jump.cpp b/TombEngine/Game/Lara/lara_jump.cpp index b84506aac..5b940035f 100644 --- a/TombEngine/Game/Lara/lara_jump.cpp +++ b/TombEngine/Game/Lara/lara_jump.cpp @@ -64,7 +64,7 @@ void lara_as_jump_forward(ItemInfo* item, CollisionInfo* coll) { DoLaraFallDamage(item); - if (item->HitPoints <= 0) USE_FEATURE_IF_CPP20([[unlikely]]) + if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; else if (IsHeld(In::Forward) && !IsHeld(In::Walk) && player.Control.WaterStatus != WaterStatus::Wade) @@ -146,7 +146,7 @@ void lara_as_freefall(ItemInfo* item, CollisionInfo* coll) if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -202,7 +202,7 @@ void lara_as_reach(ItemInfo* item, CollisionInfo* coll) if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -414,7 +414,7 @@ void lara_as_jump_back(ItemInfo* item, CollisionInfo* coll) if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -468,7 +468,7 @@ void lara_as_jump_right(ItemInfo* item, CollisionInfo* coll) if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -523,7 +523,7 @@ void lara_as_jump_left(ItemInfo* item, CollisionInfo* coll) if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -576,7 +576,7 @@ void lara_as_jump_up(ItemInfo* item, CollisionInfo* coll) { if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -673,7 +673,7 @@ void lara_as_fall_back(ItemInfo* item, CollisionInfo* coll) if (item->HitPoints <= 0) item->Animation.TargetState = LS_DEATH; - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -749,7 +749,7 @@ void lara_as_swan_dive(ItemInfo* item, CollisionInfo* coll) item->Animation.TargetState = LS_CROUCH_IDLE; TranslateItem(item, coll->Setup.ForwardAngle, CLICK(0.5f)); // HACK: Move forward to avoid standing up or falling out on an edge. } - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); @@ -823,7 +823,7 @@ void lara_as_freefall_dive(ItemInfo* item, CollisionInfo* coll) item->Animation.TargetState = LS_DEATH; Rumble(0.5f, 0.2f); } - else USE_FEATURE_IF_CPP20([[likely]]) + else item->Animation.TargetState = LS_IDLE; SetLaraLand(item, coll); diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 97cd5d730..ee7b8d809 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -1710,7 +1710,7 @@ CrawlVaultTestResult TestLaraCrawlVault(ItemInfo* item, CollisionInfo* coll) { if (IsHeld(In::Crouch) && TestLaraCrawlDownStep(item, coll).Success) crawlVaultResult.TargetState = LS_CRAWL_STEP_DOWN; - else USE_FEATURE_IF_CPP20([[likely]]) + else crawlVaultResult.TargetState = LS_CRAWL_EXIT_STEP_DOWN; crawlVaultResult.Success = HasStateDispatch(item, crawlVaultResult.TargetState); @@ -1723,7 +1723,7 @@ CrawlVaultTestResult TestLaraCrawlVault(ItemInfo* item, CollisionInfo* coll) { if (IsHeld(In::Walk)) crawlVaultResult.TargetState = LS_CRAWL_EXIT_FLIP; - else USE_FEATURE_IF_CPP20([[likely]]) + else crawlVaultResult.TargetState = LS_CRAWL_EXIT_JUMP; crawlVaultResult.Success = HasStateDispatch(item, crawlVaultResult.TargetState); diff --git a/TombEngine/framework.h b/TombEngine/framework.h index 9f5b27cb4..133da0a80 100644 --- a/TombEngine/framework.h +++ b/TombEngine/framework.h @@ -23,10 +23,4 @@ using namespace DirectX; using namespace DirectX::SimpleMath; -#if __cplusplus >= 202002L -#define USE_FEATURE_IF_CPP20(x) x -#else -#define USE_FEATURE_IF_CPP20(x) -#endif - constexpr auto NO_VALUE = -1; From 49b014bc88b3636925ee23528f2b986600fc33be Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 19 Jun 2024 15:05:03 +1000 Subject: [PATCH 211/410] Avoid inappropriate tooltips --- TombEngine/Math/Constants.h | 2 ++ TombEngine/Math/Geometry.h | 8 ++++++++ TombEngine/Math/Random.h | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/TombEngine/Math/Constants.h b/TombEngine/Math/Constants.h index 2e2a1e26d..7147986d0 100644 --- a/TombEngine/Math/Constants.h +++ b/TombEngine/Math/Constants.h @@ -4,6 +4,7 @@ //namespace TEN::Math //{ // Math constants + constexpr auto PI = 3.14159265358979323846264338327950288419716939937510f; constexpr auto PI_MUL_2 = PI * 2; constexpr auto PI_DIV_2 = PI / 2; @@ -16,6 +17,7 @@ constexpr auto CUBE = [](auto x) { return (x * x * x); }; // World constants + constexpr auto BLOCK_UNIT = 1024; constexpr auto NO_HEIGHT = INT_MIN + UCHAR_MAX; constexpr auto MAX_HEIGHT = INT_MIN + 1; // NOTE: +1 prevents issues with sign change. diff --git a/TombEngine/Math/Geometry.h b/TombEngine/Math/Geometry.h index 25a00ed9a..f47482a01 100644 --- a/TombEngine/Math/Geometry.h +++ b/TombEngine/Math/Geometry.h @@ -8,6 +8,7 @@ class Vector3i; namespace TEN::Math::Geometry { // Integer-based point translation + Vector3i TranslatePoint(const Vector3i& point, short headingAngle, float forward, float down = 0.0f, float right = 0.0f, const Vector3& axis = Vector3::UnitY); Vector3i TranslatePoint(const Vector3i& point, short headingAngle, const Vector3i& relOffset, const Vector3& axis = Vector3::UnitY); Vector3i TranslatePoint(const Vector3i& point, const EulerAngles& orient, const Vector3i& relOffset); @@ -16,6 +17,7 @@ namespace TEN::Math::Geometry Vector3i TranslatePoint(const Vector3i& point, const Vector3& dir, float dist); // Float-based point translation + Vector3 TranslatePoint(const Vector3& point, short headingAngle, float forward, float down = 0.0f, float right = 0.0f, const Vector3& axis = Vector3::UnitY); Vector3 TranslatePoint(const Vector3& point, short headingAngle, const Vector3& relOffset, const Vector3& axis = Vector3::UnitY); Vector3 TranslatePoint(const Vector3& point, const EulerAngles& orient, const Vector3& relOffset); @@ -24,15 +26,18 @@ namespace TEN::Math::Geometry Vector3 TranslatePoint(const Vector3& point, const Vector3& dir, float dist); // Rotation + Vector3 RotatePoint(const Vector3& point, const EulerAngles& rot); Vector3 RotatePoint(const Vector3& point, const AxisAngle& rot); // Angle getters + short GetShortestAngle(short fromAngle, short toAngle); short GetSurfaceSlopeAngle(const Vector3& normal, const Vector3& axis = Vector3::UnitY); short GetSurfaceAspectAngle(const Vector3& normal, const Vector3& axis = Vector3::UnitY); // Misc. getters + float GetDistanceToLine(const Vector3& origin, const Vector3& linePoint0, const Vector3& linePoint1); Vector3 GetClosestPointOnLine(const Vector3& origin, const Vector3& linePoint0, const Vector3& linePoint1); Vector3 GetClosestPointOnLinePerp(const Vector3& origin, const Vector3& linePoint0, const Vector3& linePoint1, const Vector3& axis = Vector3::UnitY); @@ -41,10 +46,12 @@ namespace TEN::Math::Geometry BoundingBox GetBoundingBox(const std::vector& points); // Converters + Quaternion ConvertDirectionToQuat(const Vector3& dir); Vector3 ConvertQuatToDirection(const Quaternion& quat); // Point relation inquirers + bool IsPointInFront(const Pose& pose, const Vector3& target); bool IsPointInFront(const Vector3& origin, const Vector3& target, const EulerAngles& orient); bool IsPointInFront(const Vector3& origin, const Vector3& target, const Vector3& refPoint); @@ -56,5 +63,6 @@ namespace TEN::Math::Geometry bool IsPointInSphere(const Vector3& point, const BoundingSphere& sphere); // Intersection inquirers + bool CircleIntersects(const Vector3& circle0, const Vector3& circle1); } diff --git a/TombEngine/Math/Random.h b/TombEngine/Math/Random.h index fd7508d35..97b783993 100644 --- a/TombEngine/Math/Random.h +++ b/TombEngine/Math/Random.h @@ -5,16 +5,19 @@ class EulerAngles; namespace TEN::Math::Random { // Value generation + int GenerateInt(int low = 0, int high = SHRT_MAX); float GenerateFloat(float low = 0.0f, float high = 1.0f); short GenerateAngle(short low = SHRT_MIN, short high = SHRT_MAX); // 2D geometric generation + Vector2 GenerateDirection2D(); Vector2 GeneratePoint2DInSquare(const Vector2& pos, short orient, float apothem); Vector2 GeneratePoint2DInCircle(const Vector2& pos, float radius); // 3D geometric generation + Vector3 GenerateDirection(); Vector3 GenerateDirectionInCone(const Vector3& dir, float semiangleInDeg); Vector3 GeneratePointInBox(const BoundingOrientedBox& box); @@ -22,5 +25,7 @@ namespace TEN::Math::Random Vector3 GeneratePointOnSphere(const BoundingSphere& sphere); Vector3 GeneratePointInSpheroid(const Vector3& center, const EulerAngles& orient, const Vector3& semiMajorAxis); + // Probability + bool TestProbability(float prob); } From 2e6db4e01ce871c47010c186c78c5a13b7e6128b Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 19 Jun 2024 15:29:46 +1000 Subject: [PATCH 212/410] Add TEN::Debug namespace --- TombEngine/Game/Hud/PickupSummary.cpp | 2 +- TombEngine/Game/Lara/lara_struct.h | 2 +- TombEngine/Game/animation.cpp | 2 +- TombEngine/Game/debug/debug.cpp | 103 +++++++++--------- TombEngine/Game/debug/debug.h | 63 ++++++----- TombEngine/Game/effects/Streamer.cpp | 8 +- TombEngine/Game/effects/effects.h | 2 +- TombEngine/Game/savegame.cpp | 4 +- TombEngine/Math/Solvers.cpp | 2 +- TombEngine/Objects/TR5/Trap/LaserBarrier.cpp | 2 +- .../Internal/TEN/Flow/Level/FlowLevel.cpp | 6 +- TombEngine/TombEngine.vcxproj | 4 +- TombEngine/framework.h | 2 + 13 files changed, 106 insertions(+), 96 deletions(-) diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index 8bd2fc4fd..f38c0f6b6 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -196,7 +196,7 @@ namespace TEN::Hud DisplayPickup& PickupSummaryController::GetNewDisplayPickup() { - assertion(_displayPickups.size() <= DISPLAY_PICKUP_COUNT_MAX, "Display pickup overflow."); + TENAssert(_displayPickups.size() <= DISPLAY_PICKUP_COUNT_MAX, "Display pickup overflow."); // Add and return new display pickup. if (_displayPickups.size() < DISPLAY_PICKUP_COUNT_MAX) diff --git a/TombEngine/Game/Lara/lara_struct.h b/TombEngine/Game/Lara/lara_struct.h index fa21dd987..1f1758096 100644 --- a/TombEngine/Game/Lara/lara_struct.h +++ b/TombEngine/Game/Lara/lara_struct.h @@ -1025,7 +1025,7 @@ public: Ammo& operator --() { - assertion(Count > 0, "Ammo count is already 0."); + TENAssert(Count > 0, "Ammo count is already 0."); --Count; return *this; } diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 3003f6292..d4f5cd6d1 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -506,7 +506,7 @@ const AnimFrame* GetFrame(GAME_OBJECT_ID objectID, int animNumber, int frameNumb const auto& object = Objects[objectID]; int animIndex = object.animIndex + animNumber; - assertion(animIndex < g_Level.Anims.size(), "GetFrame() attempted to access missing animation."); + TENAssert(animIndex < g_Level.Anims.size(), "GetFrame() attempted to access missing animation."); const auto& anim = GetAnimData(object, animNumber); diff --git a/TombEngine/Game/debug/debug.cpp b/TombEngine/Game/debug/debug.cpp index a5102b454..a5cba1b3f 100644 --- a/TombEngine/Game/debug/debug.cpp +++ b/TombEngine/Game/debug/debug.cpp @@ -5,57 +5,62 @@ #include #include -void InitTENLog(const std::string& logDirContainingDir) +namespace TEN::Debug { - // "true" means create new log file each time game is run. - auto logPath = logDirContainingDir + "Logs/TENLog.txt"; - auto fileSink = std::make_shared(logPath, true); - - std::shared_ptr logger; - - // Set file and console log targets. - auto consoleSink = std::make_shared(); - logger = std::make_shared(std::string{ "multi_sink" }, spdlog::sinks_init_list{ fileSink, consoleSink }); - - spdlog::initialize_logger(logger); - logger->set_level(spdlog::level::info); - logger->flush_on(spdlog::level::info); - logger->set_pattern("[%Y-%b-%d %T] [%^%l%$] %v"); -} - -void TENLog(std::string_view str, LogLevel level, LogConfig config, bool allowSpam) -{ - static std::string lastString = {}; - - if (lastString == str && !allowSpam) - return; - - if constexpr (!DebugBuild) + void InitTENLog(const std::string& logDirContainingDir) { - if (LogConfig::Debug == config) + // "true" means create new log file each time game is run. + auto logPath = logDirContainingDir + "Logs/TENLog.txt"; + auto fileSink = std::make_shared(logPath, true); + + auto logger = std::shared_ptr(); + + // Set file and console log targets. + auto consoleSink = std::make_shared(); + logger = std::make_shared(std::string("multi_sink"), spdlog::sinks_init_list{ fileSink, consoleSink }); + + spdlog::initialize_logger(logger); + logger->set_level(spdlog::level::info); + logger->flush_on(spdlog::level::info); + logger->set_pattern("[%Y-%b-%d %T] [%^%l%$] %v"); + } + + void ShutdownTENLog() + { + spdlog::shutdown(); + } + + void TENLog(const std::string_view& string, LogLevel level, LogConfig config, bool allowSpam) + { + static auto prevString = std::string(); + + if (prevString == string && !allowSpam) return; + + if constexpr (!DebugBuild) + { + if (config == LogConfig::Debug) + return; + } + + auto logger = spdlog::get("multi_sink"); + switch (level) + { + case LogLevel::Error: + logger->error(string); + break; + + case LogLevel::Warning: + logger->warn(string); + break; + + case LogLevel::Info: + logger->info(string); + break; + } + + logger->flush(); + + prevString = std::string(string); } - - auto logger = spdlog::get("multi_sink"); - switch (level) - { - case LogLevel::Error: - logger->error(str); - break; - case LogLevel::Warning: - logger->warn(str); - break; - case LogLevel::Info: - logger->info(str); - break; - } - - logger->flush(); - - lastString = std::string(str); -} - -void ShutdownTENLog() -{ - spdlog::shutdown(); } diff --git a/TombEngine/Game/debug/debug.h b/TombEngine/Game/debug/debug.h index c668d40e2..561a2d28a 100644 --- a/TombEngine/Game/debug/debug.h +++ b/TombEngine/Game/debug/debug.h @@ -9,37 +9,40 @@ constexpr bool DebugBuild = false; #include #include -enum class LogLevel +namespace TEN::Debug { - Error, - Warning, - Info -}; - -enum class LogConfig -{ - Debug, - All -}; - -void TENLog(std::string_view str, LogLevel level = LogLevel::Info, LogConfig config = LogConfig::All, bool allowSpam = false); -void ShutdownTENLog(); -void InitTENLog(const std::string& logDirContainingDir); - -class TENScriptException : public std::runtime_error -{ -public: - using std::runtime_error::runtime_error; -}; - -inline void assertion(const bool& expr, const char* msg) -{ - if constexpr (DebugBuild) + enum class LogLevel { - if (!expr) + Error, + Warning, + Info + }; + + enum class LogConfig + { + Debug, + All + }; + + class TENScriptException : public std::runtime_error + { + public: + using std::runtime_error::runtime_error; + }; + + void InitTENLog(const std::string& logDirContainingDir); + void ShutdownTENLog(); + void TENLog(const std::string_view& string, LogLevel level = LogLevel::Info, LogConfig config = LogConfig::All, bool allowSpam = false); + + inline void TENAssert(const bool& cond, const char* msg) + { + if constexpr (DebugBuild) { - TENLog(msg, LogLevel::Error); - throw std::runtime_error(msg); + if (!cond) + { + TENLog(msg, LogLevel::Error); + throw std::runtime_error(msg); + } } - } -}; + }; +} diff --git a/TombEngine/Game/effects/Streamer.cpp b/TombEngine/Game/effects/Streamer.cpp index ec7bad158..ae9f8ed55 100644 --- a/TombEngine/Game/effects/Streamer.cpp +++ b/TombEngine/Game/effects/Streamer.cpp @@ -99,7 +99,7 @@ namespace TEN::Effects::Streamer Streamer::StreamerSegment& Streamer::GetNewSegment() { - assertion(Segments.size() <= SEGMENT_COUNT_MAX, "Streamer segment count overflow."); + TENAssert(Segments.size() <= SEGMENT_COUNT_MAX, "Streamer segment count overflow."); // Clear oldest segment if vector is full. if (Segments.size() == SEGMENT_COUNT_MAX) @@ -112,7 +112,7 @@ namespace TEN::Effects::Streamer void StreamerModule::AddStreamer(int tag, const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, float width, float life, float vel, float scaleRate, short rot, int flags) { - assertion(Pools.size() <= POOL_COUNT_MAX, "Streamer pool count overflow."); + TENAssert(Pools.size() <= POOL_COUNT_MAX, "Streamer pool count overflow."); // Return early if pool map is full and element with tag key doesn't already exist. if (Pools.size() == POOL_COUNT_MAX && !Pools.count(tag)) @@ -150,7 +150,7 @@ namespace TEN::Effects::Streamer Streamer& StreamerModule::GetStreamer(int tag) { auto& pool = GetPool(tag); - assertion(pool.size() <= STREAMER_COUNT_MAX, "Streamer pool size overflow."); + TENAssert(pool.size() <= STREAMER_COUNT_MAX, "Streamer pool size overflow."); // Return most recent streamer iteration if it exists and is unbroken. if (!pool.empty()) @@ -197,7 +197,7 @@ namespace TEN::Effects::Streamer void StreamerEffectController::Spawn(int itemNumber, int tag, const Vector3& pos, const Vector3& direction, short orient, const Vector4& color, float width, float life, float vel, float scaleRate, short rot, int flags) { - assertion(Modules.size() <= MODULE_COUNT_MAX, "Streamer module count overflow."); + TENAssert(Modules.size() <= MODULE_COUNT_MAX, "Streamer module count overflow."); // Return early if module map is full and element with itemNumber key doesn't already exist. if (Modules.size() == MODULE_COUNT_MAX && !Modules.count(itemNumber)) diff --git a/TombEngine/Game/effects/effects.h b/TombEngine/Game/effects/effects.h index 2b77640a0..0613feaf1 100644 --- a/TombEngine/Game/effects/effects.h +++ b/TombEngine/Game/effects/effects.h @@ -211,7 +211,7 @@ extern FX_INFO EffectList[NUM_EFFECTS]; template TEffect& GetNewEffect(std::vector& effects, unsigned int countMax) { - assertion(effects.size() <= countMax, "Too many particle effects."); + TENAssert(effects.size() <= countMax, "Too many particle effects."); // Add and return new effect. if (effects.size() < countMax) diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 98100796f..9c821dd10 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -2010,7 +2010,7 @@ static void ParseEffects(const Save::SaveGame* s) // Restore soundtracks. for (int i = 0; i < s->soundtracks()->size(); i++) { - assertion(i < (int)SoundTrackType::Count, "Soundtrack type count was changed"); + TENAssert(i < (int)SoundTrackType::Count, "Soundtrack type count was changed"); auto track = s->soundtracks()->Get(i); PlaySoundTrack(track->name()->str(), (SoundTrackType)i, track->position()); @@ -2228,7 +2228,7 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) // Restore action queue. for (int i = 0; i < s->action_queue()->size(); i++) { - assertion(i < ActionQueue.size(), "Action queue size was changed"); + TENAssert(i < ActionQueue.size(), "Action queue size was changed"); ActionQueue[i] = (QueueState)s->action_queue()->Get(i); } diff --git a/TombEngine/Math/Solvers.cpp b/TombEngine/Math/Solvers.cpp index 017b70d15..0b6b3da43 100644 --- a/TombEngine/Math/Solvers.cpp +++ b/TombEngine/Math/Solvers.cpp @@ -56,7 +56,7 @@ namespace TEN::Math::Solvers float a = flipXY ? (scaledTarget.y - origin.y) : (scaledTarget.x - origin.x); float b = flipXY ? (scaledTarget.x - origin.x) : (scaledTarget.y - origin.y); - assertion(abs(a) >= EPSILON, "SolveIK2D() failed."); + TENAssert(abs(a) >= EPSILON, "SolveIK2D() failed."); float m = ((SQUARE(length0) - SQUARE(length1)) + (SQUARE(a) + SQUARE(b))) / (2.0f * a); float n = b / a; diff --git a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp index cf44a2b01..cece3c862 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp @@ -60,7 +60,7 @@ namespace TEN::Traps::TR5 auto beamOffset = Vector3(0.0f, -LaserBarrierBeam::HEIGHT, 0.0f); for (auto& beam : Beams) { - assertion(beam.VertexPoints.size() == baseVertices.size(), "Laser barrier beam vertex count out of sync."); + TENAssert(beam.VertexPoints.size() == baseVertices.size(), "Laser barrier beam vertex count out of sync."); for (int i = 0; i < beam.VertexPoints.size(); i++) beam.VertexPoints[i] = baseVertices[i] + beamOffset; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp index 55067e76a..31cc26320 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/Level/FlowLevel.cpp @@ -167,7 +167,7 @@ void Level::SetLevelFarView(short val) RGBAColor8Byte Level::GetSkyLayerColor(int index) const { - assertion(index == 0 || index == 1, "Sky layer index must be 0 or 1."); + TENAssert(index == 0 || index == 1, "Sky layer index must be 0 or 1."); if (index == 0) { @@ -181,7 +181,7 @@ RGBAColor8Byte Level::GetSkyLayerColor(int index) const bool Level::GetSkyLayerEnabled(int index) const { - assertion(index == 0 || index == 1, "Sky layer index must be 0 or 1."); + TENAssert(index == 0 || index == 1, "Sky layer index must be 0 or 1."); if (index == 0) { @@ -195,7 +195,7 @@ bool Level::GetSkyLayerEnabled(int index) const short Level::GetSkyLayerSpeed(int index) const { - assertion(index == 0 || index == 1, "Sky layer index must be 0 or 1."); + TENAssert(index == 0 || index == 1, "Sky layer index must be 0 or 1."); if (index == 0) { diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index c4de82af7..81d212c5a 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -340,6 +340,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -385,7 +386,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -869,7 +869,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - + diff --git a/TombEngine/framework.h b/TombEngine/framework.h index 133da0a80..46ce3d07a 100644 --- a/TombEngine/framework.h +++ b/TombEngine/framework.h @@ -23,4 +23,6 @@ using namespace DirectX; using namespace DirectX::SimpleMath; +using namespace TEN::Debug; + constexpr auto NO_VALUE = -1; From 7248091ca9c02a14d31078ecfe4b9a2ac7b0fe17 Mon Sep 17 00:00:00 2001 From: Adngel <60930991+Adngel@users.noreply.github.com> Date: Wed, 19 Jun 2024 12:19:39 +0200 Subject: [PATCH 213/410] Adngel several traps fixes (#1379) * Fix: Impale animation When I jump in the TR1 spikes, or when I'm over the emerging TR4 spikes, the value it gets is INTERSECT not CONTAINS I think it is because the TR1 spikes are 2 clicks, it won't contain Lara's collider. And TR4 when they are emerging, also have smaller collider box, so it will neither CONTAINS Lara's collider until it get already very late (for then, Lara is already dead and doing another death animation). Removing the condition, it will activate where is INTERSECTS or CONTAINS. * Fix Rome Hammer damage. It won't hurt Lara anymore while it's deactivated. * Fix Traps Collision Updated the code of 4blades (used by floor and ceiling versions). Added a condition in the colliion check for non-itelligent objects (like traps) so collision will push Lara only for the traps that have ItemFlags[4] equal to 0. TODO: Consider a different method. * Update collide_item.cpp I tried item->Collidable, but deactivating it, has more consecuencies, where spheres collisions are not detected so traps don't harm Lara, therefore I couldn't use it. I returned it to coll->Setup.EnableObjectPush boolean, this variable is set in GenericSphereBoxCollision reading the ItemFlags[4] like it was before. (Most of the traps are builded around this) changing it could require a refactor of the traps that uses this feature. * Fixes and Refactor of Joby Spikes - Created references variables to replace ItemFlags, to make the code more readable. - Replaced the deprecated GetRandomControl function from this code by Random::GenerateInt function. - Fix bug with collider. This trap is using an internal collision detection routine to hurt Lara based in her position and the spike height, instead of the sphers. So it wasn't using the GenericSphereBoxCollision, I removed from its obj->collision to avoid it pushing Lara away. - Fix bug about endless scale. Before it was increasing the spike far beyond the room bounds, now it will only increase 3 blocks and 1 click (3328, based in Troye's code). Leaving for a future enhace it for it to adapt at other room heights. * Fix Mine bug Now when Lara steps on a mine with OCB 1, the death animation will trigger correctly without crash the game. * Increase damage Statue with Blade from 20 to 200 So it's more likely it removes Lara more than 1/3 per hit. * Fix and refactor of Sentry Gun - Created references variables to replace ItemFlags, to make the code more readable. - Added new ItemFlags [3] to contain the ID of the deactivator inventory item. - Changed item pointer for item reference. - Fix bug sentry gun rotation meshes: Looks like the the function "SetBoneRotationFlags" wasn't set properly. * Changed namespace in 4blades code. - Changed namespace name From namespace TEN::Entities::TR4 to namespace TEN::Entities::Traps - Fixed Damage variables names. * Fix Rolling Spindle Moving through high steps. Added extra condition to stop the movement of the rolling spindle blade. In addition to walls, the spinning blade will stop if: - Ceiling is lower than 4 clicks - The floor ahead is lower or higher than 2.5 clicks. (To stop it moving up and down into pits, but still allow it to move through 1 and 2 click slopes). - If there is a stopper flag (so they can be stopped with pushables). * Update WreckingBall code Still pending of refactor, but I think it's better manage that in a different branch. * Update traps namespace * Update TR4 traps Disable trap push for Birdblade, Sethblade and Plough. Deleted duplicated initialization of Plough and Chain in TR4 objects. * Merge develop branch There was a conflict with develop, this should fix it. * Fix Dart Emitter Antitrigger * Fix Homing Dart Emiter When triggering, it was continously spawning darts, that was because the trigger code was resetting the item->Timer variable. This variable is aimed to be used to delay the activation or provoke a timed deactivation. Using the variable adittionaly for internal behaviour like the dart spawn frequency, may lead to uncertain results like this actual bug. Using a separate variable (ItemFlags[1]) the dart spawn frequency timer won't be influenced by the triggers code. * Formatting * Update CHANGELOG.md * Moved the routine from ControlCog to AnimatingControl So now Animatings will can have the OCB 666 (used in Train level for the helicopter animating) and OCB 2 to make animating dissapear when Antitriggered. (Legacy features of TR4 code, maybe they got lost in the TR5 code). * Fix SwingingBlade deactivation It was happening that when the swinging blade got antitriggered, it was going to the stopping animation, but the object state remained activated, doing control calls on every loop. Now it will remove itself from the control loop calls. --------- Co-authored-by: Sezz --- CHANGELOG.md | 12 + TombEngine/Game/collision/collide_item.cpp | 2 +- TombEngine/Game/control/control.cpp | 4 +- TombEngine/Objects/Generic/Object/objects.cpp | 28 +- .../Objects/Generic/Traps/dart_emitter.cpp | 275 ++++---- .../Objects/Generic/Traps/dart_emitter.h | 8 +- .../Objects/Generic/generic_objects.cpp | 8 +- TombEngine/Objects/TR1/Trap/DamoclesSword.cpp | 2 +- TombEngine/Objects/TR1/Trap/DamoclesSword.h | 2 +- TombEngine/Objects/TR1/Trap/SlammingDoors.cpp | 2 +- TombEngine/Objects/TR1/Trap/SlammingDoors.h | 2 +- TombEngine/Objects/TR1/Trap/SwingingBlade.cpp | 13 +- TombEngine/Objects/TR1/Trap/SwingingBlade.h | 2 +- TombEngine/Objects/TR1/tr1_objects.cpp | 2 +- .../Objects/TR2/Trap/tr2_killerstatue.cpp | 59 +- .../Objects/TR2/Trap/tr2_killerstatue.h | 7 +- .../Objects/TR2/Trap/tr2_spinningblade.cpp | 103 +-- .../Objects/TR2/Trap/tr2_spinningblade.h | 7 +- TombEngine/Objects/TR2/tr2_objects.cpp | 5 +- .../Objects/TR3/Entity/tr3_tribesman.cpp | 3 +- TombEngine/Objects/TR3/Trap/train.cpp | 215 +++---- TombEngine/Objects/TR3/Trap/train.h | 11 +- TombEngine/Objects/TR3/tr3_objects.cpp | 4 +- .../Objects/TR4/Entity/tr4_sentry_gun.cpp | 165 +++-- .../Objects/TR4/Entity/tr4_sentry_gun.h | 2 +- TombEngine/Objects/TR4/Trap/tr4_birdblade.cpp | 40 +- TombEngine/Objects/TR4/Trap/tr4_birdblade.h | 5 +- TombEngine/Objects/TR4/Trap/tr4_blade.cpp | 81 +-- TombEngine/Objects/TR4/Trap/tr4_blade.h | 4 +- .../Objects/TR4/Trap/tr4_catwalkblade.cpp | 33 +- .../Objects/TR4/Trap/tr4_catwalkblade.h | 4 +- TombEngine/Objects/TR4/Trap/tr4_chain.cpp | 35 +- TombEngine/Objects/TR4/Trap/tr4_chain.h | 7 +- TombEngine/Objects/TR4/Trap/tr4_cog.cpp | 100 ++- TombEngine/Objects/TR4/Trap/tr4_cog.h | 6 +- .../Objects/TR4/Trap/tr4_fourblades.cpp | 53 +- TombEngine/Objects/TR4/Trap/tr4_fourblades.h | 5 +- TombEngine/Objects/TR4/Trap/tr4_hammer.cpp | 308 ++++----- TombEngine/Objects/TR4/Trap/tr4_hammer.h | 4 +- .../Objects/TR4/Trap/tr4_joby_spikes.cpp | 108 ++-- TombEngine/Objects/TR4/Trap/tr4_joby_spikes.h | 4 +- TombEngine/Objects/TR4/Trap/tr4_mine.cpp | 157 ++--- TombEngine/Objects/TR4/Trap/tr4_mine.h | 6 +- .../Objects/TR4/Trap/tr4_moving_blade.cpp | 27 +- .../Objects/TR4/Trap/tr4_moving_blade.h | 4 +- .../Objects/TR4/Trap/tr4_plinthblade.cpp | 33 +- TombEngine/Objects/TR4/Trap/tr4_plinthblade.h | 4 +- TombEngine/Objects/TR4/Trap/tr4_plough.cpp | 32 +- TombEngine/Objects/TR4/Trap/tr4_plough.h | 5 +- TombEngine/Objects/TR4/Trap/tr4_sethblade.cpp | 5 +- TombEngine/Objects/TR4/Trap/tr4_sethblade.h | 4 +- .../Objects/TR4/Trap/tr4_slicerdicer.cpp | 52 +- TombEngine/Objects/TR4/Trap/tr4_slicerdicer.h | 4 +- TombEngine/Objects/TR4/Trap/tr4_spikeball.cpp | 35 +- TombEngine/Objects/TR4/Trap/tr4_spikeball.h | 4 +- .../Objects/TR4/Trap/tr4_teethspike.cpp | 157 ++--- TombEngine/Objects/TR4/Trap/tr4_teethspike.h | 2 +- TombEngine/Objects/TR4/tr4_objects.cpp | 70 +-- TombEngine/Objects/TR5/Trap/LaserBarrier.cpp | 2 +- TombEngine/Objects/TR5/Trap/LaserBarrier.h | 2 +- TombEngine/Objects/TR5/Trap/LaserBeam.cpp | 2 +- TombEngine/Objects/TR5/Trap/LaserBeam.h | 2 +- TombEngine/Objects/TR5/Trap/ZipLine.cpp | 2 +- TombEngine/Objects/TR5/Trap/ZipLine.h | 2 +- TombEngine/Objects/TR5/Trap/tr5_explosion.cpp | 279 ++++---- TombEngine/Objects/TR5/Trap/tr5_explosion.h | 7 +- .../Objects/TR5/Trap/tr5_fallingceiling.cpp | 67 +- .../Objects/TR5/Trap/tr5_fallingceiling.h | 5 +- .../Objects/TR5/Trap/tr5_romehammer.cpp | 38 +- TombEngine/Objects/TR5/Trap/tr5_romehammer.h | 6 +- .../Objects/TR5/Trap/tr5_ventilator.cpp | 538 ++++++++-------- TombEngine/Objects/TR5/Trap/tr5_ventilator.h | 7 +- .../Objects/TR5/Trap/tr5_wreckingball.cpp | 595 ++++++++++-------- .../Objects/TR5/Trap/tr5_wreckingball.h | 9 +- TombEngine/Objects/TR5/tr5_objects.cpp | 16 +- TombEngine/Renderer/RendererDrawEffect.cpp | 2 +- 76 files changed, 2142 insertions(+), 1780 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bb3f8a02..57f1b3d4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,8 +18,20 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed Squishy blocks crashing the level. * Fixed the path finding zones of Larson and Pierre. * Fixed the torch flame delay in disappearing when Lara threw or dropped the torch object. +* Fixed Dart emitters which was failing when it was antitriggered. +* Fixed Homing Dart emitter which was spawning darts continously while Lara was on the trigger. +* Fixed Floor 4 blades and ceiling 4 blades collision. +* Fixed Joby spikes collision and abnormal streetching. +* Fixed Sentry Gun to rotate its parts correctly. +* Fixed Teeth Spikes bug, now they will activates the Lara impale animation. +* Fixed TR4 mine with OCB1, to don't crash the game when Lara steps the mine. ### Features/Amendments +* Changed Rome Hammer for it to don't hurt Lara while it's deactivated. +* Changed Statue with blade damage, from 20 to 200. +* Enhaced Rolling Spindle detection to avoid them going down through pits. +* Enhaced Sentry Guns, with a new ItemFlags[3] to contain the ID of the inventory item that deactivates the sentry guns (by default PUZZLE_ITEM5 ID) +* Enhaced Dart Emitter, with a new ItemFlags[0] to contain the number of frames between shots (by default 32 in dart emitter, and 24 in homing dar emitter). ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index b979c66eb..a60ac2b82 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -706,7 +706,7 @@ bool ItemPushItem(ItemInfo* item0, ItemInfo* item1, CollisionInfo* coll, bool en item1->Pose.Position.Lerp(item0->Pose.Position + newDeltaPos, SOFT_PUSH_LERP_ALPHA); } // Snap to new position. - else + else if (coll->Setup.EnableObjectPush) { item1->Pose.Position = item0->Pose.Position + newDeltaPos; } diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 4502e5a59..026ff78ff 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -76,8 +76,10 @@ using namespace TEN::Effects::Ripple; using namespace TEN::Effects::Smoke; using namespace TEN::Effects::Spark; using namespace TEN::Effects::Streamer; +using namespace TEN::Entities::Creatures::TR3; using namespace TEN::Entities::Generic; using namespace TEN::Entities::Switches; +using namespace TEN::Entities::Traps; using namespace TEN::Entities::TR4; using namespace TEN::Collision::Floordata; using namespace TEN::Control::Volumes; @@ -85,8 +87,6 @@ using namespace TEN::Hud; using namespace TEN::Input; using namespace TEN::Math; using namespace TEN::Renderer; -using namespace TEN::Traps::TR5; -using namespace TEN::Entities::Creatures::TR3; int GameTimer = 0; int GlobalCounter = 0; diff --git a/TombEngine/Objects/Generic/Object/objects.cpp b/TombEngine/Objects/Generic/Object/objects.cpp index 184674ae9..5207da4f0 100644 --- a/TombEngine/Objects/Generic/Object/objects.cpp +++ b/TombEngine/Objects/Generic/Object/objects.cpp @@ -236,13 +236,31 @@ void InitializeAnimating(short itemNumber) void AnimatingControl(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (!TriggerActive(item)) - return; + if (TriggerActive(&item)) + { + item.Status = ITEM_ACTIVE; + AnimateItem(&item); - item->Status = ITEM_ACTIVE; - AnimateItem(item); + if (item.TriggerFlags == 666) //OCB used for the helicopter animating in the Train level. + { + auto pos = GetJointPosition(item, 0); + SoundEffect(SFX_TR4_HELICOPTER_LOOP, (Pose*)&pos); + + if (item.Animation.FrameNumber == GetAnimData(item).frameEnd) + { + item.Flags &= 0xC1; + RemoveActiveItem(itemNumber); + item.Status = ITEM_NOT_ACTIVE; + } + } + } + else if (item.TriggerFlags == 2) //Make the animating dissapear when anti-triggered. + { + RemoveActiveItem(itemNumber); + item.Status |= ITEM_INVISIBLE; + } // TODO: ID_SHOOT_SWITCH2 is probably the bell in Trajan Markets, use Lua for that. /*if (item->frameNumber >= g_Level.Anims[item->animNumber].frameEnd) diff --git a/TombEngine/Objects/Generic/Traps/dart_emitter.cpp b/TombEngine/Objects/Generic/Traps/dart_emitter.cpp index eb7fa126e..f786b659c 100644 --- a/TombEngine/Objects/Generic/Traps/dart_emitter.cpp +++ b/TombEngine/Objects/Generic/Traps/dart_emitter.cpp @@ -9,188 +9,225 @@ #include "Sound/sound.h" #include "Specific/level.h" +// NOTES: +// ItemFlags[0]: Delay between darts in frame time. +// ItemFlags[1]: Timer in frame time. + namespace TEN::Entities::Traps { - constexpr auto DART_DEFAULT_DAMAGE = 25; + constexpr auto DART_DEFAULT_HARM_DAMAGE = 25; + constexpr auto DART_DEFAULT_VELOCITY = BLOCK(0.25f); + constexpr auto DART_DEFAULT_DELAY = 32; + constexpr auto DART_DEFAULT_HOMING_DELAY = 24; - void DartControl(short itemNumber) + void InitializeDartEmitter(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (item->TouchBits.TestAny()) + auto& delay = item.ItemFlags[0]; + + if (item.ObjectNumber == ID_HOMING_DART_EMITTER) { - if (item->TriggerFlags < 0) + if (delay == 0) + delay = DART_DEFAULT_HOMING_DELAY; + } + else + { + if (delay == 0) + delay = DART_DEFAULT_DELAY; + } + } + + void ControlDart(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (item.TouchBits.TestAny()) + { + if (item.TriggerFlags < 0) Lara.Status.Poison += 1; - DoDamage(LaraItem, item->TriggerFlags ? abs(item->TriggerFlags) : DART_DEFAULT_DAMAGE); - DoBloodSplat(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, (GetRandomControl() & 3) + 4, LaraItem->Pose.Orientation.y, LaraItem->RoomNumber); + DoDamage(LaraItem, item.TriggerFlags ? abs(item.TriggerFlags) : DART_DEFAULT_HARM_DAMAGE); + DoBloodSplat(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, (GetRandomControl() & 3) + 4, LaraItem->Pose.Orientation.y, LaraItem->RoomNumber); KillItem(itemNumber); } else { - int oldX = item->Pose.Position.x; - int oldZ = item->Pose.Position.z; + auto prevPos = item.Pose.Position; - int velocity = item->Animation.Velocity.z * phd_cos(item->Pose.Orientation.x); + float vel = item.Animation.Velocity.z * phd_cos(item.Pose.Orientation.x); - item->Pose.Position.x += velocity * phd_sin(item->Pose.Orientation.y); - item->Pose.Position.y -= item->Animation.Velocity.z * phd_sin(item->Pose.Orientation.x); - item->Pose.Position.z += velocity * phd_cos(item->Pose.Orientation.y); + item.Pose.Position.x += vel * phd_sin(item.Pose.Orientation.y); + item.Pose.Position.y -= item.Animation.Velocity.z * phd_sin(item.Pose.Orientation.x); + item.Pose.Position.z += vel * phd_cos(item.Pose.Orientation.y); - short roomNumber = item->RoomNumber; - FloorInfo* floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); + short roomNumber = item.RoomNumber; + auto* floor = GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &roomNumber); - if (item->RoomNumber != roomNumber) + if (item.RoomNumber != roomNumber) ItemNewRoom(itemNumber, roomNumber); - int height = GetFloorHeight(floor, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); - item->Floor = height; + int height = GetFloorHeight(floor, item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z); + item.Floor = height; - if (item->Pose.Position.y >= height) + if (item.Pose.Position.y >= height) { for (int i = 0; i < 4; i++) - TriggerDartSmoke(oldX, item->Pose.Position.y, oldZ, 0, 0, true); + SpawnDartSmoke(Vector3(prevPos.x, item.Pose.Position.y, prevPos.z), Vector3::Zero, true); KillItem(itemNumber); } } } - void DartEmitterControl(short itemNumber) + void ControlDartEmitter(short itemNumber) { - ItemInfo* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (item->Active) + if (TriggerActive(&item)) { - if (item->Timer > 0) + if (item.Active) { - item->Timer--; + auto& delay = item.ItemFlags[0]; + auto& timer = item.ItemFlags[1]; + + if (timer > 0) + { + timer--; + return; + } + else + { + timer = delay; + } + } + + int dartItemNumber = CreateItem(); + if (dartItemNumber == NO_VALUE) return; - } - else - { - item->Timer = 24; - } - } - int dartItemNumber = CreateItem(); - if (dartItemNumber == NO_VALUE) - return; + auto& dartItem = g_Level.Items[dartItemNumber]; + dartItem.ObjectNumber = ID_DARTS; + dartItem.Pose.Position = item.Pose.Position + Vector3i(0, -CLICK(0.9f), 0); + dartItem.Pose.Orientation = item.Pose.Orientation + EulerAngles(0, ANGLE(180.0f), 0); + dartItem.RoomNumber = item.RoomNumber; - ItemInfo* dartItem = &g_Level.Items[dartItemNumber]; + InitializeItem(dartItemNumber); - dartItem->ObjectNumber = ID_DARTS; - dartItem->RoomNumber = item->RoomNumber; + dartItem.Animation.Velocity.z = DART_DEFAULT_VELOCITY; + dartItem.TriggerFlags = item.TriggerFlags; + dartItem.Model.Color = item.Model.Color; - dartItem->Pose.Position.x = item->Pose.Position.x; - dartItem->Pose.Position.y = item->Pose.Position.y - CLICK(0.9); - dartItem->Pose.Position.z = item->Pose.Position.z; + for (int i = 0; i < 4; i++) + SpawnDartSmoke(dartItem.Pose.Position.ToVector3(), Vector3::Zero, false); - InitializeItem(dartItemNumber); + AddActiveItem(dartItemNumber); + dartItem.Status = ITEM_ACTIVE; - dartItem->Pose.Orientation.x = item->Pose.Orientation.x - ANGLE(180.0f); - dartItem->Pose.Orientation.y = item->Pose.Orientation.y; - dartItem->Pose.Orientation.z = item->Pose.Orientation.z; - dartItem->Animation.Velocity.z = BLOCK(0.25f); - dartItem->TriggerFlags = item->TriggerFlags; - dartItem->Model.Color = item->Model.Color; - - for (int i = 0; i < 4; i++) - TriggerDartSmoke(dartItem->Pose.Position.x, dartItem->Pose.Position.y, dartItem->Pose.Position.z, 0, 0, false); - - AddActiveItem(dartItemNumber); - dartItem->Status = ITEM_ACTIVE; - - SoundEffect(SFX_TR4_DART_SPIT, &dartItem->Pose); - } - - void TriggerDartSmoke(int x, int y, int z, int xv, int zv, bool hit) - { - int dx = LaraItem->Pose.Position.x - x; - int dz = LaraItem->Pose.Position.z - z; - - if (dx < -16384 || dx > 16384 || dz < -16384 || dz > 16384) - return; - - auto* spark = GetFreeParticle(); - - spark->on = true; - - spark->sR = 16; - spark->sG = 8; - spark->sB = 4; - - spark->dR = 64; - spark->dG = 48; - spark->dB = 32; - - spark->colFadeSpeed = 8; - spark->fadeToBlack = 4; - - spark->blendMode = BlendMode::Additive; - - spark->life = spark->sLife = (GetRandomControl() & 3) + 32; - - spark->x = x + ((GetRandomControl() & 31) - 16); - spark->y = y + ((GetRandomControl() & 31) - 16); - spark->z = z + ((GetRandomControl() & 31) - 16); - - if (hit) - { - spark->xVel = -xv + ((GetRandomControl() & 255) - 128); - spark->yVel = -(GetRandomControl() & 3) - 4; - spark->zVel = -zv + ((GetRandomControl() & 255) - 128); - spark->friction = 3; + SoundEffect(SFX_TR4_DART_SPIT, &dartItem.Pose); } else { - if (xv) - spark->xVel = -xv; - else - spark->xVel = ((GetRandomControl() & 255) - 128); + item.Status = ITEM_NOT_ACTIVE; + RemoveActiveItem(itemNumber, false); + item.Active = false; + } + } - spark->yVel = -(GetRandomControl() & 3) - 4; - if (zv) - spark->zVel = -zv; - else - spark->zVel = ((GetRandomControl() & 255) - 128); + void SpawnDartSmoke(const Vector3& pos, const Vector3& vel, bool isHit) + { + auto& part = *GetFreeParticle(); - spark->friction = 3; + part.on = true; + + part.sR = 16; + part.sG = 8; + part.sB = 4; + + part.dR = 64; + part.dG = 48; + part.dB = 32; + + part.colFadeSpeed = 8; + part.fadeToBlack = 4; + + part.blendMode = BlendMode::Additive; + + part.life = part.sLife = (GetRandomControl() & 3) + 32; + + part.x = pos.x + ((GetRandomControl() & 31) - 16); + part.y = pos.y + ((GetRandomControl() & 31) - 16); + part.z = pos.z + ((GetRandomControl() & 31) - 16); + + if (isHit) + { + part.xVel = -vel.x + ((GetRandomControl() & 255) - 128); + part.yVel = -(GetRandomControl() & 3) - 4; + part.zVel = -vel.z + ((GetRandomControl() & 255) - 128); + part.friction = 3; + } + else + { + if (vel.x != 0.0f) + { + part.xVel = -vel.x; + } + else + { + part.xVel = ((GetRandomControl() & 255) - 128); + } + + part.yVel = -(GetRandomControl() & 3) - 4; + if (vel.z != 0.0f) + { + part.zVel = -vel.z; + } + else + { + part.zVel = ((GetRandomControl() & 255) - 128); + } + + part.friction = 3; } - spark->friction = 3; + part.friction = 3; if (GetRandomControl() & 1) { - spark->flags = SP_EXPDEF | SP_ROTATE | SP_DEF | SP_SCALE; + part.flags = SP_EXPDEF | SP_ROTATE | SP_DEF | SP_SCALE; - spark->rotAng = GetRandomControl() & 0xFFF; + part.rotAng = GetRandomControl() & 0xFFF; if (GetRandomControl() & 1) - spark->rotAdd = -16 - (GetRandomControl() & 0xF); + { + part.rotAdd = -16 - (GetRandomControl() & 0xF); + } else - spark->rotAdd = (GetRandomControl() & 0xF) + 16; + { + part.rotAdd = (GetRandomControl() & 0xF) + 16; + } } else { - spark->flags = SP_EXPDEF | SP_DEF | SP_SCALE; + part.flags = SP_EXPDEF | SP_DEF | SP_SCALE; } - spark->scalar = 1; + part.scalar = 1; int size = (GetRandomControl() & 63) + 72; - if (hit) + if (isHit) { - size >>= 1; - spark->size = spark->sSize = size >> 2; - spark->gravity = spark->maxYvel = 0; + size /= 2; + part.size = + part.sSize = size *= 4; + part.gravity = part.maxYvel = 0; } else { - spark->size = spark->sSize = size >> 4; - spark->gravity = -(GetRandomControl() & 3) - 4; - spark->maxYvel = -(GetRandomControl() & 3) - 4; + part.size = part.sSize = size >> 4; + part.gravity = -(GetRandomControl() & 3) - 4; + part.maxYvel = -(GetRandomControl() & 3) - 4; } - spark->dSize = size; + part.dSize = size; } } diff --git a/TombEngine/Objects/Generic/Traps/dart_emitter.h b/TombEngine/Objects/Generic/Traps/dart_emitter.h index f7bc3244c..4a91cc7bb 100644 --- a/TombEngine/Objects/Generic/Traps/dart_emitter.h +++ b/TombEngine/Objects/Generic/Traps/dart_emitter.h @@ -2,7 +2,9 @@ namespace TEN::Entities::Traps { - void DartControl(short itemNumber); - void DartEmitterControl(short itemNumber); - void TriggerDartSmoke(int x, int y, int z, int xv, int zv, bool hit); + void InitializeDartEmitter(short itemNumber); + void ControlDart(short itemNumber); + void ControlDartEmitter(short itemNumber); + + void SpawnDartSmoke(const Vector3& pos, const Vector3& vel, bool isHit); } diff --git a/TombEngine/Objects/Generic/generic_objects.cpp b/TombEngine/Objects/Generic/generic_objects.cpp index 7d57948c5..5e09d44ba 100644 --- a/TombEngine/Objects/Generic/generic_objects.cpp +++ b/TombEngine/Objects/Generic/generic_objects.cpp @@ -347,14 +347,15 @@ void StartTraps(ObjectInfo* object) if (object->loaded) { object->collision = ObjectCollision; - object->control = DartControl; + object->control = ControlDart; object->shadowType = ShadowMode::All; } object = &Objects[ID_DART_EMITTER]; if (object->loaded) { - object->control = DartEmitterControl; + object->Initialize = InitializeDartEmitter; + object->control = ControlDartEmitter; object->drawRoutine = nullptr; object->usingDrawAnimatingItem = false; } @@ -362,7 +363,8 @@ void StartTraps(ObjectInfo* object) object = &Objects[ID_HOMING_DART_EMITTER]; if (object->loaded) { - object->control = DartEmitterControl; + object->Initialize = InitializeDartEmitter; + object->control = ControlDartEmitter; object->drawRoutine = nullptr; object->usingDrawAnimatingItem = false; } diff --git a/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp b/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp index 348827f7e..1a9d9998b 100644 --- a/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp +++ b/TombEngine/Objects/TR1/Trap/DamoclesSword.cpp @@ -14,7 +14,7 @@ using namespace TEN::Collision::Point; using namespace TEN::Math; -namespace TEN::Entities::Traps::TR1 +namespace TEN::Entities::Traps { // NOTES: // ItemFlags[0] = random turn rate when active. diff --git a/TombEngine/Objects/TR1/Trap/DamoclesSword.h b/TombEngine/Objects/TR1/Trap/DamoclesSword.h index 5e76ec675..c5cc457f5 100644 --- a/TombEngine/Objects/TR1/Trap/DamoclesSword.h +++ b/TombEngine/Objects/TR1/Trap/DamoclesSword.h @@ -4,7 +4,7 @@ struct CollisionInfo; struct ItemInfo; struct ObjectInfo; -namespace TEN::Entities::Traps::TR1 +namespace TEN::Entities::Traps { void InitializeDamoclesSword(short itemNumber); diff --git a/TombEngine/Objects/TR1/Trap/SlammingDoors.cpp b/TombEngine/Objects/TR1/Trap/SlammingDoors.cpp index cb1974298..9c41a6a64 100644 --- a/TombEngine/Objects/TR1/Trap/SlammingDoors.cpp +++ b/TombEngine/Objects/TR1/Trap/SlammingDoors.cpp @@ -9,7 +9,7 @@ using namespace TEN::Math; -namespace TEN::Entities::Traps::TR1 +namespace TEN::Entities::Traps { constexpr auto SLAMMING_DOORS_HARM_DAMAGE = 400; diff --git a/TombEngine/Objects/TR1/Trap/SlammingDoors.h b/TombEngine/Objects/TR1/Trap/SlammingDoors.h index 700de7700..92e111334 100644 --- a/TombEngine/Objects/TR1/Trap/SlammingDoors.h +++ b/TombEngine/Objects/TR1/Trap/SlammingDoors.h @@ -3,7 +3,7 @@ struct BiteInfo; struct ItemInfo; -namespace TEN::Entities::Traps::TR1 +namespace TEN::Entities::Traps { void InitializeSlammingDoors(short itemNumber); void ControlSlammingDoors(short itemNumber); diff --git a/TombEngine/Objects/TR1/Trap/SwingingBlade.cpp b/TombEngine/Objects/TR1/Trap/SwingingBlade.cpp index 05420db62..1475d5662 100644 --- a/TombEngine/Objects/TR1/Trap/SwingingBlade.cpp +++ b/TombEngine/Objects/TR1/Trap/SwingingBlade.cpp @@ -3,7 +3,7 @@ #include "Game/Setup.h" -namespace TEN::Entities::Traps::TR1 +namespace TEN::Entities::Traps { constexpr auto SWINGING_BLADE_HARM_DAMAGE = 100; @@ -57,6 +57,17 @@ namespace TEN::Entities::Traps::TR1 // Unset harm joints. item.ItemFlags[0] = 0; } + else + { + if (item.Animation.AnimNumber == GetAnimIndex(item, SWINGING_BLADE_ANIM_DISABLED) && + item.Animation.FrameNumber == GetAnimData(item).frameEnd) + { + item.Flags &= 0xC1; + RemoveActiveItem(itemNumber, false); + item.Active = false; + item.Status = ITEM_NOT_ACTIVE; + } + } } AnimateItem(&item); diff --git a/TombEngine/Objects/TR1/Trap/SwingingBlade.h b/TombEngine/Objects/TR1/Trap/SwingingBlade.h index d85880131..ac88336e6 100644 --- a/TombEngine/Objects/TR1/Trap/SwingingBlade.h +++ b/TombEngine/Objects/TR1/Trap/SwingingBlade.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::Traps::TR1 +namespace TEN::Entities::Traps { void InitializeSwingingBlade(short itemNumber); void ControlSwingingBlade(short itemNumber); diff --git a/TombEngine/Objects/TR1/tr1_objects.cpp b/TombEngine/Objects/TR1/tr1_objects.cpp index 244deb99f..3a051cd50 100644 --- a/TombEngine/Objects/TR1/tr1_objects.cpp +++ b/TombEngine/Objects/TR1/tr1_objects.cpp @@ -30,7 +30,7 @@ #include "Objects/TR1/Trap/SwingingBlade.h" using namespace TEN::Entities::Creatures::TR1; -using namespace TEN::Entities::Traps::TR1; +using namespace TEN::Entities::Traps; static void StartEntity(ObjectInfo* obj) { diff --git a/TombEngine/Objects/TR2/Trap/tr2_killerstatue.cpp b/TombEngine/Objects/TR2/Trap/tr2_killerstatue.cpp index 9bad3ef5b..f351788ae 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_killerstatue.cpp +++ b/TombEngine/Objects/TR2/Trap/tr2_killerstatue.cpp @@ -9,35 +9,44 @@ #include "Game/Setup.h" #include "Specific/level.h" -void InitializeKillerStatue(short itemNumber) +namespace TEN::Entities::Traps { - auto* item = &g_Level.Items[itemNumber]; + constexpr auto KILLER_STATUE_HARM_DAMAGE = 200; - item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex + 3; - item->Animation.FrameNumber = GetAnimData(item).frameBase; - item->Animation.ActiveState = 1; -} - -void KillerStatueControl(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - if (TriggerActive(item) && item->Animation.ActiveState == 1) - item->Animation.TargetState = 2; - else - item->Animation.TargetState = 1; - - if (item->TouchBits & 0x80 && item->Animation.ActiveState == 2) + void InitializeKillerStatue(short itemNumber) { - DoDamage(LaraItem, 20); + auto& item = g_Level.Items[itemNumber]; - int x = LaraItem->Pose.Position.x + (GetRandomControl() - BLOCK(16)) / CLICK(1); - int z = LaraItem->Pose.Position.z + (GetRandomControl() - BLOCK(16)) / CLICK(1); - int y = LaraItem->Pose.Position.y - GetRandomControl() / 44; - int d = (GetRandomControl() - BLOCK(16)) / 8 + LaraItem->Pose.Orientation.y; - - DoBloodSplat(x, y, z, LaraItem->Animation.Velocity.z, d, LaraItem->RoomNumber); + item.Animation.AnimNumber = Objects[item.ObjectNumber].animIndex + 3; + item.Animation.FrameNumber = GetAnimData(item).frameBase; + item.Animation.ActiveState = 1; } - AnimateItem(item); + void ControlKillerStatue(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (TriggerActive(&item) && item.Animation.ActiveState == 1) + { + item.Animation.TargetState = 2; + } + else + { + item.Animation.TargetState = 1; + } + + if (item.TouchBits & 0x80 && item.Animation.ActiveState == 2) + { + DoDamage(LaraItem, KILLER_STATUE_HARM_DAMAGE); + + int x = LaraItem->Pose.Position.x + (GetRandomControl() - BLOCK(16)) / CLICK(1); + int z = LaraItem->Pose.Position.z + (GetRandomControl() - BLOCK(16)) / CLICK(1); + int y = LaraItem->Pose.Position.y - GetRandomControl() / 44; + int d = (GetRandomControl() - BLOCK(16)) / 8 + LaraItem->Pose.Orientation.y; + + DoBloodSplat(x, y, z, LaraItem->Animation.Velocity.z, d, LaraItem->RoomNumber); + } + + AnimateItem(&item); + } } diff --git a/TombEngine/Objects/TR2/Trap/tr2_killerstatue.h b/TombEngine/Objects/TR2/Trap/tr2_killerstatue.h index 91878614c..fac277086 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_killerstatue.h +++ b/TombEngine/Objects/TR2/Trap/tr2_killerstatue.h @@ -1,4 +1,7 @@ #pragma once -void InitializeKillerStatue(short itemNumber); -void KillerStatueControl(short itemNumber); +namespace TEN::Entities::Traps +{ + void InitializeKillerStatue(short itemNumber); + void ControlKillerStatue(short itemNumber); +} diff --git a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp index dc027a558..f3107871b 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp +++ b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.cpp @@ -14,58 +14,71 @@ using namespace TEN::Collision::Point; -void InitializeSpinningBlade(short itemNumber) +namespace TEN::Entities::Traps { - auto* item = &g_Level.Items[itemNumber]; - SetAnimation(item, 3); -} + constexpr auto SPINNING_BLADE_DAMAGE = 100; -void SpinningBladeControl(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - bool isSpinning = false; - - if (item->Animation.ActiveState == 2) + void InitializeSpinningBlade(short itemNumber) { - if (item->Animation.TargetState != 1) - { - int x = item->Pose.Position.x + BLOCK(3) * phd_sin(item->Pose.Orientation.y) / 2; - int z = item->Pose.Position.z + BLOCK(3) * phd_cos(item->Pose.Orientation.y) / 2; - - int floorHeight = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetFloorHeight(); - if (floorHeight == NO_HEIGHT) - item->Animation.TargetState = 1; - } - - isSpinning = true; - - if (item->TouchBits.TestAny()) - { - DoDamage(LaraItem, 100); - DoLotsOfBlood(LaraItem->Pose.Position.x, LaraItem->Pose.Position.y - CLICK(2), LaraItem->Pose.Position.z, (short)(item->Animation.Velocity.z * 2), LaraItem->Pose.Orientation.y, LaraItem->RoomNumber, 2); - } - - SoundEffect(SFX_TR2_ROLLING_BLADE, &item->Pose); - } - else - { - if (TriggerActive(item)) - item->Animation.TargetState = 2; - - isSpinning = false; + auto* item = &g_Level.Items[itemNumber]; + SetAnimation(item, 3); } - AnimateItem(item); + void ControlSpinningBlade(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; - auto pointColl = GetPointCollision(*item); + bool isSpinning = false; - item->Floor = pointColl.GetFloorHeight(); - item->Pose.Position.y = pointColl.GetFloorHeight(); + if (item.Animation.ActiveState == 2) + { + if (item.Animation.TargetState != 1) + { + int x = item.Pose.Position.x + BLOCK(3) * phd_sin(item.Pose.Orientation.y) / 2; + int z = item.Pose.Position.z + BLOCK(3) * phd_cos(item.Pose.Orientation.y) / 2; - if (pointColl.GetRoomNumber() != item->RoomNumber) - ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); + auto aheadPointColl = GetPointCollision(Vector3i(x, item.Pose.Position.y, z), item.RoomNumber); + int floorHeight = aheadPointColl.GetFloorHeight(); + int relFloorHeight = abs(floorHeight - item.Pose.Position.y); + int relCeilHeight = abs(aheadPointColl.GetCeilingHeight() - floorHeight); - if (isSpinning && item->Animation.ActiveState == 1) - item->Pose.Orientation.y += -ANGLE(180.0f); + if (floorHeight == NO_HEIGHT || // Is wall. + aheadPointColl.GetSector().Stopper || // Sector has stopper flag. + relCeilHeight < BLOCK(1) || // Ceiling is lower than 1 block. + relFloorHeight >= CLICK(2.5)) // Is step. + + item.Animation.TargetState = 1; + } + + isSpinning = true; + + if (item.TouchBits.TestAny()) + { + DoDamage(LaraItem, SPINNING_BLADE_DAMAGE); + DoLotsOfBlood(LaraItem->Pose.Position.x, LaraItem->Pose.Position.y - CLICK(2), LaraItem->Pose.Position.z, (short)(item.Animation.Velocity.z * 2), LaraItem->Pose.Orientation.y, LaraItem->RoomNumber, 2); + } + + SoundEffect(SFX_TR2_ROLLING_BLADE, &item.Pose); + } + else + { + if (TriggerActive(&item)) + item.Animation.TargetState = 2; + + isSpinning = false; + } + + AnimateItem(&item); + + auto pointColl = GetPointCollision(item); + + item.Floor = pointColl.GetFloorHeight(); + item.Pose.Position.y = pointColl.GetFloorHeight(); + + if (pointColl.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); + + if (isSpinning && item.Animation.ActiveState == 1) + item.Pose.Orientation.y += -ANGLE(180.0f); + } } diff --git a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.h b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.h index f1d321b8c..dc612b9cf 100644 --- a/TombEngine/Objects/TR2/Trap/tr2_spinningblade.h +++ b/TombEngine/Objects/TR2/Trap/tr2_spinningblade.h @@ -1,4 +1,7 @@ #pragma once -void InitializeSpinningBlade(short itemNumber); -void SpinningBladeControl(short itemNumber); +namespace TEN::Entities::Traps +{ + void InitializeSpinningBlade(short itemNumber); + void ControlSpinningBlade(short itemNumber); +} diff --git a/TombEngine/Objects/TR2/tr2_objects.cpp b/TombEngine/Objects/TR2/tr2_objects.cpp index 98462ec63..c69e12e3f 100644 --- a/TombEngine/Objects/TR2/tr2_objects.cpp +++ b/TombEngine/Objects/TR2/tr2_objects.cpp @@ -41,6 +41,7 @@ #include "Objects/TR2/Vehicles/skidoo.h" using namespace TEN::Entities::Creatures::TR2; +using namespace TEN::Entities::Traps; static void StartEntity(ObjectInfo* obj) { @@ -534,7 +535,7 @@ static void StartTrap(ObjectInfo* obj) if (obj->loaded) { obj->Initialize = InitializeSpinningBlade; - obj->control = SpinningBladeControl; + obj->control = ControlSpinningBlade; obj->collision = ObjectCollision; } @@ -548,7 +549,7 @@ static void StartTrap(ObjectInfo* obj) if (obj->loaded) { obj->Initialize = InitializeKillerStatue; - obj->control = KillerStatueControl; + obj->control = ControlKillerStatue; obj->collision = ObjectCollision; obj->SetHitEffect(true); } diff --git a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp index f97c28937..f32925ff2 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp @@ -391,8 +391,7 @@ namespace TEN::Entities::Creatures::TR3 pos1.z += 96; pos1 = GetJointPosition(item, TribesmanDartBite2.BoneID, pos1); - TriggerDartSmoke(pos1.x, pos1.y, pos1.z, 0, 0, true); - TriggerDartSmoke(pos1.x, pos1.y, pos1.z, 0, 0, true); + SpawnDartSmoke(pos1.ToVector3(), Vector3::Zero, true); } void TribemanDartsControl(short itemNumber) diff --git a/TombEngine/Objects/TR3/Trap/train.cpp b/TombEngine/Objects/TR3/Trap/train.cpp index 0bd209b1d..aee8a2e81 100644 --- a/TombEngine/Objects/TR3/Trap/train.cpp +++ b/TombEngine/Objects/TR3/Trap/train.cpp @@ -19,121 +19,126 @@ using namespace TEN::Collision::Point; -constexpr auto TRAIN_VEL = 260; - -long TrainTestHeight(ItemInfo* item, long x, long z, short* roomNumber) +namespace TEN::Entities::Traps { - float sinX = phd_sin(item->Pose.Orientation.x); - float sinY = phd_sin(item->Pose.Orientation.y); - float cosY = phd_cos(item->Pose.Orientation.y); - float sinZ = phd_sin(item->Pose.Orientation.z); + constexpr auto TRAIN_VEL = 260; - auto pos = Vector3i( - round(item->Pose.Position.x + ((z * sinY) + (x * cosY))), - round(item->Pose.Position.y - ((z * sinX) + (x * sinZ))), - round(item->Pose.Position.z + ((z * cosY) - (x * sinY)))); - auto pointColl = GetPointCollision(pos, item->RoomNumber); - - *roomNumber = pointColl.GetRoomNumber(); - return pointColl.GetFloorHeight(); -} - -void TrainControl(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - if (!TriggerActive(item)) - return; - - if (item->ItemFlags[0] == 0) - item->ItemFlags[0] = item->ItemFlags[1] = TRAIN_VEL; - - float sinY = phd_sin(item->Pose.Orientation.y); - float cosY = phd_cos(item->Pose.Orientation.y); - - item->Pose.Position.x += item->ItemFlags[1] * sinY; - item->Pose.Position.z += item->ItemFlags[1] * cosY; - - short roomNumber; - long rh = TrainTestHeight(item, 0, BLOCK(5), &roomNumber); - long floorHeight = TrainTestHeight(item, 0, 0, &roomNumber); - item->Pose.Position.y = floorHeight; - - if (floorHeight == NO_HEIGHT) + long TrainTestHeight(ItemInfo* item, long x, long z, short* roomNumber) { - KillItem(itemNumber); - return; + float sinX = phd_sin(item->Pose.Orientation.x); + float sinY = phd_sin(item->Pose.Orientation.y); + float cosY = phd_cos(item->Pose.Orientation.y); + float sinZ = phd_sin(item->Pose.Orientation.z); + + auto pos = Vector3i( + round(item->Pose.Position.x + ((z * sinY) + (x * cosY))), + round(item->Pose.Position.y - ((z * sinX) + (x * sinZ))), + round(item->Pose.Position.z + ((z * cosY) - (x * sinY)))); + auto pointColl = GetPointCollision(pos, item->RoomNumber); + + *roomNumber = pointColl.GetRoomNumber(); + return pointColl.GetFloorHeight(); } - item->Pose.Position.y -= 32;// ? - - short probedRoomNumber = GetPointCollision(*item).GetRoomNumber(); - if (probedRoomNumber != item->RoomNumber) - ItemNewRoom(itemNumber, probedRoomNumber); - - item->Pose.Orientation.x = -(rh - floorHeight) * 2; - - TriggerDynamicLight(item->Pose.Position.x + BLOCK(3) * sinY, item->Pose.Position.y, item->Pose.Position.z + BLOCK(3) * cosY, 16, 31, 31, 31); - - if (item->ItemFlags[1] != TRAIN_VEL) + void ControlTrain(short itemNumber) { - item->ItemFlags[1] -= 48; - if (item->ItemFlags[1] < 0) - item->ItemFlags[1] = 0; + auto& item = g_Level.Items[itemNumber]; - if (!UseForcedFixedCamera) + if (!TriggerActive(&item)) + return; + + if (item.ItemFlags[0] == 0) + item.ItemFlags[0] = item.ItemFlags[1] = TRAIN_VEL; + + float sinY = phd_sin(item.Pose.Orientation.y); + float cosY = phd_cos(item.Pose.Orientation.y); + + item.Pose.Position.x += item.ItemFlags[1] * sinY; + item.Pose.Position.z += item.ItemFlags[1] * cosY; + + short roomNumber; + long rh = TrainTestHeight(&item, 0, BLOCK(5), &roomNumber); + long floorHeight = TrainTestHeight(&item, 0, 0, &roomNumber); + item.Pose.Position.y = floorHeight; + + if (floorHeight == NO_HEIGHT) { - ForcedFixedCamera.x = item->Pose.Position.x + BLOCK(8) * sinY; - ForcedFixedCamera.z = item->Pose.Position.z + BLOCK(8) * cosY; + KillItem(itemNumber); + return; + } - ForcedFixedCamera.y = GetPointCollision(Vector3i(ForcedFixedCamera.x, item->Pose.Position.y - CLICK(2), ForcedFixedCamera.z), item->RoomNumber).GetFloorHeight(); + item.Pose.Position.y -= 32;// ? - ForcedFixedCamera.RoomNumber = roomNumber; - UseForcedFixedCamera = 1; + int probedRoomNumber = GetPointCollision(item).GetRoomNumber(); + if (probedRoomNumber != item.RoomNumber) + ItemNewRoom(itemNumber, probedRoomNumber); + + item.Pose.Orientation.x = -(rh - floorHeight) * 2; + + TriggerDynamicLight(item.Pose.Position.x + BLOCK(3) * sinY, item.Pose.Position.y, item.Pose.Position.z + BLOCK(3) * cosY, 16, 31, 31, 31); + + if (item.ItemFlags[1] != TRAIN_VEL) + { + item.ItemFlags[1] -= 48; + if (item.ItemFlags[1] < 0) + item.ItemFlags[1] = 0; + + if (!UseForcedFixedCamera) + { + ForcedFixedCamera.x = item.Pose.Position.x + BLOCK(8) * sinY; + ForcedFixedCamera.z = item.Pose.Position.z + BLOCK(8) * cosY; + + ForcedFixedCamera.y = GetPointCollision(Vector3i(ForcedFixedCamera.x, item.Pose.Position.y - CLICK(2), ForcedFixedCamera.z), item.RoomNumber).GetFloorHeight(); + + ForcedFixedCamera.RoomNumber = roomNumber; + UseForcedFixedCamera = 1; + } + } + else + { + SoundEffect(SFX_TR3_TUBE_LOOP, &item.Pose, SoundEnvironment::Always); } } - else - SoundEffect(SFX_TR3_TUBE_LOOP, &item->Pose, SoundEnvironment::Always); -} - -void TrainCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) -{ - auto* item = &g_Level.Items[itemNumber]; - auto* laraInfo = GetLaraInfo(laraItem); - - if (!TestBoundsCollide(item, laraItem, coll->Setup.Radius)) - return; - - if (!TestCollision(item, laraItem)) - return; - - SoundEffect(SFX_TR4_LARA_GENERAL_DEATH, &laraItem->Pose, SoundEnvironment::Always); - SoundEffect(SFX_TR4_LARA_HIGH_FALL_DEATH, &laraItem->Pose, SoundEnvironment::Always); - StopSoundEffect(SFX_TR3_TUBE_LOOP); - - SetAnimation(*laraItem, ID_LARA_EXTRA_ANIMS, LEA_TRAIN_DEATH_START); - laraItem->Animation.IsAirborne = false; - laraItem->Animation.Velocity.y = 0.0f; - laraItem->Animation.Velocity.z = 0.0f; - laraItem->Pose.Orientation.y = item->Pose.Orientation.y; - - DoDamage(laraItem, INT_MAX); - - AnimateItem(laraItem); - - laraInfo->ExtraAnim = 1; - laraInfo->Control.HandStatus = HandStatus::Busy; - laraInfo->Control.Weapon.GunType = LaraWeaponType::None; - laraInfo->HitDirection = -1; - laraInfo->Status.Air = -1; - - item->ItemFlags[1] = 160; - - float sinY = phd_sin(item->Pose.Orientation.y); - float cosY = phd_cos(item->Pose.Orientation.y); - - long x = laraItem->Pose.Position.x + CLICK(1) * sinY; - long z = laraItem->Pose.Position.z + CLICK(1) * cosY; - - DoLotsOfBlood(x, laraItem->Pose.Position.y - CLICK(2), z, BLOCK(1), item->Pose.Orientation.y, laraItem->RoomNumber, 15); + + void CollideTrain(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) + { + auto& item = g_Level.Items[itemNumber]; + auto& player = GetLaraInfo(*playerItem); + + if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) + return; + + if (!TestCollision(&item, playerItem)) + return; + + SoundEffect(SFX_TR4_LARA_GENERAL_DEATH, &playerItem->Pose, SoundEnvironment::Always); + SoundEffect(SFX_TR4_LARA_HIGH_FALL_DEATH, &playerItem->Pose, SoundEnvironment::Always); + StopSoundEffect(SFX_TR3_TUBE_LOOP); + + SetAnimation(*playerItem, ID_LARA_EXTRA_ANIMS, LEA_TRAIN_DEATH_START); + playerItem->Animation.IsAirborne = false; + playerItem->Animation.Velocity.y = 0.0f; + playerItem->Animation.Velocity.z = 0.0f; + playerItem->Pose.Orientation.y = item.Pose.Orientation.y; + + DoDamage(playerItem, INT_MAX); + + AnimateItem(playerItem); + + player.ExtraAnim = 1; + player.Control.HandStatus = HandStatus::Busy; + player.Control.Weapon.GunType = LaraWeaponType::None; + player.HitDirection = NO_VALUE; + player.Status.Air = NO_VALUE; + + item.ItemFlags[1] = 160; + + float sinY = phd_sin(item.Pose.Orientation.y); + float cosY = phd_cos(item.Pose.Orientation.y); + + long x = playerItem->Pose.Position.x + CLICK(1) * sinY; + long z = playerItem->Pose.Position.z + CLICK(1) * cosY; + + DoLotsOfBlood(x, playerItem->Pose.Position.y - CLICK(2), z, BLOCK(1), item.Pose.Orientation.y, playerItem->RoomNumber, 15); + } } diff --git a/TombEngine/Objects/TR3/Trap/train.h b/TombEngine/Objects/TR3/Trap/train.h index 4d58d54d7..c8780d0ed 100644 --- a/TombEngine/Objects/TR3/Trap/train.h +++ b/TombEngine/Objects/TR3/Trap/train.h @@ -1,7 +1,10 @@ #pragma once -#include "Game/items.h" -#include "Game/collision/collide_room.h" +struct CollisionInfo; +struct ItemInfo; -void TrainControl(short itemNumber); -void TrainCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); +namespace TEN::Entities::Traps +{ + void ControlTrain(short itemNumber); + void CollideTrain(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); +} diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index 2b607a6ca..663f8de36 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -484,8 +484,8 @@ static void StartTrap(ObjectInfo* obj) obj = &Objects[ID_TRAIN]; if (obj->loaded) { - obj->control = TrainControl; - obj->collision = TrainCollision; + obj->control = ControlTrain; + obj->collision = CollideTrain; obj->SetHitEffect(true); } diff --git a/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp b/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp index 83900153e..6a54d69eb 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.cpp @@ -18,124 +18,159 @@ using namespace TEN::Gui; +// NOTES: +// item.ItemFlags[0] = Gun flash duration in frame time. +// item.ItemFlags[1] = Radar angle. +// item.ItemFlags[2] = Barrel angle. +// item.ItemFlags[3] = Object ID of inventory item which deactivates sentry gun if present. + namespace TEN::Entities::TR4 { + constexpr auto SENTRYGUN_SHOT_DAMAGE = 5; + + const auto SentryGunRadarJoints = std::vector{ 3 }; + const auto SentryGunBarrelJoints = std::vector{ 4 }; + const auto SentryGunFuelCanJoints = std::vector{ 6 }; + const auto SentryGunFlashJoints = std::vector{ 8 }; + const auto SentryGunBodyJoints = std::vector{ 7, 9 }; + const auto SentryGunFlameOffset = Vector3i(-140, 0, 0); const auto SentryGunBite = CreatureBiteInfo(Vector3::Zero, 8); void InitializeSentryGun(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; InitializeCreature(itemNumber); - item->ItemFlags[0] = 0; - item->ItemFlags[1] = 768; - item->ItemFlags[2] = 0; + + auto& flashDuration = item.ItemFlags[0]; + auto& radarAngle = item.ItemFlags[1]; + auto& barrelAngle = item.ItemFlags[2]; + auto& deactivatorItemObjctID = item.ItemFlags[3]; + + flashDuration = 0; + radarAngle = 768; + barrelAngle = 0; + + if (deactivatorItemObjctID == 0) + deactivatorItemObjctID = ID_PUZZLE_ITEM5; } - void SentryGunControl(short itemNumber) + void ControlSentryGun(short itemNumber) { if (!CreatureActive(itemNumber)) return; - auto* item = &g_Level.Items[itemNumber]; - auto* creature = GetCreatureInfo(item); + auto& item = g_Level.Items[itemNumber]; + auto* creature = GetCreatureInfo(&item); - int c = 0; + auto& flashDuration = item.ItemFlags[0]; + auto& radarAngle = item.ItemFlags[1]; + auto& barrelAngle = item.ItemFlags[2]; + auto& deactivatorItemObjectID = item.ItemFlags[3]; - if (!creature) + int headingAngle = 0; + + // TODO: Why this check? + if (creature == nullptr) return; // Was fuel can exploded? - if (item->MeshBits.Test(6)) + if (item.MeshBits.Test(SentryGunFuelCanJoints)) { - if (item->ItemFlags[0]) + if (flashDuration) { auto pos = GetJointPosition(item, SentryGunBite); - TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * item->ItemFlags[0] + 12, 24, 16, 4); - item->ItemFlags[0]--; + TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * flashDuration + 12, 24, 16, 4); + flashDuration--; } - if (item->ItemFlags[0] & 1) - item->MeshBits.Set(8); - else - item->MeshBits.Clear(8); - - if (item->TriggerFlags == 0) + if (flashDuration & 1) { - item->Pose.Position.y -= CLICK(2); + item.MeshBits.Set(SentryGunFlashJoints); + } + else + { + item.MeshBits.Clear(SentryGunFlashJoints); + } - AI_INFO AI; - CreatureAIInfo(item, &AI); + if (item.TriggerFlags == 0) + { + item.Pose.Position.y -= CLICK(2); - item->Pose.Position.y += CLICK(2); + AI_INFO ai; + CreatureAIInfo(&item, &ai); - int deltaAngle = AI.angle - creature->JointRotation[0]; + item.Pose.Position.y += CLICK(2); - AI.ahead = true; - if (deltaAngle <= -ANGLE(90.0f) || deltaAngle >= ANGLE(90.0f)) - AI.ahead = false; + int deltaAngle = ai.angle - creature->JointRotation[0]; - if (Targetable(item, &AI)) + ai.ahead = true; + if (deltaAngle <= ANGLE(-90.0f) || deltaAngle >= ANGLE(90.0f)) + ai.ahead = false; + + if (Targetable(&item, &ai)) { - if (AI.distance < pow(BLOCK(9), 2)) + if (ai.distance < SQUARE(BLOCK(9))) { - if (!g_Gui.IsObjectInInventory(ID_PUZZLE_ITEM5) && !item->ItemFlags[0]) + if (!g_Gui.IsObjectInInventory(deactivatorItemObjectID) && !flashDuration) { - if (AI.distance <= pow(BLOCK(2), 2)) + if (ai.distance <= SQUARE(BLOCK(2))) { - // Throw fire + // Throw fire. ThrowFire(itemNumber, 7, SentryGunFlameOffset, SentryGunFlameOffset); - c = phd_sin((GlobalCounter & 0x1F) * 2048) * 4096; + headingAngle = phd_sin((GlobalCounter & 0x1F) * 2048) * 4096; // TODO: Demagic. } else { - // Shot to Lara with bullets - c = 0; - item->ItemFlags[0] = 2; + // Shoot player. + headingAngle = 0; + flashDuration = 2; - ShotLara(item, &AI, SentryGunBite, creature->JointRotation[0], 5); - SoundEffect(SFX_TR4_AUTOGUNS, &item->Pose); + ShotLara(&item, &ai, SentryGunBite, creature->JointRotation[0], SENTRYGUN_SHOT_DAMAGE); + SoundEffect(SFX_TR4_AUTOGUNS, &item.Pose); - item->ItemFlags[2] += 256; - if (item->ItemFlags[2] > 6144) - item->ItemFlags[2] = 6144; + barrelAngle += ANGLE(1.5f); + if (barrelAngle > ANGLE(45.0f)) + barrelAngle = ANGLE(45.0f); } } - deltaAngle = c + AI.angle - creature->JointRotation[0]; + deltaAngle = (headingAngle + ai.angle) - creature->JointRotation[0]; if (deltaAngle <= ANGLE(10.0f)) { - if (deltaAngle < -ANGLE(10.0f)) - deltaAngle = -ANGLE(10.0f); + if (deltaAngle < ANGLE(-10.0f)) + deltaAngle = ANGLE(-10.0f); } else + { deltaAngle = ANGLE(10.0f); + } creature->JointRotation[0] += deltaAngle; - CreatureJoint(item, 1, -AI.xAngle); + CreatureJoint(&item, 1, -ai.xAngle); } } - // Rotating gunbarrel - item->ItemFlags[2] -= 32; - if (item->ItemFlags[2] < 0) - item->ItemFlags[2] = 0; + // Rotate barrel. + barrelAngle -= 32; + if (barrelAngle < 0) + barrelAngle = 0; - creature->JointRotation[3] += item->ItemFlags[2]; + creature->JointRotation[3] += barrelAngle; - // Rotating radar - creature->JointRotation[2] += item->ItemFlags[1]; - if (creature->JointRotation[2] > ANGLE(90.0f) || creature->JointRotation[2] < -ANGLE(90.0f)) - item->ItemFlags[1] = -item->ItemFlags[1]; + // Rotate radar. + creature->JointRotation[2] += radarAngle; + if (creature->JointRotation[2] > ANGLE(90.0f) || creature->JointRotation[2] < ANGLE(-90.0f)) + radarAngle = -radarAngle; } else { - // Stuck sentry gun - CreatureJoint(item, 0, (GetRandomControl() & 0x7FF) - 1024); - CreatureJoint(item, 1, ANGLE(45.0f)); - CreatureJoint(item, 2, (GetRandomControl() & 0x3FFF) - ANGLE(45.0f)); + // Stuck sentry gun. + CreatureJoint(&item, 0, (GetRandomControl() & 0x7FF) - 1024); + CreatureJoint(&item, 1, ANGLE(45.0f)); + CreatureJoint(&item, 2, (GetRandomControl() & 0x3FFF) - ANGLE(45.0f)); } } else @@ -144,17 +179,17 @@ namespace TEN::Entities::TR4 DisableEntityAI(itemNumber); KillItem(itemNumber); - item->Flags |= 1u; - item->Status = ITEM_DEACTIVATED; + item.Flags |= 1; + item.Status = ITEM_DEACTIVATED; - RemoveAllItemsInRoom(item->RoomNumber, ID_SMOKE_EMITTER_BLACK); + RemoveAllItemsInRoom(item.RoomNumber, ID_SMOKE_EMITTER_BLACK); - TriggerExplosionSparks(item->Pose.Position.x, item->Pose.Position.y - CLICK(3), item->Pose.Position.z, 3, -2, 0, item->RoomNumber); + TriggerExplosionSparks(item.Pose.Position.x, item.Pose.Position.y - CLICK(3), item.Pose.Position.z, 3, -2, 0, item.RoomNumber); for (int i = 0; i < 2; i++) - TriggerExplosionSparks(item->Pose.Position.x, item->Pose.Position.y - CLICK(3), item->Pose.Position.z, 3, -1, 0, item->RoomNumber); + TriggerExplosionSparks(item.Pose.Position.x, item.Pose.Position.y - CLICK(3), item.Pose.Position.z, 3, -1, 0, item.RoomNumber); - SoundEffect(SFX_TR4_EXPLOSION1, &item->Pose, SoundEnvironment::Land, 1.5f); - SoundEffect(SFX_TR4_EXPLOSION2, &item->Pose); + SoundEffect(SFX_TR4_EXPLOSION1, &item.Pose, SoundEnvironment::Land, 1.5f); + SoundEffect(SFX_TR4_EXPLOSION2, &item.Pose); } } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.h b/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.h index 195f268eb..937553872 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.h +++ b/TombEngine/Objects/TR4/Entity/tr4_sentry_gun.h @@ -3,5 +3,5 @@ namespace TEN::Entities::TR4 { void InitializeSentryGun(short itemNumber); - void SentryGunControl(short itemNumber); + void ControlSentryGun(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_birdblade.cpp b/TombEngine/Objects/TR4/Trap/tr4_birdblade.cpp index cf9626f90..e897279ce 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_birdblade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_birdblade.cpp @@ -1,33 +1,45 @@ #include "framework.h" -#include "tr4_birdblade.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_birdblade.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void BirdBladeControl(short itemNumber) + void InitializeBirdBlade(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - item->ItemFlags[3] = 100; + item.ItemFlags[4] = 1; + } - if (!TriggerActive(item)) + void ControlBirdBlade(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + item.ItemFlags[3] = 100; + + if (!TriggerActive(&item)) { - item->Animation.FrameNumber = GetAnimData(item).frameBase; - *((int*)&item->ItemFlags[0]) = 0; + item.Animation.FrameNumber = GetAnimData(item).frameBase; + *((int*)&item.ItemFlags[0]) = 0; } else { - int frameNumber = item->Animation.FrameNumber - GetAnimData(item).frameBase; + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; if (frameNumber <= 14 || frameNumber >= 31) - *((int*)&item->ItemFlags[0]) = 0; + { + *((int*)&item.ItemFlags[0]) = 0; + } else - *((int*)&item->ItemFlags[0]) = 6; + { + *((int*)&item.ItemFlags[0]) = 6; + } - AnimateItem(item); + AnimateItem(&item); } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_birdblade.h b/TombEngine/Objects/TR4/Trap/tr4_birdblade.h index 31ec3dce3..397834fdb 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_birdblade.h +++ b/TombEngine/Objects/TR4/Trap/tr4_birdblade.h @@ -1,6 +1,7 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void BirdBladeControl(short itemNumber); + void InitializeBirdBlade(short itemNumber); + void ControlBirdBlade(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_blade.cpp b/TombEngine/Objects/TR4/Trap/tr4_blade.cpp index cb6369593..ed011bb4d 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_blade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_blade.cpp @@ -1,62 +1,49 @@ #include "framework.h" -#include "tr4_blade.h" -#include "Specific/level.h" -#include "Game/collision/collide_room.h" +#include "Objects/TR4/Trap/tr4_blade.h" + #include "Game/collision/collide_item.h" -#include "Game/Lara/lara.h" +#include "Game/collision/collide_room.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void BladeCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) + void CollideBlade(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) { - auto* bladeItem = &g_Level.Items[itemNumber]; + auto& bladeItem = g_Level.Items[itemNumber]; - if (bladeItem->Status == ITEM_INVISIBLE) + if (bladeItem.Status == ITEM_INVISIBLE) return; - if (bladeItem->ItemFlags[3]) + if (!bladeItem.ItemFlags[3]) + return; + + if (!TestBoundsCollide(&bladeItem, playerItem, coll->Setup.Radius)) + return; + + auto prevPos = playerItem->Pose.Position; + + if (!ItemPushItem(&bladeItem, playerItem, coll, true, 1)) + return; + + DoDamage(playerItem, bladeItem.ItemFlags[3]); + + auto deltaPos = prevPos - playerItem->Pose.Position; + if (deltaPos != Vector3i::Zero && TriggerActive(&bladeItem)) { - if (TestBoundsCollide(bladeItem, laraItem, coll->Setup.Radius)) - { - int oldX = laraItem->Pose.Position.x; - int oldY = laraItem->Pose.Position.y; - int oldZ = laraItem->Pose.Position.z; - - int dx = 0; - int dy = 0; - int dz = 0; - - if (ItemPushItem(bladeItem, laraItem, coll, true, 1)) - { - DoDamage(laraItem, bladeItem->ItemFlags[3]); - - dx = oldX - laraItem->Pose.Position.x; - dy = oldY - laraItem->Pose.Position.y; - dz = oldZ - laraItem->Pose.Position.z; - - if ((dx || dy || dz) && TriggerActive(bladeItem)) - { - DoBloodSplat( - (GetRandomControl() & 0x3F) + laraItem->Pose.Position.x - 32, - laraItem->Pose.Position.y - (GetRandomControl() & 0x1FF) - 256, - (GetRandomControl() & 0x3F) + laraItem->Pose.Position.z - 32, - (GetRandomControl() & 3) + (bladeItem->ItemFlags[3] / 32) + 2, - 2 * GetRandomControl(), - laraItem->RoomNumber - ); - } - - if (!coll->Setup.EnableObjectPush) - { - laraItem->Pose.Position.x += dx; - laraItem->Pose.Position.y += dy; - laraItem->Pose.Position.z += dz; - } - } - } + DoBloodSplat( + (GetRandomControl() & 0x3F) + playerItem->Pose.Position.x - 32, + playerItem->Pose.Position.y - (GetRandomControl() & 0x1FF) - 256, + (GetRandomControl() & 0x3F) + playerItem->Pose.Position.z - 32, + (GetRandomControl() & 3) + (bladeItem.ItemFlags[3] / 32) + 2, + Random::GenerateAngle(), + playerItem->RoomNumber); } + + if (!coll->Setup.EnableObjectPush) + playerItem->Pose.Position += deltaPos; } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_blade.h b/TombEngine/Objects/TR4/Trap/tr4_blade.h index 799b20831..616ea4514 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_blade.h +++ b/TombEngine/Objects/TR4/Trap/tr4_blade.h @@ -3,7 +3,7 @@ struct ItemInfo; struct CollisionInfo; -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void BladeCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); + void CollideBlade(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.cpp b/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.cpp index 887ccb796..32772265c 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.cpp @@ -1,28 +1,35 @@ #include "framework.h" -#include "tr4_catwalkblade.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_catwalkblade.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void CatwalkBladeControl(short itemNumber) + void ControlCatwalkBlade(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (!TriggerActive(item)) - item->Animation.FrameNumber = GetAnimData(item).frameBase; + if (!TriggerActive(&item)) + { + item.Animation.FrameNumber = GetAnimData(item).frameBase; + } else { - int frameNumber = item->Animation.FrameNumber - GetAnimData(item).frameBase; + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; - if (item->Animation.FrameNumber == GetAnimData(item).frameEnd || frameNumber < 38) - item->ItemFlags[3] = 0; + if (item.Animation.FrameNumber == GetAnimData(item).frameEnd || frameNumber < 38) + { + item.ItemFlags[3] = 0; + } else - item->ItemFlags[3] = 100; + { + item.ItemFlags[3] = 100; + } - AnimateItem(item); + AnimateItem(&item); } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.h b/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.h index c95f05ff8..b470b7005 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.h +++ b/TombEngine/Objects/TR4/Trap/tr4_catwalkblade.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void CatwalkBladeControl(short itemNumber); + void ControlCatwalkBlade(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_chain.cpp b/TombEngine/Objects/TR4/Trap/tr4_chain.cpp index c81b77f49..d6f650447 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_chain.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_chain.cpp @@ -1,40 +1,41 @@ #include "framework.h" -#include "tr4_chain.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_chain.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void ChainControl(short itemNumber) + void ControlChain(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (item->TriggerFlags) + if (item.TriggerFlags) { - item->ItemFlags[2] = 1; - item->ItemFlags[3] = 75; + item.ItemFlags[2] = 1; + item.ItemFlags[3] = 75; - if (TriggerActive(item)) + if (TriggerActive(&item)) { - *((int*)&item->ItemFlags[0]) = 0x787E; - AnimateItem(item); + *((int*)&item.ItemFlags[0]) = 0x787E; + AnimateItem(&item); return; } } else { - item->ItemFlags[3] = 25; + item.ItemFlags[3] = 25; - if (TriggerActive(item)) + if (TriggerActive(&item)) { - *((int*)&item->ItemFlags[0]) = 0x780; - AnimateItem(item); + *((int*)&item.ItemFlags[0]) = 0x780; + AnimateItem(&item); return; } } - *((int*)&item->ItemFlags[0]) = 0; + *((int*)&item.ItemFlags[0]) = 0; } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_chain.h b/TombEngine/Objects/TR4/Trap/tr4_chain.h index de97e60bd..6a09dd1a6 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_chain.h +++ b/TombEngine/Objects/TR4/Trap/tr4_chain.h @@ -1,9 +1,6 @@ #pragma once -struct ItemInfo; -struct CollisionInfo; - -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void ChainControl(short itemNumber); + void ControlChain(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_cog.cpp b/TombEngine/Objects/TR4/Trap/tr4_cog.cpp index e334eb854..514b4bcc9 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_cog.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_cog.cpp @@ -1,64 +1,58 @@ #include "framework.h" -#include "tr4_cog.h" -#include "Specific/level.h" -#include "Game/control/control.h" -#include "Sound/sound.h" -#include "Game/collision/collide_room.h" -#include "Game/collision/collide_item.h" -#include "Game/effects/effects.h" -#include "Game/Lara/lara.h" +#include "Objects/TR4/Trap/tr4_cog.h" + #include "Game/animation.h" +#include "Game/collision/collide_item.h" +#include "Game/collision/collide_room.h" +#include "Game/control/control.h" +#include "Game/effects/effects.h" #include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Sound/sound.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void CogControl(short itemNumber) - { - auto* item = &g_Level.Items[itemNumber]; + void ControlCog(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; - if (TriggerActive(item)) - { - item->Status = ITEM_ACTIVE; - AnimateItem(item); + if (TriggerActive(&item)) + { + item.Status = ITEM_ACTIVE; + AnimateItem(&item); + } + else if (item.TriggerFlags == 2) + { + item.Status |= ITEM_INVISIBLE; + } + } - if (item->TriggerFlags == 666) - { - auto pos = GetJointPosition(item, 0); - SoundEffect(SFX_TR4_LIBRARY_COG_LOOP, (Pose*)&pos); - - //Shouldnt this be TR4_LIBRARY_COG_LOOP? Changed. Rollback if incorrect. Stranger1992 06/06/22 + void CollideCog(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) + { + auto& cogItem = g_Level.Items[itemNumber]; + + if (cogItem.Status == ITEM_INVISIBLE) + return; - if (item->Animation.FrameNumber == GetAnimData(item).frameEnd) - item->Flags &= 0xC1; - } - } - else if (item->TriggerFlags == 2) - item->Status |= ITEM_INVISIBLE; - } + if (!TestBoundsCollide(&cogItem, playerItem, coll->Setup.Radius)) + return; - void CogCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) - { - auto* cogItem = &g_Level.Items[itemNumber]; - - if (cogItem->Status != ITEM_INVISIBLE) - { - if (TestBoundsCollide(cogItem, laraItem, coll->Setup.Radius)) - { - if (TriggerActive(cogItem)) - { - DoBloodSplat( - (GetRandomControl() & 0x3F) + laraItem->Pose.Position.x - 32, - (GetRandomControl() & 0x1F) + cogItem->Pose.Position.y - 16, - (GetRandomControl() & 0x3F) + laraItem->Pose.Position.z - 32, - (GetRandomControl() & 3) + 2, - 2 * GetRandomControl(), - laraItem->RoomNumber); + if (TriggerActive(&cogItem)) + { + DoBloodSplat( + (GetRandomControl() & 0x3F) + playerItem->Pose.Position.x - 32, + (GetRandomControl() & 0x1F) + cogItem.Pose.Position.y - 16, + (GetRandomControl() & 0x3F) + playerItem->Pose.Position.z - 32, + (GetRandomControl() & 3) + 2, + Random::GenerateAngle(), + playerItem->RoomNumber); - DoDamage(laraItem, 10); - } - else if (coll->Setup.EnableObjectPush) - ItemPushItem(cogItem, laraItem, coll, false, 0); - } - } - } + DoDamage(playerItem, 10); + } + else if (coll->Setup.EnableObjectPush) + { + ItemPushItem(&cogItem, playerItem, coll, false, 0); + } + } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_cog.h b/TombEngine/Objects/TR4/Trap/tr4_cog.h index db7829b22..22a4c8bb9 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_cog.h +++ b/TombEngine/Objects/TR4/Trap/tr4_cog.h @@ -3,8 +3,8 @@ struct ItemInfo; struct CollisionInfo; -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void CogControl(short itemNumber); - void CogCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); + void ControlCog(short itemNumber); + void CollideCog(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_fourblades.cpp b/TombEngine/Objects/TR4/Trap/tr4_fourblades.cpp index bae0f4d45..0c5d0d0d0 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_fourblades.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_fourblades.cpp @@ -1,45 +1,64 @@ #include "framework.h" -#include "tr4_fourblades.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_fourblades.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +// NOTES: +// item.ItemFlags[0] = Damage joints. +// item.ItemFlags[3] = Damage. +// item.ItemFlags[4] = Push player (bool). + +namespace TEN::Entities::Traps { - void FourBladesControl(short itemNumber) - { - auto* item = &g_Level.Items[itemNumber]; + constexpr auto FOUR_BLADES_EMERGE_HARM_DAMAGE = 20; + constexpr auto FOUR_BLADES_IDLE_HARM_DAMAGE = 200; - if (!TriggerActive(item)) + constexpr auto FOUR_BLADES_HARM_JOINTS = MESH_BITS(1) | MESH_BITS(2) | MESH_BITS(3) | MESH_BITS(4); + + void InitializeFourBlades(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + item.ItemFlags[4] = 1; + } + + void ControlFourBlades(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (!TriggerActive(&item)) { - item->Animation.FrameNumber = GetAnimData(item).frameBase; - *((int*)&item->ItemFlags[0]) = 0; + item.Animation.FrameNumber = GetAnimData(item).frameBase; + item.ItemFlags[0] = 0; } else { - int frameNumber = item->Animation.FrameNumber - GetAnimData(item).frameBase; + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; if (frameNumber <= 5 || frameNumber >= 58 || frameNumber >= 8 && frameNumber <= 54) { - *((int*)&item->ItemFlags[0]) = 0; + item.ItemFlags[0] = 0; + item.ItemFlags[3] = 0; } else { + item.ItemFlags[0] = FOUR_BLADES_HARM_JOINTS; + if (frameNumber >= 6 && frameNumber <= 7) { - item->ItemFlags[3] = 20; - *((int*)&item->ItemFlags[0]) = 30; + item.ItemFlags[3] = FOUR_BLADES_EMERGE_HARM_DAMAGE; } else if (frameNumber >= 55 && frameNumber <= 57) { - item->ItemFlags[3] = 200; - *((int*)&item->ItemFlags[0]) = 30; + item.ItemFlags[3] = FOUR_BLADES_IDLE_HARM_DAMAGE; } } - AnimateItem(item); + AnimateItem(&item); } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_fourblades.h b/TombEngine/Objects/TR4/Trap/tr4_fourblades.h index dc5dd0f9b..7c89e948a 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_fourblades.h +++ b/TombEngine/Objects/TR4/Trap/tr4_fourblades.h @@ -1,6 +1,7 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void FourBladesControl(short itemNumber); + void InitializeFourBlades(short itemNumber); + void ControlFourBlades(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp b/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp index 8dcd9c655..773134cf9 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp @@ -14,171 +14,185 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" -constexpr auto RIGHT_HAMMER_BITS = ((1 << 5) | (1 << 6) | (1 << 7)); -constexpr auto LEFT_HAMMER_BITS = ((1 << 8) | (1 << 9) | (1 << 10)); -constexpr auto HAMMER_HIT_DAMAGE = 150; -constexpr auto HAMMER_OCB4_INTERVAL = 60; -constexpr auto HAMMER_HIT_FRAME = 8; //frame the hammer explodes pushables -constexpr auto HAMMER_CLOSED_FRAME = 52; //frame the hammer is fully closed +// NOTES: +// ItemFlags[0] | ItemFlags[1] = Harm joints. +// ItemFlags[2] = Timer in frame time before next activation. +// ItemFlags[3] = Damage. -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { + constexpr auto HAMMER_HIT_DAMAGE = 150; + constexpr auto HAMMER_OCB4_INTERVAL = 60; + constexpr auto HAMMER_HIT_FRAME = 8; // Frame pushables can be destroyed. + constexpr auto HAMMER_CLOSED_FRAME = 52; // Frame on whcih hammer is fully closed. - enum HammerState - { - HAMMER_STATE_NONE = 0, - HAMMER_STATE_IDLE = 1, - HAMMER_STATE_ACTIVE = 2, - }; + constexpr auto RIGHT_HAMMER_BITS = (1 << 5) | (1 << 6) | (1 << 7); + constexpr auto LEFT_HAMMER_BITS = (1 << 8) | (1 << 9) | (1 << 10); - enum HammerAnim - { - HAMMER_ANIM_NOT_ACTIVATED = 0, - HAMMER_ANIM_ACTIVATED = 1 - }; + enum HammerState + { + HAMMER_STATE_NONE = 0, + HAMMER_STATE_IDLE = 1, + HAMMER_STATE_ACTIVE = 2, + }; - //ItemFlags[0] | ItemFlags[1] = hurtful bits. - //ItemFlags[2] = Timer. (X amount of frames before triggering again) - //ItemFlags[3] = Famage dealt to Lara at touch, per frame. + enum HammerAnim + { + HAMMER_ANIM_INACTIVE = 0, + HAMMER_ANIM_ACTIVE = 1 + }; - void HammerControl(short itemNumber) - { - auto* item = &g_Level.Items[itemNumber]; - int frameNumber = item->Animation.FrameNumber - GetAnimData(item).frameBase; - item->ItemFlags[3] = HAMMER_HIT_DAMAGE; + void ControlHammer(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; - if (!TriggerActive(item)) - { - *(long*)&item->ItemFlags[0] = 0; - return; - } + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; + item.ItemFlags[3] = HAMMER_HIT_DAMAGE; - int hammerTouched = 0; + if (!TriggerActive(&item)) + { + *(long*)&item.ItemFlags[0] = 0; + return; + } - if (!item->TriggerFlags) - { - if (frameNumber < HAMMER_CLOSED_FRAME) - *(long*)&item->ItemFlags[0] = RIGHT_HAMMER_BITS; - else - *(long*)&item->ItemFlags[0] = 0; - } - else if (item->Animation.ActiveState == HAMMER_STATE_IDLE && item->Animation.TargetState == HAMMER_STATE_IDLE) - { - if (item->ItemFlags[2]) - { - if (item->TriggerFlags == 3) - { - item->Flags &= ~CODE_BITS; - item->ItemFlags[2] = 0; - } - else if (item->TriggerFlags == 4) - item->ItemFlags[2]--; - else - item->ItemFlags[2] = 0; - } - else - { - item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex + HAMMER_ANIM_ACTIVATED; - item->Animation.FrameNumber = GetAnimData(item).frameBase; - item->Animation.ActiveState = HAMMER_STATE_ACTIVE; - item->Animation.TargetState = HAMMER_STATE_ACTIVE; - item->ItemFlags[2] = HAMMER_OCB4_INTERVAL; - } - } - else - { - item->Animation.TargetState = HAMMER_STATE_IDLE; + bool isHammerTouched = false; - if (frameNumber < HAMMER_CLOSED_FRAME) - *(long*)&item->ItemFlags[0] = RIGHT_HAMMER_BITS | LEFT_HAMMER_BITS; - else - *(long*)&item->ItemFlags[0] = 0; + if (!item.TriggerFlags) + { + if (frameNumber < HAMMER_CLOSED_FRAME) + { + *(long*)&item.ItemFlags[0] = RIGHT_HAMMER_BITS; + } + else + { + *(long*)&item.ItemFlags[0] = 0; + } + } + else if (item.Animation.ActiveState == HAMMER_STATE_IDLE && item.Animation.TargetState == HAMMER_STATE_IDLE) + { + if (item.ItemFlags[2]) + { + if (item.TriggerFlags == 3) + { + item.Flags &= ~CODE_BITS; + item.ItemFlags[2] = 0; + } + else if (item.TriggerFlags == 4) + { + item.ItemFlags[2]--; + } + else + { + item.ItemFlags[2] = 0; + } + } + else + { + item.Animation.AnimNumber = Objects[item.ObjectNumber].animIndex + HAMMER_ANIM_ACTIVE; + item.Animation.FrameNumber = GetAnimData(item).frameBase; + item.Animation.ActiveState = HAMMER_STATE_ACTIVE; + item.Animation.TargetState = HAMMER_STATE_ACTIVE; + item.ItemFlags[2] = HAMMER_OCB4_INTERVAL; + } + } + else + { + item.Animation.TargetState = HAMMER_STATE_IDLE; - if (frameNumber == HAMMER_HIT_FRAME) - { - if (item->TriggerFlags == 2) - { - short targetItem = g_Level.Rooms[item->RoomNumber].itemNumber; + if (frameNumber < HAMMER_CLOSED_FRAME) + { + *(long*)&item.ItemFlags[0] = RIGHT_HAMMER_BITS | LEFT_HAMMER_BITS; + } + else + { + *(long*)&item.ItemFlags[0] = 0; + } - if (targetItem != NO_VALUE) - { - auto* target = &g_Level.Items[targetItem]; - for (; targetItem != NO_VALUE; targetItem = target->NextItem) - { - target = &g_Level.Items[targetItem]; + if (frameNumber == HAMMER_HIT_FRAME) + { + if (item.TriggerFlags == 2) + { + short targetItem = g_Level.Rooms[item.RoomNumber].itemNumber; - if (target->ObjectNumber == ID_OBELISK && target->Pose.Orientation.y == -ANGLE(270) && - g_Level.Items[target->ItemFlags[0]].Pose.Orientation.y == ANGLE(90) && - g_Level.Items[target->ItemFlags[1]].Pose.Orientation.y == 0) - { - target->Flags |= CODE_BITS; - g_Level.Items[target->ItemFlags[0]].Flags |= CODE_BITS; - g_Level.Items[target->ItemFlags[1]].Flags |= CODE_BITS; - break; - } - } - } + if (targetItem != NO_VALUE) + { + auto* target = &g_Level.Items[targetItem]; + for (; targetItem != NO_VALUE; targetItem = target->NextItem) + { + target = &g_Level.Items[targetItem]; - SoundEffect(SFX_TR4_GENERIC_HEAVY_THUD, &item->Pose); - SoundEffect(SFX_TR4_EXPLOSION2, &item->Pose); - } - else - { - short targetItem = g_Level.Rooms[item->RoomNumber].itemNumber; + if (target->ObjectNumber == ID_OBELISK && target->Pose.Orientation.y == -ANGLE(270) && + g_Level.Items[target->ItemFlags[0]].Pose.Orientation.y == ANGLE(90) && + g_Level.Items[target->ItemFlags[1]].Pose.Orientation.y == 0) + { + target->Flags |= CODE_BITS; + g_Level.Items[target->ItemFlags[0]].Flags |= CODE_BITS; + g_Level.Items[target->ItemFlags[1]].Flags |= CODE_BITS; + break; + } + } + } - if (targetItem != NO_VALUE) - { - auto* target = &g_Level.Items[targetItem]; - for (; targetItem != NO_VALUE; targetItem = target->NextItem) - { - target = &g_Level.Items[targetItem]; + SoundEffect(SFX_TR4_GENERIC_HEAVY_THUD, &item.Pose); + SoundEffect(SFX_TR4_EXPLOSION2, &item.Pose); + } + else + { + int targetItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; + if (targetItemNumber != NO_VALUE) + { + // TODO: What is this syntax? + auto* targetItem = &g_Level.Items[targetItemNumber]; + for (; targetItemNumber != NO_VALUE; targetItemNumber = targetItem->NextItem) + { + targetItem = &g_Level.Items[targetItemNumber]; - if ( (target->ObjectNumber >= ID_PUSHABLE_OBJECT1 && target->ObjectNumber <= ID_PUSHABLE_OBJECT10) || - (target->ObjectNumber >= ID_PUSHABLE_OBJECT_CLIMBABLE1 && target->ObjectNumber <= ID_PUSHABLE_OBJECT_CLIMBABLE10)) - { - if (item->Pose.Position.x == target->Pose.Position.x && - item->Pose.Position.z == target->Pose.Position.z) - { - ExplodeItemNode(target, 0, 0, 128); - KillItem(targetItem); - hammerTouched = 1; - } - } - } - } + if ((targetItem->ObjectNumber >= ID_PUSHABLE_OBJECT1 && targetItem->ObjectNumber <= ID_PUSHABLE_OBJECT10) || + (targetItem->ObjectNumber >= ID_PUSHABLE_OBJECT_CLIMBABLE1 && targetItem->ObjectNumber <= ID_PUSHABLE_OBJECT_CLIMBABLE10)) + { + if (item.Pose.Position.x == targetItem->Pose.Position.x && + item.Pose.Position.z == targetItem->Pose.Position.z) + { + ExplodeItemNode(targetItem, 0, 0, 128); + KillItem(targetItemNumber); + isHammerTouched = true; + } + } + } + } - if (hammerTouched) - { - targetItem = g_Level.Rooms[item->RoomNumber].itemNumber; + if (isHammerTouched) + { + targetItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; - if (targetItem != NO_VALUE) - { - auto* target = &g_Level.Items[targetItem]; - for (; targetItem != NO_VALUE; targetItem = target->NextItem) - { - target = &g_Level.Items[targetItem]; + if (targetItemNumber != NO_VALUE) + { + auto* target = &g_Level.Items[targetItemNumber]; + for (; targetItemNumber != NO_VALUE; targetItemNumber = target->NextItem) + { + target = &g_Level.Items[targetItemNumber]; - //changed to take all puzzle items, keys and their combos. Original is hardcoded to a few slots. -Troye - if ((target->ObjectNumber >= ID_PUZZLE_ITEM1 && target->ObjectNumber <= ID_PUZZLE_ITEM16) || - (target->ObjectNumber >= ID_PUZZLE_ITEM1_COMBO1 && target->ObjectNumber <= ID_PUZZLE_ITEM16_COMBO2) || - (target->ObjectNumber >= ID_KEY_ITEM1 && target->ObjectNumber <= ID_KEY_ITEM16) || - (target->ObjectNumber >= ID_KEY_ITEM1_COMBO1 && target->ObjectNumber <= ID_KEY_ITEM16_COMBO2)) - { - if (item->Pose.Position.x == target->Pose.Position.x && - item->Pose.Position.z == target->Pose.Position.z) - { - target->Status = ITEM_NOT_ACTIVE; - } - } - } - } - } - } - } - else if (frameNumber > HAMMER_CLOSED_FRAME && item->TriggerFlags == 2) - item->Flags &= ~CODE_BITS; - } + // Take all puzzle items, keys, and their combos. + if ((target->ObjectNumber >= ID_PUZZLE_ITEM1 && target->ObjectNumber <= ID_PUZZLE_ITEM16) || + (target->ObjectNumber >= ID_PUZZLE_ITEM1_COMBO1 && target->ObjectNumber <= ID_PUZZLE_ITEM16_COMBO2) || + (target->ObjectNumber >= ID_KEY_ITEM1 && target->ObjectNumber <= ID_KEY_ITEM16) || + (target->ObjectNumber >= ID_KEY_ITEM1_COMBO1 && target->ObjectNumber <= ID_KEY_ITEM16_COMBO2)) + { + if (item.Pose.Position.x == target->Pose.Position.x && + item.Pose.Position.z == target->Pose.Position.z) + { + target->Status = ITEM_NOT_ACTIVE; + } + } + } + } + } + } + } + else if (frameNumber > HAMMER_CLOSED_FRAME && item.TriggerFlags == 2) + item.Flags &= ~CODE_BITS; + } - AnimateItem(item); - } + AnimateItem(&item); + } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_hammer.h b/TombEngine/Objects/TR4/Trap/tr4_hammer.h index 649d2f079..5b8998e22 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_hammer.h +++ b/TombEngine/Objects/TR4/Trap/tr4_hammer.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void HammerControl(short itemNumber); + void ControlHammer(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp index ea72a171b..1caf7e87c 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.cpp @@ -1,89 +1,109 @@ #include "framework.h" -#include "tr4_joby_spikes.h" -#include "Specific/level.h" +#include "Objects/TR4/Trap/tr4_joby_spikes.h" + +#include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" #include "Game/control/control.h" -#include "Game/animation.h" -#include "Sound/sound.h" -#include "Game/Lara/lara.h" #include "Game/effects/effects.h" #include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Sound/sound.h" +#include "Specific/level.h" using namespace TEN::Collision::Point; -namespace TEN::Entities::TR4 +// TODO: Need to test and adapt formula for scaling to other heights. + +namespace TEN::Entities::Traps { + constexpr auto JOBY_SPIKES_HARM_DAMAGE = 8; + constexpr auto JOBY_SPIKES_EXTRA_ROTATION_SPEED = 2; + constexpr auto JOBY_SPIKES_SCALE_INCREMENT = 3; + constexpr auto JOBY_SPIKES_MAX_SCALE = BLOCK(3.25f); + void InitializeJobySpikes(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; + + auto& angleRotationSpeed = item.ItemFlags[0]; + auto& spikeLength = item.ItemFlags[1]; + auto& clockworkDirection = item.ItemFlags[2]; // ?? + auto& maxExtensionLength = item.ItemFlags[3]; // Set bone mutators to EulerAngles identity by default. - for (auto& mutator : item->Model.Mutators) + for (auto& mutator : item.Model.Mutators) mutator.Scale.y = 0.0f; - item->Pose.Orientation.y = GetRandomControl() * 1024; - item->ItemFlags[2] = GetRandomControl() & 1; + item.Pose.Orientation.y = Random::GenerateInt(0, INT16_MAX) * ANGLE(5.5f); + clockworkDirection = Random::GenerateInt(0, 1); - auto probe = GetPointCollision(*item); - - // TODO: Check this optimized division. - //v6 = 1321528399i64 * ((probe.GetFloorHeight() - probe.GetCeilingHeight()) << 12); - //item->itemFlags[3] = (HIDWORD(v6) >> 31) + (SHIDWORD(v6) >> 10); - - item->ItemFlags[3] = (short)((probe.GetFloorHeight() - probe.GetCeilingHeight()) * 1024 * 12 / 13); + auto pointColl = GetPointCollision(item); + maxExtensionLength = (short)(4096 * (pointColl.GetFloorHeight() - pointColl.GetCeilingHeight()) / JOBY_SPIKES_MAX_SCALE); } - void JobySpikesControl(short itemNumber) + void ControlJobySpikes(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (!TriggerActive(item)) + if (!TriggerActive(&item)) return; - SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP1, &item->Pose); - auto frameData = GetFrameInterpData(*LaraItem); + auto& angleRotationSpeed = item.ItemFlags[0]; + auto& spikeLength = item.ItemFlags[1]; + auto& clockworkDirection = item.ItemFlags[2]; + auto& maxExtensionLength = item.ItemFlags[3]; - int dy = LaraItem->Pose.Position.y + frameData.FramePtr0->BoundingBox.Y1; - int dl = 3328 * item->ItemFlags[1] / 4096; + SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP1, &item.Pose); + auto frameData = GetFrameInterpData(*LaraItem); + + // Damage player. + int playerHeight = LaraItem->Pose.Position.y + frameData.FramePtr0->BoundingBox.Y1; + int spikeHeight = JOBY_SPIKES_MAX_SCALE * spikeLength / 4096; if (LaraItem->HitPoints > 0) { - if (item->Pose.Position.y + dl > dy) + if (item.Pose.Position.y + spikeHeight > playerHeight) { - if (abs(item->Pose.Position.x - LaraItem->Pose.Position.x) < CLICK(2)) + if (abs(item.Pose.Position.x - LaraItem->Pose.Position.x) < BLOCK(0.5)) { - if (abs(item->Pose.Position.z - LaraItem->Pose.Position.z) < CLICK(2)) + if (abs(item.Pose.Position.z - LaraItem->Pose.Position.z) < BLOCK(0.5)) { - int x = (GetRandomControl() & 0x7F) + LaraItem->Pose.Position.x - 64; - int y = dy + GetRandomControl() % (item->Pose.Position.y - dy + dl); - int z = (GetRandomControl() & 0x7F) + LaraItem->Pose.Position.z - 64; + DoDamage(LaraItem, JOBY_SPIKES_HARM_DAMAGE); - DoBloodSplat(x, y, z, (GetRandomControl() & 3) + 2, 2 * GetRandomControl(), item->RoomNumber); - DoDamage(LaraItem, 8); + int bloodPosX = LaraItem->Pose.Position.x + Random::GenerateInt(-64, 64); + int bloodPosY = playerHeight + Random::GenerateInt( 0, item.Pose.Position.y - playerHeight + spikeHeight); + int bloodPosZ = LaraItem->Pose.Position.z + Random::GenerateInt(-64, 64); + + DoBloodSplat(bloodPosX, bloodPosY, bloodPosZ, Random::GenerateInt (2,5), 2 * GetRandomControl(), item.RoomNumber); + } } } } - if (item->ItemFlags[2]) + // Rotate. + if (clockworkDirection == 1) { - if (item->ItemFlags[0] > -4096) - item->ItemFlags[0] = item->ItemFlags[1] + (item->ItemFlags[1] / 64) - 2; + if (angleRotationSpeed < 4096) + angleRotationSpeed = (spikeLength / 64) + spikeLength + JOBY_SPIKES_EXTRA_ROTATION_SPEED; + } + else + { + if (angleRotationSpeed > -4096) + angleRotationSpeed = spikeLength + (spikeLength / 64) - JOBY_SPIKES_EXTRA_ROTATION_SPEED; } - else if (item->ItemFlags[0] < 4096) - item->ItemFlags[0] = (item->ItemFlags[1] / 64) + item->ItemFlags[1] + 2; - if (item->ItemFlags[1] < item->ItemFlags[3]) - item->ItemFlags[1] += 3; + if (spikeLength < maxExtensionLength) + spikeLength += JOBY_SPIKES_SCALE_INCREMENT; - item->Pose.Orientation.y += item->ItemFlags[0]; + item.Pose.Orientation.y += angleRotationSpeed; - // Update bone mutators. - if (item->ItemFlags[1]) + // Scale. + if (spikeLength) { - for (auto& mutator : item->Model.Mutators) - mutator.Scale = Vector3(1.0f, item->ItemFlags[1] / 4096.0f, 1.0f); + for (auto& mutator : item.Model.Mutators) + mutator.Scale = Vector3(1.0f, spikeLength / 4096.0f, 1.0f); } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.h b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.h index 9a27c4fed..ff4e2a37f 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.h +++ b/TombEngine/Objects/TR4/Trap/tr4_joby_spikes.h @@ -1,7 +1,7 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeJobySpikes(short itemNumber); - void JobySpikesControl(short itemNumber); + void ControlJobySpikes(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_mine.cpp b/TombEngine/Objects/TR4/Trap/tr4_mine.cpp index 41c38608d..5601c2c8e 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_mine.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_mine.cpp @@ -1,62 +1,65 @@ #include "framework.h" -#include "tr4_mine.h" -#include "Specific/level.h" +#include "Objects/TR4/Trap/tr4_mine.h" + +#include "Game/collision/collide_item.h" #include "Game/collision/sphere.h" -#include "Sound/sound.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/weather.h" #include "Game/items.h" -#include "Game/collision/collide_item.h" #include "Objects/objectslist.h" +#include "Sound/sound.h" +#include "Specific/level.h" using namespace TEN::Effects::Environment; -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeMine(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (item->TriggerFlags) - item->MeshBits = 0; + if (item.TriggerFlags) + item.MeshBits = 0; } - void MineControl(short itemNumber) + void ControlMine(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - int num = GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - if (item->ItemFlags[0] >= 150) + int sphereCount = GetSpheres(&item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); + if (item.ItemFlags[0] >= 150) { - SoundEffect(SFX_TR4_EXPLOSION1, &item->Pose); - SoundEffect(SFX_TR4_EXPLOSION2, &item->Pose); - SoundEffect(SFX_TR4_EXPLOSION1, &item->Pose, SoundEnvironment::Land, 0.7f, 0.5f); + SoundEffect(SFX_TR4_EXPLOSION1, &item.Pose); + SoundEffect(SFX_TR4_EXPLOSION2, &item.Pose); + SoundEffect(SFX_TR4_EXPLOSION1, &item.Pose, SoundEnvironment::Land, 0.7f, 0.5f); - if (num > 0) + if (sphereCount > 0) { - for (int i = 0; i < num; i++) + for (int i = 0; i < sphereCount; i++) { if (i >= 7 && i != 9) { - auto* sphere = &CreatureSpheres[i]; + auto& sphere = CreatureSpheres[i]; - TriggerExplosionSparks(sphere->x, sphere->y, sphere->z, 3, -2, 0, -item->RoomNumber); - TriggerExplosionSparks(sphere->x, sphere->y, sphere->z, 3, -1, 0, -item->RoomNumber); - TriggerShockwave((Pose*)sphere, 48, 304, (GetRandomControl() & 0x1F) + 112, 0, 96, 128, 32, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); + auto pose = Pose(Vector3i(sphere.x, sphere.y, sphere.z)); + + TriggerExplosionSparks(sphere.x, sphere.y, sphere.z, 3, -2, 0, -item.RoomNumber); + TriggerExplosionSparks(sphere.x, sphere.y, sphere.z, 3, -1, 0, -item.RoomNumber); + TriggerShockwave(&pose, 48, 304, (GetRandomControl() & 0x1F) + 112, 0, 96, 128, 32, EulerAngles(ANGLE(11.25f), 0, 0), 0, true, false, false, (int)ShockwaveStyle::Normal); } } - for (int i = 0; i < num; i++) - ExplodeItemNode(item, i, 0, -128); + for (int i = 0; i < sphereCount; i++) + ExplodeItemNode(&item, i, 0, -128); } Weather.Flash(255, 192, 64, 0.03f); - short currentItemNumber = g_Level.Rooms[item->RoomNumber].itemNumber; + int currentItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; - // Make the sentry gun explode? + // Make sentry gun explode? while (currentItemNumber != NO_VALUE) { auto* currentItem = &g_Level.Items[currentItemNumber]; @@ -71,93 +74,93 @@ namespace TEN::Entities::TR4 } else { - item->ItemFlags[0]++; + item.ItemFlags[0]++; - int fade = 4 * item->ItemFlags[0]; + int fade = 4 * item.ItemFlags[0]; if (fade > 255) fade = 0; - for (int i = 0; i < num; i++) + for (int i = 0; i < sphereCount; i++) { if (i == 0 || i > 5) { - auto* sphere = &CreatureSpheres[i]; - AddFire(sphere->x, sphere->y, sphere->z, item->RoomNumber, 0.25f, fade); + auto& sphere = CreatureSpheres[i]; + AddFire(sphere.x, sphere.y, sphere.z, item.RoomNumber, 0.25f, fade); } } - SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item->Pose); + SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item.Pose); } } - void MineCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) + void CollideMine(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) { - auto* mineItem = &g_Level.Items[itemNumber]; + auto& mineItem = g_Level.Items[itemNumber]; - if (mineItem->TriggerFlags && !mineItem->ItemFlags[3]) + if (!mineItem.TriggerFlags || mineItem.ItemFlags[3]) + return; + + if (playerItem->Animation.AnimNumber != LA_DETONATOR_USE || + playerItem->Animation.FrameNumber < (GetAnimData(playerItem).frameBase + 57)) { - if (laraItem->Animation.AnimNumber != LA_DETONATOR_USE || - laraItem->Animation.FrameNumber < GetAnimData(laraItem).frameBase + 57) + if (TestBoundsCollide(&mineItem, playerItem, BLOCK(0.5f))) { - if (TestBoundsCollide(mineItem, laraItem, 512)) - { - TriggerExplosionSparks(mineItem->Pose.Position.x, mineItem->Pose.Position.y, mineItem->Pose.Position.z, 3, -2, 0, mineItem->RoomNumber); - for (int i = 0; i < 2; i++) - TriggerExplosionSparks(mineItem->Pose.Position.x, mineItem->Pose.Position.y, mineItem->Pose.Position.z, 3, -1, 0, mineItem->RoomNumber); + TriggerExplosionSparks(mineItem.Pose.Position.x, mineItem.Pose.Position.y, mineItem.Pose.Position.z, 3, -2, 0, mineItem.RoomNumber); + for (int i = 0; i < 2; i++) + TriggerExplosionSparks(mineItem.Pose.Position.x, mineItem.Pose.Position.y, mineItem.Pose.Position.z, 3, -1, 0, mineItem.RoomNumber); - mineItem->MeshBits = 1; + mineItem.MeshBits = 1; - ExplodeItemNode(mineItem, 0, 0, 128); - KillItem(itemNumber); + ExplodeItemNode(&mineItem, 0, 0, 128); + KillItem(itemNumber); - laraItem->Animation.AnimNumber = LA_MINE_DEATH; - laraItem->Animation.FrameNumber = GetAnimData(*mineItem).frameBase; - laraItem->Animation.ActiveState = LS_DEATH; - laraItem->Animation.Velocity.z = 0; + playerItem->Animation.AnimNumber = LA_MINE_DEATH; + playerItem->Animation.FrameNumber = GetAnimData(*playerItem).frameBase; + playerItem->Animation.ActiveState = LS_DEATH; + playerItem->Animation.Velocity.z = 0; - SoundEffect(SFX_TR4_MINE_EXPLOSION_OVERLAY, &mineItem->Pose); - } + SoundEffect(SFX_TR4_MINE_EXPLOSION_OVERLAY, &mineItem.Pose); } - else + } + else + { + for (int i = 0; i < g_Level.NumItems; i++) { - for (int i = 0; i < g_Level.NumItems; i++) - { - auto* currentItem = &g_Level.Items[i]; + auto* currentItem = &g_Level.Items[i]; - // Explode other mines - if (currentItem->ObjectNumber == ID_MINE && - currentItem->Status != ITEM_INVISIBLE && - currentItem->TriggerFlags == 0) - { + // Explode other mines. + if (currentItem->ObjectNumber == ID_MINE && + currentItem->Status != ITEM_INVISIBLE && + currentItem->TriggerFlags == 0) + { + TriggerExplosionSparks( + currentItem->Pose.Position.x, + currentItem->Pose.Position.y, + currentItem->Pose.Position.z, + 3, + -2, + 0, + currentItem->RoomNumber); + + for (int j = 0; j < 2; j++) TriggerExplosionSparks( currentItem->Pose.Position.x, currentItem->Pose.Position.y, currentItem->Pose.Position.z, 3, - -2, + -1, 0, currentItem->RoomNumber); - for (int j = 0; j < 2; j++) - TriggerExplosionSparks( - currentItem->Pose.Position.x, - currentItem->Pose.Position.y, - currentItem->Pose.Position.z, - 3, - -1, - 0, - currentItem->RoomNumber); + currentItem->MeshBits = 1; - currentItem->MeshBits = 1; + ExplodeItemNode(currentItem, 0, 0, -32); + KillItem(i); - ExplodeItemNode(currentItem, 0, 0, -32); - KillItem(i); + if (!(GetRandomControl() & 3)) + SoundEffect(SFX_TR4_MINE_EXPLOSION_OVERLAY, ¤tItem->Pose); - if (!(GetRandomControl() & 3)) - SoundEffect(SFX_TR4_MINE_EXPLOSION_OVERLAY, ¤tItem->Pose); - - currentItem->Status = ITEM_INVISIBLE; - } + currentItem->Status = ITEM_INVISIBLE; } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_mine.h b/TombEngine/Objects/TR4/Trap/tr4_mine.h index ba19b8010..fb080e401 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_mine.h +++ b/TombEngine/Objects/TR4/Trap/tr4_mine.h @@ -3,9 +3,9 @@ struct ItemInfo; struct CollisionInfo; -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeMine(short itemNumber); - void MineControl(short itemNumber); - void MineCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); + void ControlMine(short itemNumber); + void CollideMine(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp b/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp index e54965255..48064341d 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp @@ -1,26 +1,29 @@ #include "framework.h" -#include "tr4_moving_blade.h" -#include "Specific/level.h" -#include "Game/control/control.h" -#include "Sound/sound.h" +#include "Objects/TR4/Trap/tr4_moving_blade.h"\ + #include "Game/animation.h" -#include "Game/Lara/lara.h" +#include "Game/control/control.h" #include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Sound/sound.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void MovingBladeControl(short itemNumber) + void ControlMovingBlade(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (TriggerActive(item)) + if (TriggerActive(&item)) { - item->ItemFlags[3] = 50; - AnimateItem(item); + item.ItemFlags[3] = 50; + AnimateItem(&item); } else - item->Animation.FrameNumber = GetAnimData(item).frameBase; + { + item.Animation.FrameNumber = GetAnimData(item).frameBase; + } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_moving_blade.h b/TombEngine/Objects/TR4/Trap/tr4_moving_blade.h index 84233080e..0deb9ee30 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_moving_blade.h +++ b/TombEngine/Objects/TR4/Trap/tr4_moving_blade.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void MovingBladeControl(short itemNumber); + void ControlMovingBlade(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_plinthblade.cpp b/TombEngine/Objects/TR4/Trap/tr4_plinthblade.cpp index e9727ca2b..e5288a731 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_plinthblade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_plinthblade.cpp @@ -1,28 +1,35 @@ #include "framework.h" -#include "tr4_plinthblade.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_plinthblade.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void PlinthBladeControl(short itemNumber) + void ControlPlinthBlade(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (!TriggerActive(item)) - item->Animation.FrameNumber = GetAnimData(item).frameBase; + if (!TriggerActive(&item)) + { + item.Animation.FrameNumber = GetAnimData(item).frameBase; + } else { - int frameNumber = item->Animation.FrameNumber - GetAnimData(item).frameBase; + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; - if (item->Animation.FrameNumber == GetAnimData(item).frameEnd) - item->ItemFlags[3] = 0; + if (item.Animation.FrameNumber == GetAnimData(item).frameEnd) + { + item.ItemFlags[3] = 0; + } else - item->ItemFlags[3] = 200; + { + item.ItemFlags[3] = 200; + } - AnimateItem(item); + AnimateItem(&item); } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_plinthblade.h b/TombEngine/Objects/TR4/Trap/tr4_plinthblade.h index b0393769a..30668c5f2 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_plinthblade.h +++ b/TombEngine/Objects/TR4/Trap/tr4_plinthblade.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void PlinthBladeControl(short itemNumber); + void ControlPlinthBlade(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_plough.cpp b/TombEngine/Objects/TR4/Trap/tr4_plough.cpp index 465c303ea..1985d08c3 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_plough.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_plough.cpp @@ -1,24 +1,34 @@ #include "framework.h" -#include "tr4_plough.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_plough.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void PloughControl(short itemNumber) + void InitializePlough(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - item->ItemFlags[3] = 50; + item.ItemFlags[4] = 1; + } - if (TriggerActive(item)) + void ControlPlough(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + item.ItemFlags[3] = 50; + + if (TriggerActive(&item)) { - *((int*)&item->ItemFlags) = 0x3F000; - AnimateItem(item); + *((int*)&item.ItemFlags) = 0x3F000; + AnimateItem(&item); } else - *((int*)&item->ItemFlags) = 0; + { + *((int*)&item.ItemFlags) = 0; + } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_plough.h b/TombEngine/Objects/TR4/Trap/tr4_plough.h index 3485dc324..3b37cfdf3 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_plough.h +++ b/TombEngine/Objects/TR4/Trap/tr4_plough.h @@ -1,6 +1,7 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void PloughControl(short itemNumber); + void InitializePlough(short itemNumber); + void ControlPlough(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_sethblade.cpp b/TombEngine/Objects/TR4/Trap/tr4_sethblade.cpp index b690d616d..105abf25f 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_sethblade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_sethblade.cpp @@ -7,7 +7,7 @@ #include "Game/Setup.h" #include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { constexpr auto SETH_BLADE_HARM_DAMAGE = 1000; @@ -32,9 +32,10 @@ namespace TEN::Entities::TR4 item.ItemFlags[2] = item.TriggerFlags >= 0 ? 1 : abs(item.TriggerFlags); //ItemFlags[2] stores blade timer. item.ItemFlags[3] = SETH_BLADE_HARM_DAMAGE; //ItemFlags[3] stored blade harm damage. + item.ItemFlags[4] = 1; } - void SethBladeControl(short itemNumber) + void ControlSethBlade(short itemNumber) { auto& item = g_Level.Items[itemNumber]; diff --git a/TombEngine/Objects/TR4/Trap/tr4_sethblade.h b/TombEngine/Objects/TR4/Trap/tr4_sethblade.h index d0ad89ef0..d042b3e3a 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_sethblade.h +++ b/TombEngine/Objects/TR4/Trap/tr4_sethblade.h @@ -1,7 +1,7 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeSethBlade(short itemNumber); - void SethBladeControl(short itemNumber); + void ControlSethBlade(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp index d24178af5..c7b23f32d 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.cpp @@ -1,50 +1,52 @@ #include "framework.h" -#include "tr4_slicerdicer.h" -#include "Specific/level.h" -#include "Sound/sound.h" +#include "Objects/TR4/Trap/tr4_slicerdicer.h" + +#include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" #include "Game/items.h" -#include "Game/animation.h" #include "Math/Math.h" +#include "Sound/sound.h" +#include "Specific/level.h" using namespace TEN::Collision::Point; +using namespace TEN::Math; -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeSlicerDicer(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - int dx = phd_sin(item->Pose.Orientation.y + ANGLE(90.0f)) * 512; - int dz = phd_cos(item->Pose.Orientation.y + ANGLE(90.0f)) * 512; + int dx = phd_sin(item.Pose.Orientation.y + ANGLE(90.0f)) * 512; + int dz = phd_cos(item.Pose.Orientation.y + ANGLE(90.0f)) * 512; - item->Pose.Position.x += dx; - item->Pose.Position.z += dz; + item.Pose.Position.x += dx; + item.Pose.Position.z += dz; - item->ItemFlags[0] = item->Pose.Position.x / 256; - item->ItemFlags[1] = (item->Pose.Position.y - 4608) / 256; - item->ItemFlags[2] = item->Pose.Position.z / 256; - item->ItemFlags[3] = 50; + item.ItemFlags[0] = item.Pose.Position.x / 256; + item.ItemFlags[1] = (item.Pose.Position.y - 4608) / 256; + item.ItemFlags[2] = item.Pose.Position.z / 256; + item.ItemFlags[3] = 50; } - void SlicerDicerControl(short itemNumber) + void ControlSlicerDicer(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP1, &item->Pose); - SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP2, &item->Pose); + SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP1, &item.Pose); + SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP2, &item.Pose); - item->Pose.Position.x = (item->ItemFlags[0] * 256) + 4608 * phd_cos(item->TriggerFlags) * phd_sin(item->Pose.Orientation.y); - item->Pose.Position.y = (item->ItemFlags[1] * 256) - 4608 * phd_sin(item->TriggerFlags); - item->Pose.Position.z = (item->ItemFlags[2] * 256) + 4608 * phd_cos(item->TriggerFlags) * phd_cos(item->Pose.Orientation.y); + item.Pose.Position.x = (item.ItemFlags[0] * 256) + 4608 * phd_cos(item.TriggerFlags) * phd_sin(item.Pose.Orientation.y); + item.Pose.Position.y = (item.ItemFlags[1] * 256) - 4608 * phd_sin(item.TriggerFlags); + item.Pose.Position.z = (item.ItemFlags[2] * 256) + 4608 * phd_cos(item.TriggerFlags) * phd_cos(item.Pose.Orientation.y); - item->TriggerFlags += 170; + item.TriggerFlags += 170; - auto probedRoomNumber = GetPointCollision(*item).GetRoomNumber(); - if (item->RoomNumber != probedRoomNumber) + int probedRoomNumber = GetPointCollision(item).GetRoomNumber(); + if (item.RoomNumber != probedRoomNumber) ItemNewRoom(itemNumber, probedRoomNumber); - AnimateItem(item); + AnimateItem(&item); } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.h b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.h index 524476fb6..1b25343f2 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.h +++ b/TombEngine/Objects/TR4/Trap/tr4_slicerdicer.h @@ -1,7 +1,7 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeSlicerDicer(short itemNumber); - void SlicerDicerControl(short itemNumber); + void ControlSlicerDicer(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_spikeball.cpp b/TombEngine/Objects/TR4/Trap/tr4_spikeball.cpp index 79d353557..95fd2cc79 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_spikeball.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_spikeball.cpp @@ -1,43 +1,46 @@ #include "framework.h" -#include "tr4_spikeball.h" -#include "Specific/level.h" -#include "Game/control/control.h" +#include "Objects/TR4/Trap/tr4_spikeball.h" + #include "Game/animation.h" +#include "Game/control/control.h" #include "Game/items.h" +#include "Specific/level.h" -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void SpikeballControl(short itemNumber) + void ControlSpikeball(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (TriggerActive(item)) + if (TriggerActive(&item)) { - int frameNumber = item->Animation.FrameNumber - GetAnimData(item).frameBase; + int frameNumber = item.Animation.FrameNumber - GetAnimData(item).frameBase; if ((frameNumber <= 14 || frameNumber >= 24) && (frameNumber < 138 || frameNumber > 140)) { if (frameNumber < 141) - *((int*)&item->ItemFlags[0]) = 0; + { + *((int*)&item.ItemFlags[0]) = 0; + } else { - item->ItemFlags[3] = 50; - *((int*)&item->ItemFlags[0]) = 0x7FF800; + item.ItemFlags[3] = 50; + *((int*)&item.ItemFlags[0]) = 0x7FF800; } } else { - item->ItemFlags[3] = 150; - *((int*)&item->ItemFlags[0]) = 0x7FF800; + item.ItemFlags[3] = 150; + *((int*)&item.ItemFlags[0]) = 0x7FF800; } - AnimateItem(item); + AnimateItem(&item); } else { - item->Animation.FrameNumber = GetAnimData(item).frameBase; - *((int*)&item->ItemFlags[0]) = 0; + item.Animation.FrameNumber = GetAnimData(item).frameBase; + *((int*)&item.ItemFlags[0]) = 0; } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_spikeball.h b/TombEngine/Objects/TR4/Trap/tr4_spikeball.h index 3603e843d..38a001cee 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_spikeball.h +++ b/TombEngine/Objects/TR4/Trap/tr4_spikeball.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - void SpikeballControl(short itemNumber); + void ControlSpikeball(short itemNumber); } diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp index 2983d3832..0774e0666 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp @@ -8,30 +8,30 @@ #include "Game/items.h" #include "Game/Lara/lara.h" #include "Game/Setup.h" +#include "Math/Math.h" #include "Sound/sound.h" #include "Specific/level.h" -#include "Math/Math.h" using namespace TEN::Collision::Point; -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { - constexpr auto TEETH_SPIKE_HARM_DAMAGE_CONSTANT = 8; - constexpr auto TEETH_SPIKE_HARM_DAMAGE_EMERGING = 30; - constexpr auto TEETH_SPIKES_DEFAULT_INTERVAL = 64; + constexpr auto TEETH_SPIKE_HARM_DAMAGE_CONSTANT = 8; + constexpr auto TEETH_SPIKE_HARM_DAMAGE_EMERGING = 30; + constexpr auto TEETH_SPIKES_DEFAULT_INTERVAL = 64; constexpr auto TEETH_SPIKE_BOUNDS_TOLERANCE_RATIO = 0.95f; void InitializeTeethSpikes(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; // Set mutators to EulerAngles identity by default. - for (auto& mutator : item->Model.Mutators) + for (auto& mutator : item.Model.Mutators) mutator.Scale.y = 0.0f; - item->Status = ITEM_INVISIBLE; - item->ItemFlags[0] = 1024; - item->ItemFlags[2] = 0; + item.Status = ITEM_INVISIBLE; + item.ItemFlags[0] = 1024; + item.ItemFlags[2] = 0; } ContainmentType TestBoundsCollideTeethSpikes(ItemInfo* item, ItemInfo* collidingItem) @@ -57,94 +57,96 @@ namespace TEN::Entities::TR4 void ControlTeethSpikes(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; - if (TriggerActive(item) && item->ItemFlags[2] == 0) + if (TriggerActive(&item) && item.ItemFlags[2] == 0) { // Get current item bounds and radius. - const auto& bounds = GetBestFrame(*item).BoundingBox; + const auto& bounds = GetBestFrame(item).BoundingBox; int radius = std::max(abs(bounds.X2 - bounds.X1), abs(bounds.Z2 - bounds.Z1)) / 2; // Play sound only if spikes are just emerging. - if (item->ItemFlags[0] == 1024 && item->TriggerFlags != 1) - SoundEffect(SFX_TR4_TEETH_SPIKES, &item->Pose); + if (item.ItemFlags[0] == 1024 && item.TriggerFlags != 1) + SoundEffect(SFX_TR4_TEETH_SPIKES, &item.Pose); // Immediately set spike state to fully protruded if flag is set. - if (item->TriggerFlags == 1) - item->ItemFlags[1] = 5120; + if (item.TriggerFlags == 1) + item.ItemFlags[1] = 5120; // Kill enemies. - item->Animation.Velocity.z = VEHICLE_COLLISION_TERMINAL_VELOCITY; - DoTeethSpikeCollision(item, radius * TEETH_SPIKE_BOUNDS_TOLERANCE_RATIO); + item.Animation.Velocity.z = VEHICLE_COLLISION_TERMINAL_VELOCITY; + DoTeethSpikeCollision(&item, radius * TEETH_SPIKE_BOUNDS_TOLERANCE_RATIO); - item->Status = ITEM_ACTIVE; + item.Status = ITEM_ACTIVE; - auto intersection = TestBoundsCollideTeethSpikes(item, LaraItem); + auto intersection = TestBoundsCollideTeethSpikes(&item, LaraItem); if (LaraItem->Animation.ActiveState != LS_DEATH && intersection != ContainmentType::DISJOINT) { - // Calculate spike angle to the horizon. If angle is upward, impale Lara. - auto normal = Vector3::Transform(Vector3::UnitY, item->Pose.Orientation.ToRotationMatrix()); + // Calculate spike angle to horizon. If angle is upward, impale player. + auto normal = Vector3::Transform(Vector3::UnitY, item.Pose.Orientation.ToRotationMatrix()); float dot = Vector3::UnitX.Dot(normal); float angle = acos(dot / sqrt(normal.LengthSquared() * Vector3::UnitX.LengthSquared())); - const auto& laraBounds = GetBestFrame(*LaraItem).BoundingBox; + const auto& playerBounds = GetBestFrame(*LaraItem).BoundingBox; int bloodCount = 0; - // Spikes are upward and Lara is jumping, or spikes have just emerged - impale. - if ((item->ItemFlags[0] >= 1024 || LaraItem->Animation.IsAirborne) && + // Spikes are upward and player is jumping, or spikes have just emerged - impale. + if ((item.ItemFlags[0] >= 1024 || LaraItem->Animation.IsAirborne) && (angle > PI * 0.25f && angle < PI * 0.75f)) { - if (LaraItem->Animation.Velocity.y > 6.0f || item->ItemFlags[0] > 1024) + if (LaraItem->Animation.Velocity.y > 6.0f || item.ItemFlags[0] > 1024) { LaraItem->HitPoints = -1; bloodCount = 20; } } - // Spikes are emerging or already fully protruded (in latter case, only damage Lara if she runs). - else if ((item->TriggerFlags != 1) || LaraItem->Animation.Velocity.z >= 30.0f) + // Spikes emerging or already fully protruded (in latter case, only damage player if running). + else if ((item.TriggerFlags != 1) || LaraItem->Animation.Velocity.z >= 30.0f) { - int damage = item->ItemFlags[0] == 1024 ? TEETH_SPIKE_HARM_DAMAGE_EMERGING : TEETH_SPIKE_HARM_DAMAGE_CONSTANT; + int damage = item.ItemFlags[0] == 1024 ? TEETH_SPIKE_HARM_DAMAGE_EMERGING : TEETH_SPIKE_HARM_DAMAGE_CONSTANT; DoDamage(LaraItem, damage); bloodCount = (GetRandomControl() & 3) + 2; } - // Spikes are retracting; do nothing. + // Spikes retracting; do nothing. else + { bloodCount = 0; + } int y1, y2; - int yTop = laraBounds.Y1 + LaraItem->Pose.Position.y; - int yBottom = laraBounds.Y2 + LaraItem->Pose.Position.y; + int yTop = playerBounds.Y1 + LaraItem->Pose.Position.y; + int yBottom = playerBounds.Y2 + LaraItem->Pose.Position.y; - // Spikes are downward; move blood origin to top. + // Spikes pointing downward; move blood origin to top. if (angle < PI * 0.125f || angle > PI * 0.825f) { y1 = -bounds.Y2; y2 = -bounds.Y1; } - // Spikes are upward; leave origin as is. + // Spikes pointing upward; leave origin as is. else { y1 = bounds.Y1; y2 = bounds.Y2; } - if (yTop < y1 + item->Pose.Position.y) - yTop = y1 + item->Pose.Position.y; - if (yBottom > y2 + item->Pose.Position.y) - yBottom = y2 + item->Pose.Position.y; + if (yTop < y1 + item.Pose.Position.y) + yTop = y1 + item.Pose.Position.y; + if (yBottom > y2 + item.Pose.Position.y) + yBottom = y2 + item.Pose.Position.y; int dy = (abs(yTop - yBottom)) + 1; - // Increase blood if spikes are protruding from the side. + // Increase blood if spikes are protruding from side. if ((angle > PI * 0.125f && angle < PI * 0.375f) || (angle > PI * 0.625f && angle < PI * 0.750f)) { bloodCount >>= 1; } - for (size_t i = 0; i < bloodCount; i++) + for (int i = 0; i < bloodCount; i++) { int dx = LaraItem->Pose.Position.x + (GetRandomControl() & 127) - 64; int dz = LaraItem->Pose.Position.z + (GetRandomControl() & 127) - 64; @@ -155,8 +157,7 @@ namespace TEN::Entities::TR4 { int heightFromFloor = GetPointCollision(*LaraItem).GetFloorHeight() - LaraItem->Pose.Position.y; - if (item->Pose.Position.y >= LaraItem->Pose.Position.y && heightFromFloor < CLICK(1) && - intersection == ContainmentType::CONTAINS) + if (item.Pose.Position.y >= LaraItem->Pose.Position.y && heightFromFloor < CLICK(1)) { SetAnimation(LaraItem, LA_SPIKE_DEATH); LaraItem->Animation.IsAirborne = false; @@ -164,62 +165,70 @@ namespace TEN::Entities::TR4 } } - item->ItemFlags[0] += 128; - item->ItemFlags[1] += item->ItemFlags[0]; - if (item->ItemFlags[1] >= 5120) + item.ItemFlags[0] += 128; + item.ItemFlags[1] += item.ItemFlags[0]; + if (item.ItemFlags[1] >= 5120) { - item->ItemFlags[1] = 5120; - if (item->ItemFlags[0] <= 1024) + item.ItemFlags[1] = 5120; + if (item.ItemFlags[0] <= 1024) { - item->ItemFlags[0] = 0; - if (item->TriggerFlags != 1 && LaraItem->HitPoints > 0) + item.ItemFlags[0] = 0; + if (item.TriggerFlags != 1 && LaraItem->HitPoints > 0) { - int customInterval = item->TriggerFlags; - item->ItemFlags[2] = customInterval ? customInterval : TEETH_SPIKES_DEFAULT_INTERVAL; + int customInterval = item.TriggerFlags; + item.ItemFlags[2] = customInterval ? customInterval : TEETH_SPIKES_DEFAULT_INTERVAL; } } else - item->ItemFlags[0] = -item->ItemFlags[0] >> 1; + { + item.ItemFlags[0] = -item.ItemFlags[0] >> 1; + } } } - else if (TriggerActive(item)) + else if (TriggerActive(&item)) { - item->ItemFlags[0] += (item->ItemFlags[0] >> 3) + 32; - item->ItemFlags[1] -= item->ItemFlags[0]; - if (item->ItemFlags[1] <= 0) + item.ItemFlags[0] += (item.ItemFlags[0] >> 3) + 32; + item.ItemFlags[1] -= item.ItemFlags[0]; + if (item.ItemFlags[1] <= 0) { - item->ItemFlags[0] = 1024; - item->ItemFlags[1] = 0; - item->Status = ITEM_INVISIBLE; + item.ItemFlags[0] = 1024; + item.ItemFlags[1] = 0; + item.Status = ITEM_INVISIBLE; } - if (item->TriggerFlags != 2) + if (item.TriggerFlags != 2) { - if (item->ItemFlags[2]) - item->ItemFlags[2]--; + if (item.ItemFlags[2]) + item.ItemFlags[2]--; } else - item->ItemFlags[2] = 1; - } - else if (!item->Timer) - { - if (item->ItemFlags[1] > 0) { - item->ItemFlags[0] += (item->ItemFlags[0] >> 3) + 32; - item->ItemFlags[1] -= item->ItemFlags[0]; - if (item->ItemFlags[1] < 0) - item->ItemFlags[1] = 0; + item.ItemFlags[2] = 1; + } + } + else if (!item.Timer) + { + if (item.ItemFlags[1] > 0) + { + item.ItemFlags[0] += (item.ItemFlags[0] >> 3) + 32; + item.ItemFlags[1] -= item.ItemFlags[0]; + if (item.ItemFlags[1] < 0) + item.ItemFlags[1] = 0; } } // Update bone mutators. - for (auto& mutator : item->Model.Mutators) + for (auto& mutator : item.Model.Mutators) { - float scale = (float)item->ItemFlags[1] / 4096.0f; + float scale = (float)item.ItemFlags[1] / 4096.0f; if (scale > 0.0f) + { mutator.Scale = Vector3(1.0f, scale, 1.0f); + } else + { mutator.Scale = Vector3::Zero; + } } } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.h b/TombEngine/Objects/TR4/Trap/tr4_teethspike.h index 8f075cde3..5bcc50302 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.h +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.h @@ -1,6 +1,6 @@ #pragma once -namespace TEN::Entities::TR4 +namespace TEN::Entities::Traps { void InitializeTeethSpikes(short itemNumber); void ControlTeethSpikes(short itemNumber); diff --git a/TombEngine/Objects/TR4/tr4_objects.cpp b/TombEngine/Objects/TR4/tr4_objects.cpp index b54171260..f17c818de 100644 --- a/TombEngine/Objects/TR4/tr4_objects.cpp +++ b/TombEngine/Objects/TR4/tr4_objects.cpp @@ -410,7 +410,7 @@ namespace TEN::Entities if (obj->loaded) { obj->Initialize = InitializeSentryGun; - obj->control = SentryGunControl; + obj->control = ControlSentryGun; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; obj->damageType = DamageMode::None; @@ -420,9 +420,8 @@ namespace TEN::Entities obj->intelligent = true; obj->explodableMeshbits = 0x40; obj->SetBoneRotationFlags(0, ROT_X | ROT_Y); - obj->SetBoneRotationFlags(1, ROT_X | ROT_X); - obj->SetBoneRotationFlags(2, ROT_X | ROT_Z); - obj->SetBoneRotationFlags(3, ROT_X | ROT_Z); + obj->SetBoneRotationFlags(2, ROT_Z); + obj->SetBoneRotationFlags(3, ROT_Z); obj->SetHitEffect(true); } @@ -768,7 +767,7 @@ namespace TEN::Entities obj = &Objects[ID_CHAIN]; if (obj->loaded) { - obj->control = ChainControl; + obj->control = ControlChain; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -776,7 +775,8 @@ namespace TEN::Entities obj = &Objects[ID_PLOUGH]; if (obj->loaded) { - obj->control = PloughControl; + obj->Initialize = InitializePlough; + obj->control = ControlPlough; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -784,8 +784,8 @@ namespace TEN::Entities obj = &Objects[ID_CATWALK_BLADE]; if (obj->loaded) { - obj->control = CatwalkBladeControl; - obj->collision = BladeCollision; + obj->control = ControlCatwalkBlade; + obj->collision = CollideBlade; obj->SetHitEffect(true); } @@ -793,7 +793,7 @@ namespace TEN::Entities if (obj->loaded) { obj->Initialize = InitializeSethBlade; - obj->control = SethBladeControl; + obj->control = ControlSethBlade; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -801,15 +801,16 @@ namespace TEN::Entities obj = &Objects[ID_PLINTH_BLADE]; if (obj->loaded) { - obj->control = PlinthBladeControl; - obj->collision = BladeCollision; + obj->control = ControlPlinthBlade; + obj->collision = CollideBlade; obj->SetHitEffect(true); } obj = &Objects[ID_BIRD_BLADE]; if (obj->loaded) { - obj->control = BirdBladeControl; + obj->Initialize = InitializeBirdBlade; + obj->control = ControlBirdBlade; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -818,39 +819,22 @@ namespace TEN::Entities if (obj->loaded) { obj->Initialize = InitializeJobySpikes; - obj->control = JobySpikesControl; - obj->collision = GenericSphereBoxCollision; + obj->control = ControlJobySpikes; obj->SetHitEffect(true); } obj = &Objects[ID_MOVING_BLADE]; if (obj->loaded) { - obj->control = MovingBladeControl; - obj->collision = BladeCollision; + obj->control = ControlMovingBlade; + obj->collision = CollideBlade; obj->SetHitEffect(true); } obj = &Objects[ID_SPIKEBALL]; if (obj->loaded) { - obj->control = SpikeballControl; - obj->collision = GenericSphereBoxCollision; - obj->SetHitEffect(true); - } - - obj = &Objects[ID_CHAIN]; - if (obj->loaded) - { - obj->control = ChainControl; - obj->collision = GenericSphereBoxCollision; - obj->SetHitEffect(true); - } - - obj = &Objects[ID_PLOUGH]; - if (obj->loaded) - { - obj->control = PloughControl; + obj->control = ControlSpikeball; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -858,7 +842,8 @@ namespace TEN::Entities obj = &Objects[ID_FLOOR_4BLADES]; if (obj->loaded) { - obj->control = FourBladesControl; + obj->Initialize = InitializeFourBlades; + obj->control = ControlFourBlades; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -866,7 +851,8 @@ namespace TEN::Entities obj = &Objects[ID_CEILING_4BLADES]; if (obj->loaded) { - obj->control = FourBladesControl; + obj->Initialize = InitializeFourBlades; + obj->control = ControlFourBlades; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } @@ -883,8 +869,8 @@ namespace TEN::Entities if (obj->loaded) { obj->Initialize = InitializeSlicerDicer; - obj->control = SlicerDicerControl; - obj->collision = BladeCollision; + obj->control = ControlSlicerDicer; + obj->collision = CollideBlade; obj->SetHitEffect(true); } @@ -892,8 +878,8 @@ namespace TEN::Entities if (obj->loaded) { obj->Initialize = InitializeMine; - obj->control = MineControl; - obj->collision = MineCollision; + obj->control = ControlMine; + obj->collision = CollideMine; } obj = &Objects[ID_SPIKY_WALL]; @@ -917,8 +903,8 @@ namespace TEN::Entities obj = &Objects[ID_COG]; if (obj->loaded) { - obj->control = CogControl; - obj->collision = CogCollision; + obj->control = ControlCog; + obj->collision = CollideCog; obj->SetHitEffect(true); } @@ -946,7 +932,7 @@ namespace TEN::Entities obj = &Objects[ID_HAMMER]; if (obj->loaded) { - obj->control = HammerControl; + obj->control = ControlHammer; obj->collision = GenericSphereBoxCollision; obj->SetHitEffect(true); } diff --git a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp index cece3c862..45db36846 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBarrier.cpp @@ -13,7 +13,7 @@ using namespace TEN::Collision::Point; using namespace TEN::Effects::Items; -namespace TEN::Traps::TR5 +namespace TEN::Entities::Traps { // NOTES: // item.ItemFlags[0] = barrier height. diff --git a/TombEngine/Objects/TR5/Trap/LaserBarrier.h b/TombEngine/Objects/TR5/Trap/LaserBarrier.h index 4f0f6bfa2..e2c9e6023 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBarrier.h +++ b/TombEngine/Objects/TR5/Trap/LaserBarrier.h @@ -6,7 +6,7 @@ using namespace TEN::Math; struct CollisionInfo; struct ItemInfo; -namespace TEN::Traps::TR5 +namespace TEN::Entities::Traps { struct LaserBarrierBeam { diff --git a/TombEngine/Objects/TR5/Trap/LaserBeam.cpp b/TombEngine/Objects/TR5/Trap/LaserBeam.cpp index ae227bcbc..18ee502f5 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBeam.cpp +++ b/TombEngine/Objects/TR5/Trap/LaserBeam.cpp @@ -21,7 +21,7 @@ using namespace TEN::Effects::Spark; using namespace TEN::Math; using namespace TEN::Renderer; -namespace TEN::Traps::TR5 +namespace TEN::Entities::Traps { constexpr auto LASER_BEAM_LIGHT_INTENSITY = 0.2f; constexpr auto LASER_BEAM_LIGHT_AMPLITUDE_MAX = 0.1f; diff --git a/TombEngine/Objects/TR5/Trap/LaserBeam.h b/TombEngine/Objects/TR5/Trap/LaserBeam.h index 168e1e2fc..ab6569c68 100644 --- a/TombEngine/Objects/TR5/Trap/LaserBeam.h +++ b/TombEngine/Objects/TR5/Trap/LaserBeam.h @@ -6,7 +6,7 @@ using namespace TEN::Math; struct CollisionInfo; struct ItemInfo; -namespace TEN::Traps::TR5 +namespace TEN::Entities::Traps { struct LaserBeamEffect { diff --git a/TombEngine/Objects/TR5/Trap/ZipLine.cpp b/TombEngine/Objects/TR5/Trap/ZipLine.cpp index e53c5bcae..661ecfc8b 100644 --- a/TombEngine/Objects/TR5/Trap/ZipLine.cpp +++ b/TombEngine/Objects/TR5/Trap/ZipLine.cpp @@ -17,7 +17,7 @@ using namespace TEN::Collision::Point; using namespace TEN::Input; using namespace TEN::Math; -namespace TEN::Traps::TR5 +namespace TEN::Entities::Traps { const auto ZipLineInteractOffset = Vector3i(0, 0, 371); const auto ZipLineInteractBasis = ObjectCollisionBounds diff --git a/TombEngine/Objects/TR5/Trap/ZipLine.h b/TombEngine/Objects/TR5/Trap/ZipLine.h index 3cdcb5c50..5c5c2fbab 100644 --- a/TombEngine/Objects/TR5/Trap/ZipLine.h +++ b/TombEngine/Objects/TR5/Trap/ZipLine.h @@ -3,7 +3,7 @@ struct CollisionInfo; struct ItemInfo; -namespace TEN::Traps::TR5 +namespace TEN::Entities::Traps { void InitializeZipLine(short itemNumber); void CollideZipLine(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); diff --git a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp index 70bf86659..b80b0de18 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_explosion.cpp @@ -23,168 +23,175 @@ using namespace TEN::Effects::Items; using namespace TEN::Entities::Switches; -void InitializeExplosion(short itemNumber) +namespace TEN::Entities::Traps { - auto* item = &g_Level.Items[itemNumber]; - - if (item->TriggerFlags >= 30000) + void InitializeExplosion(short itemNumber) { - item->ItemFlags[1] = 3; - item->TriggerFlags -= 30000; - } - else if (item->TriggerFlags >= 20000) - { - item->ItemFlags[1] = 2; - item->TriggerFlags -= 20000; - } - else if (item->TriggerFlags >= 10000) - { - item->ItemFlags[1] = 1; - item->TriggerFlags -= 10000; - } + auto& item = g_Level.Items[itemNumber]; - if (item->TriggerFlags >= 1000) - { - item->ItemFlags[3] = 1; - item->TriggerFlags -= 1000; - } - - item->ItemFlags[2] = item->TriggerFlags / 100; - item->TriggerFlags = 7 * (item->TriggerFlags % 100); -} - -void ExplosionControl(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - if (TriggerActive(item)) - { - item->Flags |= IFLAG_INVISIBLE; - - if (item->ItemFlags[0] < item->TriggerFlags) + if (item.TriggerFlags >= 30000) { - ++item->ItemFlags[0]; + item.ItemFlags[1] = 3; + item.TriggerFlags -= 30000; } - else if (item->ItemFlags[0] == item->TriggerFlags) + else if (item.TriggerFlags >= 20000) { - int flag; - ++item->ItemFlags[0]; + item.ItemFlags[1] = 2; + item.TriggerFlags -= 20000; + } + else if (item.TriggerFlags >= 10000) + { + item.ItemFlags[1] = 1; + item.TriggerFlags -= 10000; + } - if (TestEnvironment(ENV_FLAG_WATER, item->RoomNumber) || - TestEnvironment(ENV_FLAG_SWAMP, item->RoomNumber)) - { - flag = 1; - } - else - { - flag = item->ItemFlags[1] == 1 ? 2 : 0; - } - - SoundEffect(SFX_TR4_EXPLOSION1, &item->Pose, SoundEnvironment::Land, 1.5f); - SoundEffect(SFX_TR4_EXPLOSION2, &item->Pose); - TriggerExplosionSparks(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 3, -2, flag, item->RoomNumber); - - for (int i = 0; i < item->ItemFlags[2]; ++i) - { - TriggerExplosionSparks( - item->Pose.Position.x + (GetRandomControl() % 128 - 64) * item->ItemFlags[2], - item->Pose.Position.y + (GetRandomControl() % 128 - 64) * item->ItemFlags[2], - item->Pose.Position.z + (GetRandomControl() % 128 - 64) * item->ItemFlags[2], - 2, 0, flag, item->RoomNumber); - } - - Pose pos; - pos.Position.x = item->Pose.Position.x; - pos.Position.y = item->Pose.Position.y - 128; - pos.Position.z = item->Pose.Position.z; - - if (item->ItemFlags[3]) - { - if (flag == 2) - TriggerShockwave(&pos, 48, 32 * item->ItemFlags[2] + 304, 4 * item->ItemFlags[2] + 96, 0, 96, 128, 24, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); - else - TriggerShockwave(&pos, 48, 32 * item->ItemFlags[2] + 304, 4 * item->ItemFlags[2] + 96, 128, 96, 0, 24, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); - } + if (item.TriggerFlags >= 1000) + { + item.ItemFlags[3] = 1; + item.TriggerFlags -= 1000; + } - if (flag != 2) - { - auto vec = GetJointPosition(LaraItem, LM_HIPS); + item.ItemFlags[2] = item.TriggerFlags / 100; + item.TriggerFlags = 7 * (item.TriggerFlags % 100); + } - int dx = vec.x - item->Pose.Position.x; - int dy = vec.y - item->Pose.Position.y; - int dz = vec.z - item->Pose.Position.z; - - if (abs(dx) < BLOCK(1) && - abs(dy) < BLOCK(1) && - abs(dz) < BLOCK(1)) + void ControlExplosion(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (TriggerActive(&item)) + { + item.Flags |= IFLAG_INVISIBLE; + + if (item.ItemFlags[0] < item.TriggerFlags) + { + ++item.ItemFlags[0]; + } + else if (item.ItemFlags[0] == item.TriggerFlags) + { + int flag; + ++item.ItemFlags[0]; + + if (TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) || + TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) { - int distance = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2)); - if (distance < BLOCK(2)) - { - DoDamage(LaraItem, distance / 16); - - if (distance < CLICK(3)) - ItemBurn(LaraItem); - } + flag = 1; } - } - - auto collObjects = GetCollidedObjects(*item, true, true, BLOCK(2), ObjectCollectionMode::All); - if (!collObjects.IsEmpty()) - { - for (auto* itemPtr : collObjects.Items) + else { - if (itemPtr->ObjectNumber >= ID_SMASH_OBJECT1 && itemPtr->ObjectNumber <= ID_SMASH_OBJECT16) + flag = item.ItemFlags[1] == 1 ? 2 : 0; + } + + SoundEffect(SFX_TR4_EXPLOSION1, &item.Pose, SoundEnvironment::Land, 1.5f); + SoundEffect(SFX_TR4_EXPLOSION2, &item.Pose); + TriggerExplosionSparks(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, 3, -2, flag, item.RoomNumber); + + for (int i = 0; i < item.ItemFlags[2]; ++i) + { + TriggerExplosionSparks( + item.Pose.Position.x + (GetRandomControl() % 128 - 64) * item.ItemFlags[2], + item.Pose.Position.y + (GetRandomControl() % 128 - 64) * item.ItemFlags[2], + item.Pose.Position.z + (GetRandomControl() % 128 - 64) * item.ItemFlags[2], + 2, 0, flag, item.RoomNumber); + } + + auto pose = Pose::Zero; + pose.Position.x = item.Pose.Position.x; + pose.Position.y = item.Pose.Position.y - 128; + pose.Position.z = item.Pose.Position.z; + + if (item.ItemFlags[3]) + { + if (flag == 2) { - TriggerExplosionSparks(itemPtr->Pose.Position.x, itemPtr->Pose.Position.y, itemPtr->Pose.Position.z, 3, -2, 0, itemPtr->RoomNumber); - itemPtr->Pose.Position.y -= 128; - TriggerShockwave(&itemPtr->Pose, 48, 304, 96, 128, 96, 0, 24, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); - itemPtr->Pose.Position.y += 128; - ExplodeItemNode(itemPtr, 0, 0, 80); - SmashObject(itemPtr->Index); - KillItem(itemPtr->Index); - } - else if (itemPtr->ObjectNumber != ID_SWITCH_TYPE7 && itemPtr->ObjectNumber != ID_SWITCH_TYPE8) - { - if (Objects[itemPtr->ObjectNumber].intelligent) - DoExplosiveDamage(*LaraItem, *itemPtr, *item, Weapons[(int)LaraWeaponType::GrenadeLauncher].ExplosiveDamage); + TriggerShockwave(&pose, 48, 32 * item.ItemFlags[2] + 304, 4 * item.ItemFlags[2] + 96, 0, 96, 128, 24, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); } else { - // @FIXME: This calls CrossbowHitSwitchType78() + TriggerShockwave(&pose, 48, 32 * item.ItemFlags[2] + 304, 4 * item.ItemFlags[2] + 96, 128, 96, 0, 24, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); } } - for (auto* staticPtr : collObjects.Statics) + if (flag != 2) { - if (StaticObjects[staticPtr->staticNumber].shatterType != ShatterType::None) + auto vec = GetJointPosition(LaraItem, LM_HIPS); + + int dx = vec.x - item.Pose.Position.x; + int dy = vec.y - item.Pose.Position.y; + int dz = vec.z - item.Pose.Position.z; + + if (abs(dx) < BLOCK(1) && + abs(dy) < BLOCK(1) && + abs(dz) < BLOCK(1)) { - TriggerExplosionSparks(staticPtr->pos.Position.x, staticPtr->pos.Position.y, staticPtr->pos.Position.z, 3, -2, 0, item->RoomNumber); - staticPtr->pos.Position.y -= 128; - TriggerShockwave(&staticPtr->pos, 40, 176, 64, 128, 96, 0, 16, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); - staticPtr->pos.Position.y += 128; - SoundEffect(GetShatterSound(staticPtr->staticNumber), &staticPtr->pos); - ShatterObject(nullptr, staticPtr, -128, item->RoomNumber, 0); + int distance = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2)); + if (distance < BLOCK(2)) + { + DoDamage(LaraItem, distance / 16); + + if (distance < CLICK(3)) + ItemBurn(LaraItem); + } } } - AlertNearbyGuards(item); - } - - if (item->ItemFlags[1] >= 2) - { - if (item->ItemFlags[1] == 3) + auto collObjects = GetCollidedObjects(item, true, true, BLOCK(2), ObjectCollectionMode::All); + if (!collObjects.IsEmpty()) { - short triggerItems[8]; - for (int i = GetSwitchTrigger(item, triggerItems, 1); i > 0; --i) - g_Level.Items[triggerItems[i - 1]].ItemFlags[0] = 0; - - item->ItemFlags[0] = 0; + for (auto* itemPtr : collObjects.Items) + { + if (itemPtr->ObjectNumber >= ID_SMASH_OBJECT1 && itemPtr->ObjectNumber <= ID_SMASH_OBJECT16) + { + TriggerExplosionSparks(itemPtr->Pose.Position.x, itemPtr->Pose.Position.y, itemPtr->Pose.Position.z, 3, -2, 0, itemPtr->RoomNumber); + itemPtr->Pose.Position.y -= 128; + TriggerShockwave(&itemPtr->Pose, 48, 304, 96, 128, 96, 0, 24, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); + itemPtr->Pose.Position.y += 128; + ExplodeItemNode(itemPtr, 0, 0, 80); + SmashObject(itemPtr->Index); + KillItem(itemPtr->Index); + } + else if (itemPtr->ObjectNumber != ID_SWITCH_TYPE7 && itemPtr->ObjectNumber != ID_SWITCH_TYPE8) + { + if (Objects[itemPtr->ObjectNumber].intelligent) + DoExplosiveDamage(*LaraItem, *itemPtr, item, Weapons[(int)LaraWeaponType::GrenadeLauncher].ExplosiveDamage); + } + else + { + // @FIXME: This calls CrossbowHitSwitchType78() + } + } + + for (auto* staticPtr : collObjects.Statics) + { + if (StaticObjects[staticPtr->staticNumber].shatterType != ShatterType::None) + { + TriggerExplosionSparks(staticPtr->pos.Position.x, staticPtr->pos.Position.y, staticPtr->pos.Position.z, 3, -2, 0, item.RoomNumber); + staticPtr->pos.Position.y -= 128; + TriggerShockwave(&staticPtr->pos, 40, 176, 64, 128, 96, 0, 16, EulerAngles::Identity, 0, true, false, false, (int)ShockwaveStyle::Normal); + staticPtr->pos.Position.y += 128; + SoundEffect(GetShatterSound(staticPtr->staticNumber), &staticPtr->pos); + ShatterObject(nullptr, staticPtr, -128, item.RoomNumber, 0); + } + } + + AlertNearbyGuards(&item); + } + + if (item.ItemFlags[1] >= 2) + { + if (item.ItemFlags[1] == 3) + { + short triggerItems[8]; + for (int i = GetSwitchTrigger(&item, triggerItems, 1); i > 0; --i) + g_Level.Items[triggerItems[i - 1]].ItemFlags[0] = 0; + + item.ItemFlags[0] = 0; + } + } + else + { + KillItem(itemNumber); } - } - else - { - KillItem(itemNumber); } } } diff --git a/TombEngine/Objects/TR5/Trap/tr5_explosion.h b/TombEngine/Objects/TR5/Trap/tr5_explosion.h index d8e67972e..54f49956b 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_explosion.h +++ b/TombEngine/Objects/TR5/Trap/tr5_explosion.h @@ -1,4 +1,7 @@ #pragma once -void InitializeExplosion(short itemNumber); -void ExplosionControl(short itemNumber); +namespace TEN::Entities::Traps +{ + void InitializeExplosion(short itemNumber); + void ControlExplosion(short itemNumber); +} diff --git a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp index a086231d5..624b65c70 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.cpp @@ -11,42 +11,49 @@ using namespace TEN::Collision::Point; -void FallingCeilingControl(short itemNumber) +namespace TEN::Entities::Traps { - auto* item = &g_Level.Items[itemNumber]; + constexpr auto FALLING_CEILING_HARM_DAMAGE = 300; - if (item->Animation.ActiveState) + void ControlFallingCeiling(short itemNumber) { - if (item->Animation.ActiveState == 1 && item->TouchBits.TestAny()) - DoDamage(LaraItem, 300); - } - else - { - item->Animation.TargetState = 1; - item->Animation.IsAirborne = true; - } + auto& item = g_Level.Items[itemNumber]; - AnimateItem(item); - - if (item->Status == ITEM_DEACTIVATED) - RemoveActiveItem(itemNumber); - else - { - auto probe = GetPointCollision(*item); - - item->Floor = probe.GetFloorHeight(); - - if (probe.GetRoomNumber() != item->RoomNumber) - ItemNewRoom(itemNumber, probe.GetRoomNumber()); - - if (item->Animation.ActiveState == 1) + if (item.Animation.ActiveState) { - if (item->Pose.Position.y >= item->Floor) + if (item.Animation.ActiveState == 1 && item.TouchBits.TestAny()) + DoDamage(LaraItem, FALLING_CEILING_HARM_DAMAGE); + } + else + { + item.Animation.TargetState = 1; + item.Animation.IsAirborne = true; + } + + AnimateItem(&item); + + if (item.Status == ITEM_DEACTIVATED) + { + RemoveActiveItem(itemNumber); + } + else + { + auto pointColl = GetPointCollision(item); + + item.Floor = pointColl.GetFloorHeight(); + + if (pointColl.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); + + if (item.Animation.ActiveState == 1) { - item->Pose.Position.y = item->Floor; - item->Animation.TargetState = 2; - item->Animation.IsAirborne = false; - item->Animation.Velocity.y = 0.0f; + if (item.Pose.Position.y >= item.Floor) + { + item.Pose.Position.y = item.Floor; + item.Animation.TargetState = 2; + item.Animation.IsAirborne = false; + item.Animation.Velocity.y = 0.0f; + } } } } diff --git a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.h b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.h index dc01af23d..30f0ab103 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.h +++ b/TombEngine/Objects/TR5/Trap/tr5_fallingceiling.h @@ -1,3 +1,6 @@ #pragma once -void FallingCeilingControl(short itemNumber); +namespace TEN::Entities::Traps +{ + void ControlFallingCeiling(short itemNumber); +} diff --git a/TombEngine/Objects/TR5/Trap/tr5_romehammer.cpp b/TombEngine/Objects/TR5/Trap/tr5_romehammer.cpp index 9b26ff77c..14d198faf 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_romehammer.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_romehammer.cpp @@ -4,10 +4,38 @@ #include "Game/items.h" #include "Specific/level.h" -void InitializeRomeHammer(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; +// NOTES: +// item.ItemFlags[0] = Harm joints. +// item.ItemFlags[3] = Damage. +// item.ItemFlags[4] = Push player (bool). - item->ItemFlags[0] = 2; - item->ItemFlags[3] = 250; +namespace TEN::Entities::Traps +{ + constexpr auto ROME_HAMMER_HARM_DAMAGE = 250; + constexpr auto ROME_HAMMER_JOINTS = MESH_BITS(1); + + const auto RomeHammerHarmJoints = std::vector{ 2 }; + + void InitializeRomeHammer(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + item.ItemFlags[0] = ROME_HAMMER_JOINTS; + item.ItemFlags[3] = 0; + } + + void ControlRomeHammer(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (TriggerActive(&item)) + { + item.ItemFlags[3] = ROME_HAMMER_HARM_DAMAGE; + AnimateItem(&item); + } + else + { + item.ItemFlags[3] = 0; + } + } } diff --git a/TombEngine/Objects/TR5/Trap/tr5_romehammer.h b/TombEngine/Objects/TR5/Trap/tr5_romehammer.h index fe2442331..0b436861f 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_romehammer.h +++ b/TombEngine/Objects/TR5/Trap/tr5_romehammer.h @@ -1,3 +1,7 @@ #pragma once -void InitializeRomeHammer(short itemNumber); +namespace TEN::Entities::Traps +{ + void InitializeRomeHammer(short itemNumber); + void ControlRomeHammer(short itemNumber); +} diff --git a/TombEngine/Objects/TR5/Trap/tr5_ventilator.cpp b/TombEngine/Objects/TR5/Trap/tr5_ventilator.cpp index 37515b543..d6ffc7706 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_ventilator.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_ventilator.cpp @@ -9,305 +9,327 @@ #include "Game/Lara/lara.h" #include "Specific/level.h" -void VentilatorEffect(GameBoundingBox* bounds, int intensity, short rot, int speed) +namespace TEN::Entities::Traps { - int x, y, z; + void VentilatorEffect(GameBoundingBox* bounds, int intensity, short rot, int speed) + { + int x, y, z; - if (abs(intensity) == 1) - { - x = (bounds->X1 + bounds->X2) / 2; - if (intensity >= 0) - y = bounds->Y2; - else - y = bounds->Y1; - z = (bounds->Z1 + bounds->Z2) / 2; - } - else - { - y = (bounds->Y1 + bounds->Y2) / 2; - if (rot & 0x7FFF) + if (abs(intensity) == 1) { - if (intensity >= 0) - z = bounds->Z2; - else - z = bounds->Z1; x = (bounds->X1 + bounds->X2) / 2; - } - else - { if (intensity >= 0) - x = bounds->X2; + { + y = bounds->Y2; + } else - x = bounds->X1; + { + y = bounds->Y1; + } z = (bounds->Z1 + bounds->Z2) / 2; } - } - - if (abs(Camera.pos.x - x) <= BLOCK(7)) - { - if (abs(Camera.pos.y - y) <= BLOCK(7)) - { - if (abs(Camera.pos.z - z) <= BLOCK(7)) - { - auto* spark = GetFreeParticle(); - - spark->on = 1; - spark->sR = 0; - spark->sG = 0; - spark->sB = 0; - spark->dR = spark->dG = (48 * speed) / 128; - spark->colFadeSpeed = 4; - spark->fadeToBlack = 8; - spark->dB = (speed * ((GetRandomControl() & 8) + 48)) / 128; - spark->blendMode = BlendMode::Additive; - spark->life = spark->sLife = (GetRandomControl() & 3) + 20; - - if (abs(intensity) == 1) - { - int factor = 3 * (bounds->X2 - bounds->X1) / 8; - short angle = 2 * GetRandomControl(); - - spark->x = ((bounds->X1 + bounds->X2) / 2) + (GetRandomControl() % factor) * phd_sin(angle); - spark->z = ((bounds->Z1 + bounds->Z2) / 2) + (GetRandomControl() % factor) * phd_cos(angle); - - if (intensity >= 0) - spark->y = bounds->Y2; - else - spark->y = bounds->Y1; - - spark->zVel = 0; - spark->xVel = 0; - spark->yVel = 32 * intensity * ((GetRandomControl() & 0x1F) + 224); - } - else - { - int factor = 3 * bounds->GetHeight() / 8; - short angle = 2 * GetRandomControl(); - - spark->y = (bounds->Y1 + bounds->Y2) / 2; - - if (rot & 0x7FFF) - { - if (intensity >= 0) - spark->z = bounds->Z2; - else - spark->z = bounds->Z1; - - spark->x = ((bounds->X1 + bounds->X2) / 2) + (GetRandomControl() % factor) * phd_cos(angle); - spark->y += (GetRandomControl() % factor) * phd_sin(angle); - spark->xVel = 0; - spark->zVel = 16 * intensity * ((GetRandomControl() & 0x1F) + 224); - } - else - { - if (intensity >= 0) - spark->x = bounds->X2; - else - spark->x = bounds->X1; - - spark->y += (GetRandomControl() % factor) * phd_sin(angle); - spark->z = ((bounds->Z1 + bounds->Z2) / 2) + (GetRandomControl() % factor) * phd_cos(angle); - spark->zVel = 0; - spark->xVel = 16 * intensity * ((GetRandomControl() & 0x1F) + 224); - } - - spark->yVel = 0; - } - - spark->friction = 85; - spark->xVel = (speed * spark->xVel) / 128; - spark->yVel = (speed * spark->yVel) / 128; - spark->zVel = (speed * spark->zVel) / 128; - spark->maxYvel = 0; - spark->gravity = 0; - spark->flags = SP_NONE; - } - } - } -} - -void InitializeVentilator(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - item->ItemFlags[0] = item->TriggerFlags * BLOCK(1); - if (item->ItemFlags[0] < 2048) - item->ItemFlags[0] = 3072; -} - -void VentilatorControl(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - AnimateItem(item); - - int xChange = 0; - int zChange = 0; - - if (TriggerActive(item)) - xChange = 1; - else - { - xChange = 1; - TestTriggers(item, true); - if (item->Animation.ActiveState == 1) - { - //result = 5 * item->animNumber; - if (item->Animation.FrameNumber == GetAnimData(item).frameEnd) - return; - } else - item->Animation.TargetState = 1; - } - - int speed = 0; - if (item->Animation.ActiveState == 1) - speed = GetAnimData(item).frameEnd - item->Animation.FrameNumber; - else - speed = 128; - - auto bounds = GameBoundingBox(item); - auto effectBounds = GameBoundingBox::Zero; - - effectBounds.Y1 = item->Pose.Position.y + bounds.Y1; - effectBounds.Y2 = item->Pose.Position.y + bounds.Y2; - - if (item->ObjectNumber != ID_PROPELLER_V) // TODO: check this ID - { - if (item->Pose.Orientation.y != -ANGLE(180.0f)) { - if (item->Pose.Orientation.y == -ANGLE(90.0f)) + y = (bounds->Y1 + bounds->Y2) / 2; + if (rot & 0x7FFF) { - effectBounds.X1 = item->Pose.Position.x - bounds.Z2; - effectBounds.X2 = item->Pose.Position.x - bounds.Z1; - effectBounds.Z1 = item->Pose.Position.z + bounds.X1; - effectBounds.Z2 = item->Pose.Position.z + bounds.X2; - xChange = 0; - zChange = 1; + if (intensity >= 0) + z = bounds->Z2; + else + z = bounds->Z1; + x = (bounds->X1 + bounds->X2) / 2; } else { - if (item->Pose.Orientation.y != ANGLE(90.0f)) + if (intensity >= 0) + x = bounds->X2; + else + x = bounds->X1; + z = (bounds->Z1 + bounds->Z2) / 2; + } + } + + auto& part = *GetFreeParticle(); + + part.on = 1; + part.sR = 0; + part.sG = 0; + part.sB = 0; + part.dR = part.dG = (48 * speed) / 128; + part.colFadeSpeed = 4; + part.fadeToBlack = 8; + part.dB = (speed * ((GetRandomControl() & 8) + 48)) / 128; + part.blendMode = BlendMode::Additive; + part.life = part.sLife = (GetRandomControl() & 3) + 20; + + if (abs(intensity) == 1) + { + int factor = 3 * (bounds->X2 - bounds->X1) / 8; + short angle = 2 * GetRandomControl(); + + part.x = ((bounds->X1 + bounds->X2) / 2) + (GetRandomControl() % factor) * phd_sin(angle); + part.z = ((bounds->Z1 + bounds->Z2) / 2) + (GetRandomControl() % factor) * phd_cos(angle); + + if (intensity >= 0) + { + part.y = bounds->Y2; + } + else + { + part.y = bounds->Y1; + } + + part.zVel = 0; + part.xVel = 0; + part.yVel = 32 * intensity * ((GetRandomControl() & 0x1F) + 224); + } + else + { + int factor = 3 * bounds->GetHeight() / 8; + short angle = Random::GenerateAngle(); + + part.y = (bounds->Y1 + bounds->Y2) / 2; + + if (rot & 0x7FFF) + { + if (intensity >= 0) { - effectBounds.X1 = item->Pose.Position.x + bounds.X1; - effectBounds.X2 = item->Pose.Position.x + bounds.X2; - effectBounds.Z1 = item->Pose.Position.z + bounds.Z1; - effectBounds.Z2 = item->Pose.Position.z + bounds.Z2; - zChange = 0; + part.z = bounds->Z2; } else { - effectBounds.X1 = item->Pose.Position.x + bounds.Z1; - effectBounds.X2 = item->Pose.Position.x + bounds.Z2; - effectBounds.Z1 = item->Pose.Position.z - bounds.X2; - effectBounds.Z2 = item->Pose.Position.z - bounds.X1; + part.z = bounds->Z1; + } + + part.x = ((bounds->X1 + bounds->X2) / 2) + (GetRandomControl() % factor) * phd_cos(angle); + part.y += (GetRandomControl() % factor) * phd_sin(angle); + part.xVel = 0; + part.zVel = 16 * intensity * ((GetRandomControl() & 0x1F) + 224); + } + else + { + if (intensity >= 0) + { + part.x = bounds->X2; + } + else + { + part.x = bounds->X1; + } + + part.y += (GetRandomControl() % factor) * phd_sin(angle); + part.z = ((bounds->Z1 + bounds->Z2) / 2) + (GetRandomControl() % factor) * phd_cos(angle); + part.zVel = 0; + part.xVel = 16 * intensity * ((GetRandomControl() & 0x1F) + 224); + } + + part.yVel = 0; + } + + part.friction = 85; + part.xVel = (speed * part.xVel) / 128; + part.yVel = (speed * part.yVel) / 128; + part.zVel = (speed * part.zVel) / 128; + part.maxYvel = 0; + part.gravity = 0; + part.flags = SP_NONE; + } + + void InitializeVentilator(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + item.ItemFlags[0] = item.TriggerFlags * BLOCK(1); + if (item.ItemFlags[0] < 2048) + item.ItemFlags[0] = 3072; + } + + void ControlVentilator(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + AnimateItem(&item); + + int xChange = 0; + int zChange = 0; + + if (TriggerActive(&item)) + { + xChange = 1; + } + else + { + xChange = 1; + TestTriggers(&item, true); + if (item.Animation.ActiveState == 1) + { + // result = 5 * item.animNumber; + if (item.Animation.FrameNumber == GetAnimData(item).frameEnd) + return; + } + else + { + item.Animation.TargetState = 1; + } + } + + int speed = 0; + if (item.Animation.ActiveState == 1) + { + speed = GetAnimData(item).frameEnd - item.Animation.FrameNumber; + } + else + { + speed = 128; + } + + auto bounds = GameBoundingBox(&item); + auto effectBounds = GameBoundingBox::Zero; + + effectBounds.Y1 = item.Pose.Position.y + bounds.Y1; + effectBounds.Y2 = item.Pose.Position.y + bounds.Y2; + + if (item.ObjectNumber != ID_PROPELLER_V) // TODO: check this ID + { + if (item.Pose.Orientation.y != -ANGLE(180.0f)) + { + if (item.Pose.Orientation.y == -ANGLE(90.0f)) + { + effectBounds.X1 = item.Pose.Position.x - bounds.Z2; + effectBounds.X2 = item.Pose.Position.x - bounds.Z1; + effectBounds.Z1 = item.Pose.Position.z + bounds.X1; + effectBounds.Z2 = item.Pose.Position.z + bounds.X2; xChange = 0; zChange = 1; } - } - } - else - { - effectBounds.X1 = item->Pose.Position.x - bounds.X2; - effectBounds.X2 = item->Pose.Position.x - bounds.X1; - effectBounds.Z1 = item->Pose.Position.z - bounds.Z2; - effectBounds.Z2 = item->Pose.Position.z - bounds.Z1; - zChange = 0; - } - - VentilatorEffect(&effectBounds, 2, item->Pose.Orientation.y, speed); - VentilatorEffect(&effectBounds, -2, item->Pose.Orientation.y, speed); - - if (LaraItem->Pose.Position.y >= effectBounds.Y1 && LaraItem->Pose.Position.y <= effectBounds.Y2) - { - if (zChange) - { - if (LaraItem->Pose.Position.x >= effectBounds.X1 && LaraItem->Pose.Position.x <= effectBounds.X2) + else { - int z1 = abs(LaraItem->Pose.Position.z - effectBounds.Z1); - int z2 = abs(LaraItem->Pose.Position.z - effectBounds.Z2); - - if (z2 >= z1) - zChange = -zChange; - else - z1 = z2; - - if (z1 < item->ItemFlags[0]) + if (item.Pose.Orientation.y != ANGLE(90.0f)) { - int dz = 96 * zChange * (item->ItemFlags[0] - z1) / item->ItemFlags[0]; - - if (item->Animation.ActiveState == 1) - dz = speed * dz / 120; - - LaraItem->Pose.Position.z += dz; + effectBounds.X1 = item.Pose.Position.x + bounds.X1; + effectBounds.X2 = item.Pose.Position.x + bounds.X2; + effectBounds.Z1 = item.Pose.Position.z + bounds.Z1; + effectBounds.Z2 = item.Pose.Position.z + bounds.Z2; + zChange = 0; + } + else + { + effectBounds.X1 = item.Pose.Position.x + bounds.Z1; + effectBounds.X2 = item.Pose.Position.x + bounds.Z2; + effectBounds.Z1 = item.Pose.Position.z - bounds.X2; + effectBounds.Z2 = item.Pose.Position.z - bounds.X1; + xChange = 0; + zChange = 1; } } } else { - if (LaraItem->Pose.Position.z >= effectBounds.Z1 && LaraItem->Pose.Position.z <= effectBounds.Z2) + effectBounds.X1 = item.Pose.Position.x - bounds.X2; + effectBounds.X2 = item.Pose.Position.x - bounds.X1; + effectBounds.Z1 = item.Pose.Position.z - bounds.Z2; + effectBounds.Z2 = item.Pose.Position.z - bounds.Z1; + zChange = 0; + } + + VentilatorEffect(&effectBounds, 2, item.Pose.Orientation.y, speed); + VentilatorEffect(&effectBounds, -2, item.Pose.Orientation.y, speed); + + if (LaraItem->Pose.Position.y >= effectBounds.Y1 && LaraItem->Pose.Position.y <= effectBounds.Y2) + { + if (zChange) { - int x1 = abs(LaraItem->Pose.Position.x - effectBounds.X1); - int x2 = abs(LaraItem->Pose.Position.x - effectBounds.X2); - - if (x2 >= x1) - xChange = -xChange; - else - x1 = x2; - - if (x1 < item->ItemFlags[0]) + if (LaraItem->Pose.Position.x >= effectBounds.X1 && LaraItem->Pose.Position.x <= effectBounds.X2) { - int dx = 96 * xChange * (item->ItemFlags[0] - x1) / item->ItemFlags[0]; + int z1 = abs(LaraItem->Pose.Position.z - effectBounds.Z1); + int z2 = abs(LaraItem->Pose.Position.z - effectBounds.Z2); - if (item->Animation.ActiveState == 1) - dx = speed * dx / 120; + if (z2 >= z1) + zChange = -zChange; + else + z1 = z2; - LaraItem->Pose.Position.x += dx; + if (z1 < item.ItemFlags[0]) + { + int dz = 96 * zChange * (item.ItemFlags[0] - z1) / item.ItemFlags[0]; + + if (item.Animation.ActiveState == 1) + dz = speed * dz / 120; + + LaraItem->Pose.Position.z += dz; + } + } + } + else + { + if (LaraItem->Pose.Position.z >= effectBounds.Z1 && LaraItem->Pose.Position.z <= effectBounds.Z2) + { + int x1 = abs(LaraItem->Pose.Position.x - effectBounds.X1); + int x2 = abs(LaraItem->Pose.Position.x - effectBounds.X2); + + if (x2 >= x1) + { + xChange = -xChange; + } + else + { + x1 = x2; + } + + if (x1 < item.ItemFlags[0]) + { + int dx = 96 * xChange * (item.ItemFlags[0] - x1) / item.ItemFlags[0]; + + if (item.Animation.ActiveState == 1) + dx = speed * dx / 120; + + LaraItem->Pose.Position.x += dx; + } } } } } - } - else - { - auto tBounds = bounds; - tBounds.Rotate(item->Pose.Orientation); - - effectBounds.X1 = item->Pose.Position.x + tBounds.X1; - effectBounds.X2 = item->Pose.Position.x + tBounds.X2; - effectBounds.Z1 = item->Pose.Position.z + tBounds.Z1; - effectBounds.Z2 = item->Pose.Position.z + tBounds.Z2; - - VentilatorEffect(&effectBounds, 1, 0, speed); - VentilatorEffect(&effectBounds, -1, 0, speed); - - if (LaraItem->Pose.Position.x >= effectBounds.X1 && - LaraItem->Pose.Position.x <= effectBounds.X2) + else { - if (LaraItem->Pose.Position.z >= effectBounds.Z1 && - LaraItem->Pose.Position.z <= effectBounds.Z2) + auto tBounds = bounds; + tBounds.Rotate(item.Pose.Orientation); + + effectBounds.X1 = item.Pose.Position.x + tBounds.X1; + effectBounds.X2 = item.Pose.Position.x + tBounds.X2; + effectBounds.Z1 = item.Pose.Position.z + tBounds.Z1; + effectBounds.Z2 = item.Pose.Position.z + tBounds.Z2; + + VentilatorEffect(&effectBounds, 1, 0, speed); + VentilatorEffect(&effectBounds, -1, 0, speed); + + if (LaraItem->Pose.Position.x >= effectBounds.X1 && + LaraItem->Pose.Position.x <= effectBounds.X2) { - int y = effectBounds.Y2; - - if (LaraItem->Pose.Position.y <= effectBounds.Y2) + if (LaraItem->Pose.Position.z >= effectBounds.Z1 && + LaraItem->Pose.Position.z <= effectBounds.Z2) { - if (effectBounds.Y1 - LaraItem->Pose.Position.y >= item->ItemFlags[0]) - return; + int y = effectBounds.Y2; - y = 96 * (effectBounds.Y2 - item->ItemFlags[0]) / item->ItemFlags[0]; + if (LaraItem->Pose.Position.y <= effectBounds.Y2) + { + if (effectBounds.Y1 - LaraItem->Pose.Position.y >= item.ItemFlags[0]) + return; + + y = 96 * (effectBounds.Y2 - item.ItemFlags[0]) / item.ItemFlags[0]; + } + else + { + if (LaraItem->Pose.Position.y - effectBounds.Y2 >= item.ItemFlags[0]) + return; + + y = 96 * (item.ItemFlags[0] - (LaraItem->Pose.Position.y - effectBounds.Y2)) / item.ItemFlags[0]; + } + + if (item.Animation.ActiveState == 1) + y = speed * y / 120; + + LaraItem->Pose.Position.y += y; } - else - { - if (LaraItem->Pose.Position.y - effectBounds.Y2 >= item->ItemFlags[0]) - return; - - y = 96 * (item->ItemFlags[0] - (LaraItem->Pose.Position.y - effectBounds.Y2)) / item->ItemFlags[0]; - } - - if (item->Animation.ActiveState == 1) - y = speed * y / 120; - - LaraItem->Pose.Position.y += y; } } } diff --git a/TombEngine/Objects/TR5/Trap/tr5_ventilator.h b/TombEngine/Objects/TR5/Trap/tr5_ventilator.h index a80f1fe83..d0e920538 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_ventilator.h +++ b/TombEngine/Objects/TR5/Trap/tr5_ventilator.h @@ -1,4 +1,7 @@ #pragma once -void InitializeVentilator(short itemNumber); -void VentilatorControl(short itemNumber); +namespace TEN::Entities::Traps +{ + void InitializeVentilator(short itemNumber); + void ControlVentilator(short itemNumber); +} diff --git a/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp b/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp index 3df7c9b76..6774daacc 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp @@ -19,296 +19,347 @@ using namespace TEN::Effects::Environment; -static short WreckingBallData[2] = { 0, 0 }; +// TODO: Refactor. +// - Modularize. +// - Remove all legacy magic garbage. +// - Revise logic to remove constrains and allow it to move around different structures. +// - Change management of base object (item2). +// - Make light effect optional. +// +// NOTES +// ItemFlags[0] = ?? +// ItemFlags[1] = ?? +// ItemFlags[2] = ?? +// ItemFlags[3] = Base object ID (by default ANIMATING16) -void InitializeWreckingBall(short itemNumber) +namespace TEN::Entities::Traps { - auto* item = &g_Level.Items[itemNumber]; + static short WreckingBallData[2] = { 0, 0 }; - item->ItemFlags[3] = FindAllItems(ID_ANIMATING16)[0]; - - short RoomNumber = item->RoomNumber; - item->Pose.Position.y = GetCeiling(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &RoomNumber), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z) + 1644; - GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &RoomNumber); - - if (RoomNumber != item->RoomNumber) - ItemNewRoom(itemNumber, RoomNumber); -} - -void WreckingBallCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) -{ - auto* item = &g_Level.Items[itemNumber]; - - if (TestBoundsCollide(item, laraItem, coll->Setup.Radius)) + void InitializeWreckingBall(short itemNumber) { - int x = laraItem->Pose.Position.x; - int y = laraItem->Pose.Position.y; - int z = laraItem->Pose.Position.z; + auto& item = g_Level.Items[itemNumber]; - bool test = false; - if ((x & WALL_MASK) > CLICK(1) && - (x & WALL_MASK) < CLICK(3) && - (z & WALL_MASK) > CLICK(1) && - (z & WALL_MASK) < CLICK(3)) + auto pointColl = GetPointCollision(item); + + item.ItemFlags[3] = FindAllItems(ID_ANIMATING16)[0]; + item.Pose.Position.y = pointColl.GetCeilingHeight() + 1644; + + if (pointColl.GetRoomNumber() != item.RoomNumber) + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); + } + + void CollideWreckingBall(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) + { + auto& item = g_Level.Items[itemNumber]; + + if (TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) { - test = true; + auto prevPos = playerItem->Pose.Position; + + bool test = false; + if ((prevPos.x & WALL_MASK) > CLICK(1) && + (prevPos.x & WALL_MASK) < CLICK(3) && + (prevPos.z & WALL_MASK) > CLICK(1) && + (prevPos.z & WALL_MASK) < CLICK(3)) + { + test = true; + } + + int damage = (item.Animation.Velocity.y > 0.0f) ? 96 : 0; + + if (ItemPushItem(&item, playerItem, coll, coll->Setup.EnableSpasm, 1)) + { + if (test) + { + DoDamage(playerItem, INT_MAX); + } + else + { + DoDamage(playerItem, damage); + } + + prevPos -= playerItem->Pose.Position; + + if (damage != 0) + { + for (int i = 14 + (GetRandomControl() & 3); i > 0; --i) + { + TriggerBlood(playerItem->Pose.Position.x + (GetRandomControl() & 63) - 32, playerItem->Pose.Position.y - (GetRandomControl() & 511) - 256, + playerItem->Pose.Position.z + (GetRandomControl() & 63) - 32, -1, 1); + } + } + + if (!coll->Setup.EnableObjectPush || test) + playerItem->Pose.Position += prevPos; + } + } + } + + void ControlWreckingBall(short itemNumber) + { + int x, z, oldX, oldZ, wx, wz, flagX, flagZ, height, dx, dz, ceilingX, ceilingZ, adx, adz; + short room; + + auto& item = g_Level.Items[itemNumber]; + auto& item2 = g_Level.Items[item.ItemFlags[3]]; + + bool test = true; + + if ((LaraItem->Pose.Position.x >= BLOCK(44) && + LaraItem->Pose.Position.x <= BLOCK(56) && + LaraItem->Pose.Position.z >= BLOCK(26) && + LaraItem->Pose.Position.z <= BLOCK(42)) || + item.ItemFlags[2] < 900) + { + if (item.ItemFlags[2] < 900) + { + if (!item.ItemFlags[2] || !(GlobalCounter & 0x3F)) + { + WreckingBallData[0] = GetRandomControl() % 7 - 3; + WreckingBallData[1] = GetRandomControl() % 7 - 3; + } + + x = (WreckingBallData[0] << 10) + 51712; + z = (WreckingBallData[1] << 10) + 34304; + test = false; + } + else + { + x = LaraItem->Pose.Position.x; + z = LaraItem->Pose.Position.z; + } + } + else + { + x = 51200; + z = 33792; + test = false; } - int damage = (item->Animation.Velocity.y > 0.0f) ? 96 : 0; + if (item.ItemFlags[2] < 900) + ++item.ItemFlags[2]; - if (ItemPushItem(item, laraItem, coll, coll->Setup.EnableSpasm, 1)) + if (item.ItemFlags[1] <= 0) { - if (test) - DoDamage(laraItem, INT_MAX); - else - DoDamage(laraItem, damage); + oldX = item.Pose.Position.x; + oldZ = item.Pose.Position.z; + x = x & 0xFFFFFE00 | 0x200; + z = z & 0xFFFFFE00 | 0x200; + dx = x - item.Pose.Position.x; + dz = z - item.Pose.Position.z; + wx = 0; - x -= laraItem->Pose.Position.x; - y -= laraItem->Pose.Position.y; - z -= laraItem->Pose.Position.z; - - if (damage) + if (dx < 0) { - for (int i = 14 + (GetRandomControl() & 3); i > 0; --i) + wx = -1024; + } + else if (dx > 0) + { + wx = 1024; + } + wz = 0; + + if (dz < 0) + { + wz = -1024; + } + else if (dz > 0) + { + wz = 1024; + } + + room = item.RoomNumber; + ceilingX = GetCeiling(GetFloor(item.Pose.Position.x + wx, item2.Pose.Position.y, item.Pose.Position.z, &room), item.Pose.Position.x + wx, item2.Pose.Position.y, item.Pose.Position.z); + room = item.RoomNumber; + + ceilingZ = GetCeiling(GetFloor(item.Pose.Position.x, item2.Pose.Position.y, item.Pose.Position.z + wz, &room), item.Pose.Position.x, item2.Pose.Position.y, item.Pose.Position.z + wz); + if (ceilingX <= item2.Pose.Position.y && ceilingX != NO_HEIGHT) + { + flagX = 1; + } + else + { + flagX = 0; + } + + if (ceilingZ <= item2.Pose.Position.y && ceilingZ != NO_HEIGHT) + { + flagZ = 1; + } + else + { + flagZ = 0; + } + + if (!item.ItemFlags[0]) + { + if (flagX && dx && (abs(dx) > abs(dz) || !flagZ || GetRandomControl() & 1)) { - TriggerBlood(laraItem->Pose.Position.x + (GetRandomControl() & 63) - 32, laraItem->Pose.Position.y - (GetRandomControl() & 511) - 256, - laraItem->Pose.Position.z + (GetRandomControl() & 63) - 32, -1, 1); + item.ItemFlags[0] = 1; + } + else if (flagZ && dz) + { + item.ItemFlags[0] = 2; } } - if (!coll->Setup.EnableObjectPush || test) + if (item.ItemFlags[0] == 1) { - laraItem->Pose.Position.x += x; - laraItem->Pose.Position.y += y; - laraItem->Pose.Position.z += z; + SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item.Pose); + + adx = abs(dx); + if (adx >= 32) + adx = 32; + + if (dx > 0) + { + item.Pose.Position.x += adx; + } + else if (dx < 0) + { + item.Pose.Position.x -= adx; + } + else + { + item.ItemFlags[0] = 0; + } + } + + if (item.ItemFlags[0] == 2) + { + SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item.Pose); + + adz = abs(dz); + if (adz >= 32) + adz = 32; + + if (dz > 0) + { + item.Pose.Position.z += adz; + } + else if (dz < 0) + { + item.Pose.Position.z -= adz; + } + else + { + item.ItemFlags[0] = 0; + } + } + + if (item.ItemFlags[1] == -1 && (oldX != item.Pose.Position.x || oldZ != item.Pose.Position.z)) + { + item.ItemFlags[1] = 0; + SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_A, &item.Pose); + } + + if ((item.Pose.Position.x & 0x3FF) == 512 && (item.Pose.Position.z & 0x3FF) == 512) + item.ItemFlags[0] = 0; + + if (x == item.Pose.Position.x && z == item.Pose.Position.z && test) + { + if (item.ItemFlags[1] != -1) + { + StopSoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP); + SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_C, &item.Pose); + } + + item.ItemFlags[1] = 1; + item.TriggerFlags = 30; } } + else if (item.ItemFlags[1] == 1) + { + if (!item.TriggerFlags) + { + --item.TriggerFlags; + } + else if (!item.Animation.ActiveState) + { + item.Animation.TargetState = 1; + } + else if (item.Animation.FrameNumber == GetAnimData(item).frameEnd) + { + SoundEffect(SFX_TR5_BASE_CLAW_DROP, &item.Pose); + ++item.ItemFlags[1]; + item.Animation.Velocity.y = 6; + item.Pose.Position.y += item.Animation.Velocity.y; + } + } + else if (item.ItemFlags[1] == 2) + { + item.Animation.Velocity.y += 24; + item.Pose.Position.y += item.Animation.Velocity.y; + room = item.RoomNumber; + + height = GetFloorHeight(GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &room), item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z); + if (height < item.Pose.Position.y) + { + item.Pose.Position.y = height; + if (item.Animation.Velocity.y > 48) + { + BounceCamera(&item, 64, 8192); + item.Animation.Velocity.y = -item.Animation.Velocity.y / 8.0f; + } + else + { + ++item.ItemFlags[1]; + item.Animation.Velocity.y = 0; + } + } + else if (height - item.Pose.Position.y < 1536 && item.Animation.ActiveState) + { + item.Animation.TargetState = 0; + } + } + else if (item.ItemFlags[1] == 3) + { + item.Animation.Velocity.y -= 3; + item.Pose.Position.y += item.Animation.Velocity.y; + + if (item.Pose.Position.y < item2.Pose.Position.y + 1644) + { + StopSoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP); + item.ItemFlags[0] = 1; + item.Pose.Position.y = item2.Pose.Position.y + 1644; + + if (item.Animation.Velocity.y < -32.0f) + { + SoundEffect(SFX_TR5_BASE_CLAW_TOP_IMPACT, &item.Pose, SoundEnvironment::Land, 1.0f, 0.5f); + item.Animation.Velocity.y = -item.Animation.Velocity.y / 8.0f; + BounceCamera(&item, 16, 8192); + } + else + { + item.ItemFlags[1] = -1; + item.Animation.Velocity.y = 0; + item.ItemFlags[0] = 0; + } + } + else if (!item.ItemFlags[0]) + { + SoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP, &item.Pose); + } + } + + item2.Pose.Position.x = item.Pose.Position.x; + item2.Pose.Position.z = item.Pose.Position.z; + room = item.RoomNumber; + item2.Pose.Position.y = GetCeiling(GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &room), item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z); + + GetFloor(item2.Pose.Position.x, item2.Pose.Position.y, item2.Pose.Position.z, &room); + if (room != item2.RoomNumber) + ItemNewRoom(item.ItemFlags[3], room); + + TriggerAlertLight(item2.Pose.Position.x, item2.Pose.Position.y + 64, item2.Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter & 0x3F), item2.RoomNumber, 24); + TriggerAlertLight(item2.Pose.Position.x, item2.Pose.Position.y + 64, item2.Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter - 32) & 0xFFF, item2.RoomNumber, 24); + + room = item.RoomNumber; + GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &room); + if (room != item.RoomNumber) + ItemNewRoom(itemNumber, room); + + AnimateItem(&item); } } - -void WreckingBallControl(short itemNumber) -{ - int x, z, oldX, oldZ, wx, wz, flagX, flagZ, height, dx, dz, ceilingX, ceilingZ, adx, adz; - short room; - - auto* item = &g_Level.Items[itemNumber]; - auto* item2 = &g_Level.Items[item->ItemFlags[3]]; - - bool test = true; - - if ((LaraItem->Pose.Position.x >= BLOCK(44) && - LaraItem->Pose.Position.x <= BLOCK(56)&& - LaraItem->Pose.Position.z >= BLOCK(26) && - LaraItem->Pose.Position.z <= BLOCK(42)) || - item->ItemFlags[2] < 900) - { - if (item->ItemFlags[2] < 900) - { - if (!item->ItemFlags[2] || !(GlobalCounter & 0x3F)) - { - WreckingBallData[0] = GetRandomControl() % 7 - 3; - WreckingBallData[1] = GetRandomControl() % 7 - 3; - } - - x = (WreckingBallData[0] << 10) + 51712; - z = (WreckingBallData[1] << 10) + 34304; - test = false; - } - else - { - x = LaraItem->Pose.Position.x; - z = LaraItem->Pose.Position.z; - } - } - else - { - x = 51200; - z = 33792; - test = false; - } - - if (item->ItemFlags[2] < 900) - ++item->ItemFlags[2]; - - if (item->ItemFlags[1] <= 0) - { - oldX = item->Pose.Position.x; - oldZ = item->Pose.Position.z; - x = x & 0xFFFFFE00 | 0x200; - z = z & 0xFFFFFE00 | 0x200; - dx = x - item->Pose.Position.x; - dz = z - item->Pose.Position.z; - wx = 0; - - if (dx < 0) - wx = -1024; - else if (dx > 0) - wx = 1024; - wz = 0; - - if (dz < 0) - wz = -1024; - else if (dz > 0) - wz = 1024; - - room = item->RoomNumber; - ceilingX = GetCeiling(GetFloor(item->Pose.Position.x + wx, item2->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x + wx, item2->Pose.Position.y, item->Pose.Position.z); - room = item->RoomNumber; - - ceilingZ = GetCeiling(GetFloor(item->Pose.Position.x, item2->Pose.Position.y, item->Pose.Position.z + wz, &room), item->Pose.Position.x, item2->Pose.Position.y, item->Pose.Position.z + wz); - if (ceilingX <= item2->Pose.Position.y && ceilingX != NO_HEIGHT) - flagX = 1; - else - flagX = 0; - - if (ceilingZ <= item2->Pose.Position.y && ceilingZ != NO_HEIGHT) - flagZ = 1; - else - flagZ = 0; - - if (!item->ItemFlags[0]) - { - if (flagX && dx && (abs(dx) > abs(dz) || !flagZ || GetRandomControl() & 1)) - item->ItemFlags[0] = 1; - else if (flagZ && dz) - item->ItemFlags[0] = 2; - } - - if (item->ItemFlags[0] == 1) - { - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item->Pose); - - adx = abs(dx); - if (adx >= 32) - adx = 32; - - if (dx > 0) - item->Pose.Position.x += adx; - else if (dx < 0) - item->Pose.Position.x -= adx; - else - item->ItemFlags[0] = 0; - } - - if (item->ItemFlags[0] == 2) - { - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item->Pose); - - adz = abs(dz); - if (adz >= 32) - adz = 32; - - if (dz > 0) - item->Pose.Position.z += adz; - else if (dz < 0) - item->Pose.Position.z -= adz; - else - item->ItemFlags[0] = 0; - } - - if (item->ItemFlags[1] == -1 && (oldX != item->Pose.Position.x || oldZ != item->Pose.Position.z)) - { - item->ItemFlags[1] = 0; - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_A, &item->Pose); - } - - if ((item->Pose.Position.x & 0x3FF) == 512 && (item->Pose.Position.z & 0x3FF) == 512) - item->ItemFlags[0] = 0; - - if (x == item->Pose.Position.x && z == item->Pose.Position.z && test) - { - if (item->ItemFlags[1] != -1) - { - StopSoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP); - SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_C, &item->Pose); - } - - item->ItemFlags[1] = 1; - item->TriggerFlags = 30; - } - } - else if (item->ItemFlags[1] == 1) - { - if (!item->TriggerFlags) - --item->TriggerFlags; - else if (!item->Animation.ActiveState) - item->Animation.TargetState = 1; - else if (item->Animation.FrameNumber == GetAnimData(item).frameEnd) - { - SoundEffect(SFX_TR5_BASE_CLAW_DROP, &item->Pose); - ++item->ItemFlags[1]; - item->Animation.Velocity.y = 6; - item->Pose.Position.y += item->Animation.Velocity.y; - } - } - else if (item->ItemFlags[1] == 2) - { - item->Animation.Velocity.y += 24; - item->Pose.Position.y += item->Animation.Velocity.y; - room = item->RoomNumber; - - height = GetFloorHeight(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); - if (height < item->Pose.Position.y) - { - item->Pose.Position.y = height; - if (item->Animation.Velocity.y > 48) - { - BounceCamera(item, 64, 8192); - item->Animation.Velocity.y = -item->Animation.Velocity.y / 8.0f; - } - else - { - ++item->ItemFlags[1]; - item->Animation.Velocity.y = 0; - } - } - else if (height - item->Pose.Position.y < 1536 && item->Animation.ActiveState) - item->Animation.TargetState = 0; - } - else if (item->ItemFlags[1] == 3) - { - item->Animation.Velocity.y -= 3; - item->Pose.Position.y += item->Animation.Velocity.y; - - if (item->Pose.Position.y < item2->Pose.Position.y + 1644) - { - StopSoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP); - item->ItemFlags[0] = 1; - item->Pose.Position.y = item2->Pose.Position.y + 1644; - - if (item->Animation.Velocity.y < -32.0f) - { - SoundEffect(SFX_TR5_BASE_CLAW_TOP_IMPACT, &item->Pose, SoundEnvironment::Land, 1.0f, 0.5f); - item->Animation.Velocity.y = -item->Animation.Velocity.y / 8.0f; - BounceCamera(item, 16, 8192); - } - else - { - item->ItemFlags[1] = -1; - item->Animation.Velocity.y = 0; - item->ItemFlags[0] = 0; - } - } - else if (!item->ItemFlags[0]) - SoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP, &item->Pose); - } - - item2->Pose.Position.x = item->Pose.Position.x; - item2->Pose.Position.z = item->Pose.Position.z; - room = item->RoomNumber; - item2->Pose.Position.y = GetCeiling(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z); - - GetFloor(item2->Pose.Position.x, item2->Pose.Position.y, item2->Pose.Position.z, &room); - if (room != item2->RoomNumber) - ItemNewRoom(item->ItemFlags[3], room); - - TriggerAlertLight(item2->Pose.Position.x, item2->Pose.Position.y + 64, item2->Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter & 0x3F), item2->RoomNumber, 24); - TriggerAlertLight(item2->Pose.Position.x, item2->Pose.Position.y + 64, item2->Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter - 32) & 0xFFF, item2->RoomNumber, 24); - - room = item->RoomNumber; - GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room); - if (room != item->RoomNumber) - ItemNewRoom(itemNumber, room); - - AnimateItem(item); -} diff --git a/TombEngine/Objects/TR5/Trap/tr5_wreckingball.h b/TombEngine/Objects/TR5/Trap/tr5_wreckingball.h index f69f4ebef..625c2749e 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_wreckingball.h +++ b/TombEngine/Objects/TR5/Trap/tr5_wreckingball.h @@ -3,6 +3,9 @@ struct CollisionInfo; struct ItemInfo; -void InitializeWreckingBall(short itemNumber); -void WreckingBallCollision(short itemNumber, ItemInfo* l, CollisionInfo* coll); -void WreckingBallControl(short itemNumber); \ No newline at end of file +namespace TEN::Entities::Traps +{ + void InitializeWreckingBall(short itemNumber); + void CollideWreckingBall(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); + void ControlWreckingBall(short itemNumber); +} diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp index 6a72a81b2..e4f112013 100644 --- a/TombEngine/Objects/TR5/tr5_objects.cpp +++ b/TombEngine/Objects/TR5/tr5_objects.cpp @@ -76,7 +76,7 @@ using namespace TEN::Effects::EmberEmitter; using namespace TEN::Entities::Creatures::TR5; using namespace TEN::Entities::Switches; -using namespace TEN::Traps::TR5; +using namespace TEN::Entities::Traps; static void StartEntity(ObjectInfo *obj) { @@ -853,7 +853,7 @@ static void StartTrap(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeVentilator; - obj->control = VentilatorControl; + obj->control = ControlVentilator; obj->SetHitEffect(true); } @@ -861,7 +861,7 @@ static void StartTrap(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeVentilator; - obj->control = VentilatorControl; + obj->control = ControlVentilator; obj->SetHitEffect(true); } @@ -876,7 +876,7 @@ static void StartTrap(ObjectInfo *obj) { obj->Initialize = InitializeRomeHammer; obj->collision = GenericSphereBoxCollision; - obj->control = AnimatingControl; + obj->control = ControlRomeHammer; obj->SetHitEffect(true); } @@ -884,7 +884,7 @@ static void StartTrap(ObjectInfo *obj) if (obj->loaded) { obj->collision = TrapCollision; - obj->control = FallingCeilingControl; + obj->control = ControlFallingCeiling; } obj = &Objects[ID_ROLLINGBALL]; @@ -934,7 +934,7 @@ static void StartTrap(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeExplosion; - obj->control = ExplosionControl; + obj->control = ControlExplosion; obj->drawRoutine = nullptr; obj->usingDrawAnimatingItem = false; } @@ -983,8 +983,8 @@ static void StartSwitch(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeWreckingBall; - obj->collision = WreckingBallCollision; - obj->control = WreckingBallControl; + obj->collision = CollideWreckingBall; + obj->control = ControlWreckingBall; obj->SetHitEffect(true); } } diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 8055fe78d..b515bebe4 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -43,8 +43,8 @@ using namespace TEN::Effects::Footprint; using namespace TEN::Effects::Ripple; using namespace TEN::Effects::Streamer; using namespace TEN::Entities::Creatures::TR5; +using namespace TEN::Entities::Traps; using namespace TEN::Math; -using namespace TEN::Traps::TR5; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; From 2a6a96e03ae4b133af57e8f7d7f550ace09440e4 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:20:57 +0100 Subject: [PATCH 214/410] Implement KeyClearAll() Lua function (#1374) * Implement KeyClearAll * add entry to CHANGELOG.md --- CHANGELOG.md | 1 + TombEngine/Scripting/Internal/ReservedScriptNames.h | 1 + .../Scripting/Internal/TEN/Input/InputHandler.cpp | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57f1b3d4f..4bff581ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. +* Added Input.KeyClearAll() * Removed anims.monkeyAutoJump. It is now a player menu configuration. ## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21 diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 8d0e58181..25c27763e 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -318,6 +318,7 @@ static constexpr char ScriptReserved_KeyIsHeld[] = "KeyIsHeld"; static constexpr char ScriptReserved_KeyIsHit[] = "KeyIsHit"; static constexpr char ScriptReserved_KeyPush[] = "KeyPush"; static constexpr char ScriptReserved_KeyClear[] = "KeyClear"; +static constexpr char ScriptReserved_KeyClearAll[] = "KeyClearAll"; static constexpr char ScriptReserved_FlipMap[] = "FlipMap"; static constexpr char ScriptReserved_GetFlipMapStatus[] = "GetFlipMapStatus"; diff --git a/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp b/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp index 650854e48..ac1e5c794 100644 --- a/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp @@ -86,6 +86,16 @@ namespace TEN::Scripting::Input ActionQueue[actionID] = QueueState::Clear; } +# + /// Clear all action keys. + // @function KeyClear + static void KeyClearAll() + { + for (auto& queue : ActionQueue) + { + queue = QueueState::Clear; + } + } /// Get the display position of the cursor in percent. // @function GetMouseDisplayPosition() @@ -110,6 +120,7 @@ namespace TEN::Scripting::Input table.set_function(ScriptReserved_KeyIsHit, &KeyIsHit); table.set_function(ScriptReserved_KeyPush, &KeyPush); table.set_function(ScriptReserved_KeyClear, &KeyClear); + table.set_function(ScriptReserved_KeyClearAll, &KeyClearAll); table.set_function(ScriptReserved_GetMouseDisplayPosition, &GetMouseDisplayPosition); table.set_function(ScriptReserved_GetCursorDisplayPosition, &GetMouseDisplayPosition); From cb05e0eae802b6812de9dcd00d23b714af3c77f8 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 19 Jun 2024 21:07:26 +1000 Subject: [PATCH 215/410] Grammar --- CHANGELOG.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bff581ce..c9e542b5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,20 +11,20 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Bug fixes * Fixed original issue with classic switch off trigger wrongly activating some trigger actions. * Fixed incorrect diving animation when swandiving from a high place. -* Fixed camera rotating with Lara's hips when climbing out of water. +* Fixed camera rotating with player's hips when climbing out of water. * Fixed AI for skidoo driver and worker with shotgun TR2 enemies. -* Fixed Ember emitter crashing when ocb is between -1 and -10 -* Fixed Electric cleaner and Squishy block not detecting collision with certain block heights. -* Fixed Squishy blocks crashing the level. -* Fixed the path finding zones of Larson and Pierre. -* Fixed the torch flame delay in disappearing when Lara threw or dropped the torch object. -* Fixed Dart emitters which was failing when it was antitriggered. -* Fixed Homing Dart emitter which was spawning darts continously while Lara was on the trigger. -* Fixed Floor 4 blades and ceiling 4 blades collision. -* Fixed Joby spikes collision and abnormal streetching. -* Fixed Sentry Gun to rotate its parts correctly. -* Fixed Teeth Spikes bug, now they will activates the Lara impale animation. -* Fixed TR4 mine with OCB1, to don't crash the game when Lara steps the mine. +* Fixed ember emitter crashing when ocb is between -1 and -10. +* Fixed electric cleaner and squishy block not detecting collision with certain block heights. +* Fixed squishy blocks crashing the level. +* Fixed Larson and Pierre pathfinding. +* Fixed torch flame delay when the player throws or drops a torch. +* Fixed dart emitters failing with antitrigger. +* Fixed homing dart emitter spawning darts continously when player is on its trigger. +* Fixed four blade trap floor and ceiling collision. +* Fixed Joby spikes collision and deformation. +* Fixed sentry gun joint rotation. +* Fixed teeth spikes not triggering the player impale animation. +* Fixed TR4 mine crash with OCB1 when triggered. ### Features/Amendments * Changed Rome Hammer for it to don't hurt Lara while it's deactivated. From 8a8e63b8e6cdd2712ed8d63019b7f1db1f384d35 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 19 Jun 2024 21:15:03 +1000 Subject: [PATCH 216/410] Formatting --- TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp b/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp index ac1e5c794..4870ae1c2 100644 --- a/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp @@ -92,9 +92,7 @@ namespace TEN::Scripting::Input static void KeyClearAll() { for (auto& queue : ActionQueue) - { queue = QueueState::Clear; - } } /// Get the display position of the cursor in percent. From c70bba367e1655613bdb49a902e74c212ba88609 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 21 Jun 2024 13:36:27 +1000 Subject: [PATCH 217/410] Further organise math --- TombEngine/Math/Interpolation.h | 10 ----- TombEngine/Math/Math.cpp | 35 --------------- TombEngine/Math/Math.h | 12 +---- TombEngine/Math/Objects/AxisAngle.h | 8 ++++ TombEngine/Math/Objects/EulerAngles.h | 7 +++ TombEngine/Math/Objects/GameBoundingBox.h | 7 +++ TombEngine/Math/Objects/GameVector.h | 5 +++ TombEngine/Math/Objects/Pose.h | 5 +++ TombEngine/Math/Objects/Vector2i.h | 6 +++ TombEngine/Math/Objects/Vector3i.h | 6 +++ .../Math/{Interpolation.cpp => Utils.cpp} | 45 ++++++++++++++++++- TombEngine/Math/Utils.h | 27 +++++++++++ TombEngine/TombEngine.vcxproj | 5 +-- 13 files changed, 118 insertions(+), 60 deletions(-) delete mode 100644 TombEngine/Math/Interpolation.h delete mode 100644 TombEngine/Math/Math.cpp rename TombEngine/Math/{Interpolation.cpp => Utils.cpp} (54%) create mode 100644 TombEngine/Math/Utils.h diff --git a/TombEngine/Math/Interpolation.h b/TombEngine/Math/Interpolation.h deleted file mode 100644 index 83bb060e2..000000000 --- a/TombEngine/Math/Interpolation.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace TEN::Math -{ - float Lerp(float value0, float value1, float alpha); - float InterpolateCos(float value0, float value1, float alpha); - float InterpolateCubic(float value0, float value1, float value2, float value3, float alpha); - float Smoothstep(float alpha); - float Smoothstep(float value0, float value1, float alpha); -} diff --git a/TombEngine/Math/Math.cpp b/TombEngine/Math/Math.cpp deleted file mode 100644 index 3ede4ffd8..000000000 --- a/TombEngine/Math/Math.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "framework.h" - -#include -#include "Math/Math.h" - -namespace TEN::Math -{ - float Luma(const Vector3& color) - { - constexpr auto RED_COEFF = 0.2126f; - constexpr auto GREEN_COEFF = 0.7152f; - constexpr auto BLUE_COEFF = 0.0722f; - - // Use Rec.709 trichromat formula to get perceptive luma value. - return float((color.x * RED_COEFF) + (color.y * GREEN_COEFF) + (color.z * BLUE_COEFF)); - } - - Vector3 Screen(const Vector3& ambient, const Vector3& tint) - { - float luma = Luma(tint); - auto multiplicative = ambient * tint; - auto additive = ambient + tint; - - return Vector3( - Lerp(multiplicative.x, additive.x, luma), - Lerp(multiplicative.y, additive.y, luma), - Lerp(multiplicative.z, additive.z, luma)); - } - - Vector4 Screen(const Vector4& ambient, const Vector4& tint) - { - auto result = Screen(Vector3(ambient), Vector3(tint)); - return Vector4(result.x, result.y, result.z, ambient.w * tint.w); - } -} diff --git a/TombEngine/Math/Math.h b/TombEngine/Math/Math.h index e95d96fe2..cb625c648 100644 --- a/TombEngine/Math/Math.h +++ b/TombEngine/Math/Math.h @@ -1,7 +1,6 @@ #pragma once #include "Math/Constants.h" #include "Math/Geometry.h" -#include "Math/Interpolation.h" #include "Math/Legacy.h" #include "Math/Objects/EulerAngles.h" #include "Math/Objects/GameBoundingBox.h" @@ -11,13 +10,4 @@ #include "Math/Objects/Vector3i.h" #include "Math/Random.h" #include "Math/Solvers.h" - -namespace TEN::Math -{ - constexpr inline auto OFFSET_RADIUS = [](auto x) { return ((x * SQRT_2) + 4); }; - constexpr inline auto MESH_BITS = [](auto x) { return (1 << x); }; - - float Luma(const Vector3& color); - Vector3 Screen(const Vector3& ambient, const Vector3& tint); - Vector4 Screen(const Vector4& ambient, const Vector4& tint); -} +#include "Math/Utils.h" diff --git a/TombEngine/Math/Objects/AxisAngle.h b/TombEngine/Math/Objects/AxisAngle.h index 7ccc2cd90..ddcc72e31 100644 --- a/TombEngine/Math/Objects/AxisAngle.h +++ b/TombEngine/Math/Objects/AxisAngle.h @@ -8,14 +8,17 @@ class EulerAngles; { private: // Members + Vector3 _axis = Vector3::Backward; short _angle = 0; public: // Constants + static const AxisAngle Identity; // Constructors + AxisAngle() {}; AxisAngle(const Vector3& axis, short angle); AxisAngle(const EulerAngles& eulers); @@ -23,24 +26,29 @@ class EulerAngles; AxisAngle(const Matrix& rotMatrix); // Getters + Vector3 GetAxis() const; short GetAngle() const; // Setters + void SetAxis(const Vector3& axis); void SetAngle(short angle); // Utilities + void Slerp(const AxisAngle& axisAngleTo, float alpha); static AxisAngle Slerp(const AxisAngle& axisAngleFrom, const AxisAngle& axisAngleTo, float alpha); // Converters + Vector3 ToDirection() const; EulerAngles ToEulerAngles() const; Quaternion ToQuaternion() const; Matrix ToRotationMatrix() const; // Operators + bool operator ==(const AxisAngle& axisAngle) const; bool operator !=(const AxisAngle& axisAngle) const; AxisAngle& operator =(const AxisAngle& axisAngle); diff --git a/TombEngine/Math/Objects/EulerAngles.h b/TombEngine/Math/Objects/EulerAngles.h index e08973cfa..f25f69d1a 100644 --- a/TombEngine/Math/Objects/EulerAngles.h +++ b/TombEngine/Math/Objects/EulerAngles.h @@ -7,14 +7,17 @@ { public: // Members (CONVENTION: X = Pitch, Y = Yaw, Z = Roll) + short x = 0; short y = 0; short z = 0; // Constants + static const EulerAngles Identity; // Constructors + constexpr EulerAngles() {}; constexpr EulerAngles(short x, short y, short z) { this->x = x; this->y = y; this->z = z; }; EulerAngles(const Vector3& dir); @@ -23,6 +26,7 @@ EulerAngles(const Matrix& rotMatrix); // Utilities + static bool Compare(const EulerAngles& eulers0, const EulerAngles& eulers1, short epsilon = 3); void Lerp(const EulerAngles& eulersTo, float alpha, short epsilon = 3); static EulerAngles Lerp(const EulerAngles& eulersFrom, const EulerAngles& eulersTo, float alpha, short epsilon = 3); @@ -32,12 +36,14 @@ static EulerAngles InterpolateConstant(const EulerAngles& eulersFrom, const EulerAngles& eulerTo, short angularVel); // Converters + Vector3 ToDirection() const; AxisAngle ToAxisAngle() const; Quaternion ToQuaternion() const; Matrix ToRotationMatrix() const; // Operators + bool operator ==(const EulerAngles& eulers) const; bool operator !=(const EulerAngles& eulers) const; EulerAngles& operator =(const EulerAngles& eulers); @@ -54,6 +60,7 @@ private: // Temporary. Will be integrated into eventual Angle class. + static float ClampAlpha(float alpha); static bool Compare(short angle0, short angle1, short epsilon = 3); static short Lerp(short angleFrom, short angleTo, float alpha, short epsilon = 3); diff --git a/TombEngine/Math/Objects/GameBoundingBox.h b/TombEngine/Math/Objects/GameBoundingBox.h index 705688145..17569391d 100644 --- a/TombEngine/Math/Objects/GameBoundingBox.h +++ b/TombEngine/Math/Objects/GameBoundingBox.h @@ -12,6 +12,7 @@ struct ObjectInfo; { public: // Members + int X1 = 0; int X2 = 0; int Y1 = 0; @@ -20,15 +21,18 @@ struct ObjectInfo; int Z2 = 0; // Constants + static const GameBoundingBox Zero; // Constructors + GameBoundingBox() {}; GameBoundingBox(float x1, float x2, float y1, float y2, float z1, float z2); GameBoundingBox(GAME_OBJECT_ID objectID, int animNumber = 0, int frameNumber = 0); GameBoundingBox(const ItemInfo* item); // Getters + int GetWidth() const; int GetHeight() const; int GetDepth() const; @@ -36,13 +40,16 @@ struct ObjectInfo; Vector3 GetExtents() const; // Utilities + void Rotate(const EulerAngles& rot); // Converters + BoundingOrientedBox ToBoundingOrientedBox(const Pose& pose) const; BoundingOrientedBox ToBoundingOrientedBox(const Vector3& pos, const Quaternion& orient) const; // Operators + GameBoundingBox operator +(const GameBoundingBox& bounds) const; GameBoundingBox operator +(const Pose& pose) const; GameBoundingBox operator -(const GameBoundingBox& bounds) const; diff --git a/TombEngine/Math/Objects/GameVector.h b/TombEngine/Math/Objects/GameVector.h index f75cc748c..ac43cdd2e 100644 --- a/TombEngine/Math/Objects/GameVector.h +++ b/TombEngine/Math/Objects/GameVector.h @@ -8,6 +8,7 @@ class Vector3i; { public: // Members + int x = 0; int y = 0; int z = 0; @@ -15,9 +16,11 @@ class Vector3i; int BoxNumber = 0; // Unused. // Constants + static const GameVector Zero; // Constructors + GameVector(); GameVector(const Vector3i& pos); GameVector(const Vector3i& pos, short roomNumber); @@ -25,10 +28,12 @@ class Vector3i; GameVector(int xPos, int yPos, int zPos, short roomNumber); // Converters + Vector3 ToVector3() const; Vector3i ToVector3i() const; // Operators + bool operator ==(const GameVector& vector) const; bool operator !=(const GameVector& vector) const; GameVector& operator =(const GameVector& vector); diff --git a/TombEngine/Math/Objects/Pose.h b/TombEngine/Math/Objects/Pose.h index 1a4342262..e60a7bc73 100644 --- a/TombEngine/Math/Objects/Pose.h +++ b/TombEngine/Math/Objects/Pose.h @@ -8,13 +8,16 @@ { public: // Members + Vector3i Position = Vector3i::Zero; EulerAngles Orientation = EulerAngles::Identity; // Constants + static const Pose Zero; // Constructors + Pose(); Pose(const Vector3i& pos); Pose(int xPos, int yPos, int zPos); @@ -26,11 +29,13 @@ Pose(int xPos, int yPos, int zPos, short xOrient, short yOrient, short zOrient); // Utilities + void Translate(short headingAngle, float forward, float down = 0.0f, float right = 0.0f); void Translate(const EulerAngles& orient, float dist); void Translate(const Vector3& dir, float dist); // Operators + bool operator ==(const Pose& pose) const; bool operator !=(const Pose& pose) const; }; diff --git a/TombEngine/Math/Objects/Vector2i.h b/TombEngine/Math/Objects/Vector2i.h index bf0e7d44b..38fef4d0e 100644 --- a/TombEngine/Math/Objects/Vector2i.h +++ b/TombEngine/Math/Objects/Vector2i.h @@ -6,25 +6,31 @@ namespace TEN::Math { public: // Members + int x = 0; int y = 0; // Constants + static const Vector2i Zero; // Constructors + constexpr Vector2i() {}; constexpr Vector2i(int x, int y) { this->x = x; this->y = y; }; Vector2i(const Vector2& vector); // Utilities + static float Distance(const Vector2i& origin, const Vector2i& target); static float DistanceSquared(const Vector2i& origin, const Vector2i& target); // Converters + Vector2 ToVector2() const; // Operators + bool operator ==(const Vector2i& vector) const; bool operator !=(const Vector2i& vector) const; Vector2i& operator =(const Vector2i& vector); diff --git a/TombEngine/Math/Objects/Vector3i.h b/TombEngine/Math/Objects/Vector3i.h index 9a8c75bdf..efa9ec3bb 100644 --- a/TombEngine/Math/Objects/Vector3i.h +++ b/TombEngine/Math/Objects/Vector3i.h @@ -6,28 +6,34 @@ { public: // Members + int x = 0; int y = 0; int z = 0; // Constants + static const Vector3i Zero; // Constructors + constexpr Vector3i() {}; constexpr Vector3i(int x, int y, int z) { this->x = x; this->y = y; this->z = z; }; Vector3i(const Vector3& vector); // Utilities + static float Distance(const Vector3i& origin, const Vector3i& target); static float DistanceSquared(const Vector3i& origin, const Vector3i& target); void Lerp(const Vector3i& target, float alpha); static Vector3i Lerp(const Vector3i& origin, const Vector3i& target, float alpha); // Converters + Vector3 ToVector3() const; // Operators + bool operator ==(const Vector3i& vector) const; bool operator !=(const Vector3i& vector) const; Vector3i& operator =(const Vector3i& vector); diff --git a/TombEngine/Math/Interpolation.cpp b/TombEngine/Math/Utils.cpp similarity index 54% rename from TombEngine/Math/Interpolation.cpp rename to TombEngine/Math/Utils.cpp index 12e8cfb4f..eb5245f02 100644 --- a/TombEngine/Math/Interpolation.cpp +++ b/TombEngine/Math/Utils.cpp @@ -1,5 +1,5 @@ #include "framework.h" -#include "Math/Interpolation.h" +#include "Math/Utils.h" #include "Math/Constants.h" @@ -55,4 +55,47 @@ namespace TEN::Math // Evaluate polynomial. return (CUBE(alpha) * (alpha * (alpha * 6 - 15) + 10)); } + + float Luma(const Vector3& color) + { + constexpr auto RED_COEFF = 0.2126f; + constexpr auto GREEN_COEFF = 0.7152f; + constexpr auto BLUE_COEFF = 0.0722f; + + // Use Rec.709 trichromat formula to get perceptive luma value. + return float((color.x * RED_COEFF) + (color.y * GREEN_COEFF) + (color.z * BLUE_COEFF)); + } + + Vector3 Screen(const Vector3& ambient, const Vector3& tint) + { + float luma = Luma(tint); + auto multiplicative = ambient * tint; + auto additive = ambient + tint; + + return Vector3( + Lerp(multiplicative.x, additive.x, luma), + Lerp(multiplicative.y, additive.y, luma), + Lerp(multiplicative.z, additive.z, luma)); + } + + Vector4 Screen(const Vector4& ambient, const Vector4& tint) + { + auto result = Screen(Vector3(ambient), Vector3(tint)); + return Vector4(result.x, result.y, result.z, ambient.w * tint.w); + } + + float FloorToStep(float value, float step) + { + return (floor(value / step) * step); + } + + float CeilToStep(float value, float step) + { + return (ceil(value / step) * step); + } + + float RoundToStep(float value, float step) + { + return (round(value / step) * step); + } } diff --git a/TombEngine/Math/Utils.h b/TombEngine/Math/Utils.h new file mode 100644 index 000000000..53e4e1c7d --- /dev/null +++ b/TombEngine/Math/Utils.h @@ -0,0 +1,27 @@ +#pragma once + +namespace TEN::Math +{ + constexpr inline auto OFFSET_RADIUS = [](auto x) { return ((x * SQRT_2) + 4); }; + constexpr inline auto MESH_BITS = [](auto x) { return (1 << x); }; + + // Interpolation + + float Lerp(float value0, float value1, float alpha); + float InterpolateCos(float value0, float value1, float alpha); + float InterpolateCubic(float value0, float value1, float value2, float value3, float alpha); + float Smoothstep(float alpha); + float Smoothstep(float value0, float value1, float alpha); + + // Color + + float Luma(const Vector3& color); + Vector3 Screen(const Vector3& ambient, const Vector3& tint); + Vector4 Screen(const Vector4& ambient, const Vector4& tint); + + // Misc. + + float FloorToStep(float value, float step); + float CeilToStep(float value, float step); + float RoundToStep(float value, float step); +} diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 81d212c5a..b9a6701e9 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -427,7 +427,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -439,6 +438,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -936,9 +936,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - - @@ -948,6 +946,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From ba6841bb180b3e5ffa71b4c7e5175615321b3fcf Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 21 Jun 2024 13:37:06 +1000 Subject: [PATCH 218/410] Add tab --- TombEngine/Math/Utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Math/Utils.h b/TombEngine/Math/Utils.h index 53e4e1c7d..abaf295b4 100644 --- a/TombEngine/Math/Utils.h +++ b/TombEngine/Math/Utils.h @@ -15,7 +15,7 @@ namespace TEN::Math // Color - float Luma(const Vector3& color); + float Luma(const Vector3& color); Vector3 Screen(const Vector3& ambient, const Vector3& tint); Vector4 Screen(const Vector4& ambient, const Vector4& tint); From 399c039f2127d1e6ab5ac4db4470e3151551dc8a Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 25 Jun 2024 01:24:32 +1000 Subject: [PATCH 219/410] Prevent more inappropriate tooltips --- TombEngine/Game/collision/Point.h | 5 +++++ TombEngine/Specific/BitField.h | 9 +++++++++ TombEngine/Specific/Input/InputAction.h | 11 ++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/Point.h b/TombEngine/Game/collision/Point.h index 9f1651f10..9dbc6fe32 100644 --- a/TombEngine/Game/collision/Point.h +++ b/TombEngine/Game/collision/Point.h @@ -14,6 +14,7 @@ namespace TEN::Collision::Point { private: // Members + Vector3i _position = Vector3i::Zero; int _roomNumber = 0; @@ -34,9 +35,11 @@ namespace TEN::Collision::Point public: // Constructors + PointCollisionData(const Vector3i& pos, int roomNumber); // Getters + Vector3i GetPosition() const; int GetRoomNumber() const; @@ -56,6 +59,7 @@ namespace TEN::Collision::Point int GetWaterTopHeight(); // Inquirers + bool IsWall(); bool IsSteepFloor(); bool IsSteepCeiling(); @@ -70,6 +74,7 @@ namespace TEN::Collision::Point private: // Helpers + Vector3 GetBridgeNormal(bool isFloor); }; diff --git a/TombEngine/Specific/BitField.h b/TombEngine/Specific/BitField.h index 98592fd1e..5bd3104e3 100644 --- a/TombEngine/Specific/BitField.h +++ b/TombEngine/Specific/BitField.h @@ -9,23 +9,28 @@ namespace TEN::Utils { private: // Constants + static constexpr auto SIZE_DEFAULT = 32; // Members + std::vector _bits = {}; public: // Presets + static const BitField Empty; static const BitField Default; // Constructors + BitField(); BitField(unsigned int size); BitField(unsigned int size, unsigned int packedBits); BitField(const std::string& bitString); // Getters + unsigned int GetSize() const; unsigned int GetCount() const; @@ -41,17 +46,20 @@ namespace TEN::Utils void FlipAll(); // Inquirers + bool Test(const std::vector& indices, bool testAny = true) const; bool Test(unsigned int index) const; bool TestAny() const; bool TestAll() const; // Converters + unsigned int ToPackedBits() const; std::string ToString() const; // Operators // NOTE: packedBits will not be assessed in full if the size of the given BitField object is less than SIZE_DEFAULT. + bool operator ==(unsigned int packedBits) const; bool operator !=(unsigned int packedBits) const; BitField& operator =(unsigned int packedBits); @@ -62,6 +70,7 @@ namespace TEN::Utils private: // Helpers + void Fill(bool value); }; } diff --git a/TombEngine/Specific/Input/InputAction.h b/TombEngine/Specific/Input/InputAction.h index 29abd2bf0..adeb7eda6 100644 --- a/TombEngine/Specific/Input/InputAction.h +++ b/TombEngine/Specific/Input/InputAction.h @@ -5,6 +5,7 @@ namespace TEN::Input typedef enum class ActionID { // General actions + Forward, Back, Left, @@ -21,6 +22,7 @@ namespace TEN::Input Look, // Vehicle actions + Accelerate, Reverse, Faster, @@ -29,6 +31,7 @@ namespace TEN::Input Fire, // Quick actions + Flare, SmallMedipack, LargeMedipack, @@ -46,6 +49,7 @@ namespace TEN::Input Weapon10, // Menu actions + Select, Deselect, Pause, @@ -56,11 +60,11 @@ namespace TEN::Input Count } In; - // TODO: For analog triggers, use Value range [0.0f, 1.0f] with deadzone up to a quarter press. class InputAction { private: // Members + ActionID ID = In::Forward; float Value = 0.0f; float PrevValue = 0.0f; @@ -70,21 +74,25 @@ namespace TEN::Input public: // Constructors + InputAction(ActionID actionID); // Getters + ActionID GetID() const; float GetValue() const; float GetTimeActive() const; float GetTimeInactive() const; // Inquirers + bool IsClicked() const; bool IsHeld(float delayInSec = 0.0f) const; bool IsPulsed(float delayInSec, float initialDelayInSec = 0.0f) const; bool IsReleased(float maxDelayInSec = INFINITY) const; // Utilities + void Update(bool value); void Update(float value); void Clear(); @@ -93,6 +101,7 @@ namespace TEN::Input private: // Helpers + void UpdateValue(float value); }; } From 9f2cf860c5aa1e89e12a15ba6579b9d88afe0213 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:14:30 +0100 Subject: [PATCH 220/410] Update CHANGELOG.md Small changes to text to improve clarity --- CHANGELOG.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9e542b5b..5460278fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,10 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## Version 1.5 - xxxx-xx-xx ### Bug fixes -* Fixed original issue with classic switch off trigger wrongly activating some trigger actions. +* Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. * Fixed incorrect diving animation when swandiving from a high place. -* Fixed camera rotating with player's hips when climbing out of water. -* Fixed AI for skidoo driver and worker with shotgun TR2 enemies. +* Fixed camera rotating with the player's hips when climbing out of water. +* Fixed AI for TR2 skidoo driver and worker with shotgun. * Fixed ember emitter crashing when ocb is between -1 and -10. * Fixed electric cleaner and squishy block not detecting collision with certain block heights. * Fixed squishy blocks crashing the level. @@ -24,14 +24,14 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed Joby spikes collision and deformation. * Fixed sentry gun joint rotation. * Fixed teeth spikes not triggering the player impale animation. -* Fixed TR4 mine crash with OCB1 when triggered. +* Fixed TR4 mine crash with OCB 1 when triggered. ### Features/Amendments -* Changed Rome Hammer for it to don't hurt Lara while it's deactivated. +* Changed Rome Hammer to not hurt player whilst deactivated. * Changed Statue with blade damage, from 20 to 200. * Enhaced Rolling Spindle detection to avoid them going down through pits. -* Enhaced Sentry Guns, with a new ItemFlags[3] to contain the ID of the inventory item that deactivates the sentry guns (by default PUZZLE_ITEM5 ID) -* Enhaced Dart Emitter, with a new ItemFlags[0] to contain the number of frames between shots (by default 32 in dart emitter, and 24 in homing dar emitter). +* Enhaced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) +* Enhaced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. From e39193497f19b7243a44bd94ae663691537f8942 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 25 Jun 2024 17:32:02 +1000 Subject: [PATCH 221/410] Update sector class; disambiguate pathfinding boxes --- TombEngine/Game/Lara/lara.cpp | 2 +- TombEngine/Game/collision/floordata.h | 20 +++-- TombEngine/Game/control/box.cpp | 76 ++++++++--------- TombEngine/Game/control/box.h | 3 + TombEngine/Game/control/lot.cpp | 8 +- TombEngine/Game/items.cpp | 2 +- TombEngine/Game/misc.cpp | 6 +- .../Objects/Generic/Doors/generic_doors.cpp | 30 +++---- TombEngine/Objects/TR3/Entity/Lizard.cpp | 2 +- TombEngine/Objects/TR3/Entity/Shiva.cpp | 4 +- TombEngine/Objects/TR3/Entity/tr3_civvy.cpp | 2 +- TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp | 2 +- .../Objects/TR3/Entity/tr3_mp_stick.cpp | 2 +- .../TR5/Object/tr5_expandingplatform.cpp | 2 +- .../Objects/TR5/Object/tr5_raisingblock.cpp | 4 +- .../Objects/TR5/Shatter/tr5_smashobject.cpp | 6 +- TombEngine/Specific/level.cpp | 85 ++++++++++--------- TombEngine/Specific/level.h | 4 +- 18 files changed, 135 insertions(+), 125 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 550f1397f..053a5ce44 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -335,7 +335,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll) if (DebugMode) { - DrawNearbyPathfinding(GetPointCollision(*item).GetBottomSector().Box); + DrawNearbyPathfinding(GetPointCollision(*item).GetBottomSector().PathfindingBoxID); DrawNearbySectorFlags(*item); } } diff --git a/TombEngine/Game/collision/floordata.h b/TombEngine/Game/collision/floordata.h index be6e2c456..56dff4dec 100644 --- a/TombEngine/Game/collision/floordata.h +++ b/TombEngine/Game/collision/floordata.h @@ -136,16 +136,18 @@ class FloorInfo { public: // Members - int RoomNumber = 0; - int SidePortalRoomNumber = 0; - SectorSurfaceData FloorSurface = {}; - SectorSurfaceData CeilingSurface = {}; - std::set BridgeItemNumbers = {}; - SectorFlagData Flags = {}; + Vector2i Position = Vector2i::Zero; + int RoomNumber = 0; + SectorSurfaceData FloorSurface = {}; + SectorSurfaceData CeilingSurface = {}; + SectorFlagData Flags = {}; - int Box = 0; - int TriggerIndex = 0; - bool Stopper = true; + std::set BridgeItemNumbers = {}; + int SidePortalRoomNumber = 0; + + int PathfindingBoxID = 0; + int TriggerIndex = 0; + bool Stopper = true; // Getters int GetSurfaceTriangleID(int x, int z, bool isFloor) const; diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 7f19d68b9..3166286f2 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -55,7 +55,7 @@ void DrawBox(int boxIndex, Vector3 color) if (boxIndex == NO_VALUE) return; - auto& currBox = g_Level.Boxes[boxIndex]; + auto& currBox = g_Level.PathfindingBoxes[boxIndex]; float x = ((float)currBox.left + (float)(currBox.right - currBox.left) / 2.0f) * 1024.0f; auto y = currBox.height - CLICK(1); @@ -78,7 +78,7 @@ void DrawNearbyPathfinding(int boxIndex) if (boxIndex == NO_VALUE) return; - auto& currBox = g_Level.Boxes[boxIndex]; + auto& currBox = g_Level.PathfindingBoxes[boxIndex]; auto index = currBox.overlapIndex; // Grey flag box. @@ -155,13 +155,13 @@ bool SameZone(CreatureInfo* creature, ItemInfo* target) auto* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); auto& roomSource = g_Level.Rooms[item.RoomNumber]; - auto& boxSource = GetSector(&roomSource, item.Pose.Position.x - roomSource.x, item.Pose.Position.z - roomSource.z)->Box; + auto& boxSource = GetSector(&roomSource, item.Pose.Position.x - roomSource.x, item.Pose.Position.z - roomSource.z)->PathfindingBoxID; if (boxSource == NO_VALUE) return false; item.BoxNumber = boxSource; auto& roomTarget = g_Level.Rooms[target->RoomNumber]; - auto& boxTarget = GetSector(&roomTarget, target->Pose.Position.x - roomTarget.x, target->Pose.Position.z - roomTarget.z)->Box; + auto& boxTarget = GetSector(&roomTarget, target->Pose.Position.x - roomTarget.x, target->Pose.Position.z - roomTarget.z)->PathfindingBoxID; if (boxTarget == NO_VALUE) return false; target->BoxNumber = boxTarget; @@ -257,7 +257,7 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) int boxHeight; if (item->BoxNumber != NO_VALUE) - boxHeight = g_Level.Boxes[item->BoxNumber].height; + boxHeight = g_Level.PathfindingBoxes[item->BoxNumber].height; else boxHeight = item->Floor; @@ -267,31 +267,31 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) GetFloor(prevPos.x, y, prevPos.z, &roomNumber); auto* floor = GetFloor(item->Pose.Position.x, y, item->Pose.Position.z, &roomNumber); - if (floor->Box == NO_VALUE) + if (floor->PathfindingBoxID == NO_VALUE) return false; - int height = g_Level.Boxes[floor->Box].height; + int height = g_Level.PathfindingBoxes[floor->PathfindingBoxID].height; int nextHeight = 0; int nextBox; if (!Objects[item->ObjectNumber].nonLot) { - nextBox = LOT->Node[floor->Box].exitBox; + nextBox = LOT->Node[floor->PathfindingBoxID].exitBox; } else { floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); - height = g_Level.Boxes[floor->Box].height; - nextBox = floor->Box; + height = g_Level.PathfindingBoxes[floor->PathfindingBoxID].height; + nextBox = floor->PathfindingBoxID; } if (nextBox == NO_VALUE) nextHeight = height; else - nextHeight = g_Level.Boxes[nextBox].height; + nextHeight = g_Level.PathfindingBoxes[nextBox].height; - if (floor->Box == NO_VALUE || !LOT->IsJumping && - (LOT->Fly == NO_FLYING && item->BoxNumber != NO_VALUE && zone[item->BoxNumber] != zone[floor->Box] || + if (floor->PathfindingBoxID == NO_VALUE || !LOT->IsJumping && + (LOT->Fly == NO_FLYING && item->BoxNumber != NO_VALUE && zone[item->BoxNumber] != zone[floor->PathfindingBoxID] || boxHeight - height > LOT->Step || boxHeight - height < LOT->Drop)) { @@ -311,22 +311,22 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt) item->Pose.Position.z = prevPos.z | WALL_MASK; floor = GetFloor(item->Pose.Position.x, y, item->Pose.Position.z, &roomNumber); - height = g_Level.Boxes[floor->Box].height; + height = g_Level.PathfindingBoxes[floor->PathfindingBoxID].height; if (!Objects[item->ObjectNumber].nonLot) { - nextBox = LOT->Node[floor->Box].exitBox; + nextBox = LOT->Node[floor->PathfindingBoxID].exitBox; } else { floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); - height = g_Level.Boxes[floor->Box].height; - nextBox = floor->Box; + height = g_Level.PathfindingBoxes[floor->PathfindingBoxID].height; + nextBox = floor->PathfindingBoxID; } if (nextBox == NO_VALUE) nextHeight = height; else - nextHeight = g_Level.Boxes[nextBox].height; + nextHeight = g_Level.PathfindingBoxes[nextBox].height; } int x = item->Pose.Position.x; @@ -857,13 +857,13 @@ void CreatureDie(int itemNumber, bool doExplosion, int flags) bool BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumber, LOTInfo* LOT) { auto* floor = GetFloor(x, y, z, &roomNumber); - if (floor->Box == NO_VALUE) + if (floor->PathfindingBoxID == NO_VALUE) return true; if (LOT->IsJumping) return false; - auto* box = &g_Level.Boxes[floor->Box]; + auto* box = &g_Level.PathfindingBoxes[floor->PathfindingBoxID]; if (box->flags & LOT->BlockMask) return true; @@ -928,7 +928,7 @@ bool ValidBox(ItemInfo* item, short zoneNumber, short boxNumber) if (creature.LOT.Fly == NO_FLYING && zone[boxNumber] != zoneNumber) return false; - const auto& box = g_Level.Boxes[boxNumber]; + const auto& box = g_Level.PathfindingBoxes[boxNumber]; if (creature.LOT.BlockMask & box.flags) return false; @@ -948,7 +948,7 @@ bool EscapeBox(ItemInfo* item, ItemInfo* enemy, int boxNumber) if (boxNumber == NO_VALUE) return false; - const auto& box = g_Level.Boxes[boxNumber]; + const auto& box = g_Level.PathfindingBoxes[boxNumber]; int x = ((box.top + box.bottom) * BLOCK(0.5f)) - enemy->Pose.Position.x; int z = ((box.left + box.right) * BLOCK(0.5f)) - enemy->Pose.Position.z; @@ -966,7 +966,7 @@ void TargetBox(LOTInfo* LOT, int boxNumber) { if (boxNumber == NO_VALUE) return; - auto* box = &g_Level.Boxes[boxNumber]; + auto* box = &g_Level.PathfindingBoxes[boxNumber]; // Maximize target precision. DO NOT change bracket precedence! LOT->Target.x = (int)((box->top * BLOCK(1)) + (float)GetRandomControl() * (((float)(box->bottom - box->top) - 1.0f) / 32.0f) + CLICK(2.0f)); @@ -1016,7 +1016,7 @@ bool SearchLOT(LOTInfo* LOT, int depth) return false; } - auto* box = &g_Level.Boxes[LOT->Head]; + auto* box = &g_Level.PathfindingBoxes[LOT->Head]; auto* node = &LOT->Node[LOT->Head]; int index = box->overlapIndex; @@ -1034,7 +1034,7 @@ bool SearchLOT(LOTInfo* LOT, int depth) if (LOT->Fly == NO_FLYING && searchZone != zone[boxNumber]) continue; - int delta = g_Level.Boxes[boxNumber].height - box->height; + int delta = g_Level.PathfindingBoxes[boxNumber].height - box->height; if ((delta > LOT->Step || delta < LOT->Drop) && (!(flags & BOX_MONKEY) || !LOT->CanMonkey)) continue; @@ -1057,7 +1057,7 @@ bool SearchLOT(LOTInfo* LOT, int depth) if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & BLOCKED_SEARCH)) continue; - if (g_Level.Boxes[boxNumber].flags & LOT->BlockMask) + if (g_Level.PathfindingBoxes[boxNumber].flags & LOT->BlockMask) { expand->searchNumber = node->searchNumber | BLOCKED_SEARCH; } @@ -1145,7 +1145,7 @@ bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber) { if (enemy == nullptr || boxNumber == NO_VALUE) return false; - auto* box = &g_Level.Boxes[boxNumber]; + auto* box = &g_Level.PathfindingBoxes[boxNumber]; int xRange = STALK_DIST + ((box->bottom - box->top) * BLOCK(1)); int zRange = STALK_DIST + ((box->right - box->left) * BLOCK(1)); @@ -1461,9 +1461,9 @@ void FindAITargetObject(CreatureInfo* creature, int objectNumber, int ocb, bool int* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); auto* room = &g_Level.Rooms[item.RoomNumber]; - item.BoxNumber = GetSector(room, item.Pose.Position.x - room->x, item.Pose.Position.z - room->z)->Box; + item.BoxNumber = GetSector(room, item.Pose.Position.x - room->x, item.Pose.Position.z - room->z)->PathfindingBoxID; room = &g_Level.Rooms[aiObject.roomNumber]; - aiObject.boxNumber = GetSector(room, aiObject.pos.Position.x - room->x, aiObject.pos.Position.z - room->z)->Box; + aiObject.boxNumber = GetSector(room, aiObject.pos.Position.x - room->x, aiObject.pos.Position.z - room->z)->PathfindingBoxID; if (item.BoxNumber == NO_VALUE || aiObject.boxNumber == NO_VALUE) return; @@ -1524,7 +1524,7 @@ int TargetReachable(ItemInfo* item, ItemInfo* enemy) isReachable = abs(enemy->Pose.Position.y - pointColl.GetFloorHeight()) < bounds.GetHeight(); } - return (isReachable ? floor->Box : NO_VALUE); + return (isReachable ? floor->PathfindingBoxID : NO_VALUE); } void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) @@ -1546,7 +1546,7 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) auto* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); auto* room = &g_Level.Rooms[item->RoomNumber]; - item->BoxNumber = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z)->Box; + item->BoxNumber = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z)->PathfindingBoxID; AI->zoneNumber = zone[item->BoxNumber]; enemy->BoxNumber = TargetReachable(item, enemy); @@ -1554,7 +1554,7 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) if (!object->nonLot) { - if (enemy->BoxNumber != NO_VALUE && g_Level.Boxes[enemy->BoxNumber].flags & creature->LOT.BlockMask) + if (enemy->BoxNumber != NO_VALUE && g_Level.PathfindingBoxes[enemy->BoxNumber].flags & creature->LOT.BlockMask) { AI->enemyZone |= BLOCKED; } @@ -1754,7 +1754,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) int endBox = LOT->Node[item->BoxNumber].exitBox; if (endBox != NO_VALUE) { - int overlapIndex = g_Level.Boxes[item->BoxNumber].overlapIndex; + int overlapIndex = g_Level.PathfindingBoxes[item->BoxNumber].overlapIndex; int nextBox = 0; int flags = 0; @@ -1901,7 +1901,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) if (boxNumber == NO_VALUE) return TARGET_TYPE::NO_TARGET; - auto* box = &g_Level.Boxes[boxNumber]; + auto* box = &g_Level.PathfindingBoxes[boxNumber]; int boxLeft = ((int)box->left * BLOCK(1)); int boxRight = ((int)box->right * BLOCK(1)) - 1; @@ -1915,7 +1915,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) do { - box = &g_Level.Boxes[boxNumber]; + box = &g_Level.PathfindingBoxes[boxNumber]; if (LOT->Fly != NO_FLYING) { @@ -2096,7 +2096,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) } boxNumber = LOT->Node[boxNumber].exitBox; - if (boxNumber != NO_VALUE && (g_Level.Boxes[boxNumber].flags & LOT->BlockMask)) + if (boxNumber != NO_VALUE && (g_Level.PathfindingBoxes[boxNumber].flags & LOT->BlockMask)) break; } while (boxNumber != NO_VALUE); @@ -2157,10 +2157,10 @@ void InitializeItemBoxData() continue; auto* floor = &room.floor[index]; - if (floor->Box == NO_VALUE) + if (floor->PathfindingBoxID == NO_VALUE) continue; - if (!(g_Level.Boxes[floor->Box].flags & BLOCKED)) + if (!(g_Level.PathfindingBoxes[floor->PathfindingBoxID].flags & BLOCKED)) { int floorHeight = floor->GetSurfaceHeight(mesh.pos.Position.x, mesh.pos.Position.z, true); const auto& bBox = GetBoundsAccurate(mesh, false); diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 50ceb5142..7bf26d8c2 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -1,4 +1,5 @@ #pragma once + #include "Specific/level.h" #include "Math/Math.h" @@ -33,12 +34,14 @@ struct AI_INFO short enemyFacing; }; +// TODO: Use DX BoundingBox class to store AABB. struct BOX_INFO { unsigned int left; unsigned int right; unsigned int top; unsigned int bottom; + int height; int overlapIndex; int flags; diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 01dc1f065..74a9b7771 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -25,7 +25,7 @@ void InitializeLOTarray(int itemNumber) if (!creature->LOT.Initialized) { - creature->LOT.Node = std::vector(g_Level.Boxes.size(), BoxNode{}); + creature->LOT.Node = std::vector(g_Level.PathfindingBoxes.size(), BoxNode{}); creature->LOT.Initialized = true; } } @@ -240,14 +240,14 @@ void CreateZone(ItemInfo* item) auto* creature = GetCreatureInfo(item); auto* room = &g_Level.Rooms[item->RoomNumber]; - item->BoxNumber = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z)->Box; + item->BoxNumber = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z)->PathfindingBoxID; if (creature->LOT.Fly) { auto* node = creature->LOT.Node.data(); creature->LOT.ZoneCount = 0; - for (int i = 0; i < g_Level.Boxes.size(); i++) + for (int i = 0; i < g_Level.PathfindingBoxes.size(); i++) { node->boxNumber = i; node++; @@ -265,7 +265,7 @@ void CreateZone(ItemInfo* item) auto* node = creature->LOT.Node.data(); creature->LOT.ZoneCount = 0; - for (int i = 0; i < g_Level.Boxes.size(); i++) + for (int i = 0; i < g_Level.PathfindingBoxes.size(); i++) { if (*zone == zoneNumber || *flippedZone == flippedZoneNumber) { diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 718b83fff..bd3631e8b 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -586,7 +586,7 @@ void InitializeItem(short itemNumber) FloorInfo* floor = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z); item->Floor = floor->GetSurfaceHeight(item->Pose.Position.x, item->Pose.Position.z, true); - item->BoxNumber = floor->Box; + item->BoxNumber = floor->PathfindingBoxID; item->ResetModelToDefault(); diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 29fa3e945..6365f6209 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -132,13 +132,13 @@ bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, boo } // Check for inaccessible sector. - if (pointColl.GetSector().Box == NO_VALUE) + if (pointColl.GetSector().PathfindingBoxID == NO_VALUE) return false; // Check for blocked grey box. - if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKABLE) + if (g_Level.PathfindingBoxes[pointColl.GetSector().PathfindingBoxID].flags & BLOCKABLE) { - if (g_Level.Boxes[pointColl.GetSector().Box].flags & BLOCKED) + if (g_Level.PathfindingBoxes[pointColl.GetSector().PathfindingBoxID].flags & BLOCKED) return false; } diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index a12db1847..84bc395df 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -81,14 +81,14 @@ namespace TEN::Entities::Doors auto roomNumber = doorData->d1.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) - boxNumber = doorData->d1.floor->Box; + boxNumber = doorData->d1.floor->PathfindingBoxID; else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->Box; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->PathfindingBoxID; } - doorData->d1.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; + doorData->d1.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d1.data = *doorData->d1.floor; if (r->flippedRoom != -1) @@ -98,14 +98,14 @@ namespace TEN::Entities::Doors roomNumber = doorData->d1flip.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) - boxNumber = doorData->d1flip.floor->Box; + boxNumber = doorData->d1flip.floor->PathfindingBoxID; else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->Box; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->PathfindingBoxID; } - doorData->d1flip.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; + doorData->d1flip.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d1flip.data = *doorData->d1flip.floor; } else @@ -128,14 +128,14 @@ namespace TEN::Entities::Doors roomNumber = doorData->d2.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) - boxNumber = doorData->d2.floor->Box; + boxNumber = doorData->d2.floor->PathfindingBoxID; else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->Box; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->PathfindingBoxID; } - doorData->d2.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; + doorData->d2.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d2.data = *doorData->d2.floor; if (r->flippedRoom != -1) @@ -145,14 +145,14 @@ namespace TEN::Entities::Doors roomNumber = doorData->d2flip.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) - boxNumber = doorData->d2flip.floor->Box; + boxNumber = doorData->d2flip.floor->PathfindingBoxID; else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->Box; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->PathfindingBoxID; } - doorData->d2flip.block = (boxNumber != NO_VALUE && g_Level.Boxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; + doorData->d2flip.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; doorData->d2flip.data = *doorData->d2flip.floor; } else @@ -401,7 +401,7 @@ namespace TEN::Entities::Doors short boxIndex = doorPos->block; if (boxIndex != NO_VALUE) { - g_Level.Boxes[boxIndex].flags &= ~BLOCKED; + g_Level.PathfindingBoxes[boxIndex].flags &= ~BLOCKED; for (auto& currentCreature : ActiveCreatures) currentCreature->LOT.TargetBox = NO_VALUE; } @@ -416,7 +416,7 @@ namespace TEN::Entities::Doors if (floor) { - floor->Box = NO_VALUE; + floor->PathfindingBoxID = NO_VALUE; floor->TriggerIndex = 0; // FIXME: HACK!!!!!!! @@ -435,7 +435,7 @@ namespace TEN::Entities::Doors short boxIndex = doorPos->block; if (boxIndex != NO_VALUE) { - g_Level.Boxes[boxIndex].flags |= BLOCKED; + g_Level.PathfindingBoxes[boxIndex].flags |= BLOCKED; for (auto& currentCreature : ActiveCreatures) currentCreature->LOT.TargetBox = NO_VALUE; diff --git a/TombEngine/Objects/TR3/Entity/Lizard.cpp b/TombEngine/Objects/TR3/Entity/Lizard.cpp index d5a10e72b..a57c724a0 100644 --- a/TombEngine/Objects/TR3/Entity/Lizard.cpp +++ b/TombEngine/Objects/TR3/Entity/Lizard.cpp @@ -69,7 +69,7 @@ namespace TEN::Entities::Creatures::TR3 auto& creature = *GetCreatureInfo(&item); return (creature.Enemy && creature.Enemy->BoxNumber != NO_VALUE && - (g_Level.Boxes[creature.Enemy->BoxNumber].flags & BLOCKABLE)); + (g_Level.PathfindingBoxes[creature.Enemy->BoxNumber].flags & BLOCKABLE)); } static void SpawnLizardGas(int itemNumber, const CreatureBiteInfo& bite, int speed) diff --git a/TombEngine/Objects/TR3/Entity/Shiva.cpp b/TombEngine/Objects/TR3/Entity/Shiva.cpp index 21ccd1586..de1c28033 100644 --- a/TombEngine/Objects/TR3/Entity/Shiva.cpp +++ b/TombEngine/Objects/TR3/Entity/Shiva.cpp @@ -341,9 +341,9 @@ namespace TEN::Entities::Creatures::TR3 { int x = item->Pose.Position.x + BLOCK(1) * phd_sin(item->Pose.Orientation.y + ANGLE(180.0f)); int z = item->Pose.Position.z + BLOCK(1) * phd_cos(item->Pose.Orientation.y + ANGLE(180.0f)); - auto box = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetBottomSector().Box; + auto box = GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetBottomSector().PathfindingBoxID; - if (box != NO_VALUE && !(g_Level.Boxes[box].flags & BLOCKABLE) && !creature.Flags) + if (box != NO_VALUE && !(g_Level.PathfindingBoxes[box].flags & BLOCKABLE) && !creature.Flags) item->Animation.TargetState = SHIVA_STATE_WALK_BACK; else item->Animation.TargetState = SHIVA_STATE_GUARD_IDLE; diff --git a/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp b/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp index 7a86c5c01..0a98b223c 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_civvy.cpp @@ -182,7 +182,7 @@ namespace TEN::Entities::Creatures::TR3 auto jointHeadRot = EulerAngles::Identity; auto jointTorsoRot = EulerAngles::Identity; - if (item.BoxNumber != NO_VALUE && (g_Level.Boxes[item.BoxNumber].flags & BLOCKED) && item.HitPoints > 0) + if (item.BoxNumber != NO_VALUE && (g_Level.PathfindingBoxes[item.BoxNumber].flags & BLOCKED) && item.HitPoints > 0) { DoDamage(&item, INT_MAX); DoLotsOfBlood(item.Pose.Position.x, item.Pose.Position.y - (GetRandomControl() & 255) - 32, item.Pose.Position.z, (GetRandomControl() & 127) + 128, GetRandomControl() << 1, item.RoomNumber, 3); diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp index 7383b8925..31c011d34 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp @@ -72,7 +72,7 @@ namespace TEN::Entities::Creatures::TR3 if (creature->MuzzleFlash[0].Delay != 0) creature->MuzzleFlash[0].Delay--; - if (item->BoxNumber != NO_VALUE && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) + if (item->BoxNumber != NO_VALUE && (g_Level.PathfindingBoxes[item->BoxNumber].flags & BLOCKED)) { DoDamage(item, 20); DoLotsOfBlood(item->Pose.Position.x, item->Pose.Position.y - (GetRandomControl() & 255) - 32, item->Pose.Position.z, (GetRandomControl() & 127) + 128, GetRandomControl() * 2, item->RoomNumber, 3); diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp index 643f4d6c6..7b1bf2bab 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_stick.cpp @@ -77,7 +77,7 @@ namespace TEN::Entities::Creatures::TR3 short head = 0; auto extraTorsoRot = EulerAngles::Identity; - if (item->BoxNumber != NO_VALUE && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED)) + if (item->BoxNumber != NO_VALUE && (g_Level.PathfindingBoxes[item->BoxNumber].flags & BLOCKED)) { DoDamage(item, 20); DoLotsOfBlood(item->Pose.Position.x, item->Pose.Position.y - (GetRandomControl() & 255) - 32, item->Pose.Position.z, (GetRandomControl() & 127) + 128, GetRandomControl() * 2, item->RoomNumber, 3); diff --git a/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp index 9fb14881b..b6de0dbcd 100644 --- a/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_expandingplatform.cpp @@ -131,7 +131,7 @@ namespace TEN::Entities::Generic short roomNumber = item.RoomNumber; FloorInfo* floor = GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &roomNumber); - g_Level.Boxes[floor->Box].flags &= ~BLOCKED; + g_Level.PathfindingBoxes[floor->PathfindingBoxID].flags &= ~BLOCKED; // Set mutators to default. UpdateExpandingPlatformMutators(itemNumber); diff --git a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp index 24835ed4d..ac204e528 100644 --- a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp @@ -74,8 +74,8 @@ namespace TEN::Entities::Generic short roomNumber = item->RoomNumber; auto* floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber); - if (floor->Box != NO_VALUE) - g_Level.Boxes[floor->Box].flags &= ~BLOCKED; + if (floor->PathfindingBoxID != NO_VALUE) + g_Level.PathfindingBoxes[floor->PathfindingBoxID].flags &= ~BLOCKED; // Set mutators to EulerAngles identity by default. for (auto& mutator : item->Model.Mutators) diff --git a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp index 4125df0a4..54f008213 100644 --- a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp +++ b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp @@ -18,13 +18,13 @@ void InitializeSmashObject(short itemNumber) // NOTE: Avoids crash when attempting to access Boxes[] array while box is equal to NO_VALUE. -- TokyoSU 2022.12.20 FloorInfo* floor = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z); - if (floor->Box == NO_VALUE) + if (floor->PathfindingBoxID == NO_VALUE) { TENLog("Smash object with ID " + std::to_string(itemNumber) + " may be inside a wall." , LogLevel::Warning); return; } - auto* box = &g_Level.Boxes[floor->Box]; + auto* box = &g_Level.PathfindingBoxes[floor->PathfindingBoxID]; if (box->flags & 0x8000) box->flags |= BLOCKED; } @@ -36,7 +36,7 @@ void SmashObject(short itemNumber) int sector = ((item->Pose.Position.z - room->z) / 1024) + room->zSize * ((item->Pose.Position.x - room->x) / 1024); - auto* box = &g_Level.Boxes[room->floor[sector].Box]; + auto* box = &g_Level.PathfindingBoxes[room->floor[sector].PathfindingBoxID]; if (box->flags & 0x8000) box->flags &= ~BOX_BLOCKED; diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index 88596ddc4..6a3caf420 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -771,52 +771,57 @@ void ReadRooms() room.zSize = ReadInt32(); room.xSize = ReadInt32(); + auto roomPos = Vector2i(room.x, room.z); room.floor.reserve(room.zSize * room.xSize); - for (int j = 0; j < (room.zSize * room.xSize); j++) + for (int x = 0; x < room.xSize; x++) { - auto sector = FloorInfo{}; + for (int z = 0; z < room.zSize; z++) + { + auto sector = FloorInfo{}; - sector.TriggerIndex = ReadInt32(); - sector.Box = ReadInt32(); + sector.Position = roomPos + Vector2i(BLOCK(x), BLOCK(z)); + sector.RoomNumber = i; - sector.FloorSurface.Triangles[0].Material = - sector.FloorSurface.Triangles[1].Material = - sector.CeilingSurface.Triangles[0].Material = - sector.CeilingSurface.Triangles[1].Material = (MaterialType)ReadInt32(); + sector.TriggerIndex = ReadInt32(); + sector.PathfindingBoxID = ReadInt32(); - sector.Stopper = (bool)ReadInt32(); + sector.FloorSurface.Triangles[0].Material = + sector.FloorSurface.Triangles[1].Material = + sector.CeilingSurface.Triangles[0].Material = + sector.CeilingSurface.Triangles[1].Material = (MaterialType)ReadInt32(); - sector.FloorSurface.SplitAngle = FROM_RAD(ReadFloat()); - sector.FloorSurface.Triangles[0].SteepSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; - sector.FloorSurface.Triangles[1].SteepSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; - sector.FloorSurface.Triangles[0].PortalRoomNumber = ReadInt32(); - sector.FloorSurface.Triangles[1].PortalRoomNumber = ReadInt32(); - sector.FloorSurface.Triangles[0].Plane = ConvertFakePlaneToPlane(ReadVector3(), true); - sector.FloorSurface.Triangles[1].Plane = ConvertFakePlaneToPlane(ReadVector3(), true); + sector.Stopper = (bool)ReadInt32(); - sector.CeilingSurface.SplitAngle = FROM_RAD(ReadFloat()); - sector.CeilingSurface.Triangles[0].SteepSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; - sector.CeilingSurface.Triangles[1].SteepSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; - sector.CeilingSurface.Triangles[0].PortalRoomNumber = ReadInt32(); - sector.CeilingSurface.Triangles[1].PortalRoomNumber = ReadInt32(); - sector.CeilingSurface.Triangles[0].Plane = ConvertFakePlaneToPlane(ReadVector3(), false); - sector.CeilingSurface.Triangles[1].Plane = ConvertFakePlaneToPlane(ReadVector3(), false); + sector.FloorSurface.SplitAngle = FROM_RAD(ReadFloat()); + sector.FloorSurface.Triangles[0].SteepSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; + sector.FloorSurface.Triangles[1].SteepSlopeAngle = ILLEGAL_FLOOR_SLOPE_ANGLE; + sector.FloorSurface.Triangles[0].PortalRoomNumber = ReadInt32(); + sector.FloorSurface.Triangles[1].PortalRoomNumber = ReadInt32(); + sector.FloorSurface.Triangles[0].Plane = ConvertFakePlaneToPlane(ReadVector3(), true); + sector.FloorSurface.Triangles[1].Plane = ConvertFakePlaneToPlane(ReadVector3(), true); - sector.SidePortalRoomNumber = ReadInt32(); - sector.Flags.Death = ReadBool(); - sector.Flags.Monkeyswing = ReadBool(); - sector.Flags.ClimbNorth = ReadBool(); - sector.Flags.ClimbSouth = ReadBool(); - sector.Flags.ClimbEast = ReadBool(); - sector.Flags.ClimbWest = ReadBool(); - sector.Flags.MarkTriggerer = ReadBool(); - sector.Flags.MarkTriggererActive = 0; // TODO: Needs to be written to and read from savegames. - sector.Flags.MarkBeetle = ReadBool(); + sector.CeilingSurface.SplitAngle = FROM_RAD(ReadFloat()); + sector.CeilingSurface.Triangles[0].SteepSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; + sector.CeilingSurface.Triangles[1].SteepSlopeAngle = ILLEGAL_CEILING_SLOPE_ANGLE; + sector.CeilingSurface.Triangles[0].PortalRoomNumber = ReadInt32(); + sector.CeilingSurface.Triangles[1].PortalRoomNumber = ReadInt32(); + sector.CeilingSurface.Triangles[0].Plane = ConvertFakePlaneToPlane(ReadVector3(), false); + sector.CeilingSurface.Triangles[1].Plane = ConvertFakePlaneToPlane(ReadVector3(), false); - sector.RoomNumber = i; + sector.SidePortalRoomNumber = ReadInt32(); + sector.Flags.Death = ReadBool(); + sector.Flags.Monkeyswing = ReadBool(); + sector.Flags.ClimbNorth = ReadBool(); + sector.Flags.ClimbSouth = ReadBool(); + sector.Flags.ClimbEast = ReadBool(); + sector.Flags.ClimbWest = ReadBool(); + sector.Flags.MarkTriggerer = ReadBool(); + sector.Flags.MarkTriggererActive = 0; // TODO: Needs to be written to and read from savegames. + sector.Flags.MarkBeetle = ReadBool(); - room.floor.push_back(sector); + room.floor.push_back(sector); + } } room.ambient = ReadVector3(); @@ -948,7 +953,7 @@ void FreeLevel() g_Level.Meshes.resize(0); MoveablesIds.resize(0); SpriteSequencesIds.resize(0); - g_Level.Boxes.resize(0); + g_Level.PathfindingBoxes.resize(0); g_Level.Overlaps.resize(0); g_Level.Anims.resize(0); g_Level.Changes.resize(0); @@ -1363,8 +1368,8 @@ void LoadBoxes() // Read boxes int numBoxes = ReadInt32(); TENLog("Num boxes: " + std::to_string(numBoxes), LogLevel::Info); - g_Level.Boxes.resize(numBoxes); - ReadBytes(g_Level.Boxes.data(), numBoxes * sizeof(BOX_INFO)); + g_Level.PathfindingBoxes.resize(numBoxes); + ReadBytes(g_Level.PathfindingBoxes.data(), numBoxes * sizeof(BOX_INFO)); // Read overlaps int numOverlaps = ReadInt32(); @@ -1398,8 +1403,8 @@ void LoadBoxes() // By default all blockable boxes are blocked for (int i = 0; i < numBoxes; i++) { - if (g_Level.Boxes[i].flags & BLOCKABLE) - g_Level.Boxes[i].flags |= BLOCKED; + if (g_Level.PathfindingBoxes[i].flags & BLOCKABLE) + g_Level.PathfindingBoxes[i].flags |= BLOCKED; } } diff --git a/TombEngine/Specific/level.h b/TombEngine/Specific/level.h index 01c65380a..1c0c84853 100644 --- a/TombEngine/Specific/level.h +++ b/TombEngine/Specific/level.h @@ -107,8 +107,8 @@ struct LEVEL std::vector Sinks = {}; // Pathfinding data - std::vector Boxes = {}; - std::vector Overlaps = {}; + std::vector PathfindingBoxes = {}; + std::vector Overlaps = {}; std::vector Zones[(int)ZoneType::MaxZone][2] = {}; // Sound data From 2be193a9973362b6f3608ae824ddb34ca68de51c Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 26 Jun 2024 14:50:39 +1000 Subject: [PATCH 222/410] Use NO_VALUE in GetPlayerScrolledWeaponType() --- TombEngine/Game/Lara/lara_helpers.cpp | 30 +++++++++++++-------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 35596d7df..3a18ecf09 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -278,7 +278,7 @@ void HandlePlayerStatusEffects(ItemInfo& item, WaterStatus waterStatus, PlayerWa } } -static std::optional GetPlayerScrolledWeaponType(const ItemInfo& item, LaraWeaponType currentWeaponType, bool getPrev) +static LaraWeaponType GetPlayerScrolledWeaponType(const ItemInfo& item, LaraWeaponType currentWeaponType, bool getPrev) { static const auto SCROLL_WEAPON_TYPES = std::vector { @@ -293,15 +293,15 @@ static std::optional GetPlayerScrolledWeaponType(const ItemInfo& LaraWeaponType::RocketLauncher }; - auto getNextIndex = [getPrev](unsigned int index) + auto getNextIndex = [getPrev](int index) { - return (index + (getPrev ? ((unsigned int)SCROLL_WEAPON_TYPES.size() - 1) : 1)) % (unsigned int)SCROLL_WEAPON_TYPES.size(); + return (index + (getPrev ? ((int)SCROLL_WEAPON_TYPES.size() - 1) : 1)) % (int)SCROLL_WEAPON_TYPES.size(); }; auto& player = GetLaraInfo(item); // Get vector index for current weapon type. - auto currentIndex = std::optional(std::nullopt); + auto currentIndex = NO_VALUE; for (int i = 0; i < SCROLL_WEAPON_TYPES.size(); i++) { if (SCROLL_WEAPON_TYPES[i] == currentWeaponType) @@ -311,13 +311,13 @@ static std::optional GetPlayerScrolledWeaponType(const ItemInfo& } } - // Invalid current weapon type; return nullopt. - if (!currentIndex.has_value()) - return std::nullopt; + // Invalid current weapon type; return None type. + if (currentIndex == NO_VALUE) + return LaraWeaponType::None; // Get next valid weapon type in sequence. - unsigned int nextIndex = getNextIndex(*currentIndex); - while (nextIndex != *currentIndex) + int nextIndex = getNextIndex(currentIndex); + while (nextIndex != currentIndex) { auto nextWeaponType = SCROLL_WEAPON_TYPES[nextIndex]; if (player.Weapons[(int)nextWeaponType].Present) @@ -326,8 +326,8 @@ static std::optional GetPlayerScrolledWeaponType(const ItemInfo& nextIndex = getNextIndex(nextIndex); } - // No valid weapon type; return nullopt. - return std::nullopt; + // No valid weapon type; return None type. + return LaraWeaponType::None; } void HandlePlayerQuickActions(ItemInfo& item) @@ -347,11 +347,9 @@ void HandlePlayerQuickActions(ItemInfo& item) // Handle weapon scroll request. if (IsClicked(In::PreviousWeapon) || IsClicked(In::NextWeapon)) { - bool getPrev = IsClicked(In::PreviousWeapon); - auto weaponType = GetPlayerScrolledWeaponType(item, player.Control.Weapon.GunType, getPrev); - - if (weaponType.has_value()) - player.Control.Weapon.RequestGunType = *weaponType; + auto weaponType = GetPlayerScrolledWeaponType(item, player.Control.Weapon.GunType, IsClicked(In::PreviousWeapon)); + if (weaponType != LaraWeaponType::None) + player.Control.Weapon.RequestGunType = weaponType; } // Handle weapon requests. From 4c4a0b051024fe062bafba34b35ac8a66c056c21 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 27 Jun 2024 21:10:19 +1000 Subject: [PATCH 223/410] Global access to debug objects (#1382) * Make debug object drawing globally accessible and therefore convenient * Fix case in debug includes * Add math constants * Add missing space * Fix debug strings; reduce debug string scale * Remove unused method * Remove commented lines --- TombEngine/Game/Hud/PickupSummary.cpp | 2 +- TombEngine/Game/Hud/Speedometer.cpp | 12 +- TombEngine/Game/Hud/TargetHighlighter.cpp | 8 +- TombEngine/Game/Lara/lara_helpers.cpp | 4 +- TombEngine/Game/Lara/lara_tests.cpp | 11 +- TombEngine/Game/camera.cpp | 4 +- TombEngine/Game/collision/collide_item.cpp | 8 +- TombEngine/Game/collision/collide_room.cpp | 20 +- TombEngine/Game/control/box.cpp | 3 +- TombEngine/Game/control/volume.cpp | 10 +- TombEngine/Game/debug/debug.cpp | 88 ++++- TombEngine/Game/debug/debug.h | 31 +- TombEngine/Math/Constants.h | 6 + .../Renderer/ConstantBuffers/ConstantBuffer.h | 20 +- TombEngine/Renderer/Graphics/IndexBuffer.h | 2 +- TombEngine/Renderer/Renderer.h | 10 +- TombEngine/Renderer/RendererDebug.cpp | 29 +- TombEngine/Renderer/RendererDraw.cpp | 17 +- TombEngine/Renderer/RendererDrawMenu.cpp | 321 +++++++++--------- TombEngine/Renderer/RendererUtils.cpp | 2 +- .../Scripting/Internal/TEN/Util/LevelLog.h | 2 +- TombEngine/Specific/Input/InputAction.cpp | 24 +- TombEngine/framework.h | 4 +- 23 files changed, 356 insertions(+), 282 deletions(-) diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index f38c0f6b6..b10e8bab1 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -222,6 +222,6 @@ namespace TEN::Hud void PickupSummaryController::DrawDebug() const { - g_Renderer.PrintDebugMessage("Display pickups in summary: %d", _displayPickups.size()); + PrintDebugMessage("Display pickups in summary: %d", _displayPickups.size()); } } diff --git a/TombEngine/Game/Hud/Speedometer.cpp b/TombEngine/Game/Hud/Speedometer.cpp index 5768c69cf..0fd5ed245 100644 --- a/TombEngine/Game/Hud/Speedometer.cpp +++ b/TombEngine/Game/Hud/Speedometer.cpp @@ -3,12 +3,10 @@ #include "Game/effects/DisplaySprite.h" #include "Math/Math.h" -#include "Renderer/Renderer.h" #include "Specific/clock.h" using namespace TEN::Effects::DisplaySprite; using namespace TEN::Math; -using TEN::Renderer::g_Renderer; namespace TEN::Hud { @@ -80,10 +78,10 @@ namespace TEN::Hud void SpeedometerController::DrawDebug() const { - g_Renderer.PrintDebugMessage("SPEEDOMETER DEBUG"); - g_Renderer.PrintDebugMessage("Value: %.3f", _value); - g_Renderer.PrintDebugMessage("Pointer angle: %.3f", _pointerAngle); - g_Renderer.PrintDebugMessage("Opacity: %.3f", _opacity); - g_Renderer.PrintDebugMessage("Life: %.3f", _life / FPS); + PrintDebugMessage("SPEEDOMETER DEBUG"); + PrintDebugMessage("Value: %.3f", _value); + PrintDebugMessage("Pointer angle: %.3f", _pointerAngle); + PrintDebugMessage("Opacity: %.3f", _opacity); + PrintDebugMessage("Life: %.3f", _life / FPS); } } diff --git a/TombEngine/Game/Hud/TargetHighlighter.cpp b/TombEngine/Game/Hud/TargetHighlighter.cpp index 34638f991..aed040ff5 100644 --- a/TombEngine/Game/Hud/TargetHighlighter.cpp +++ b/TombEngine/Game/Hud/TargetHighlighter.cpp @@ -350,9 +350,9 @@ namespace TEN::Hud for (const auto& [itemNumber, crosshair] : _crosshairs) crosshair.IsPrimary ? primaryCount++ : peripheralCount++; - g_Renderer.PrintDebugMessage("TARGET HIGHLIGHTER DEBUG"); - g_Renderer.PrintDebugMessage(g_Configuration.EnableTargetHighlighter ? "Enabled" : "Disabled"); - g_Renderer.PrintDebugMessage("Primary crosshairs: %d", primaryCount); - g_Renderer.PrintDebugMessage("Peripheral crosshairs: %d", peripheralCount); + PrintDebugMessage("TARGET HIGHLIGHTER DEBUG"); + PrintDebugMessage(g_Configuration.EnableTargetHighlighter ? "Enabled" : "Disabled"); + PrintDebugMessage("Primary crosshairs: %d", primaryCount); + PrintDebugMessage("Peripheral crosshairs: %d", peripheralCount); } } diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 3a18ecf09..c2b60dd45 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -22,7 +22,6 @@ #include "Game/savegame.h" #include "Game/Setup.h" #include "Math/Math.h" -#include "Renderer/Renderer.h" #include "Scripting/Include/ScriptInterfaceLevel.h" #include "Sound/sound.h" #include "Specific/Input/Input.h" @@ -46,7 +45,6 @@ using namespace TEN::Entities::Player; using namespace TEN::Gui; using namespace TEN::Input; using namespace TEN::Math; -using namespace TEN::Renderer; // ----------------------------- // HELPER FUNCTIONS @@ -1490,7 +1488,7 @@ void ModulateLaraSlideVelocity(ItemInfo* item, CollisionInfo* coll) //int slideVelocity = std::min(minVelocity + 10 * (steepness * velocityMultiplier), LARA_TERMINAL_VELOCITY); //short deltaAngle = abs((short)(direction - item->Pose.Orientation.y)); - //g_Renderer.PrintDebugMessage("%d", slideVelocity); + //PrintDebugMessage("%d", slideVelocity); //lara->ExtraVelocity.x += slideVelocity; //lara->ExtraVelocity.y += slideVelocity * phd_sin(steepness); diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index ee7b8d809..a208daf54 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -17,7 +17,7 @@ #include "Game/Lara/lara_helpers.h" #include "Game/Lara/lara_monkey.h" #include "Math/Math.h" -#include "Renderer/Renderer.h" +#include "Specific/configuration.h" #include "Specific/Input/Input.h" #include "Specific/level.h" #include "Specific/trutils.h" @@ -27,7 +27,6 @@ using namespace TEN::Collision::Point; using namespace TEN::Entities::Player; using namespace TEN::Input; using namespace TEN::Math; -using namespace TEN::Renderer; using namespace TEN::Utils; // ----------------------------- @@ -58,8 +57,8 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo if (frontLeft.GetCeilingHeight() >(item->Pose.Position.y - coll->Setup.Height) || frontRight.GetCeilingHeight() > (item->Pose.Position.y - coll->Setup.Height)) return false; - //g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xl, left, item->pos.Position.z + zl), 64, Vector4::One, RendererDebugPage::CollisionStats); - //g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xr, right, item->pos.Position.z + zr), 64, Vector4::One, RendererDebugPage::CollisionStats); + //DrawDebugSphere(Vector3(item->pos.Position.x + xl, left, item->pos.Position.z + zl), 64, Vector4::One, RendererDebugPage::CollisionStats); + //DrawDebugSphere(Vector3(item->pos.Position.x + xr, right, item->pos.Position.z + zr), 64, Vector4::One, RendererDebugPage::CollisionStats); // Determine ledge probe embed offset. // We use 0.2f radius extents here for two purposes. First - we can't guarantee that shifts weren't already applied @@ -1793,7 +1792,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl auto sphere = BoundingSphere(spherePos, poleProbeCollRadius); auto offsetSphere = BoundingSphere(spherePos + sphereOffset2D, poleProbeCollRadius); - //g_Renderer.AddDebugSphere(sphere.Center, 16.0f, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); + //DrawDebugSphere(sphere.Center, 16.0f, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); for (const auto* itemPtr : collObjects.Items) { @@ -1803,7 +1802,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl auto poleBox = GameBoundingBox(itemPtr).ToBoundingOrientedBox(itemPtr->Pose); poleBox.Extents = poleBox.Extents + Vector3(coll->Setup.Radius, 0.0f, coll->Setup.Radius); - //g_Renderer.AddDebugBox(poleBox, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats); + //DrawDebugBox(poleBox, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats); if (poleBox.Intersects(sphere) || poleBox.Intersects(offsetSphere)) { diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index e0863e650..431de8ce8 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1486,7 +1486,7 @@ void ItemsCollideCamera() if (TestBoundsCollideCamera(bounds, item->Pose, CAMERA_RADIUS)) ItemPushCamera(&bounds, &item->Pose, RADIUS); - TEN::Renderer::g_Renderer.AddDebugBox( + DrawDebugBox( bounds.ToBoundingOrientedBox(item->Pose), Vector4(1.0f, 0.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats); } @@ -1509,7 +1509,7 @@ void ItemsCollideCamera() if (TestBoundsCollideCamera(bounds, mesh->pos, CAMERA_RADIUS)) ItemPushCamera(&bounds, &mesh->pos, RADIUS); - TEN::Renderer::g_Renderer.AddDebugBox( + DrawDebugBox( bounds.ToBoundingOrientedBox(mesh->pos), Vector4(1.0f, 0.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats); } diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index a60ac2b82..077c77cc8 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -18,14 +18,12 @@ #include "Game/room.h" #include "Game/Setup.h" #include "Math/Math.h" -#include "Renderer/Renderer.h" #include "Scripting/Include/ScriptInterfaceGame.h" #include "Sound/sound.h" using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Point; using namespace TEN::Math; -using namespace TEN::Renderer; constexpr auto ANIMATED_ALIGNMENT_FRAME_COUNT_THRESHOLD = 6; @@ -307,7 +305,7 @@ void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll) auto mxR = Matrix::CreateFromYawPitchRoll(TO_RAD(coll->Setup.ForwardAngle), 0.0f, 0.0f); auto direction = (Matrix::CreateTranslation(Vector3::UnitZ) * mxR).Translation(); - // g_Renderer.AddDebugSphere(origin, 16, Vector4::One, RendererDebugPage::CollisionStats); + // DrawDebugSphere(origin, 16, Vector4::One, RendererDebugPage::CollisionStats); for (auto i : g_Level.Rooms[item->RoomNumber].neighbors) { @@ -989,7 +987,7 @@ bool CollideSolidBounds(ItemInfo* item, const GameBoundingBox& box, const Pose& itemBounds.Extents = itemBounds.Extents - Vector3(BLOCK(1)); // Draw static bounds. - g_Renderer.AddDebugBox(staticBounds, Vector4(1, 0.3f, 0, 1), RendererDebugPage::CollisionStats); + DrawDebugBox(staticBounds, Vector4(1, 0.3f, 0, 1), RendererDebugPage::CollisionStats); // Calculate horizontal item collision bounds according to radius. GameBoundingBox collBox; @@ -1016,7 +1014,7 @@ bool CollideSolidBounds(ItemInfo* item, const GameBoundingBox& box, const Pose& bool intersects = staticBounds.Intersects(collBounds); // Draw item coll bounds. - g_Renderer.AddDebugBox(collBounds, intersects ? Vector4(1, 0, 0, 1) : Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); + DrawDebugBox(collBounds, intersects ? Vector4(1, 0, 0, 1) : Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); // Decompose static bounds into top/bottom plane vertices. Vector3 corners[8]; diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 137d8d62e..04670f47a 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -11,13 +11,11 @@ #include "Game/room.h" #include "Math/Math.h" #include "Sound/sound.h" -#include "Renderer/Renderer.h" using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Point; using namespace TEN::Collision::Room; using namespace TEN::Math; -using namespace TEN::Renderer; void ShiftItem(ItemInfo* item, CollisionInfo* coll) { @@ -299,8 +297,8 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse coll->NearestLedgeAngle = GetNearestLedgeAngle(item, coll, coll->NearestLedgeDistance); // Debug angle and distance - // g_Renderer.PrintDebugMessage("Nearest angle: %d", coll->NearestLedgeAngle); - // g_Renderer.PrintDebugMessage("Nearest dist: %f", coll->NearestLedgeDistance); + // PrintDebugMessage("Nearest angle: %d", coll->NearestLedgeAngle); + // PrintDebugMessage("Nearest dist: %f", coll->NearestLedgeDistance); // TEST 2: CENTERPOINT PROBE @@ -339,7 +337,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse probePos.x = entityPos.x + xFront; probePos.z = entityPos.z + zFront; - g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); + DrawDebugSphere(probePos.ToVector3(), 32, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats); pointColl = GetPointCollision(probePos, topRoomNumber); @@ -394,7 +392,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse probePos.x = entityPos.x + xLeft; probePos.z = entityPos.z + zLeft; - g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats); + DrawDebugSphere(probePos.ToVector3(), 32, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats); pointColl = GetPointCollision(probePos, item->RoomNumber); @@ -460,7 +458,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse probePos.x = entityPos.x + xRight; probePos.z = entityPos.z + zRight; - g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); + DrawDebugSphere(probePos.ToVector3(), 32, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); pointColl = GetPointCollision(probePos, item->RoomNumber); @@ -807,7 +805,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) } // Debug probe point - // g_Renderer.AddDebugSphere(Vector3(eX, y, eZ), 16, Vector4(1, 1, 0, 1), RendererDebugPage::CollisionStats); + // DrawDebugSphere(Vector3(eX, y, eZ), 16, Vector4(1, 1, 0, 1), RendererDebugPage::CollisionStats); // Determine front floor probe offset. // It is needed to identify if there is bridge or ceiling split in front. @@ -849,7 +847,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) auto fpZ = eZ + floorProbeOffset * cosForwardAngle; // Debug probe point. - // g_Renderer.AddDebugSphere(Vector3(fpX, y, fpZ), 16, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); + // DrawDebugSphere(Vector3(fpX, y, fpZ), 16, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats); // Get true room number and block, based on derived height room = GetRoomVector(item->Location, Vector3i(fpX, height, fpZ)).RoomNumber; @@ -865,7 +863,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) auto ray = Ray(Vector3(eX, cY, eZ), direction); // Debug ray direction. - // g_Renderer.AddDebugLine(Vector3(eX, y, eZ), Vector3(eX, y, eZ) + direction * 256, Vector4(1, 0, 0, 1)); + // DrawDebugLine(Vector3(eX, y, eZ), Vector3(eX, y, eZ) + direction * 256, Vector4(1, 0, 0, 1)); // Keep origin ray to calculate true centerpoint distance to ledge later. if (p == 0) @@ -920,7 +918,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance) auto cZ = fZ + BLOCK(1) + 1; // Debug used block - // g_Renderer.AddDebugSphere(Vector3(round(eX / BLOCK(1)) * BLOCK(1) + BLOCK(0.5f), y, round(eZ / BLOCK(1)) * BLOCK(1) + BLOCK(0.5f)), 16, Vector4::One, RendererDebugPage::CollisionStats); + // DrawDebugSphere(Vector3(round(eX / BLOCK(1)) * BLOCK(1) + BLOCK(0.5f), y, round(eZ / BLOCK(1)) * BLOCK(1) + BLOCK(0.5f)), 16, Vector4::One, RendererDebugPage::CollisionStats); // Get split angle coordinates. auto sX = fX + 1 + BLOCK(0.5f); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 3166286f2..453435568 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -21,7 +21,6 @@ #include "Math/Math.h" #include "Objects/objectslist.h" #include "Objects/Generic/Object/Pushable/PushableObject.h" -#include "Renderer/Renderer.h" using namespace TEN::Collision::Point; using namespace TEN::Collision::Room; @@ -69,7 +68,7 @@ void DrawBox(int boxIndex, Vector3 color) for (int i = 0; i <= 10; i++) { dBox.Extents = extents + Vector3(i); - TEN::Renderer::g_Renderer.AddDebugBox(dBox, Vector4(color.x, color.y, color.z, 1), RendererDebugPage::PathfindingStats); + DrawDebugBox(dBox, Vector4(color.x, color.y, color.z, 1), RendererDebugPage::PathfindingStats); } } diff --git a/TombEngine/Game/control/volume.cpp b/TombEngine/Game/control/volume.cpp index 55ace1293..10bcdfe8a 100644 --- a/TombEngine/Game/control/volume.cpp +++ b/TombEngine/Game/control/volume.cpp @@ -10,12 +10,8 @@ #include "Game/room.h" #include "Game/savegame.h" #include "Game/Setup.h" -#include "Renderer/Renderer.h" -#include "Renderer/RendererEnums.h" #include "Scripting/Include/ScriptInterfaceGame.h" -using TEN::Renderer::g_Renderer; - namespace TEN::Control::Volumes { constexpr auto CAM_SIZE = 32; @@ -30,7 +26,7 @@ namespace TEN::Control::Volumes case VolumeType::Box: if (roomNumber == Camera.pos.RoomNumber) { - g_Renderer.AddDebugBox(volume.Box, + DrawDebugBox(volume.Box, Vector4(color, 0.0f, color, 1.0f), RendererDebugPage::CollisionStats); } return volume.Box.Intersects(box); @@ -38,7 +34,7 @@ namespace TEN::Control::Volumes case VolumeType::Sphere: if (roomNumber == Camera.pos.RoomNumber) { - g_Renderer.AddDebugSphere(volume.Sphere.Center, volume.Sphere.Radius, + DrawDebugSphere(volume.Sphere.Center, volume.Sphere.Radius, Vector4(color, 0.0f, color, 1.0f), RendererDebugPage::CollisionStats); } return volume.Sphere.Intersects(box); @@ -252,7 +248,7 @@ namespace TEN::Control::Volumes auto box = (coll != nullptr) ? ConstructRoughBox(item, *coll) : GameBoundingBox(&item).ToBoundingOrientedBox(item.Pose); - g_Renderer.AddDebugBox(box, Vector4(1.0f, 1.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats); + DrawDebugBox(box, Vector4(1.0f, 1.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats); if (item.IsLara() || item.Index == Lara.Context.Vehicle) { diff --git a/TombEngine/Game/debug/debug.cpp b/TombEngine/Game/debug/debug.cpp index a5cba1b3f..4e06330f3 100644 --- a/TombEngine/Game/debug/debug.cpp +++ b/TombEngine/Game/debug/debug.cpp @@ -1,9 +1,14 @@ #include "framework.h" -#include "Game/debug/debug.h" +#include "Game/Debug/Debug.h" #include #include #include +#include + +#include "Renderer/Renderer.h" + +using TEN::Renderer::g_Renderer; namespace TEN::Debug { @@ -30,11 +35,10 @@ namespace TEN::Debug spdlog::shutdown(); } - void TENLog(const std::string_view& string, LogLevel level, LogConfig config, bool allowSpam) + void TENLog(const std::string_view& msg, LogLevel level, LogConfig config, bool allowSpam) { static auto prevString = std::string(); - - if (prevString == string && !allowSpam) + if (prevString == msg && !allowSpam) return; if constexpr (!DebugBuild) @@ -47,20 +51,88 @@ namespace TEN::Debug switch (level) { case LogLevel::Error: - logger->error(string); + logger->error(msg); break; case LogLevel::Warning: - logger->warn(string); + logger->warn(msg); break; case LogLevel::Info: - logger->info(string); + logger->info(msg); break; } logger->flush(); - prevString = std::string(string); + prevString = std::string(msg); + } + + void PrintDebugMessage(LPCSTR msg, ...) + { + auto args = va_list{}; + va_start(args, msg); + g_Renderer.PrintDebugMessage(msg, args); + va_end(args); + } + + void DrawDebug2DLine(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page) + { + g_Renderer.AddLine2D(origin, target, color, page); + } + + void DrawDebugLine(const Vector3& origin, const Vector3& target, const Color& color, RendererDebugPage page) + { + g_Renderer.AddDebugLine(origin, target, color, page); + } + + void DrawDebugTriangle(const Vector3& vertex0, const Vector3& vertex1, const Vector3& vertex2, const Color& color, RendererDebugPage page) + { + g_Renderer.AddDebugTriangle(vertex0, vertex1, vertex2, color, page); + } + + void DrawDebugTarget(const Vector3& center, const Quaternion& orient, float radius, const Color& color, RendererDebugPage page) + { + g_Renderer.AddDebugTarget(center, orient, radius, color, page); + } + + void DrawDebugBox(const std::array& corners, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugBox(corners, color, page, isWireframe); + } + + void DrawDebugBox(const Vector3& min, const Vector3& max, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugBox(min, max, color, page, isWireframe); + } + + void DrawDebugBox(const BoundingOrientedBox& box, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugBox(box, color, page, isWireframe); + } + + void DrawDebugBox(const BoundingBox& box, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugBox(box, color, page, isWireframe); + } + + void DrawDebugCone(const Vector3& center, const Quaternion& orient, float radius, float length, const Vector4& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugCone(center, orient, radius, length, color, page, isWireframe); + } + + void DrawDebugCylinder(const Vector3& center, const Quaternion& orient, float radius, float length, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugCylinder(center, orient, radius, length, color, page, isWireframe); + } + + void DrawDebugSphere(const Vector3& center, float radius, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugSphere(center, radius, color, page, isWireframe); + } + + void DrawDebugSphere(const BoundingSphere& sphere, const Color& color, RendererDebugPage page, bool isWireframe) + { + g_Renderer.AddDebugSphere(sphere, color, page, isWireframe); } } diff --git a/TombEngine/Game/debug/debug.h b/TombEngine/Game/debug/debug.h index 561a2d28a..448855af6 100644 --- a/TombEngine/Game/debug/debug.h +++ b/TombEngine/Game/debug/debug.h @@ -1,16 +1,19 @@ #pragma once -#if _DEBUG -constexpr bool DebugBuild = true; -#else -constexpr bool DebugBuild = false; -#endif #include #include #include +#include "Renderer/RendererEnums.h" + namespace TEN::Debug { +#if _DEBUG + constexpr bool DebugBuild = true; +#else + constexpr bool DebugBuild = false; +#endif + enum class LogLevel { Error, @@ -32,9 +35,9 @@ namespace TEN::Debug void InitTENLog(const std::string& logDirContainingDir); void ShutdownTENLog(); - void TENLog(const std::string_view& string, LogLevel level = LogLevel::Info, LogConfig config = LogConfig::All, bool allowSpam = false); + void TENLog(const std::string_view& msg, LogLevel level = LogLevel::Info, LogConfig config = LogConfig::All, bool allowSpam = false); - inline void TENAssert(const bool& cond, const char* msg) + inline void TENAssert(const bool& cond, const std::string& msg) { if constexpr (DebugBuild) { @@ -45,4 +48,18 @@ namespace TEN::Debug } } }; + + void PrintDebugMessage(LPCSTR msg, ...); + void DrawDebug2DLine(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); + void DrawDebugLine(const Vector3& origin, const Vector3& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); + void DrawDebugTriangle(const Vector3& vertex0, const Vector3& vertex1, const Vector3& vertex2, const Color& color, RendererDebugPage page = RendererDebugPage::None); + void DrawDebugTarget(const Vector3& center, const Quaternion& orient, float radius, const Color& color, RendererDebugPage page = RendererDebugPage::None); + void DrawDebugBox(const std::array& corners, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void DrawDebugBox(const Vector3& min, const Vector3& max, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void DrawDebugBox(const BoundingOrientedBox& box, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void DrawDebugBox(const BoundingBox& box, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void DrawDebugCone(const Vector3& center, const Quaternion& orient, float radius, float length, const Vector4& color, RendererDebugPage page, bool isWireframe = true); + void DrawDebugCylinder(const Vector3& center, const Quaternion& orient, float radius, float length, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void DrawDebugSphere(const Vector3& center, float radius, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void DrawDebugSphere(const BoundingSphere& sphere, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); } diff --git a/TombEngine/Math/Constants.h b/TombEngine/Math/Constants.h index 7147986d0..a43ba00a8 100644 --- a/TombEngine/Math/Constants.h +++ b/TombEngine/Math/Constants.h @@ -16,6 +16,12 @@ constexpr auto SQUARE = [](auto x) { return (x * x); }; constexpr auto CUBE = [](auto x) { return (x * x * x); }; + // Geometry constants + + constexpr auto BOX_VERTEX_COUNT = 8; + constexpr auto BOX_EDGE_COUNT = 12; + constexpr auto BOX_FACE_COUNT = 6; + // World constants constexpr auto BLOCK_UNIT = 1024; diff --git a/TombEngine/Renderer/ConstantBuffers/ConstantBuffer.h b/TombEngine/Renderer/ConstantBuffers/ConstantBuffer.h index 3ae6c47b3..147bf2f9a 100644 --- a/TombEngine/Renderer/ConstantBuffers/ConstantBuffer.h +++ b/TombEngine/Renderer/ConstantBuffers/ConstantBuffer.h @@ -1,8 +1,10 @@ #pragma once -#include "Renderer/RendererUtils.h" -#include "Game/debug/debug.h" -#include + #include +#include + +#include "Game/Debug/Debug.h" +#include "Renderer/RendererUtils.h" namespace TEN::Renderer::ConstantBuffers { @@ -15,12 +17,12 @@ namespace TEN::Renderer::ConstantBuffers ConstantBuffer() = default; ConstantBuffer(ID3D11Device* device) { - D3D11_BUFFER_DESC desc = {}; + auto desc = D3D11_BUFFER_DESC{}; desc.ByteWidth = sizeof(CBuff); desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - Utils::throwIfFailed(device->CreateBuffer(&desc, NULL, buffer.GetAddressOf())); + Utils::throwIfFailed(device->CreateBuffer(&desc, nullptr, buffer.GetAddressOf())); buffer->SetPrivateData(WKPDID_D3DDebugObjectName, 32, typeid(CBuff).name()); } @@ -31,8 +33,8 @@ namespace TEN::Renderer::ConstantBuffers void UpdateData(CBuff& data, ID3D11DeviceContext* ctx) { - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT res = ctx->Map(buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + auto mappedResource = D3D11_MAPPED_SUBRESOURCE{}; + auto res = ctx->Map(buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (SUCCEEDED(res)) { void* dataPtr = (mappedResource.pData); @@ -40,7 +42,9 @@ namespace TEN::Renderer::ConstantBuffers ctx->Unmap(buffer.Get(), 0); } else - TENLog("Could not update constant buffer!", LogLevel::Error); + { + TENLog("Could not update constant buffer.", LogLevel::Error); + } } }; } diff --git a/TombEngine/Renderer/Graphics/IndexBuffer.h b/TombEngine/Renderer/Graphics/IndexBuffer.h index d2869b00e..690264d5d 100644 --- a/TombEngine/Renderer/Graphics/IndexBuffer.h +++ b/TombEngine/Renderer/Graphics/IndexBuffer.h @@ -3,7 +3,7 @@ #include #include #include "Renderer/RendererUtils.h" -#include "Game/debug/debug.h" +#include "Game/Debug/Debug.h" #include "Specific/fast_vector.h" namespace TEN::Renderer::Graphics diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index d738ae413..9cb74a15a 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -288,7 +288,7 @@ namespace TEN::Renderer int _numCheckPortalCalls = 0; int _numGetVisibleRoomsCalls = 0; - int _currentY; + float _currentLineHeight = 0.0f;; RendererDebugPage _debugPage = RendererDebugPage::None; @@ -404,7 +404,6 @@ namespace TEN::Renderer void ClearShadowMap(); void CalculateSSAO(RenderView& view); void UpdateItemAnimations(RenderView& view); - bool PrintDebugMessage(int x, int y, int alpha, byte r, byte g, byte b, LPCSTR Message); void InitializeScreen(int w, int h, HWND handle, bool reset); void InitializeCommonTextures(); void InitializeGameBars(); @@ -593,7 +592,8 @@ namespace TEN::Renderer void RenderScene(RenderTarget2D* renderTarget, bool doAntialiasing, RenderView& view); void ClearScene(); void SaveScreenshot(); - void PrintDebugMessage(LPCSTR message, ...); + void PrintDebugMessage(LPCSTR msg, va_list args); + void PrintDebugMessage(LPCSTR msg, ...); void DrawDebugInfo(RenderView& view); void SwitchDebugPage(bool goBack); void DrawDisplayPickup(const DisplayPickup& pickup); @@ -615,11 +615,11 @@ namespace TEN::Renderer void AddDebugLine(const Vector3& origin, const Vector3& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); void AddDebugTriangle(const Vector3& vertex0, const Vector3& vertex1, const Vector3& vertex2, const Color& color, RendererDebugPage page = RendererDebugPage::None); void AddDebugTarget(const Vector3& center, const Quaternion& orient, float radius, const Color& color, RendererDebugPage page = RendererDebugPage::None); - void AddDebugBox(const std::array& corners, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); + void AddDebugBox(const std::array& corners, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); void AddDebugBox(const Vector3& min, const Vector3& max, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); void AddDebugBox(const BoundingOrientedBox& box, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); void AddDebugBox(const BoundingBox& box, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); - void AddDebugCone(const Vector3& center, const Quaternion& orient, float radius, float length, const Vector4& color, RendererDebugPage page, bool isWireframe); + void AddDebugCone(const Vector3& center, const Quaternion& orient, float radius, float length, const Vector4& color, RendererDebugPage page, bool isWireframe = true); void AddDebugCylinder(const Vector3& center, const Quaternion& orient, float radius, float length, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); void AddDebugSphere(const Vector3& center, float radius, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); void AddDebugSphere(const BoundingSphere& sphere, const Color& color, RendererDebugPage page = RendererDebugPage::None, bool isWireframe = true); diff --git a/TombEngine/Renderer/RendererDebug.cpp b/TombEngine/Renderer/RendererDebug.cpp index 89ce89d6e..b65d6d02c 100644 --- a/TombEngine/Renderer/RendererDebug.cpp +++ b/TombEngine/Renderer/RendererDebug.cpp @@ -35,26 +35,29 @@ namespace TEN::Renderer _numCheckPortalCalls = 0; _numGetVisibleRoomsCalls = 0; - _currentY; + _currentLineHeight; } - bool Renderer::PrintDebugMessage(int x, int y, int alpha, byte r, byte g, byte b, LPCSTR Message) + void Renderer::PrintDebugMessage(LPCSTR msg, va_list args) { - return true; - } + constexpr auto LINE_X_POS = DISPLAY_SPACE_RES.x / 100; + constexpr auto LINE_SPACING = DISPLAY_SPACE_RES.y / 30; + constexpr auto COLOR = Color(1.0f, 1.0f, 1.0f); + constexpr auto SCALE = 0.8f; - void Renderer::PrintDebugMessage(LPCSTR message, ...) - { char buffer[255]; ZeroMemory(buffer, 255); + _vsprintf_l(buffer, msg, nullptr, args); + AddString(buffer, Vector2(LINE_X_POS, _currentLineHeight), COLOR, SCALE, (int)PrintStringFlags::Outline); - va_list args; - va_start(args, message); - _vsprintf_l(buffer, message, NULL, args); + _currentLineHeight += LINE_SPACING; + } + + void Renderer::PrintDebugMessage(LPCSTR msg, ...) + { + auto args = va_list{}; + va_start(args, msg); + PrintDebugMessage(msg, args); va_end(args); - - AddString(10, _currentY, buffer, 0xFFFFFFFF, (int)PrintStringFlags::Outline); - - _currentY += 20; } } diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 573141b8c..6c9fc6307 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1236,11 +1236,8 @@ namespace TEN::Renderer AddDebugLine(origin2, target2, color); } - void Renderer::AddDebugBox(const std::array& corners, const Color& color, RendererDebugPage page, bool isWireframe) + void Renderer::AddDebugBox(const std::array& corners, const Color& color, RendererDebugPage page, bool isWireframe) { - constexpr auto LINE_COUNT = 12; - constexpr auto PLANE_COUNT = 6; - if (_isLocked) return; @@ -1250,7 +1247,7 @@ namespace TEN::Renderer // Construct box. if (isWireframe) { - for (int i = 0; i < LINE_COUNT; i++) + for (int i = 0; i < BOX_EDGE_COUNT; i++) { switch (i) { @@ -1297,7 +1294,7 @@ namespace TEN::Renderer } else { - for (int i = 0; i < PLANE_COUNT; i++) + for (int i = 0; i < BOX_FACE_COUNT; i++) { switch (i) { @@ -1349,15 +1346,13 @@ namespace TEN::Renderer void Renderer::AddDebugBox(const BoundingOrientedBox& box, const Color& color, RendererDebugPage page, bool isWireframe) { - constexpr auto CORNER_COUNT = 8; - if (_isLocked) return; if (!DebugMode || (_debugPage != page && page != RendererDebugPage::None)) return; - auto corners = std::array{}; + auto corners = std::array{}; box.GetCorners(corners.data()); AddDebugBox(corners, color, page, isWireframe); @@ -1365,15 +1360,13 @@ namespace TEN::Renderer void Renderer::AddDebugBox(const BoundingBox& box, const Color& color, RendererDebugPage page, bool isWireframe) { - constexpr auto CORNER_COUNT = 8; - if (_isLocked) return; if (!DebugMode || (_debugPage != page && page != RendererDebugPage::None)) return; - auto corners = std::array{}; + auto corners = std::array{}; box.GetCorners(corners.data()); AddDebugBox(corners, color, page, isWireframe); diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 4553f5630..fc66d93c3 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1125,186 +1125,181 @@ namespace TEN::Renderer void Renderer::DrawDebugInfo(RenderView& view) { - if (CurrentLevel != 0) + if (CurrentLevel == 0) + return; + + _currentLineHeight = DISPLAY_SPACE_RES.y / 30; + + const auto& room = g_Level.Rooms[LaraItem->RoomNumber]; + + float aspectRatio = _screenWidth / (float)_screenHeight; + int thumbWidth = _screenWidth / 6; + auto rect = RECT{}; + int thumbY = 0; + + switch (_debugPage) { - _currentY = 20; + case RendererDebugPage::None: + break; - ROOM_INFO* r = &g_Level.Rooms[LaraItem->RoomNumber]; - - float aspectRatio = _screenWidth / (float)_screenHeight; - int thumbWidth = _screenWidth / 6; - RECT rect; - int thumbY = 0; - - switch (_debugPage) - { - case RendererDebugPage::None: - break; - - case RendererDebugPage::RendererStats: - PrintDebugMessage("RENDERER STATS"); - PrintDebugMessage("FPS: %3.2f", _fps); - PrintDebugMessage("Resolution: %d x %d", _screenWidth, _screenHeight); - PrintDebugMessage("GPU: %s", g_Configuration.AdapterName.c_str()); - PrintDebugMessage("Update time: %d", _timeUpdate); - PrintDebugMessage("Frame time: %d", _timeFrame); - PrintDebugMessage("ControlPhase() time: %d", ControlPhaseTime); - PrintDebugMessage("Room collector time: %d", _timeRoomsCollector); - PrintDebugMessage("TOTAL Draw calls: %d", _numDrawCalls); - PrintDebugMessage(" Rooms: %d", _numRoomsDrawCalls); - PrintDebugMessage(" Movables: %d", _numMoveablesDrawCalls); - PrintDebugMessage(" Statics: %d", _numStaticsDrawCalls); - PrintDebugMessage(" Instanced Statics: %d", _numInstancedStaticsDrawCalls); - PrintDebugMessage(" Sprites: %d", _numSpritesDrawCalls); - PrintDebugMessage(" Instanced Sprites: %d", _numInstancedSpritesDrawCalls); - PrintDebugMessage("TOTAL Triangles: %d", _numTriangles); - PrintDebugMessage("Sprites: %d", view.SpritesToDraw.size()); - PrintDebugMessage("SORTED Draw calls: %d", (_numSortedRoomsDrawCalls + _numSortedMoveablesDrawCalls + _numSortedStaticsDrawCalls - + _numSortedSpritesDrawCalls)); - PrintDebugMessage(" Rooms: %d", _numSortedRoomsDrawCalls); - PrintDebugMessage(" Movables: %d", _numSortedMoveablesDrawCalls); - PrintDebugMessage(" Statics: %d", _numSortedStaticsDrawCalls); - PrintDebugMessage(" Sprites: %d", _numSortedSpritesDrawCalls); - PrintDebugMessage("SHADOW MAPS Draw calls: %d", _numShadowMapDrawCalls); - PrintDebugMessage("DEBRIS Draw calls: %d", _numDebrisDrawCalls); - PrintDebugMessage("Rooms: %d", view.RoomsToDraw.size()); - PrintDebugMessage(" CheckPortal() calls: %d", _numCheckPortalCalls); - PrintDebugMessage(" GetVisibleRooms() calls: %d", _numGetVisibleRoomsCalls); - PrintDebugMessage(" Dot products: %d", _numDotProducts); + case RendererDebugPage::RendererStats: + PrintDebugMessage("RENDERER STATS"); + PrintDebugMessage("FPS: %3.2f", _fps); + PrintDebugMessage("Resolution: %d x %d", _screenWidth, _screenHeight); + PrintDebugMessage("GPU: %s", g_Configuration.AdapterName.c_str()); + PrintDebugMessage("Update time: %d", _timeUpdate); + PrintDebugMessage("Frame time: %d", _timeFrame); + PrintDebugMessage("ControlPhase() time: %d", ControlPhaseTime); + PrintDebugMessage("Room collector time: %d", _timeRoomsCollector); + PrintDebugMessage("TOTAL draw calls: %d", _numDrawCalls); + PrintDebugMessage(" Rooms: %d", _numRoomsDrawCalls); + PrintDebugMessage(" Movables: %d", _numMoveablesDrawCalls); + PrintDebugMessage(" Statics: %d", _numStaticsDrawCalls); + PrintDebugMessage(" Instanced Statics: %d", _numInstancedStaticsDrawCalls); + PrintDebugMessage(" Sprites: %d", _numSpritesDrawCalls); + PrintDebugMessage(" Instanced Sprites: %d", _numInstancedSpritesDrawCalls); + PrintDebugMessage("TOTAL triangles: %d", _numTriangles); + PrintDebugMessage("Sprites: %d", view.SpritesToDraw.size()); + PrintDebugMessage("SORTED draw calls: %d", (_numSortedRoomsDrawCalls + _numSortedMoveablesDrawCalls + _numSortedStaticsDrawCalls + _numSortedSpritesDrawCalls)); + PrintDebugMessage(" Rooms: %d", _numSortedRoomsDrawCalls); + PrintDebugMessage(" Movables: %d", _numSortedMoveablesDrawCalls); + PrintDebugMessage(" Statics: %d", _numSortedStaticsDrawCalls); + PrintDebugMessage(" Sprites: %d", _numSortedSpritesDrawCalls); + PrintDebugMessage("SHADOW MAP draw calls: %d", _numShadowMapDrawCalls); + PrintDebugMessage("DEBRIS draw calls: %d", _numDebrisDrawCalls); + PrintDebugMessage("Rooms: %d", view.RoomsToDraw.size()); + PrintDebugMessage(" CheckPortal() calls: %d", _numCheckPortalCalls); + PrintDebugMessage(" GetVisibleRooms() calls: %d", _numGetVisibleRoomsCalls); + PrintDebugMessage(" Dot products: %d", _numDotProducts); - _spriteBatch->Begin(SpriteSortMode_Deferred, _renderStates->Opaque()); + _spriteBatch->Begin(SpriteSortMode_Deferred, _renderStates->Opaque()); - rect.left = _screenWidth - thumbWidth; - rect.top = thumbY; - rect.right = rect.left+ thumbWidth; - rect.bottom = rect.top+thumbWidth / aspectRatio; + rect.left = _screenWidth - thumbWidth; + rect.top = thumbY; + rect.right = rect.left+ thumbWidth; + rect.bottom = rect.top+thumbWidth / aspectRatio; - _spriteBatch->Draw(_normalsRenderTarget.ShaderResourceView.Get(), rect); - thumbY += thumbWidth / aspectRatio; + _spriteBatch->Draw(_normalsRenderTarget.ShaderResourceView.Get(), rect); + thumbY += thumbWidth / aspectRatio; - rect.left = _screenWidth - thumbWidth; - rect.top = thumbY; - rect.right = rect.left + thumbWidth; - rect.bottom = rect.top + thumbWidth / aspectRatio; - - //_spriteBatch->Draw(_depthRenderTarget.ShaderResourceView.Get(), rect); - //thumbY += thumbWidth / aspectRatio; + rect.left = _screenWidth - thumbWidth; + rect.top = thumbY; + rect.right = rect.left + thumbWidth; + rect.bottom = rect.top + thumbWidth / aspectRatio; - rect.left = _screenWidth - thumbWidth; - rect.top = thumbY; - rect.right = rect.left + thumbWidth; - rect.bottom = rect.top + thumbWidth / aspectRatio; + rect.left = _screenWidth - thumbWidth; + rect.top = thumbY; + rect.right = rect.left + thumbWidth; + rect.bottom = rect.top + thumbWidth / aspectRatio; - _spriteBatch->Draw(_SSAOBlurredRenderTarget.ShaderResourceView.Get(), rect); - thumbY += thumbWidth / aspectRatio; + _spriteBatch->Draw(_SSAOBlurredRenderTarget.ShaderResourceView.Get(), rect); + thumbY += thumbWidth / aspectRatio; - if (g_Configuration.AntialiasingMode > AntialiasingMode::Low) - { - rect.left = _screenWidth - thumbWidth; - rect.top = thumbY; - rect.right = rect.left + thumbWidth; - rect.bottom = rect.top + thumbWidth / aspectRatio; - - _spriteBatch->Draw(_SMAAEdgesRenderTarget.ShaderResourceView.Get(), rect); - thumbY += thumbWidth / aspectRatio; - - rect.left = _screenWidth - thumbWidth; - rect.top = thumbY; - rect.right = rect.left + thumbWidth; - rect.bottom = rect.top + thumbWidth / aspectRatio; - - _spriteBatch->Draw(_SMAABlendRenderTarget.ShaderResourceView.Get(), rect); - thumbY += thumbWidth / aspectRatio; - } - - _spriteBatch->End(); - - break; - - case RendererDebugPage::DimensionStats: - PrintDebugMessage("DIMENSION STATS"); - PrintDebugMessage("Pos: %d %d %d", LaraItem->Pose.Position.x, LaraItem->Pose.Position.y, LaraItem->Pose.Position.z); - PrintDebugMessage("Orient: %d %d %d", LaraItem->Pose.Orientation.x, LaraItem->Pose.Orientation.y, LaraItem->Pose.Orientation.z); - PrintDebugMessage("RoomNumber: %d", LaraItem->RoomNumber); - PrintDebugMessage("Room location: %d %d", LaraItem->Location.RoomNumber, LaraItem->Location.Height); - PrintDebugMessage("BoxNumber: %d", LaraItem->BoxNumber); - PrintDebugMessage("WaterSurfaceDist: %d", Lara.Context.WaterSurfaceDist); - PrintDebugMessage("Room: %d %d %d %d", r->x, r->z, r->x + r->xSize * BLOCK(1), r->z + r->zSize * BLOCK(1)); - PrintDebugMessage("Room.y, minFloor, maxCeiling: %d %d %d ", r->y, r->minfloor, r->maxceiling); - PrintDebugMessage("Camera.pos: %d %d %d", Camera.pos.x, Camera.pos.y, Camera.pos.z); - PrintDebugMessage("Camera.target: %d %d %d", Camera.target.x, Camera.target.y, Camera.target.z); - PrintDebugMessage("Camera.RoomNumber: %d", Camera.pos.RoomNumber); - break; - - case RendererDebugPage::PlayerStats: - PrintDebugMessage("PLAYER STATS"); - PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID); - PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber); - PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber); - PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState); - PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState); - PrintDebugMessage("Velocity: %.3f %.3f %.3f", LaraItem->Animation.Velocity.z, LaraItem->Animation.Velocity.y, LaraItem->Animation.Velocity.x); - PrintDebugMessage("IsAirborne: %d", LaraItem->Animation.IsAirborne); - PrintDebugMessage("HandStatus: %d", Lara.Control.HandStatus); - PrintDebugMessage("WaterStatus: %d", Lara.Control.WaterStatus); - PrintDebugMessage("CanClimbLadder: %d", Lara.Control.CanClimbLadder); - PrintDebugMessage("CanMonkeySwing: %d", Lara.Control.CanMonkeySwing); - PrintDebugMessage("Target HitPoints: %d", Lara.TargetEntity ? Lara.TargetEntity->HitPoints : 0); - break; - - case RendererDebugPage::InputStats: + if (g_Configuration.AntialiasingMode > AntialiasingMode::Low) { - auto clickedActions = BitField((int)In::Count); - auto heldActions = BitField((int)In::Count); - auto releasedActions = BitField((int)In::Count); + rect.left = _screenWidth - thumbWidth; + rect.top = thumbY; + rect.right = rect.left + thumbWidth; + rect.bottom = rect.top + thumbWidth / aspectRatio; - for (const auto& action : ActionMap) - { - if (action.IsClicked()) - clickedActions.Set((int)action.GetID()); + _spriteBatch->Draw(_SMAAEdgesRenderTarget.ShaderResourceView.Get(), rect); + thumbY += thumbWidth / aspectRatio; - if (action.IsHeld()) - heldActions.Set((int)action.GetID()); + rect.left = _screenWidth - thumbWidth; + rect.top = thumbY; + rect.right = rect.left + thumbWidth; + rect.bottom = rect.top + thumbWidth / aspectRatio; - if (action.IsReleased()) - releasedActions.Set((int)action.GetID()); - } - - PrintDebugMessage("INPUT STATS"); - PrintDebugMessage(("Clicked actions: " + clickedActions.ToString()).c_str()); - PrintDebugMessage(("Held actions: " + heldActions.ToString()).c_str()); - PrintDebugMessage(("Released actions: " + releasedActions.ToString()).c_str()); - PrintDebugMessage("Move axes: %.3f, %.3f", AxisMap[(int)InputAxis::Move].x, AxisMap[(int)InputAxis::Move].y); - PrintDebugMessage("Camera axes: %.3f, %.3f", AxisMap[(int)InputAxis::Camera].x, AxisMap[(int)InputAxis::Camera].y); - PrintDebugMessage("Mouse axes: %.3f, %.3f", AxisMap[(int)InputAxis::Mouse].x, AxisMap[(int)InputAxis::Mouse].y); - PrintDebugMessage("Cursor pos: %.3f, %.3f", GetMouse2DPosition().x, GetMouse2DPosition().y); + _spriteBatch->Draw(_SMAABlendRenderTarget.ShaderResourceView.Get(), rect); + thumbY += thumbWidth / aspectRatio; } - break; - case RendererDebugPage::CollisionStats: - PrintDebugMessage("COLLISION STATS"); - PrintDebugMessage("Collision type: %d", LaraCollision.CollisionType); - PrintDebugMessage("Bridge item ID: %d", LaraCollision.Middle.Bridge); - PrintDebugMessage("Front floor: %d", LaraCollision.Front.Floor); - PrintDebugMessage("Front left floor: %d", LaraCollision.FrontLeft.Floor); - PrintDebugMessage("Front right floor: %d", LaraCollision.FrontRight.Floor); - PrintDebugMessage("Front ceil: %d", LaraCollision.Front.Ceiling); - PrintDebugMessage("Front left ceil: %d", LaraCollision.FrontLeft.Ceiling); - PrintDebugMessage("Front right ceil: %d", LaraCollision.FrontRight.Ceiling); - break; - - case RendererDebugPage::PathfindingStats: - PrintDebugMessage("PATHFINDING STATS"); - PrintDebugMessage("BoxNumber: %d", LaraItem->BoxNumber); - break; - - case RendererDebugPage::WireframeMode: - PrintDebugMessage("WIREFRAME MODE"); - break; + _spriteBatch->End(); - default: - break; + break; + + case RendererDebugPage::DimensionStats: + PrintDebugMessage("DIMENSION STATS"); + PrintDebugMessage("Position: %d, %d, %d", LaraItem->Pose.Position.x, LaraItem->Pose.Position.y, LaraItem->Pose.Position.z); + PrintDebugMessage("Orientation: %d, %d, %d", LaraItem->Pose.Orientation.x, LaraItem->Pose.Orientation.y, LaraItem->Pose.Orientation.z); + PrintDebugMessage("RoomNumber: %d", LaraItem->RoomNumber); + PrintDebugMessage("PathfindingBoxID: %d", LaraItem->BoxNumber); + PrintDebugMessage("WaterSurfaceDist: %d", Lara.Context.WaterSurfaceDist); + PrintDebugMessage("Room Position: %d, %d, %d, %d", room.x, room.z, room.x + BLOCK(room.xSize), room.z + BLOCK(room.zSize)); + PrintDebugMessage("Room.y, minFloor, maxCeiling: %d, %d, %d ", room.y, room.minfloor, room.maxceiling); + PrintDebugMessage("Camera Position: %d, %d, %d", Camera.pos.x, Camera.pos.y, Camera.pos.z); + PrintDebugMessage("Camera LookAt: %d, %d, %d", Camera.target.x, Camera.target.y, Camera.target.z); + PrintDebugMessage("Camera RoomNumber: %d", Camera.pos.RoomNumber); + break; + + case RendererDebugPage::PlayerStats: + PrintDebugMessage("PLAYER STATS"); + PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID); + PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber); + PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber); + PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState); + PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState); + PrintDebugMessage("Velocity: %.3f, %.3f, %.3f", LaraItem->Animation.Velocity.z, LaraItem->Animation.Velocity.y, LaraItem->Animation.Velocity.x); + PrintDebugMessage("IsAirborne: %d", LaraItem->Animation.IsAirborne); + PrintDebugMessage("HandStatus: %d", Lara.Control.HandStatus); + PrintDebugMessage("WaterStatus: %d", Lara.Control.WaterStatus); + PrintDebugMessage("CanClimbLadder: %d", Lara.Control.CanClimbLadder); + PrintDebugMessage("CanMonkeySwing: %d", Lara.Control.CanMonkeySwing); + PrintDebugMessage("Target HitPoints: %d", Lara.TargetEntity ? Lara.TargetEntity->HitPoints : 0); + break; + + case RendererDebugPage::InputStats: + { + auto clickedActions = BitField((int)In::Count); + auto heldActions = BitField((int)In::Count); + auto releasedActions = BitField((int)In::Count); + + for (const auto& action : ActionMap) + { + if (action.IsClicked()) + clickedActions.Set((int)action.GetID()); + + if (action.IsHeld()) + heldActions.Set((int)action.GetID()); + + if (action.IsReleased()) + releasedActions.Set((int)action.GetID()); } + + PrintDebugMessage("INPUT STATS"); + PrintDebugMessage(("Clicked actions: " + clickedActions.ToString()).c_str()); + PrintDebugMessage(("Held actions: " + heldActions.ToString()).c_str()); + PrintDebugMessage(("Released actions: " + releasedActions.ToString()).c_str()); + PrintDebugMessage("Move axes: %.3f, %.3f", AxisMap[(int)InputAxis::Move].x, AxisMap[(int)InputAxis::Move].y); + PrintDebugMessage("Camera axes: %.3f, %.3f", AxisMap[(int)InputAxis::Camera].x, AxisMap[(int)InputAxis::Camera].y); + PrintDebugMessage("Mouse axes: %.3f, %.3f", AxisMap[(int)InputAxis::Mouse].x, AxisMap[(int)InputAxis::Mouse].y); + PrintDebugMessage("Cursor pos: %.3f, %.3f", GetMouse2DPosition().x, GetMouse2DPosition().y); + } + break; + + case RendererDebugPage::CollisionStats: + PrintDebugMessage("COLLISION STATS"); + PrintDebugMessage("Collision type: %d", LaraCollision.CollisionType); + PrintDebugMessage("Bridge item ID: %d", LaraCollision.Middle.Bridge); + PrintDebugMessage("Front floor: %d", LaraCollision.Front.Floor); + PrintDebugMessage("Front left floor: %d", LaraCollision.FrontLeft.Floor); + PrintDebugMessage("Front right floor: %d", LaraCollision.FrontRight.Floor); + PrintDebugMessage("Front ceil: %d", LaraCollision.Front.Ceiling); + PrintDebugMessage("Front left ceil: %d", LaraCollision.FrontLeft.Ceiling); + PrintDebugMessage("Front right ceil: %d", LaraCollision.FrontRight.Ceiling); + break; + + case RendererDebugPage::PathfindingStats: + PrintDebugMessage("PATHFINDING STATS"); + PrintDebugMessage("BoxNumber: %d", LaraItem->BoxNumber); + break; + + case RendererDebugPage::WireframeMode: + PrintDebugMessage("WIREFRAME MODE"); + break; + + default: + break; } } diff --git a/TombEngine/Renderer/RendererUtils.cpp b/TombEngine/Renderer/RendererUtils.cpp index de53f6f07..b6601bbe2 100644 --- a/TombEngine/Renderer/RendererUtils.cpp +++ b/TombEngine/Renderer/RendererUtils.cpp @@ -68,7 +68,7 @@ namespace TEN::Renderer::Utils ComPtr shader; throwIfFailed(device->CreateVertexShader(bytecode->GetBufferPointer(), bytecode->GetBufferSize(), nullptr, shader.GetAddressOf())); - if constexpr(DebugBuild) + if constexpr (DebugBuild) { char buffer[100]; unsigned int size = (unsigned int)std::wcstombs(buffer, fileName.c_str(), 100); diff --git a/TombEngine/Scripting/Internal/TEN/Util/LevelLog.h b/TombEngine/Scripting/Internal/TEN/Util/LevelLog.h index a87fd9351..554dde516 100644 --- a/TombEngine/Scripting/Internal/TEN/Util/LevelLog.h +++ b/TombEngine/Scripting/Internal/TEN/Util/LevelLog.h @@ -2,7 +2,7 @@ #include #include -#include "Game/debug/debug.h" +#include "Game/Debug/Debug.h" #include "Scripting/Internal/ReservedScriptNames.h" /*** diff --git a/TombEngine/Specific/Input/InputAction.cpp b/TombEngine/Specific/Input/InputAction.cpp index 6c62db8b7..b832bcac0 100644 --- a/TombEngine/Specific/Input/InputAction.cpp +++ b/TombEngine/Specific/Input/InputAction.cpp @@ -1,10 +1,8 @@ #include "framework.h" #include "Specific/Input/InputAction.h" -#include "Renderer/Renderer.h" #include "Specific/clock.h" -using TEN::Renderer::g_Renderer; namespace TEN::Input { @@ -126,17 +124,17 @@ namespace TEN::Input void InputAction::DrawDebug() const { - g_Renderer.PrintDebugMessage("ID: %d", (int)ID); - g_Renderer.PrintDebugMessage("IsClicked: %d", IsClicked()); - g_Renderer.PrintDebugMessage("IsHeld: %d", IsHeld()); - g_Renderer.PrintDebugMessage("IsPulsed (.2s, .6s): %d", IsPulsed(0.2f, 0.6f)); - g_Renderer.PrintDebugMessage("IsReleased: %d", IsReleased()); - g_Renderer.PrintDebugMessage(""); - g_Renderer.PrintDebugMessage("Value: %.3f", Value); - g_Renderer.PrintDebugMessage("PrevValue: %.3f", PrevValue); - g_Renderer.PrintDebugMessage("TimeActive: %.3f", TimeActive); - g_Renderer.PrintDebugMessage("PrevTimeActive: %.3f", PrevTimeActive); - g_Renderer.PrintDebugMessage("TimeInactive: %.3f", TimeInactive); + PrintDebugMessage("ID: %d", (int)ID); + PrintDebugMessage("IsClicked: %d", IsClicked()); + PrintDebugMessage("IsHeld: %d", IsHeld()); + PrintDebugMessage("IsPulsed (.2s, .6s): %d", IsPulsed(0.2f, 0.6f)); + PrintDebugMessage("IsReleased: %d", IsReleased()); + PrintDebugMessage(""); + PrintDebugMessage("Value: %.3f", Value); + PrintDebugMessage("PrevValue: %.3f", PrevValue); + PrintDebugMessage("TimeActive: %.3f", TimeActive); + PrintDebugMessage("PrevTimeActive: %.3f", PrevTimeActive); + PrintDebugMessage("TimeInactive: %.3f", TimeInactive); } void InputAction::UpdateValue(float value) diff --git a/TombEngine/framework.h b/TombEngine/framework.h index 46ce3d07a..6740dadd0 100644 --- a/TombEngine/framework.h +++ b/TombEngine/framework.h @@ -18,11 +18,11 @@ #include #include -#include "Game/debug/debug.h" - using namespace DirectX; using namespace DirectX::SimpleMath; +#include "Game/Debug/Debug.h" + using namespace TEN::Debug; constexpr auto NO_VALUE = -1; From 8aae53c2c2d2c69462c169225d3993540db6f305 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 30 Jun 2024 23:25:00 +1000 Subject: [PATCH 224/410] New animation sound conditions (#1284) * Base for new sound conditions * Read flags * Refine anim sound effect handling * Add swamp check for DryLand anim sound effect * Update local variable names * Use proper math functions * Update animation.cpp * Address PR notes * Syntax --------- Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> --- TombEngine/Game/Lara/lara_flare.cpp | 2 +- TombEngine/Game/Lara/lara_helpers.cpp | 4 +- TombEngine/Game/Lara/lara_one_gun.cpp | 2 +- TombEngine/Game/animation.cpp | 112 +++++++++++------ TombEngine/Game/missile.cpp | 2 +- TombEngine/Sound/sound.cpp | 167 ++++++++++++++------------ TombEngine/Sound/sound.h | 26 ++-- 7 files changed, 186 insertions(+), 129 deletions(-) diff --git a/TombEngine/Game/Lara/lara_flare.cpp b/TombEngine/Game/Lara/lara_flare.cpp index 2cab1151e..0cae11806 100644 --- a/TombEngine/Game/Lara/lara_flare.cpp +++ b/TombEngine/Game/Lara/lara_flare.cpp @@ -260,7 +260,7 @@ void DrawFlare(ItemInfo& laraItem) SoundEffect( SFX_TR4_FLARE_IGNITE_DRY, &laraItem.Pose, - TestEnvironment(ENV_FLAG_WATER, &laraItem) ? SoundEnvironment::Water : SoundEnvironment::Land); + TestEnvironment(ENV_FLAG_WATER, &laraItem) ? SoundEnvironment::ShallowWater : SoundEnvironment::Land); } DoFlareInHand(laraItem, player.Flare.Life); diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index c2b60dd45..b706b2b20 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -990,7 +990,7 @@ void HandlePlayerAirBubbles(ItemInfo* item) { constexpr auto BUBBLE_COUNT_MAX = 3; - SoundEffect(SFX_TR4_LARA_BUBBLES, &item->Pose, SoundEnvironment::Water); + SoundEffect(SFX_TR4_LARA_BUBBLES, &item->Pose, SoundEnvironment::ShallowWater); const auto& level = *g_GameFlow->GetLevel(CurrentLevel); @@ -1465,7 +1465,7 @@ void UpdateLaraSubsuitAngles(ItemInfo* item) auto mul1 = (float)abs(lara->Control.Subsuit.Velocity[0]) / BLOCK(8); auto mul2 = (float)abs(lara->Control.Subsuit.Velocity[1]) / BLOCK(8); auto vol = ((mul1 + mul2) * 5.0f) + 0.5f; - SoundEffect(SFX_TR5_VEHICLE_DIVESUIT_ENGINE, &item->Pose, SoundEnvironment::Water, 1.0f + (mul1 + mul2), vol); + SoundEffect(SFX_TR5_VEHICLE_DIVESUIT_ENGINE, &item->Pose, SoundEnvironment::ShallowWater, 1.0f + (mul1 + mul2), vol); } } diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp index 41f841d9b..4270b6c9b 100644 --- a/TombEngine/Game/Lara/lara_one_gun.cpp +++ b/TombEngine/Game/Lara/lara_one_gun.cpp @@ -428,7 +428,7 @@ void FireShotgun(ItemInfo& laraItem) player.RightArm.GunFlash = Weapons[(int)LaraWeaponType::Shotgun].FlashTime; - SoundEffect(SFX_TR4_EXPLOSION1, &laraItem.Pose, TestEnvironment(ENV_FLAG_WATER, &laraItem) ? SoundEnvironment::Water : SoundEnvironment::Land); + SoundEffect(SFX_TR4_EXPLOSION1, &laraItem.Pose, TestEnvironment(ENV_FLAG_WATER, &laraItem) ? SoundEnvironment::ShallowWater : SoundEnvironment::Land); SoundEffect(Weapons[(int)LaraWeaponType::Shotgun].SampleNum, &laraItem.Pose); Rumble(0.5f, 0.2f); diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index d4f5cd6d1..c245ad097 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -3,6 +3,7 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/flipeffect.h" #include "Game/items.h" @@ -15,6 +16,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Point; using namespace TEN::Entities::Generic; using namespace TEN::Math; using TEN::Renderer::g_Renderer; @@ -110,49 +112,87 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased) break; case AnimCommandType::SoundEffect: - if (isFrameBased && item.Animation.FrameNumber == commandDataPtr[0]) + { + int frameNumber = commandDataPtr[0]; + if (isFrameBased && item.Animation.FrameNumber == frameNumber) { - if (!Objects[item.ObjectNumber].waterCreature) - { - bool playInWater = (commandDataPtr[1] & 0x8000) != 0; - bool playOnLand = (commandDataPtr[1] & 0x4000) != 0; - bool playAlways = (playInWater && playOnLand) || (!playInWater && !playOnLand); + // Get sound ID and sound environment flag from packed data. + int soundID = commandDataPtr[1] & 0xFFF; // Exclude last 4 bits for sound ID. + int soundEnvFlag = commandDataPtr[1] & 0xF000; // Keep only last 4 bits for sound environment flag. - if (item.IsLara()) - { - auto& player = GetLaraInfo(item); - - if (playAlways || - (playOnLand && (player.Context.WaterSurfaceDist >= -SHALLOW_WATER_DEPTH || player.Context.WaterSurfaceDist == NO_HEIGHT)) || - (playInWater && player.Context.WaterSurfaceDist < -SHALLOW_WATER_DEPTH && player.Context.WaterSurfaceDist != NO_HEIGHT && !TestEnvironment(ENV_FLAG_SWAMP, &item))) - { - SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, SoundEnvironment::Always); - } - } - else - { - if (item.RoomNumber == NO_VALUE) - { - SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, SoundEnvironment::Always); - } - else if (TestEnvironment(ENV_FLAG_WATER, &item)) - { - if (playAlways || (playInWater && TestEnvironment(ENV_FLAG_WATER, Camera.pos.RoomNumber))) - SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, SoundEnvironment::Always); - } - else if (playAlways || (playOnLand && !TestEnvironment(ENV_FLAG_WATER, Camera.pos.RoomNumber) && !TestEnvironment(ENV_FLAG_SWAMP, Camera.pos.RoomNumber))) - { - SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, SoundEnvironment::Always); - } - } - } - else + // Get required sound environment from flag. + auto requiredSoundEnv = SoundEnvironment::Always; + switch (soundEnvFlag) { - SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, TestEnvironment(ENV_FLAG_WATER, &item) ? SoundEnvironment::Water : SoundEnvironment::Land); + default: + case 0: + requiredSoundEnv = SoundEnvironment::Always; + break; + + case (1 << 14): + requiredSoundEnv = SoundEnvironment::Land; + break; + + case (1 << 15): + requiredSoundEnv = SoundEnvironment::ShallowWater; + break; + + case (1 << 12): + requiredSoundEnv = SoundEnvironment::Swamp; + break; + + case (1 << 13): + requiredSoundEnv = SoundEnvironment::Underwater; + break; } + + int roomNumberAtPos = GetPointCollision(item).GetRoomNumber(); + bool isWater = TestEnvironment(ENV_FLAG_WATER, roomNumberAtPos); + bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, roomNumberAtPos); + + // Get sound environment for sound effect. + auto soundEnv = std::optional(); + switch (requiredSoundEnv) + { + case SoundEnvironment::Always: + soundEnv = SoundEnvironment::Always; + break; + + case SoundEnvironment::Land: + if (!isWater && !isSwamp) + soundEnv = SoundEnvironment::Land; + + break; + + case SoundEnvironment::ShallowWater: + if (isWater) + { + // HACK: Must update assets before removing this exception for water creatures. + const auto& object = Objects[item.ObjectNumber]; + soundEnv = object.waterCreature ? SoundEnvironment::Underwater : SoundEnvironment::ShallowWater; + } + + break; + + case SoundEnvironment::Swamp: + if (isSwamp) + soundEnv = SoundEnvironment::Swamp; + + break; + + case SoundEnvironment::Underwater: + if (isWater) + soundEnv = SoundEnvironment::Underwater; + + break; + } + + if (soundEnv.has_value()) + SoundEffect(soundID, &item.Pose, *soundEnv); } commandDataPtr += 2; + } break; case AnimCommandType::Flipeffect: diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index 29739935a..2dba2b650 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -50,7 +50,7 @@ void ControlMissile(short fxNumber) auto& fx = EffectList[fxNumber]; auto isUnderwater = TestEnvironment(ENV_FLAG_WATER, fx.roomNumber); - auto soundFXType = isUnderwater ? SoundEnvironment::Water : SoundEnvironment::Land; + auto soundFXType = isUnderwater ? SoundEnvironment::ShallowWater : SoundEnvironment::Land; if (fx.objectNumber == ID_SCUBA_HARPOON && isUnderwater && fx.pos.Orientation.x > ANGLE(-67.5f)) diff --git a/TombEngine/Sound/sound.cpp b/TombEngine/Sound/sound.cpp index 7580fe325..fdd831cbc 100644 --- a/TombEngine/Sound/sound.cpp +++ b/TombEngine/Sound/sound.cpp @@ -11,12 +11,21 @@ #include "Game/Lara/lara.h" #include "Game/room.h" #include "Game/Setup.h" +#include "Math/Math.h" #include "Specific/configuration.h" #include "Specific/level.h" #include "Specific/trutils.h" #include "Specific/winmain.h" using namespace TEN::Gui; +using namespace TEN::Math; + +enum SoundSourceFlags +{ + SS_FLAG_PLAY_FLIP_ROOM = 1 << 13, + SS_FLAG_PLAY_BASE_ROOM = 1 << 14, + SS_FLAG_PLAY_ALWAYS = 1 << 15 +}; HSAMPLE BASS_SamplePointer[SOUND_MAX_SAMPLES]; HSTREAM BASS_3D_Mixdown; @@ -150,44 +159,46 @@ bool LoadSample(char* pointer, int compSize, int uncompSize, int index) return true; } -bool SoundEffect(int effectID, Pose* position, SoundEnvironment condition, float pitchMultiplier, float gainMultiplier) +// TODO: Use std::optional for pose argument. +bool SoundEffect(int soundID, Pose* pose, SoundEnvironment soundEnv, float pitchMult, float gainMult) { if (!g_Configuration.EnableSound) return false; - if (effectID >= g_Level.SoundMap.size()) + if (soundID >= g_Level.SoundMap.size()) return false; if (BASS_GetDevice() == -1) return false; - if (condition != SoundEnvironment::Always) + // Test if sound effect environment matches camera environment. + if (soundEnv != SoundEnvironment::Always) { - // Get current camera room's environment - auto cameraCondition = TestEnvironment(ENV_FLAG_WATER, Camera.pos.RoomNumber) ? SoundEnvironment::Water : SoundEnvironment::Land; - - // Don't play effect if effect's environment isn't the same as camera position's environment - if (condition != cameraCondition) + bool isCameraUnderwater = TestEnvironment(ENV_FLAG_WATER, Camera.pos.RoomNumber); + if ((soundEnv == SoundEnvironment::Underwater && !isCameraUnderwater) || + (soundEnv != SoundEnvironment::Underwater && isCameraUnderwater)) + { return false; + } } - // Get actual sample index from SoundMap - int sampleIndex = g_Level.SoundMap[effectID]; + // Get actual sample index from sound map. + int sampleIndex = g_Level.SoundMap[soundID]; - // -1 means no such effect exists in level file. - // We set it to -2 afterwards to prevent further debug message firings. + // -1 means no such effect exists in level file.Set to -2 afterwards to prevent further debug message firings. if (sampleIndex == -1) { - TENLog("Missing sound effect: " + std::to_string(effectID), LogLevel::Warning); - g_Level.SoundMap[effectID] = -2; + TENLog("Missing sound effect " + std::to_string(soundID), LogLevel::Warning); + g_Level.SoundMap[soundID] = -2; return false; } else if (sampleIndex == -2) + { return false; + } - SampleInfo* sampleInfo = &g_Level.SoundDetails[sampleIndex]; - - if (sampleInfo->Number < 0) + const auto& sample = g_Level.SoundDetails[sampleIndex]; + if (sample.Number < 0) { TENLog("No valid samples count for effect " + std::to_string(sampleIndex), LogLevel::Warning); return false; @@ -196,77 +207,85 @@ bool SoundEffect(int effectID, Pose* position, SoundEnvironment condition, float // Assign common sample flags. DWORD sampleFlags = SOUND_SAMPLE_FLAGS; - // Effect's chance to play. - if ((sampleInfo->Randomness) && ((GetRandomControl() & UCHAR_MAX) > sampleInfo->Randomness)) + // Test play chance. + if (sample.Randomness && ((GetRandomControl() & UCHAR_MAX) > sample.Randomness)) return false; - // Apply 3D attrib only to sound with position property - if (position) + // Apply 3D attribute only to sound with position property. + if (pose != nullptr) sampleFlags |= BASS_SAMPLE_3D; - // Set & randomize volume (if needed) - float gain = (static_cast(sampleInfo->Volume) / UCHAR_MAX) * std::clamp(gainMultiplier, SOUND_MIN_PARAM_MULTIPLIER, SOUND_MAX_PARAM_MULTIPLIER); - if ((sampleInfo->Flags & SOUND_FLAG_RND_GAIN)) - gain -= (static_cast(GetRandomControl()) / static_cast(RAND_MAX))* SOUND_MAX_GAIN_CHANGE; + // Set and randomize volume (if needed). + float gain = ((float)sample.Volume / UCHAR_MAX) * std::clamp(gainMult, SOUND_MIN_PARAM_MULTIPLIER, SOUND_MAX_PARAM_MULTIPLIER); + if ((sample.Flags & SOUND_FLAG_RND_GAIN)) + gain -= Random::GenerateFloat(0.0f, 1.0f) * SOUND_MAX_GAIN_CHANGE; - // Set and randomize pitch and additionally multiply by provided value (for vehicles etc) - float pitch = (1.0f + static_cast(sampleInfo->Pitch) / 127.0f) * std::clamp(pitchMultiplier, SOUND_MIN_PARAM_MULTIPLIER, SOUND_MAX_PARAM_MULTIPLIER); + // Set and randomize pitch and additionally multiply by provided value (e.g. for vehicles). + float pitch = (1.0f + ((float)sample.Pitch / 127.0f)) * std::clamp(pitchMult, SOUND_MIN_PARAM_MULTIPLIER, SOUND_MAX_PARAM_MULTIPLIER); // Randomize pitch (if needed) - if ((sampleInfo->Flags & SOUND_FLAG_RND_PITCH)) - pitch += ((static_cast(GetRandomControl()) / static_cast(RAND_MAX)) - 0.5f) * SOUND_MAX_PITCH_CHANGE * 2.0f; + if ((sample.Flags & SOUND_FLAG_RND_PITCH)) + pitch += Random::GenerateFloat(-0.5f, 0.5f) * (SOUND_MAX_PITCH_CHANGE * 2); - // Calculate sound radius and distance to sound - float radius = (float)(sampleInfo->Radius) * BLOCK(1); - float distance = Sound_DistanceToListener(position); + // Calculate sound radius and distance to sound. + float radius = BLOCK(sample.Radius); + float dist = Sound_DistanceToListener(pose); - // Don't play sound if it's too far from listener's position. - if (distance > radius) + // Skip playing if too far from listener position. + if (dist > radius) return false; - // Get final volume of a sound. - float volume = Sound_Attenuate(gain, distance, radius); + // Get final sound volume. + float volume = Sound_Attenuate(gain, dist, radius); - // Get existing index, if any, of sound which is playing. - int existingChannel = Sound_EffectIsPlaying(effectID, position); + // Get existing index, if any, of playing sound. + int existingChannel = Sound_EffectIsPlaying(soundID, pose); - // Select behaviour based on effect playback type (bytes 0-1 of flags field) - auto playType = (SoundPlayMode)(sampleInfo->Flags & 3); - switch (playType) + // Select behaviour based on effect playback type (bytes 0-1 of flags field). + auto playMode = (SoundPlayMode)(sample.Flags & 3); + switch (playMode) { case SoundPlayMode::Normal: break; case SoundPlayMode::Wait: - if (existingChannel != SOUND_NO_CHANNEL) // Don't play until stopped + // Don't play until stopped. + if (existingChannel != SOUND_NO_CHANNEL) return false; break; case SoundPlayMode::Restart: - if (existingChannel != SOUND_NO_CHANNEL) // Stop existing and continue + // Stop existing and continue. + if (existingChannel != SOUND_NO_CHANNEL) Sound_FreeSlot(existingChannel, SOUND_XFADETIME_CUTSOUND); break; case SoundPlayMode::Looped: - if (existingChannel != SOUND_NO_CHANNEL) // Just update parameters and return, if already playing + // Update parameters and return if already playing. + if (existingChannel != SOUND_NO_CHANNEL) { - Sound_UpdateEffectPosition(existingChannel, position); + Sound_UpdateEffectPosition(existingChannel, pose); Sound_UpdateEffectAttributes(existingChannel, pitch, volume); return false; } + sampleFlags |= BASS_SAMPLE_LOOP; break; } - // Randomly select arbitrary sample from the list, if more than one is present + // Randomly select arbitrary sample from list if more than one is present. int sampleToPlay = 0; - int numSamples = (sampleInfo->Flags >> 2) & 15; - if (numSamples == 1) - sampleToPlay = sampleInfo->Number; + int sampleCount = (sample.Flags >> 2) & 15; + if (sampleCount == 1) + { + sampleToPlay = sample.Number; + } else - sampleToPlay = sampleInfo->Number + (int)((GetRandomControl() * numSamples) >> 15); + { + sampleToPlay = sample.Number + (int)((GetRandomControl() * sampleCount) >> 15); + } - // Get free channel to play sample + // Get free channel to play sample. int freeSlot = Sound_GetFreeSlot(); if (freeSlot == SOUND_NO_CHANNEL) { @@ -280,32 +299,33 @@ bool SoundEffect(int effectID, Pose* position, SoundEnvironment condition, float if (Sound_CheckBASSError("Trying to create channel for sample %d", false, sampleToPlay)) return false; - // Finally ready to play sound, assign it to sound slot. - SoundSlot[freeSlot].State = SoundState::Idle; - SoundSlot[freeSlot].EffectID = effectID; - SoundSlot[freeSlot].Channel = channel; - SoundSlot[freeSlot].Gain = gain; - SoundSlot[freeSlot].Origin = position ? Vector3(position->Position.x, position->Position.y, position->Position.z) : SOUND_OMNIPRESENT_ORIGIN; + // Ready to play sound; assign to sound slot. + auto& soundSlot = SoundSlot[freeSlot]; + soundSlot.State = SoundState::Idle; + soundSlot.EffectID = soundID; + soundSlot.Channel = channel; + soundSlot.Gain = gain; + soundSlot.Origin = (pose != nullptr) ? pose->Position.ToVector3() : SOUND_OMNIPRESENT_ORIGIN; if (Sound_CheckBASSError("Applying pitch/gain attribs on channel %x, sample %d", false, channel, sampleToPlay)) return false; - // Set looped flag, if necessary - if (playType == SoundPlayMode::Looped) + // Set looped flag if necessary. + if (playMode == SoundPlayMode::Looped) BASS_ChannelFlags(channel, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP); - // Play channel + // Play channel. BASS_ChannelPlay(channel, false); if (Sound_CheckBASSError("Queuing channel %x on sample mixer", false, freeSlot)) return false; - // Set attributes - BASS_ChannelSet3DAttributes(channel, position ? BASS_3DMODE_NORMAL : BASS_3DMODE_OFF, SOUND_MAXVOL_RADIUS, radius, 360, 360, 0.0f); - Sound_UpdateEffectPosition(freeSlot, position, true); + // Set attributes. + BASS_ChannelSet3DAttributes(channel, pose ? BASS_3DMODE_NORMAL : BASS_3DMODE_OFF, SOUND_MAXVOL_RADIUS, radius, 360, 360, 0.0f); + Sound_UpdateEffectPosition(freeSlot, pose, true); Sound_UpdateEffectAttributes(freeSlot, pitch, volume); - if (Sound_CheckBASSError("Applying 3D attribs on channel %x, sound %d", false, channel, effectID)) + if (Sound_CheckBASSError("Applying 3D attribs on channel %x, sound %d", false, channel, soundID)) return false; return true; @@ -1070,24 +1090,19 @@ int GetShatterSound(int shatterID) void PlaySoundSources() { - static constexpr int PLAY_ALWAYS = 0x8000; - static constexpr int PLAY_BASE_ROOM = 0x4000; - static constexpr int PLAY_FLIP_ROOM = 0x2000; - - for (size_t i = 0; i < g_Level.SoundSources.size(); i++) + for (const auto& soundSource : g_Level.SoundSources) { - const auto& sound = g_Level.SoundSources[i]; - - int group = sound.Flags & 0x1FFF; + int group = soundSource.Flags & 0x1FFF; if (group >= MAX_FLIPMAP) continue; - if (!FlipStats[group] && (sound.Flags & PLAY_FLIP_ROOM)) - continue; - else if (FlipStats[group] && (sound.Flags & PLAY_BASE_ROOM)) + if ((!FlipStats[group] && (soundSource.Flags & SS_FLAG_PLAY_FLIP_ROOM)) || + (FlipStats[group] && (soundSource.Flags & SS_FLAG_PLAY_BASE_ROOM))) + { continue; + } - SoundEffect(sound.SoundID, (Pose*)&sound.Position); + SoundEffect(soundSource.SoundID, (Pose*)&soundSource.Position); } } diff --git a/TombEngine/Sound/sound.h b/TombEngine/Sound/sound.h index 8b70f7ea2..eb18997e9 100644 --- a/TombEngine/Sound/sound.h +++ b/TombEngine/Sound/sound.h @@ -48,9 +48,11 @@ enum class SoundTrackType enum class SoundEnvironment { + Always, Land, - Water, - Always + ShallowWater, + Swamp, + Underwater }; enum class SoundPlayMode @@ -121,9 +123,9 @@ struct SoundTrackInfo struct SoundSourceInfo { Vector3i Position = Vector3i::Zero; - int SoundID = 0; - int Flags = 0; - std::string Name {}; + int SoundID = 0; + int Flags = 0; + std::string Name = {}; SoundSourceInfo() { @@ -131,27 +133,27 @@ struct SoundSourceInfo SoundSourceInfo(int xPos, int yPos, int zPos) { - this->Position = Vector3i(xPos, yPos, zPos); + Position = Vector3i(xPos, yPos, zPos); } SoundSourceInfo(int xPos, int yPos, int zPos, short soundID) { - this->Position = Vector3i(xPos, yPos, zPos); - this->SoundID = soundID; + Position = Vector3i(xPos, yPos, zPos); + SoundID = soundID; } SoundSourceInfo(int xPos, int yPos, int zPos, short soundID, short newflags) { - this->Position = Vector3i(xPos, yPos, zPos); - this->SoundID = soundID; - this->Flags = newflags; + Position = Vector3i(xPos, yPos, zPos); + SoundID = soundID; + Flags = newflags; } }; extern std::map SoundTrackMap; extern std::unordered_map SoundTracks; -bool SoundEffect(int effectID, Pose* position, SoundEnvironment condition = SoundEnvironment::Land, float pitchMultiplier = 1.0f, float gainMultiplier = 1.0f); +bool SoundEffect(int soundID, Pose* pose, SoundEnvironment soundEnv = SoundEnvironment::Land, float pitchMult = 1.0f, float gainMult = 1.0f); void StopSoundEffect(short effectID); bool LoadSample(char *buffer, int compSize, int uncompSize, int currentIndex); void FreeSamples(); From 485e384286c75e2c5d3db57ede64a7c2724a4c80 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 30 Jun 2024 23:36:27 +1000 Subject: [PATCH 225/410] Additionally play underwater sound effects in quicksand --- TombEngine/Game/animation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index c245ad097..0771e965a 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -181,7 +181,7 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased) break; case SoundEnvironment::Underwater: - if (isWater) + if (isWater || isSwamp) soundEnv = SoundEnvironment::Underwater; break; From 438ed01b4f7615dc06a2af3c08602ecca8ac5f5b Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Sun, 30 Jun 2024 14:37:37 +0100 Subject: [PATCH 226/410] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5460278fc..104fd7967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,10 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Enhaced Rolling Spindle detection to avoid them going down through pits. * Enhaced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) * Enhaced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). +* Add new sound conditions: Swamp, and Underwater. + - Swamp - sound plays in swamp/quicksand. + - Underwater - sound plays when camera is submerged. +* Change Land and water sound condition to DryLand and WetLand ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. From 9ca606c64eb3e4a463f3444dcaa3545ce3485627 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Sun, 30 Jun 2024 14:41:56 +0100 Subject: [PATCH 227/410] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 104fd7967..3880af53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,10 +32,10 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Enhaced Rolling Spindle detection to avoid them going down through pits. * Enhaced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) * Enhaced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). -* Add new sound conditions: Swamp, and Underwater. - - Swamp - sound plays in swamp/quicksand. - - Underwater - sound plays when camera is submerged. -* Change Land and water sound condition to DryLand and WetLand +* Add new sound conditions: quicksand and Underwater. + - Quicksand - sound effect plays when a moveable is in quicksand. + - Underwater - sound plays when the camera is submerged. +* Changed Water sound condition to ShallowWater. ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. From acab96493038c7cd3c39247a67af170a0ec58733 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 2 Jul 2024 01:01:45 +1000 Subject: [PATCH 228/410] Update interpolkation functions --- TombEngine/Game/effects/Streamer.cpp | 4 +- TombEngine/Math/Utils.cpp | 67 +++++++++++++++------------- TombEngine/Math/Utils.h | 10 +++-- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/TombEngine/Game/effects/Streamer.cpp b/TombEngine/Game/effects/Streamer.cpp index ae9f8ed55..3d3cd2d27 100644 --- a/TombEngine/Game/effects/Streamer.cpp +++ b/TombEngine/Game/effects/Streamer.cpp @@ -23,7 +23,7 @@ namespace TEN::Effects::Streamer { // Update opacity. if (Color.w > 0.0f) - Color.w = InterpolateCos(0.0f, OpacityMax, Life / LifeMax); + Color.w = EaseInOutSine(0.0f, OpacityMax, Life / LifeMax); // TODO: Not working. // Update orientation. @@ -66,7 +66,7 @@ namespace TEN::Effects::Streamer float lifeMax = std::min(round(life * FPS), (float)SEGMENT_COUNT_MAX); float alpha = (segmentCount / lifeMax) * FADE_IN_COEFF; - float opacityMax = InterpolateCos(0.0f, color.w, alpha); + float opacityMax = EaseInOutSine(0.0f, color.w, alpha); segment.Orientation = AxisAngle(dir, orient); segment.Color = Vector4(color.x, color.y, color.z, opacityMax); diff --git a/TombEngine/Math/Utils.cpp b/TombEngine/Math/Utils.cpp index eb5245f02..bbc7c8800 100644 --- a/TombEngine/Math/Utils.cpp +++ b/TombEngine/Math/Utils.cpp @@ -11,25 +11,6 @@ namespace TEN::Math return (((1.0f - alpha) * value0) + (alpha * value1)); } - float InterpolateCos(float value0, float value1, float alpha) - { - alpha = std::clamp(alpha, 0.0f, 1.0f); - return Lerp(value0, value1, (1 - cos(alpha * PI)) * 0.5f); - } - - float InterpolateCubic(float value0, float value1, float value2, float value3, float alpha) - { - alpha = std::clamp(alpha, 0.0f, 1.0f); - - float p = (value3 - value2) - (value0 - value1); - float q = (value0 - value1) - p; - float r = value2 - value0; - float s = value1; - float x = alpha; - float xSquared = SQUARE(x); - return ((p * xSquared * x) + (q * xSquared) + (r * x) + s); - } - float Smoothstep(float alpha) { return Smoothstep(0.0f, 1.0f, alpha); @@ -39,21 +20,47 @@ namespace TEN::Math { alpha = std::clamp(alpha, value0, value1); - // Don't process if input value is same as one of the values. - if (alpha == value0) - { - return value0; - } - else if (alpha == value1) - { - return value1; - } - // Scale, bias, and saturate alpha to [0, 1] range. alpha = std::clamp((alpha - value0) / (value1 - value0), 0.0f, 1.0f); // Evaluate polynomial. - return (CUBE(alpha) * (alpha * (alpha * 6 - 15) + 10)); + return (CUBE(alpha) * (alpha * ((alpha * 6) - 15) + 10)); + } + + float EaseInSine(float value0, float value1, float alpha) + { + alpha = std::clamp(alpha, 0.0f, 1.0f); + alpha = 1.0f - cos((alpha * PI) / 2); + return value0 + (value1 - value0) * alpha; + } + + float EaseInSine(float alpha) + { + return EaseInSine(0.0f, 1.0f, alpha); + } + + float EaseOutSine(float value0, float value1, float alpha) + { + alpha = std::clamp(alpha, 0.0f, 1.0f); + alpha = sin((alpha * PI) / 2); + return (value0 + (value1 - value0) * alpha); + } + + float EaseOutSine(float alpha) + { + return EaseOutSine(0.0f, 1.0f, alpha); + } + + float EaseInOutSine(float value0, float value1, float alpha) + { + alpha = std::clamp(alpha, 0.0f, 1.0f); + alpha = (1 - cos(alpha * PI)) / 2; + return Lerp(value0, value1, alpha); + } + + float EaseInOutSine(float alpha) + { + return EaseInOutSine(0.0f, 1.0f, alpha); } float Luma(const Vector3& color) diff --git a/TombEngine/Math/Utils.h b/TombEngine/Math/Utils.h index abaf295b4..ad349a71c 100644 --- a/TombEngine/Math/Utils.h +++ b/TombEngine/Math/Utils.h @@ -8,10 +8,14 @@ namespace TEN::Math // Interpolation float Lerp(float value0, float value1, float alpha); - float InterpolateCos(float value0, float value1, float alpha); - float InterpolateCubic(float value0, float value1, float value2, float value3, float alpha); - float Smoothstep(float alpha); float Smoothstep(float value0, float value1, float alpha); + float Smoothstep(float alpha); + float EaseInSine(float value0, float value1, float alpha); + float EaseInSine(float alpha); + float EaseOutSine(float value0, float value1, float alpha); + float EaseOutSine(float alpha); + float EaseInOutSine(float value0, float value1, float alpha); + float EaseInOutSine(float alpha); // Color From a492710f93832036628a819aa453a885bf2b8116 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 2 Jul 2024 01:05:28 +1000 Subject: [PATCH 229/410] Update Utils.cpp --- TombEngine/Math/Utils.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/TombEngine/Math/Utils.cpp b/TombEngine/Math/Utils.cpp index bbc7c8800..f6d6bc8d4 100644 --- a/TombEngine/Math/Utils.cpp +++ b/TombEngine/Math/Utils.cpp @@ -30,8 +30,7 @@ namespace TEN::Math float EaseInSine(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); - alpha = 1.0f - cos((alpha * PI) / 2); - return value0 + (value1 - value0) * alpha; + return Lerp(value0, value1, 1 - cos((alpha * PI) / 2)); } float EaseInSine(float alpha) @@ -42,8 +41,7 @@ namespace TEN::Math float EaseOutSine(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); - alpha = sin((alpha * PI) / 2); - return (value0 + (value1 - value0) * alpha); + return Lerp(value0, value1, sin((alpha * PI) / 2)); } float EaseOutSine(float alpha) @@ -54,8 +52,7 @@ namespace TEN::Math float EaseInOutSine(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); - alpha = (1 - cos(alpha * PI)) / 2; - return Lerp(value0, value1, alpha); + return Lerp(value0, value1, (1 - cos(alpha * PI)) / 2); } float EaseInOutSine(float alpha) From ef16d244506c1599dbc7f40413e4eced3d4bf77e Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 2 Jul 2024 01:21:36 +1000 Subject: [PATCH 230/410] Update PushableStates.cpp --- .../Generic/Object/Pushable/PushableStates.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp index 3fe03da99..14afb8e0a 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableStates.cpp @@ -367,6 +367,20 @@ namespace TEN::Entities::Generic } } + // TODO: Remove. + static float InterpolateCubic(float value0, float value1, float value2, float value3, float alpha) + { + alpha = std::clamp(alpha, 0.0f, 1.0f); + + float p = (value3 - value2) - (value0 - value1); + float q = (value0 - value1) - p; + float r = value2 - value0; + float s = value1; + float x = alpha; + float xSquared = SQUARE(x); + return ((p * xSquared * x) + (q * xSquared) + (r * x) + s); + } + static void HandleEdgeSlipState(ItemInfo& pushableItem) { constexpr auto LEAN_ANGLE_MAX = ANGLE(40.0f); From c76b5cb0c8968563b99011e165126482c4c7a66d Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 3 Jul 2024 01:11:19 +1000 Subject: [PATCH 231/410] Update Utils.cpp --- TombEngine/Math/Utils.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/TombEngine/Math/Utils.cpp b/TombEngine/Math/Utils.cpp index f6d6bc8d4..4aecc1de1 100644 --- a/TombEngine/Math/Utils.cpp +++ b/TombEngine/Math/Utils.cpp @@ -11,11 +11,6 @@ namespace TEN::Math return (((1.0f - alpha) * value0) + (alpha * value1)); } - float Smoothstep(float alpha) - { - return Smoothstep(0.0f, 1.0f, alpha); - } - float Smoothstep(float value0, float value1, float alpha) { alpha = std::clamp(alpha, value0, value1); @@ -27,6 +22,11 @@ namespace TEN::Math return (CUBE(alpha) * (alpha * ((alpha * 6) - 15) + 10)); } + float Smoothstep(float alpha) + { + return Smoothstep(0.0f, 1.0f, alpha); + } + float EaseInSine(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); From f804c794f8adb86c3b3ae176bef380d613bdca22 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:49:38 +0100 Subject: [PATCH 232/410] Fixed an error in the KeyClearAll() function that prevented it from being displayed in the Lua API --- Documentation/doc/1 modules/Input.html | 19 +++++++++++++++++++ .../Internal/TEN/Input/InputHandler.cpp | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/doc/1 modules/Input.html b/Documentation/doc/1 modules/Input.html index 61d495f1c..282b77f59 100644 --- a/Documentation/doc/1 modules/Input.html +++ b/Documentation/doc/1 modules/Input.html @@ -129,6 +129,10 @@
    + + + + @@ -254,6 +258,21 @@ + +
    + + KeyClearAll() +
    +
    + Clear all action keys. + + + + + + + +
    diff --git a/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp b/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp index 4870ae1c2..803e02ec1 100644 --- a/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Input/InputHandler.cpp @@ -86,9 +86,9 @@ namespace TEN::Scripting::Input ActionQueue[actionID] = QueueState::Clear; } -# + /// Clear all action keys. - // @function KeyClear + // @function KeyClearAll static void KeyClearAll() { for (auto& queue : ActionQueue) From 5f95c3f0eca5a1c39b69f4755fcc2d81b09b5810 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 12 Jul 2024 01:20:47 +1000 Subject: [PATCH 233/410] Add Remap() math function --- TombEngine/Math/Utils.cpp | 46 ++++++++++++++++++++++----------------- TombEngine/Math/Utils.h | 13 ++++++----- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/TombEngine/Math/Utils.cpp b/TombEngine/Math/Utils.cpp index 4aecc1de1..4387dc1af 100644 --- a/TombEngine/Math/Utils.cpp +++ b/TombEngine/Math/Utils.cpp @@ -5,6 +5,27 @@ namespace TEN::Math { + float FloorToStep(float value, float step) + { + return (floor(value / step) * step); + } + + float CeilToStep(float value, float step) + { + return (ceil(value / step) * step); + } + + float RoundToStep(float value, float step) + { + return (round(value / step) * step); + } + + float Remap(float value, float min0, float max0, float min1, float max1) + { + float alpha = (value - min0) / (max0 - min0); + return Lerp(min1, max1, alpha); + } + float Lerp(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); @@ -19,7 +40,7 @@ namespace TEN::Math alpha = std::clamp((alpha - value0) / (value1 - value0), 0.0f, 1.0f); // Evaluate polynomial. - return (CUBE(alpha) * (alpha * ((alpha * 6) - 15) + 10)); + return (CUBE(alpha) * (alpha * ((alpha * 6) - 15.0f) + 10.0f)); } float Smoothstep(float alpha) @@ -30,7 +51,7 @@ namespace TEN::Math float EaseInSine(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); - return Lerp(value0, value1, 1 - cos((alpha * PI) / 2)); + return Lerp(value0, value1, 1.0f - cos((alpha * PI) / 2)); } float EaseInSine(float alpha) @@ -52,7 +73,7 @@ namespace TEN::Math float EaseInOutSine(float value0, float value1, float alpha) { alpha = std::clamp(alpha, 0.0f, 1.0f); - return Lerp(value0, value1, (1 - cos(alpha * PI)) / 2); + return Lerp(value0, value1, (1.0f - cos(alpha * PI)) / 2); } float EaseInOutSine(float alpha) @@ -62,9 +83,9 @@ namespace TEN::Math float Luma(const Vector3& color) { - constexpr auto RED_COEFF = 0.2126f; + constexpr auto RED_COEFF = 0.2126f; constexpr auto GREEN_COEFF = 0.7152f; - constexpr auto BLUE_COEFF = 0.0722f; + constexpr auto BLUE_COEFF = 0.0722f; // Use Rec.709 trichromat formula to get perceptive luma value. return float((color.x * RED_COEFF) + (color.y * GREEN_COEFF) + (color.z * BLUE_COEFF)); @@ -87,19 +108,4 @@ namespace TEN::Math auto result = Screen(Vector3(ambient), Vector3(tint)); return Vector4(result.x, result.y, result.z, ambient.w * tint.w); } - - float FloorToStep(float value, float step) - { - return (floor(value / step) * step); - } - - float CeilToStep(float value, float step) - { - return (ceil(value / step) * step); - } - - float RoundToStep(float value, float step) - { - return (round(value / step) * step); - } } diff --git a/TombEngine/Math/Utils.h b/TombEngine/Math/Utils.h index ad349a71c..5066188e5 100644 --- a/TombEngine/Math/Utils.h +++ b/TombEngine/Math/Utils.h @@ -5,6 +5,13 @@ namespace TEN::Math constexpr inline auto OFFSET_RADIUS = [](auto x) { return ((x * SQRT_2) + 4); }; constexpr inline auto MESH_BITS = [](auto x) { return (1 << x); }; + // Value manipulation + + float FloorToStep(float value, float step); + float CeilToStep(float value, float step); + float RoundToStep(float value, float step); + float Remap(float value, float min0, float max0, float min1, float max1); + // Interpolation float Lerp(float value0, float value1, float alpha); @@ -22,10 +29,4 @@ namespace TEN::Math float Luma(const Vector3& color); Vector3 Screen(const Vector3& ambient, const Vector3& tint); Vector4 Screen(const Vector4& ambient, const Vector4& tint); - - // Misc. - - float FloorToStep(float value, float step); - float CeilToStep(float value, float step); - float RoundToStep(float value, float step); } From 9791bd92e79866235a181aa99a675e0de6556513 Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 16 Jul 2024 17:37:01 +1000 Subject: [PATCH 234/410] Add accessible debug execution time functions --- TombEngine/Game/debug/debug.cpp | 16 ++++++++++++++++ TombEngine/Game/debug/debug.h | 9 +++++++++ 2 files changed, 25 insertions(+) diff --git a/TombEngine/Game/debug/debug.cpp b/TombEngine/Game/debug/debug.cpp index 4e06330f3..dfefef748 100644 --- a/TombEngine/Game/debug/debug.cpp +++ b/TombEngine/Game/debug/debug.cpp @@ -1,6 +1,7 @@ #include "framework.h" #include "Game/Debug/Debug.h" +#include #include #include #include @@ -12,6 +13,8 @@ using TEN::Renderer::g_Renderer; namespace TEN::Debug { + static auto StartTime = std::chrono::high_resolution_clock::time_point{}; + void InitTENLog(const std::string& logDirContainingDir) { // "true" means create new log file each time game is run. @@ -68,6 +71,19 @@ namespace TEN::Debug prevString = std::string(msg); } + void StartDebugTimer() + { + StartTime = std::chrono::high_resolution_clock::now(); + } + + void EndDebugTimer() + { + auto endTime = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(endTime - StartTime); + + PrintDebugMessage("Execution (microseconds): %d", duration); + } + void PrintDebugMessage(LPCSTR msg, ...) { auto args = va_list{}; diff --git a/TombEngine/Game/debug/debug.h b/TombEngine/Game/debug/debug.h index 448855af6..ff1a99ef5 100644 --- a/TombEngine/Game/debug/debug.h +++ b/TombEngine/Game/debug/debug.h @@ -33,6 +33,8 @@ namespace TEN::Debug using std::runtime_error::runtime_error; }; + // Logs + void InitTENLog(const std::string& logDirContainingDir); void ShutdownTENLog(); void TENLog(const std::string_view& msg, LogLevel level = LogLevel::Info, LogConfig config = LogConfig::All, bool allowSpam = false); @@ -49,6 +51,13 @@ namespace TEN::Debug } }; + // Timers + + void StartDebugTimer(); + void EndDebugTimer(); + + // Objects + void PrintDebugMessage(LPCSTR msg, ...); void DrawDebug2DLine(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); void DrawDebugLine(const Vector3& origin, const Vector3& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); From ca92b1a78ef90ee6e3a7e2353f69cad14de43b9c Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 17 Jul 2024 21:39:44 +1000 Subject: [PATCH 235/410] Add missing string function to global debug --- TombEngine/Game/collision/floordata.cpp | 2 +- TombEngine/Game/debug/debug.cpp | 5 +++++ TombEngine/Game/debug/debug.h | 3 ++- TombEngine/Renderer/Renderer.h | 2 +- TombEngine/Renderer/RendererString.cpp | 8 ++++++-- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 356997d3e..701717f42 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -889,7 +889,7 @@ namespace TEN::Collision::Floordata if (labelPos2D.has_value()) { *labelPos2D += Vector2(0.0f, verticalOffset); - g_Renderer.AddDebugString(string, *labelPos2D, color, LABEL_SCALE, 0, RendererDebugPage::CollisionStats); + DrawDebugString(string, *labelPos2D, color, LABEL_SCALE, RendererDebugPage::CollisionStats); } } diff --git a/TombEngine/Game/debug/debug.cpp b/TombEngine/Game/debug/debug.cpp index dfefef748..233632785 100644 --- a/TombEngine/Game/debug/debug.cpp +++ b/TombEngine/Game/debug/debug.cpp @@ -91,6 +91,11 @@ namespace TEN::Debug g_Renderer.PrintDebugMessage(msg, args); va_end(args); } + + void DrawDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page) + { + g_Renderer.AddDebugString(string, pos, color, scale, page); + } void DrawDebug2DLine(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page) { diff --git a/TombEngine/Game/debug/debug.h b/TombEngine/Game/debug/debug.h index ff1a99ef5..edcbbf47a 100644 --- a/TombEngine/Game/debug/debug.h +++ b/TombEngine/Game/debug/debug.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include "Renderer/RendererEnums.h" @@ -59,6 +59,7 @@ namespace TEN::Debug // Objects void PrintDebugMessage(LPCSTR msg, ...); + void DrawDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page = RendererDebugPage::None); void DrawDebug2DLine(const Vector2& origin, const Vector2& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); void DrawDebugLine(const Vector3& origin, const Vector3& target, const Color& color, RendererDebugPage page = RendererDebugPage::None); void DrawDebugTriangle(const Vector3& vertex0, const Vector3& vertex1, const Vector3& vertex2, const Color& color, RendererDebugPage page = RendererDebugPage::None); diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index 9cb74a15a..db408b8a5 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -600,7 +600,7 @@ namespace TEN::Renderer int Synchronize(); void AddString(int x, int y, const std::string& string, D3DCOLOR color, int flags); void AddString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags); - void AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags, RendererDebugPage page); + void AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page = RendererDebugPage::None); void FreeRendererData(); void AddDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b); void RenderLoadingScreen(float percentage); diff --git a/TombEngine/Renderer/RendererString.cpp b/TombEngine/Renderer/RendererString.cpp index b26196f44..1a27fc95a 100644 --- a/TombEngine/Renderer/RendererString.cpp +++ b/TombEngine/Renderer/RendererString.cpp @@ -2,14 +2,18 @@ #include "Renderer/Renderer.h" #include "Specific/trutils.h" +#include "Specific/winmain.h" namespace TEN::Renderer { - void Renderer::AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, int flags, RendererDebugPage page) + void Renderer::AddDebugString(const std::string& string, const Vector2& pos, const Color& color, float scale, RendererDebugPage page) { constexpr auto FLAGS = (int)PrintStringFlags::Outline | (int)PrintStringFlags::Center; - if (_debugPage != page) + if (_isLocked) + return; + + if (!DebugMode || (_debugPage != page && page != RendererDebugPage::None)) return; AddString(string, pos, color, scale, FLAGS); From 0c1c9d49a5dcd41661ddb636e318314390142c96 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 18 Jul 2024 00:09:36 +1000 Subject: [PATCH 236/410] Comment flipeffects to be converted to anim commands; use NO_VALUE --- TombEngine/Game/Setup.cpp | 2 +- TombEngine/Game/control/flipeffect.cpp | 52 +++++++++---------- TombEngine/Game/control/flipeffect.h | 29 ++++++----- TombEngine/Objects/TR4/Entity/Wraith.cpp | 4 +- .../Objects/TR4/Entity/tr4_beetle_swarm.cpp | 2 +- .../Objects/TR5/Emitter/tr5_rats_emitter.cpp | 2 +- .../TR5/Emitter/tr5_spider_emitter.cpp | 2 +- 7 files changed, 46 insertions(+), 47 deletions(-) diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp index a427dfe71..3f09147c6 100644 --- a/TombEngine/Game/Setup.cpp +++ b/TombEngine/Game/Setup.cpp @@ -127,7 +127,7 @@ void InitializeGameFlags() ZeroMemory(FlipMap, MAX_FLIPMAP * sizeof(int)); ZeroMemory(FlipStats, MAX_FLIPMAP * sizeof(bool)); - FlipEffect = -1; + FlipEffect = NO_VALUE; FlipStatus = false; Camera.underwater = false; } diff --git a/TombEngine/Game/control/flipeffect.cpp b/TombEngine/Game/control/flipeffect.cpp index b128351a8..486518fea 100644 --- a/TombEngine/Game/control/flipeffect.cpp +++ b/TombEngine/Game/control/flipeffect.cpp @@ -94,21 +94,17 @@ void ClearSwarmEnemies(ItemInfo* item) void FlashOrange(ItemInfo* item) { - FlipEffect = -1; + FlipEffect = NO_VALUE; Weather.Flash(255, 128, 0, 0.03f); } void MeshSwapToPour(ItemInfo* item) { - auto* lara = GetLaraInfo(item); - item->Model.MeshIndex[LM_LHAND] = Objects[item->ItemFlags[2]].meshIndex + LM_LHAND; } void MeshSwapFromPour(ItemInfo* item) { - auto* lara = GetLaraInfo(item); - item->Model.MeshIndex[LM_LHAND] = item->Model.BaseMesh + LM_LHAND; } @@ -149,60 +145,60 @@ void InvisibilityOn(ItemInfo* item) void SetFog(ItemInfo* item) { - FlipEffect = -1; + FlipEffect = NO_VALUE; } void DrawLeftPistol(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); if (item->Model.MeshIndex[LM_LHAND] == item->Model.BaseMesh + LM_LHAND) { item->Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(*item, LaraWeaponType::Pistol)].meshIndex + LM_LHAND; - lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty; + player.Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty; } else { item->Model.MeshIndex[LM_LHAND] = item->Model.BaseMesh + LM_LHAND; - lara->Control.Weapon.HolsterInfo.LeftHolster = GetWeaponHolsterSlot(LaraWeaponType::Pistol); + player.Control.Weapon.HolsterInfo.LeftHolster = GetWeaponHolsterSlot(LaraWeaponType::Pistol); } } void DrawRightPistol(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); if (item->Model.MeshIndex[LM_RHAND] == item->Model.BaseMesh + LM_RHAND) { item->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(*item, LaraWeaponType::Pistol)].meshIndex + LM_RHAND; - lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty; + player.Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty; } else { item->Model.MeshIndex[LM_RHAND] = item->Model.BaseMesh + LM_RHAND; - lara->Control.Weapon.HolsterInfo.RightHolster = GetWeaponHolsterSlot(LaraWeaponType::Pistol); + player.Control.Weapon.HolsterInfo.RightHolster = GetWeaponHolsterSlot(LaraWeaponType::Pistol); } } void ShootLeftGun(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->LeftArm.GunFlash = 3; + player.LeftArm.GunFlash = 3; } void ShootRightGun(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->RightArm.GunFlash = 3; + player.RightArm.GunFlash = 3; } void LaraHandsFree(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Control.HandStatus = HandStatus::Free; + player.Control.HandStatus = HandStatus::Free; } void KillActiveBaddys(ItemInfo* item) @@ -231,14 +227,14 @@ void KillActiveBaddys(ItemInfo* item) } while (itemNumber != NO_VALUE); } - FlipEffect = -1; + FlipEffect = NO_VALUE; } void LaraLocationPad(ItemInfo* item) { auto* lara = GetLaraInfo(item); - FlipEffect = -1; + FlipEffect = NO_VALUE; lara->Location = TriggerTimer; lara->LocationPad = TriggerTimer; @@ -248,7 +244,7 @@ void LaraLocation(ItemInfo* item) { auto* lara = GetLaraInfo(item); - FlipEffect = -1; + FlipEffect = NO_VALUE; lara->Location = TriggerTimer; if (lara->HighestLocation < TriggerTimer) @@ -259,17 +255,19 @@ void ExplosionFX(ItemInfo* item) { SoundEffect(SFX_TR4_EXPLOSION1, nullptr); Camera.bounce = -75; - FlipEffect = -1; + FlipEffect = NO_VALUE; } void SwapCrowbar(ItemInfo* item) { - auto* lara = GetLaraInfo(item); - if (item->Model.MeshIndex[LM_RHAND] == item->Model.BaseMesh + LM_RHAND) + { item->Model.MeshIndex[LM_RHAND] = Objects[ID_LARA_CROWBAR_ANIM].meshIndex + LM_RHAND; + } else + { item->Model.MeshIndex[LM_RHAND] = item->Model.BaseMesh + LM_RHAND; + } } void ActivateKey(ItemInfo* item) @@ -285,7 +283,7 @@ void ActivateCamera(ItemInfo* item) void PoseidonSFX(ItemInfo* item) { SoundEffect(SFX_TR4_WATER_FLUSHES, nullptr); - FlipEffect = -1; + FlipEffect = NO_VALUE; } void RubbleFX(ItemInfo* item) @@ -303,13 +301,13 @@ void RubbleFX(ItemInfo* item) else Camera.bounce = -150; - FlipEffect = -1; + FlipEffect = NO_VALUE; } void PlaySoundEffect(ItemInfo* item) { SoundEffect(TriggerTimer, nullptr); - FlipEffect = -1; + FlipEffect = NO_VALUE; } void FloorShake(ItemInfo* item) diff --git a/TombEngine/Game/control/flipeffect.h b/TombEngine/Game/control/flipeffect.h index 3c55622da..7e6b981a0 100644 --- a/TombEngine/Game/control/flipeffect.h +++ b/TombEngine/Game/control/flipeffect.h @@ -1,6 +1,7 @@ #pragma once -#include "Game/items.h" + #include "Game/control/control.h" +#include "Game/items.h" #define EffectFunction void(ItemInfo* item) @@ -10,35 +11,35 @@ extern int FlipEffect; extern std::function effect_routines[]; -void AddLeftFootprint(ItemInfo* item); -void AddRightFootprint(ItemInfo* item); +void AddLeftFootprint(ItemInfo* item); // TODO: To anim command. +void AddRightFootprint(ItemInfo* item); // TODO: To anim command. void VoidEffect(ItemInfo* item); void FinishLevel(ItemInfo* item); -void Turn180(ItemInfo* item); +void Turn180(ItemInfo* item); // TODO: To anim command. void FloorShake(ItemInfo* item); void PlaySoundEffect(ItemInfo* item); void RubbleFX(ItemInfo* item); void PoseidonSFX(ItemInfo* item); void ActivateCamera(ItemInfo* item); void ActivateKey(ItemInfo* item); -void SwapCrowbar(ItemInfo* item); +void SwapCrowbar(ItemInfo* item); // TODO: To anim command. void ExplosionFX(ItemInfo* item); void LaraLocation(ItemInfo* item); void LaraLocationPad(ItemInfo* item); void KillActiveBaddys(ItemInfo* item); -void LaraHandsFree(ItemInfo* item); -void ShootRightGun(ItemInfo* item); -void ShootLeftGun(ItemInfo* item); +void LaraHandsFree(ItemInfo* item); // TODO: To anim command. +void ShootRightGun(ItemInfo* item); // TODO: To anim command. +void ShootLeftGun(ItemInfo* item); // TODO: To anim command. void SetFog(ItemInfo* item); void InvisibilityOn(ItemInfo* item); void InvisibilityOff(ItemInfo* item); void ResetHair(ItemInfo* item); -void Pickup(ItemInfo* item); -void Puzzle(ItemInfo* item); -void DrawRightPistol(ItemInfo* item); -void DrawLeftPistol(ItemInfo* item); -void MeshSwapToPour(ItemInfo* item); -void MeshSwapFromPour(ItemInfo* item); +void Pickup(ItemInfo* item); // TODO: To anim command. +void Puzzle(ItemInfo* item); // TODO: To anim command. +void DrawRightPistol(ItemInfo* item); // TODO: To anim command. +void DrawLeftPistol(ItemInfo* item); // TODO: To anim command. +void MeshSwapToPour(ItemInfo* item); // TODO: To anim command. +void MeshSwapFromPour(ItemInfo* item); // TODO: To anim command. void FlashOrange(ItemInfo* item); void ClearSwarmEnemies(ItemInfo* item); diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index b03fefcb9..5ea720a34 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -712,7 +712,7 @@ namespace TEN::Entities::TR4 if (item2->NextActive == NO_VALUE) { - FlipEffect = -1; + FlipEffect = NO_VALUE; return; } } @@ -720,6 +720,6 @@ namespace TEN::Entities::TR4 item2->HitPoints = item->Index; } - FlipEffect = -1; + FlipEffect = NO_VALUE; } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp index 9951cd441..2923a4f34 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp @@ -104,7 +104,7 @@ namespace TEN::Entities::TR4 { ZeroMemory(BeetleSwarm, NUM_BEETLES * sizeof(BeetleData)); NextBeetle = 0; - FlipEffect = -1; + FlipEffect = NO_VALUE; } } diff --git a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp index bb1a1403a..f5bc962bb 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp @@ -96,7 +96,7 @@ void ClearRats() { ZeroMemory(Rats, NUM_RATS * sizeof(RatData)); NextRat = 0; - FlipEffect = -1; + FlipEffect = NO_VALUE; } } diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp index 8e201afe2..b7d0d01ee 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp @@ -47,7 +47,7 @@ void ClearSpiders() { ZeroMemory(Spiders, NUM_SPIDERS * sizeof(SpiderData)); NextSpider = 0; - FlipEffect = -1; + FlipEffect = NO_VALUE; } } From a1675b577ac82df390307999514ee3f14018667c Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 25 Jul 2024 01:29:24 +1000 Subject: [PATCH 237/410] Fix sound effect crash --- TombEngine/Game/animation.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 0771e965a..0db8e490f 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -120,6 +120,14 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased) int soundID = commandDataPtr[1] & 0xFFF; // Exclude last 4 bits for sound ID. int soundEnvFlag = commandDataPtr[1] & 0xF000; // Keep only last 4 bits for sound environment flag. + // FAILSAFE. + if (item.RoomNumber == NO_VALUE) + { + SoundEffect(soundID, &item.Pose, SoundEnvironment::Always); + commandDataPtr += 2; + break; + } + // Get required sound environment from flag. auto requiredSoundEnv = SoundEnvironment::Always; switch (soundEnvFlag) From 0ad1eb9402c5eba7a2948cc3193ca6b42948da9a Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 27 Jul 2024 01:44:18 +1000 Subject: [PATCH 238/410] Round angle calculation --- TombEngine/Math/Legacy.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/TombEngine/Math/Legacy.h b/TombEngine/Math/Legacy.h index 333968f9e..ad8a857fd 100644 --- a/TombEngine/Math/Legacy.h +++ b/TombEngine/Math/Legacy.h @@ -1,4 +1,5 @@ #pragma once + #include "Math/Constants.h" constexpr auto FP_SHIFT = 16; @@ -8,14 +9,19 @@ constexpr auto PREDICTIVE_SCALE_FACTOR = 14; constexpr auto SHORTS_TO_1_DEGREE = 65536.0f / 360.0f; constexpr auto DEGREES_TO_1_SHORT = 360.0f / 65536.0f; +constexpr float ROUND(float value) +{ + return ((value > 0.0f) ? int(value + 0.5f) : int(value - 0.5f)); +} + constexpr short ANGLE(float degrees) { - return short(degrees * SHORTS_TO_1_DEGREE); + return (short)ROUND(degrees * SHORTS_TO_1_DEGREE); } constexpr short FROM_RAD(float radians) { - return short((radians / RADIAN) * SHORTS_TO_1_DEGREE); + return (short)ROUND((radians / RADIAN) * SHORTS_TO_1_DEGREE); } constexpr float TO_DEGREES(short shortAngle) From 8e9ed77e64cc8f3266b9ee44cd9b3409d2888291 Mon Sep 17 00:00:00 2001 From: davidmarr <116632612+davidmarr@users.noreply.github.com> Date: Sat, 27 Jul 2024 19:16:13 +0200 Subject: [PATCH 239/410] Fixed Volume:GetActive() method (#1389) * Update VolumeObject.cpp fixed Volume:GetActive() method * Update CHANGELOG.md --- CHANGELOG.md | 1 + .../Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3880af53e..b9d5be69a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() * Removed anims.monkeyAutoJump. It is now a player menu configuration. +* Fixed Volume:GetActive() method ## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21 diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp index 4338ce52f..a39198ad7 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Volume/VolumeObject.cpp @@ -44,7 +44,7 @@ void Volume::Register(sol::table& parent) ScriptReserved_Disable, &Volume::Disable, ScriptReserved_ClearActivators, &Volume::ClearActivators, - ScriptReserved_GetName, &Volume::GetActive, + ScriptReserved_GetActive, &Volume::GetActive, ScriptReserved_IsMoveableInside, &Volume::IsMoveableInside); } From f0603349e2b9f74a210e51bbf93b2af856cba0c5 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 31 Jul 2024 19:21:51 +1000 Subject: [PATCH 240/410] Update RendererDraw.cpp --- TombEngine/Renderer/RendererDraw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 6c9fc6307..bbf667561 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1725,7 +1725,7 @@ namespace TEN::Renderer //RenderSimpleSceneToParaboloid(&_roomAmbientMapsCache[ambientMapCacheIndex].Back, LaraItem->Pose.Position.ToVector3(), -1); // Bind and clear render target. - _context->ClearRenderTargetView(_renderTarget.RenderTargetView.Get(), _debugPage == RendererDebugPage::WireframeMode ? Colors::White : Colors::Black); + _context->ClearRenderTargetView(_renderTarget.RenderTargetView.Get(), _debugPage == RendererDebugPage::WireframeMode ? Colors::DimGray : Colors::Black); _context->ClearDepthStencilView(_renderTarget.DepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); // Reset viewport and scissor From 33edb092a94b90ae5628f6b9461cbd8ec866e901 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 31 Jul 2024 11:31:48 +0200 Subject: [PATCH 241/410] Fixed shockwaves --- TombEngine/Game/effects/effects.h | 2 ++ TombEngine/Renderer/RendererDrawEffect.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/effects/effects.h b/TombEngine/Game/effects/effects.h index bb87f3a04..a84510945 100644 --- a/TombEngine/Game/effects/effects.h +++ b/TombEngine/Game/effects/effects.h @@ -202,6 +202,7 @@ struct SPLASH_STRUCT float oldHeight; unsigned short oldLife; float oldHeightSpeed; + float oldAnimationPhase; void StoreInterpolationData() { @@ -213,6 +214,7 @@ struct SPLASH_STRUCT oldHeight = height; oldLife = life; oldHeightSpeed = heightSpeed; + oldAnimationPhase = animationPhase; } }; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 04a28d858..bdea5031f 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -824,7 +824,7 @@ namespace TEN::Renderer b = shockwave->b * shockwave->life / 255.0f; } - for (int j = 0; j < 16; j++) + for (int j = 0; j <= 16; j++) { c = cos(angle); s = sin(angle); From 3a38e4c576f2eace1c1c467034d3ac04bbe1951a Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 6 Aug 2024 19:00:49 +1000 Subject: [PATCH 242/410] Rename previously updated creature files --- TombEngine/Objects/TR1/Entity/Centaur.cpp | 173 ++++++ .../TR1/Entity/{tr1_centaur.h => Centaur.h} | 4 +- .../Objects/TR1/Entity/WingedMutant.cpp | 573 ++++++++++++++++++ .../{tr1_winged_mutant.h => WingedMutant.h} | 3 +- TombEngine/Objects/TR1/Entity/tr1_centaur.cpp | 158 ----- .../Objects/TR1/Entity/tr1_winged_mutant.cpp | 571 ----------------- TombEngine/Objects/TR1/tr1_objects.cpp | 28 +- TombEngine/TombEngine.vcxproj | 8 +- 8 files changed, 767 insertions(+), 751 deletions(-) create mode 100644 TombEngine/Objects/TR1/Entity/Centaur.cpp rename TombEngine/Objects/TR1/Entity/{tr1_centaur.h => Centaur.h} (55%) create mode 100644 TombEngine/Objects/TR1/Entity/WingedMutant.cpp rename TombEngine/Objects/TR1/Entity/{tr1_winged_mutant.h => WingedMutant.h} (69%) delete mode 100644 TombEngine/Objects/TR1/Entity/tr1_centaur.cpp delete mode 100644 TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp diff --git a/TombEngine/Objects/TR1/Entity/Centaur.cpp b/TombEngine/Objects/TR1/Entity/Centaur.cpp new file mode 100644 index 000000000..fa5ef2fdc --- /dev/null +++ b/TombEngine/Objects/TR1/Entity/Centaur.cpp @@ -0,0 +1,173 @@ +#include "framework.h" +#include "Objects/TR1/Entity/Centaur.h" + +#include "Game/animation.h" +#include "Game/control/box.h" +#include "Game/collision/collide_item.h" +#include "Game/collision/collide_room.h" +#include "Game/effects/effects.h" +#include "Game/effects/tomb4fx.h" +#include "Game/items.h" +#include "Game/Lara/lara.h" +#include "Game/Lara/lara_one_gun.h" +#include "Game/misc.h" +#include "Game/missile.h" +#include "Game/people.h" +#include "Game/Setup.h" +#include "Math/Math.h" +#include "Sound/sound.h" +#include "Specific/level.h" + +using namespace TEN::Math; + +namespace TEN::Entities::Creatures::TR1 +{ + constexpr auto CENTAUR_REAR_DAMAGE = 200; + constexpr auto CENTAUR_REAR_RANGE = BLOCK(3 / 2.0f); + constexpr auto CENTAUR_REAR_CHANCE = 1 / 340.0f; + constexpr auto CENTAUR_BOMB_VELOCITY = CLICK(1); + + constexpr auto CENTAUR_TURN_RATE_MAX = ANGLE(4.0f); + + const auto CentaurRocketBite = CreatureBiteInfo(Vector3(11, 415, 41), 13); + const auto CentaurRearBite = CreatureBiteInfo(Vector3(50, 30, 0), 5); + const auto CentaurAttackJoints = std::vector{ 0, 3, 4, 7, 8, 16, 17 }; + + enum CentaurState + { + // No state 0. + CENTAUR_STATE_IDLE = 1, + CENTAUR_PROJECTILE_ATTACK = 2, + CENTAUR_STATE_RUN_FORWARD = 3, + CENTAUR_STATE_AIM = 4, + CENTAUR_STATE_DEATH = 5, + CENTAUR_STATE_WARNING = 6 + }; + + // TODO + enum CentaurAnim + { + CENTAUR_ANIM_DEATH = 8, + }; + + void ControlCentaur(short itemNumber) + { + if (!CreatureActive(itemNumber)) + return; + + auto& item = g_Level.Items[itemNumber]; + auto& creature = *GetCreatureInfo(&item); + + short headingAngle = 0; + short headYOrient = 0; + + if (item.HitPoints <= 0) + { + if (item.Animation.ActiveState != CENTAUR_STATE_DEATH) + SetAnimation(item, CENTAUR_ANIM_DEATH); + } + else + { + AI_INFO ai; + CreatureAIInfo(&item, &ai); + + if (ai.ahead) + headYOrient = ai.angle; + + CreatureMood(&item, &ai, true); + + headingAngle = CreatureTurn(&item, CENTAUR_TURN_RATE_MAX); + + switch (item.Animation.ActiveState) + { + case CENTAUR_STATE_IDLE: + CreatureJoint(&item, 17, 0); + + if (item.Animation.RequiredState != NO_VALUE) + { + item.Animation.TargetState = item.Animation.RequiredState; + } + else if (ai.bite && ai.distance < pow(CENTAUR_REAR_RANGE, 2)) + { + item.Animation.TargetState = CENTAUR_STATE_RUN_FORWARD; + } + else if (Targetable(&item, &ai)) + { + item.Animation.TargetState = CENTAUR_STATE_AIM; + } + else + { + item.Animation.TargetState = CENTAUR_STATE_RUN_FORWARD; + } + + break; + + case CENTAUR_STATE_RUN_FORWARD: + if (ai.bite && ai.distance < pow(CENTAUR_REAR_RANGE, 2)) + { + item.Animation.TargetState = CENTAUR_STATE_IDLE; + item.Animation.RequiredState = CENTAUR_STATE_WARNING; + } + else if (Targetable(&item, &ai)) + { + item.Animation.TargetState = CENTAUR_STATE_IDLE; + item.Animation.RequiredState = CENTAUR_STATE_AIM; + } + else if (Random::TestProbability(CENTAUR_REAR_CHANCE)) + { + item.Animation.TargetState = CENTAUR_STATE_IDLE; + item.Animation.RequiredState = CENTAUR_STATE_WARNING; + } + + break; + + case CENTAUR_STATE_AIM: + if (item.Animation.RequiredState != NO_VALUE) + { + item.Animation.TargetState = item.Animation.RequiredState; + } + else if (Targetable(&item, &ai)) + { + item.Animation.TargetState = CENTAUR_PROJECTILE_ATTACK; + } + else + { + item.Animation.TargetState = CENTAUR_STATE_IDLE; + } + + break; + + case CENTAUR_PROJECTILE_ATTACK: + if (item.Animation.RequiredState == NO_VALUE) + { + item.Animation.RequiredState = CENTAUR_STATE_AIM; + CreatureEffect2(&item, CentaurRocketBite, CENTAUR_BOMB_VELOCITY, headYOrient, BombGun); + } + + break; + + case CENTAUR_STATE_WARNING: + if (item.Animation.RequiredState == NO_VALUE && + item.TouchBits.Test(CentaurAttackJoints)) + { + DoDamage(creature.Enemy, CENTAUR_REAR_DAMAGE); + CreatureEffect(&item, CentaurRearBite, DoBloodSplat); + item.Animation.RequiredState = CENTAUR_STATE_IDLE; + } + + break; + } + } + + CreatureJoint(&item, 0, headYOrient); + CreatureAnimation(itemNumber, headingAngle, 0); + + if (item.Status == ITEM_DEACTIVATED) + { + SoundEffect(SFX_TR1_ATLANTEAN_DEATH, &item.Pose); + ExplodingDeath(itemNumber, BODY_DO_EXPLOSION); + KillItem(itemNumber); + item.Status = ITEM_DEACTIVATED; + } + } +} diff --git a/TombEngine/Objects/TR1/Entity/tr1_centaur.h b/TombEngine/Objects/TR1/Entity/Centaur.h similarity index 55% rename from TombEngine/Objects/TR1/Entity/tr1_centaur.h rename to TombEngine/Objects/TR1/Entity/Centaur.h index cf34267d2..1aa3e4f3a 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_centaur.h +++ b/TombEngine/Objects/TR1/Entity/Centaur.h @@ -3,7 +3,7 @@ namespace TEN::Entities::Creatures::TR1 { constexpr auto SHARD_VELOCITY = 250; - constexpr auto BOMB_VELOCITY = 220; + constexpr auto BOMB_VELOCITY = 220; - void CentaurControl(short itemNumber); + void ControlCentaur(short itemNumber); } diff --git a/TombEngine/Objects/TR1/Entity/WingedMutant.cpp b/TombEngine/Objects/TR1/Entity/WingedMutant.cpp new file mode 100644 index 000000000..d55729dd9 --- /dev/null +++ b/TombEngine/Objects/TR1/Entity/WingedMutant.cpp @@ -0,0 +1,573 @@ +#include "framework.h" +#include "Objects/TR1/Entity/WingedMutant.h" + +#include "Game/collision/collide_room.h" +#include "Game/control/box.h" +#include "Game/control/lot.h" +#include "Game/effects/effects.h" +#include "Game/effects/tomb4fx.h" +#include "Game/itemdata/creature_info.h" +#include "Game/items.h" +#include "Game/misc.h" +#include "Game/missile.h" +#include "Game/people.h" +#include "Math/Math.h" +#include "Sound/sound.h" +#include "Specific/level.h" + +using namespace TEN::Math; + +namespace TEN::Entities::Creatures::TR1 +{ + constexpr auto WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE = 150; + constexpr auto WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE = 100; + constexpr auto WINGED_MUTANT_SWIPE_ATTACK_DAMAGE = 200; + + constexpr auto WINGED_MUTANT_WALK_RANGE = SQUARE(BLOCK(4.5f)); + constexpr auto WINGED_MUTANT_SWIPE_ATTACK_RANGE = SQUARE(BLOCK(0.3f)); + constexpr auto WINGED_MUTANT_RUN_JUMP_ATTACK_RANGE = SQUARE(BLOCK(0.65f)); + constexpr auto WINGED_MUTANT_IDLE_JUMP_ATTACK_RANGE = SQUARE(BLOCK(2.5f)); + constexpr auto WINGED_MUTANT_PROJECTILE_ATTACK_RANGE = SQUARE(BLOCK(3.0f)); + constexpr auto WINGED_MUTANT_POSE_RANGE = SQUARE(BLOCK(4.5f)); + + constexpr auto WINGED_MUTANT_POSE_CHANCE = 1 / 400.0f; + constexpr auto WINGED_MUTANT_UNPOSE_CHANCE = 1 / 164.0f; + + constexpr auto WINGED_MUTANT_FLY_VELOCITY = BLOCK(1 / 32.0f); + constexpr auto WINGED_MUTANT_SHARD_VELOCITY = 250; + constexpr auto WINGED_MUTANT_BOMB_VELOCITY = 220; + + constexpr auto WINGED_MUTANT_WALK_TURN_RATE_MAX = ANGLE(2.0f); + constexpr auto WINGED_MUTANT_RUN_TURN_RATE_MAX = ANGLE(6.0f); + + const auto WingedMutantBiteLeftHand = CreatureBiteInfo(Vector3(0, 0, 0), 7); + const auto WingedMutantBiteRightHand = CreatureBiteInfo(Vector3(0, 0, 0), 10); + const auto WingedMutantRocketBite = CreatureBiteInfo(Vector3(0, 200, 20), 6); + const auto WingedMutantShardBite = CreatureBiteInfo(Vector3(0, 200, 20), 9); + const auto WingedMutantHeadJoints = std::vector{ 3 }; + const auto WingedMutantHandsJoints = std::vector{ 7, 10 }; + const auto WingedMutantWingsJoints = std::vector{ 15, 16, 17, 18, 19, 20 }; + + enum WingedMutantState + { + // No state 0. + WMUTANT_STATE_IDLE = 1, + WMUTANT_STATE_WALK_FORWARD = 2, + WMUTANT_STATE_RUN_FORWARD = 3, + WMUTANT_STATE_IDLE_JUMP_ATTACK = 4, + WMUTANT_STATE_DEATH = 5, + WMUTANT_STATE_POSE = 6, + WMUTANT_STATE_RUN_JUMP_ATTACK = 7, + WMUTANT_STATE_SWIPE_ATTACK = 8, + WMUTANT_STATE_AIM_DART = 9, + WMUTANT_STATE_AIM_BOMB = 10, + WMUTANT_STATE_SHOOT = 11, + WMUTANT_STATE_INACTIVE = 12, + WMUTANT_STATE_FLY = 13, + }; + + enum WingedMutantAnim + { + WMUTANT_ANIM_INACTIVE = 0, + WMUTANT_ANIM_INACTIVE_TO_IDLE = 1, + WMUTANT_ANIM_IDLE = 2, + WMUTANT_ANIM_IDLE_TO_RUN = 3, + WMUTANT_ANIM_RUN_FORWARD = 4, + WMUTANT_ANIM_IDLE_JUMP_ATTACK_START = 5, + WMUTANT_ANIM_IDLE_JUMP_ATTACK_END = 6, + WMUTANT_ANIM_IDLE_TO_POSE = 7, + WMUTANT_ANIM_POSE = 8, + WMUTANT_ANIM_POSE_TO_IDLE = 9, + WMUTANT_ANIM_POSE_TO_WALK_FORWARD = 10, + WMUTANT_ANIM_WALK_FORWARD = 11, + WMUTANT_ANIM_WALK_FORWARD_TO_IDLE = 12, + WMUTANT_ANIM_WALK_FORWARD_TO_POSE = 13, + WMUTANT_ANIM_RUN_JUMP_ATTACK = 14, + WMUTANT_ANIM_IDLE_TO_AIM_1 = 15, + WMUTANT_ANIM_AIM_DART = 16, + WMUTANT_ANIM_SHOOT_DART = 17, + WMUTANT_ANIM_AIM_DART_TO_IDLE = 18, + WMUTANT_ANIM_IDLE_TO_AIM_BOMB = 19, + WMUTANT_ANIM_SHOOT_BOMB = 20, + WMUTANT_ANIM_RUN_FORWARD_TO_IDLE = 21, + WMUTANT_ANIM_AIM_BOMB_TO_IDLE = 22, + WMUTANT_ANIM_IDLE_TO_FLY = 23, + WMUTANT_ANIM_FLY = 24, + WMUTANT_ANIM_FLY_TO_IDLE = 25, + WMUTANT_ANIM_SWIPE_ATTACK = 26 + }; + + enum WingedMutantPathFinding + { + WMUTANT_PATH_GROUND = 1, + WMUTANT_PATH_AERIAL = 2 + }; + + // NOTE: Originally, winged mutants did not have OCBs. -- TokyoSU 5/8/2022 + enum WingedMutantOcb + { + WMUTANT_OCB_START_AERIAL = (1 << 0), + WMUTANT_OCB_START_INACTIVE = (1 << 1), + WMUTANT_OCB_START_POSE = (1 << 2), + WMUTANT_OCB_NO_WINGS = (1 << 3), + WMUTANT_OCB_DISABLE_DART_WEAPON = (1 << 4), + WMUTANT_OCB_DISABLE_BOMB_WEAPON = (1 << 5) + }; + + enum WingedMutantProjectileType + { + WMUTANT_PROJ_NONE, + WMUTANT_PROJ_DART, + WMUTANT_PROJ_BOMB + }; + + enum WingedMutantConfig + { + WMUTANT_CONF_CAN_FLY, + WMUTANT_CONF_PATHFINDING_MODE, + WMUTANT_CONF_PROJECTILE_MODE, + WMUTANT_CONF_NO_WINGS, + WMUTANT_CONF_DISABLE_DART_WEAPON, + WMUTANT_CONF_DISABLE_BOMB_WEAPON + }; + + static void SwitchPathfinding(ItemInfo& item, WingedMutantPathFinding path) + { + auto& creature = *GetCreatureInfo(&item); + + switch (path) + { + case WMUTANT_PATH_GROUND: + creature.LOT.Step = CLICK(1); + creature.LOT.Drop = -CLICK(1); + creature.LOT.Fly = NO_FLYING; + creature.LOT.Zone = ZoneType::Basic; + break; + + case WMUTANT_PATH_AERIAL: + creature.LOT.Step = BLOCK(20); + creature.LOT.Drop = -BLOCK(20); + creature.LOT.Fly = WINGED_MUTANT_FLY_VELOCITY; + creature.LOT.Zone = ZoneType::Flyer; + break; + } + } + + static WingedMutantProjectileType CanTargetPlayer(ItemInfo& item, AI_INFO& ai) + { + if (Targetable(&item, &ai) && + (ai.zoneNumber != ai.enemyZone || ai.distance > WINGED_MUTANT_PROJECTILE_ATTACK_RANGE)) + { + if ((ai.angle > 0 && ai.angle < ANGLE(45.0f)) && + item.TestFlagField(WMUTANT_CONF_DISABLE_DART_WEAPON, false)) + { + return WMUTANT_PROJ_DART; + } + else if ((ai.angle < 0 && ai.angle > ANGLE(-45.0f)) && + item.TestFlagField(WMUTANT_CONF_DISABLE_BOMB_WEAPON, false)) + { + return WMUTANT_PROJ_BOMB; + } + } + + // Cannot be targeted. + return WMUTANT_PROJ_NONE; + } + + static void InitializeWingedMutantOCB(ItemInfo& item) + { + if (item.TestOcb(WMUTANT_OCB_START_AERIAL)) + { + SwitchPathfinding(item, WMUTANT_PATH_AERIAL); + SetAnimation(item, WMUTANT_ANIM_FLY); + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_AERIAL); + } + else if (item.TestOcb(WMUTANT_OCB_START_INACTIVE)) + { + SwitchPathfinding(item, WMUTANT_PATH_GROUND); + SetAnimation(item, WMUTANT_ANIM_INACTIVE); + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); + } + else if (item.TestOcb(WMUTANT_OCB_START_POSE)) + { + SwitchPathfinding(item, WMUTANT_PATH_GROUND); + SetAnimation(item, WMUTANT_ANIM_INACTIVE); + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); + } + + // Remove unnecessary OCBs. + if (item.TestOcb(WMUTANT_OCB_START_AERIAL)) + item.RemoveOcb(WMUTANT_OCB_START_AERIAL); + + if (item.TestOcb(WMUTANT_OCB_START_INACTIVE)) + item.RemoveOcb(WMUTANT_OCB_START_INACTIVE); + + if (item.TestOcb(WMUTANT_OCB_START_POSE)) + item.RemoveOcb(WMUTANT_OCB_START_POSE); + } + + void InitializeWingedMutant(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + InitializeCreature(itemNumber); + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); + item.SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_NONE); + + if (item.TestOcb(WMUTANT_OCB_NO_WINGS)) + { + item.SetFlagField(WMUTANT_CONF_CAN_FLY, false); + item.MeshBits.Clear(WingedMutantWingsJoints); + } + else + { + item.SetFlagField(WMUTANT_CONF_CAN_FLY, true); + } + + if (item.TestOcb(WMUTANT_OCB_DISABLE_BOMB_WEAPON)) + item.SetFlagField(WMUTANT_CONF_DISABLE_BOMB_WEAPON, true); + + if (item.TestOcb(WMUTANT_OCB_DISABLE_DART_WEAPON)) + item.SetFlagField(WMUTANT_CONF_DISABLE_DART_WEAPON, true); + + if (item.TestOcb(WMUTANT_OCB_DISABLE_BOMB_WEAPON)) + item.RemoveOcb(WMUTANT_OCB_DISABLE_BOMB_WEAPON); + + if (item.TestOcb(WMUTANT_OCB_DISABLE_DART_WEAPON)) + item.RemoveOcb(WMUTANT_OCB_DISABLE_DART_WEAPON); + + if (item.TestOcb(WMUTANT_OCB_NO_WINGS)) + item.RemoveOcb(WMUTANT_OCB_NO_WINGS); + } + + void ControlWingedMutant(short itemNumber) + { + if (!CreatureActive(itemNumber)) + return; + + auto& item = g_Level.Items[itemNumber]; + auto& creature = *GetCreatureInfo(&item); + + short headingAngle = 0; + short headYOrient = 0; + short torsoYOrient = 0; // Only when shooting. + + bool enableFlying = item.TestFlagField(WMUTANT_CONF_CAN_FLY, true); + bool isFlying = item.TestFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_AERIAL); + + InitializeWingedMutantOCB(item); + + if (item.HitPoints <= 0) + { + CreatureDie(itemNumber, true, BODY_DO_EXPLOSION | BODY_PART_EXPLODE | BODY_NO_SMOKE | BODY_NO_SHATTER_EFFECT); + + auto pos = item.Pose; + pos.Position.y -= CLICK(3); + TriggerExplosionSparks(pos.Position.x, pos.Position.y, pos.Position.z, 3, -2, 0, item.RoomNumber); + TriggerExplosionSparks(pos.Position.x, pos.Position.y, pos.Position.z, 3, -1, 0, item.RoomNumber); + TriggerShockwave(&pos, 48, 304, (GetRandomControl() & 0x1F) + 112, 128, 32, 32, 32, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); + + SoundEffect(SFX_TR1_ATLANTEAN_EXPLODE, &item.Pose); + return; + } + else + { + AI_INFO ai; + SwitchPathfinding(item, WMUTANT_PATH_GROUND); + CreatureAIInfo(&item, &ai); + + bool isSameZoneInGroundMode = (ai.zoneNumber == ai.enemyZone); + auto projectileType = CanTargetPlayer(item, ai); + + if (enableFlying && item.Animation.ActiveState == WMUTANT_STATE_FLY) + { + SwitchPathfinding(item, WMUTANT_PATH_AERIAL); + CreatureAIInfo(&item, &ai); + } + + if (ai.ahead) + { + headYOrient = ai.angle; + } + else + { + headYOrient = 0; + torsoYOrient = 0; + } + + GetCreatureMood(&item, &ai, isFlying); + CreatureMood(&item, &ai, isFlying); + headingAngle = CreatureTurn(&item, creature.MaxTurn); + + switch (item.Animation.ActiveState) + { + case WMUTANT_STATE_INACTIVE: + creature.MaxTurn = 0; + creature.Flags = 0; + + if (TargetVisible(&item, &ai) || creature.HurtByLara) + item.Animation.TargetState = WMUTANT_STATE_IDLE; + + break; + + case WMUTANT_STATE_IDLE: + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PROJ_NONE); + creature.MaxTurn = 0; + creature.Flags = 0; + torsoYOrient = 0; + + if (enableFlying && !isSameZoneInGroundMode) + { + item.Animation.TargetState = WMUTANT_STATE_FLY; + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_AERIAL); + } + else if (item.TouchBits.Test(WingedMutantHeadJoints)) + { + item.Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; + } + else if (ai.bite && ai.distance < WINGED_MUTANT_IDLE_JUMP_ATTACK_RANGE) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE_JUMP_ATTACK; + } + else if (ai.bite && ai.distance < WINGED_MUTANT_SWIPE_ATTACK_RANGE) + { + item.Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; + } + else if (projectileType == WMUTANT_PROJ_DART) + { + item.Animation.TargetState = WMUTANT_STATE_AIM_DART; + } + else if (projectileType == WMUTANT_PROJ_BOMB) + { + item.Animation.TargetState = WMUTANT_STATE_AIM_BOMB; + } + else if (creature.Mood == MoodType::Bored || + (creature.Mood == MoodType::Stalk && ai.distance < WINGED_MUTANT_POSE_RANGE)) + { + item.Animation.TargetState = WMUTANT_STATE_POSE; + } + else + { + item.Animation.TargetState = WMUTANT_STATE_RUN_FORWARD; + } + + break; + + case WMUTANT_STATE_POSE: + creature.Flags = 0; + creature.MaxTurn = 0; + headYOrient = 0; // NOTE: Pose has animation for head. + + if (projectileType != WMUTANT_PROJ_NONE || (isFlying && enableFlying)) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + else if (creature.Mood == MoodType::Stalk) + { + if (ai.distance < WINGED_MUTANT_WALK_RANGE) + { + if (isSameZoneInGroundMode || + Random::TestProbability(WINGED_MUTANT_UNPOSE_CHANCE)) + { + item.Animation.TargetState = WMUTANT_STATE_WALK_FORWARD; + } + } + else + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + } + else if (creature.Mood == MoodType::Bored && Random::TestProbability(WINGED_MUTANT_UNPOSE_CHANCE)) + { + item.Animation.TargetState = WMUTANT_STATE_WALK_FORWARD; + } + else if (creature.Mood == MoodType::Attack || + creature.Mood == MoodType::Escape) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + + break; + + case WMUTANT_STATE_WALK_FORWARD: + creature.MaxTurn = WINGED_MUTANT_WALK_TURN_RATE_MAX; + creature.Flags = 0; + + if (projectileType != WMUTANT_PROJ_NONE || (isFlying && enableFlying)) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + else if (creature.Mood == MoodType::Attack || creature.Mood == MoodType::Escape) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + else if (creature.Mood == MoodType::Bored || + (creature.Mood == MoodType::Stalk && !isSameZoneInGroundMode)) + { + if (Random::TestProbability(WINGED_MUTANT_POSE_CHANCE)) + item.Animation.TargetState = WMUTANT_STATE_POSE; + } + else if (creature.Mood == MoodType::Stalk && + ai.distance > WINGED_MUTANT_WALK_RANGE) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + + break; + + case WMUTANT_STATE_RUN_FORWARD: + creature.MaxTurn = WINGED_MUTANT_RUN_TURN_RATE_MAX; + creature.Flags = 0; + + if (enableFlying && !isSameZoneInGroundMode) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + else if (projectileType != WMUTANT_PROJ_NONE) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + else if (item.TouchBits.Test(WingedMutantHeadJoints)) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + else if (ai.bite && ai.distance < WINGED_MUTANT_RUN_JUMP_ATTACK_RANGE) + { + item.Animation.TargetState = WMUTANT_STATE_RUN_JUMP_ATTACK; + } + else if (ai.bite && ai.distance < WINGED_MUTANT_SWIPE_ATTACK_RANGE) + { + item.Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; + } + else if (ai.ahead && ai.distance < WINGED_MUTANT_SWIPE_ATTACK_RANGE) + { + item.Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; + } + else if (creature.Mood == MoodType::Bored || + (creature.Mood == MoodType::Stalk && ai.distance < WINGED_MUTANT_POSE_RANGE)) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + + break; + + case WMUTANT_STATE_IDLE_JUMP_ATTACK: + if (item.Animation.RequiredState == NO_VALUE && + (item.TouchBits.Test(WingedMutantHandsJoints) || item.TouchBits.Test(WingedMutantHeadJoints)) && creature.Flags == 0) + { + DoDamage(creature.Enemy, WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE / 2); + CreatureEffect(&item, WingedMutantBiteLeftHand, DoBloodSplat); + + DoDamage(creature.Enemy, WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE / 2); + CreatureEffect(&item, WingedMutantBiteRightHand, DoBloodSplat); + + item.Animation.TargetState = WMUTANT_STATE_IDLE; + creature.Flags = 1; + } + + break; + + case WMUTANT_STATE_RUN_JUMP_ATTACK: + if (item.Animation.RequiredState == NO_VALUE && + (item.TouchBits.Test(WingedMutantHandsJoints) || item.TouchBits.Test(WingedMutantHeadJoints)) && creature.Flags == 0) + { + DoDamage(creature.Enemy, WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE / 2); + CreatureEffect(&item, WingedMutantBiteLeftHand, DoBloodSplat); + + DoDamage(creature.Enemy, WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE / 2); + CreatureEffect(&item, WingedMutantBiteRightHand, DoBloodSplat); + + item.Animation.TargetState = WMUTANT_STATE_RUN_FORWARD; + creature.Flags = 1; + } + + break; + + case WMUTANT_STATE_SWIPE_ATTACK: + if (item.Animation.RequiredState == NO_VALUE && + item.TouchBits.Test(WingedMutantHandsJoints) && creature.Flags == 0) + { + DoDamage(creature.Enemy, WINGED_MUTANT_SWIPE_ATTACK_DAMAGE / 2); + CreatureEffect(&item, WingedMutantBiteLeftHand, DoBloodSplat); + + DoDamage(creature.Enemy, WINGED_MUTANT_SWIPE_ATTACK_DAMAGE / 2); + CreatureEffect(&item, WingedMutantBiteRightHand, DoBloodSplat); + + item.Animation.TargetState = WMUTANT_STATE_IDLE; + creature.Flags = 1; + } + + break; + + case WMUTANT_STATE_AIM_DART: + item.SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_DART); + creature.MaxTurn = 0; + creature.Flags = 0; + torsoYOrient = ai.angle / 2; + + if (projectileType == WMUTANT_PROJ_DART) + { + item.Animation.TargetState = WMUTANT_STATE_SHOOT; + } + else + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + + break; + + case WMUTANT_STATE_AIM_BOMB: + item.SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_BOMB); + creature.MaxTurn = 0; + creature.Flags = 0; + torsoYOrient = ai.angle / 2; + + if (projectileType == WMUTANT_PROJ_BOMB) + { + item.Animation.TargetState = WMUTANT_STATE_SHOOT; + } + else + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; + } + + break; + + case WMUTANT_STATE_SHOOT: + creature.MaxTurn = 0; + torsoYOrient = ai.angle / 2; + + if (creature.Flags == 0) + { + if (projectileType == WMUTANT_PROJ_DART) + { + CreatureEffect2(&item, WingedMutantShardBite, WINGED_MUTANT_SHARD_VELOCITY, torsoYOrient, ShardGun); + } + else if (projectileType == WMUTANT_PROJ_BOMB) + { + CreatureEffect2(&item, WingedMutantRocketBite, WINGED_MUTANT_BOMB_VELOCITY, torsoYOrient, BombGun); + } + + creature.Flags = 1; + } + + item.SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_NONE); + break; + + case WMUTANT_STATE_FLY: + if (creature.Mood != MoodType::Escape && isSameZoneInGroundMode) + { + item.Animation.TargetState = WMUTANT_STATE_IDLE; // Switch to ground mode. + item.Pose.Position.y = item.Floor; + item.SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); + } + + break; + } + } + + CreatureJoint(&item, 0, torsoYOrient); + CreatureJoint(&item, 1, headYOrient); + CreatureAnimation(itemNumber, headingAngle, 0); + } +} diff --git a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.h b/TombEngine/Objects/TR1/Entity/WingedMutant.h similarity index 69% rename from TombEngine/Objects/TR1/Entity/tr1_winged_mutant.h rename to TombEngine/Objects/TR1/Entity/WingedMutant.h index 96eefbf9d..9ed5600f7 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.h +++ b/TombEngine/Objects/TR1/Entity/WingedMutant.h @@ -3,6 +3,5 @@ namespace TEN::Entities::Creatures::TR1 { void InitializeWingedMutant(short itemNumber); - void WingedMutantControl(short itemNumber); + void ControlWingedMutant(short itemNumber); } - diff --git a/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp b/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp deleted file mode 100644 index 4e0904cdb..000000000 --- a/TombEngine/Objects/TR1/Entity/tr1_centaur.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include "framework.h" -#include "Objects/TR1/Entity/tr1_centaur.h" - -#include "Game/animation.h" -#include "Game/control/box.h" -#include "Game/collision/collide_item.h" -#include "Game/collision/collide_room.h" -#include "Game/effects/effects.h" -#include "Game/effects/tomb4fx.h" -#include "Game/items.h" -#include "Game/Lara/lara.h" -#include "Game/Lara/lara_one_gun.h" -#include "Game/misc.h" -#include "Game/missile.h" -#include "Game/people.h" -#include "Game/Setup.h" -#include "Math/Math.h" -#include "Sound/sound.h" -#include "Specific/level.h" - -using namespace TEN::Math; - -namespace TEN::Entities::Creatures::TR1 -{ - constexpr auto CENTAUR_REAR_DAMAGE = 200; - constexpr auto CENTAUR_REAR_RANGE = BLOCK(3 / 2.0f); - constexpr auto CENTAUR_REAR_CHANCE = 1 / 340.0f; - constexpr auto CENTAUR_BOMB_VELOCITY = CLICK(1); - - constexpr auto CENTAUR_TURN_RATE_MAX = ANGLE(4.0f); - - const auto CentaurRocketBite = CreatureBiteInfo(Vector3(11, 415, 41), 13); - const auto CentaurRearBite = CreatureBiteInfo(Vector3(50, 30, 0), 5); - const auto CentaurAttackJoints = std::vector{ 0, 3, 4, 7, 8, 16, 17 }; - - enum CentaurState - { - // No state 0. - CENTAUR_STATE_IDLE = 1, - CENTAUR_PROJECTILE_ATTACK = 2, - CENTAUR_STATE_RUN_FORWARD = 3, - CENTAUR_STATE_AIM = 4, - CENTAUR_STATE_DEATH = 5, - CENTAUR_STATE_WARNING = 6 - }; - - // TODO - enum CentaurAnim - { - CENTAUR_ANIM_DEATH = 8, - }; - - void CentaurControl(short itemNumber) - { - if (!CreatureActive(itemNumber)) - return; - - auto* item = &g_Level.Items[itemNumber]; - auto* creature = GetCreatureInfo(item); - - short angle = 0; - short head = 0; - - if (item->HitPoints <= 0) - { - if (item->Animation.ActiveState != CENTAUR_STATE_DEATH) - SetAnimation(item, CENTAUR_ANIM_DEATH); - } - else - { - AI_INFO AI; - CreatureAIInfo(item, &AI); - - if (AI.ahead) - head = AI.angle; - - CreatureMood(item, &AI, true); - - angle = CreatureTurn(item, CENTAUR_TURN_RATE_MAX); - - switch (item->Animation.ActiveState) - { - case CENTAUR_STATE_IDLE: - CreatureJoint(item, 17, 0); - if (item->Animation.RequiredState != NO_VALUE) - item->Animation.TargetState = item->Animation.RequiredState; - else if (AI.bite && AI.distance < pow(CENTAUR_REAR_RANGE, 2)) - item->Animation.TargetState = CENTAUR_STATE_RUN_FORWARD; - else if (Targetable(item, &AI)) - item->Animation.TargetState = CENTAUR_STATE_AIM; - else - item->Animation.TargetState = CENTAUR_STATE_RUN_FORWARD; - - break; - - case CENTAUR_STATE_RUN_FORWARD: - if (AI.bite && AI.distance < pow(CENTAUR_REAR_RANGE, 2)) - { - item->Animation.TargetState = CENTAUR_STATE_IDLE; - item->Animation.RequiredState = CENTAUR_STATE_WARNING; - } - else if (Targetable(item, &AI)) - { - item->Animation.TargetState = CENTAUR_STATE_IDLE; - item->Animation.RequiredState = CENTAUR_STATE_AIM; - } - else if (Random::TestProbability(CENTAUR_REAR_CHANCE)) - { - item->Animation.TargetState = CENTAUR_STATE_IDLE; - item->Animation.RequiredState = CENTAUR_STATE_WARNING; - } - - break; - - case CENTAUR_STATE_AIM: - if (item->Animation.RequiredState != NO_VALUE) - item->Animation.TargetState = item->Animation.RequiredState; - else if (Targetable(item, &AI)) - item->Animation.TargetState = CENTAUR_PROJECTILE_ATTACK; - else - item->Animation.TargetState = CENTAUR_STATE_IDLE; - - break; - - case CENTAUR_PROJECTILE_ATTACK: - if (item->Animation.RequiredState == NO_VALUE) - { - item->Animation.RequiredState = CENTAUR_STATE_AIM; - CreatureEffect2(item, CentaurRocketBite, CENTAUR_BOMB_VELOCITY, head, BombGun); - } - - break; - - case CENTAUR_STATE_WARNING: - if (item->Animation.RequiredState == NO_VALUE && - item->TouchBits.Test(CentaurAttackJoints)) - { - DoDamage(creature->Enemy, CENTAUR_REAR_DAMAGE); - CreatureEffect(item, CentaurRearBite, DoBloodSplat); - item->Animation.RequiredState = CENTAUR_STATE_IDLE; - } - - break; - } - } - - CreatureJoint(item, 0, head); - CreatureAnimation(itemNumber, angle, 0); - - if (item->Status == ITEM_DEACTIVATED) - { - SoundEffect(SFX_TR1_ATLANTEAN_DEATH, &item->Pose); - ExplodingDeath(itemNumber, BODY_DO_EXPLOSION); - KillItem(itemNumber); - item->Status = ITEM_DEACTIVATED; - } - } -} diff --git a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp b/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp deleted file mode 100644 index d0f36cd62..000000000 --- a/TombEngine/Objects/TR1/Entity/tr1_winged_mutant.cpp +++ /dev/null @@ -1,571 +0,0 @@ -#include "framework.h" -#include "Objects/TR1/Entity/tr1_winged_mutant.h" - -#include "Game/collision/collide_room.h" -#include "Game/control/box.h" -#include "Game/control/lot.h" -#include "Game/effects/effects.h" -#include "Game/effects/tomb4fx.h" -#include "Game/itemdata/creature_info.h" -#include "Game/items.h" -#include "Game/misc.h" -#include "Game/missile.h" -#include "Game/people.h" -#include "Math/Math.h" -#include "Sound/sound.h" -#include "Specific/level.h" - -using namespace TEN::Math; - -namespace TEN::Entities::Creatures::TR1 -{ - constexpr auto WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE = 150; - constexpr auto WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE = 100; - constexpr auto WINGED_MUTANT_SWIPE_ATTACK_DAMAGE = 200; - - constexpr auto WINGED_MUTANT_WALK_RANGE = SQUARE(BLOCK(4.5f)); - constexpr auto WINGED_MUTANT_SWIPE_ATTACK_RANGE = SQUARE(BLOCK(0.3f)); - constexpr auto WINGED_MUTANT_RUN_JUMP_ATTACK_RANGE = SQUARE(BLOCK(0.65f)); - constexpr auto WINGED_MUTANT_IDLE_JUMP_ATTACK_RANGE = SQUARE(BLOCK(2.5f)); - constexpr auto WINGED_MUTANT_PROJECTILE_ATTACK_RANGE = SQUARE(BLOCK(3.0f)); - constexpr auto WINGED_MUTANT_POSE_RANGE = SQUARE(BLOCK(4.5f)); - - constexpr auto WINGED_MUTANT_POSE_CHANCE = 1 / 400.0f; - constexpr auto WINGED_MUTANT_UNPOSE_CHANCE = 1 / 164.0f; - - constexpr auto WINGED_MUTANT_FLY_VELOCITY = BLOCK(1 / 32.0f); - constexpr auto WINGED_MUTANT_SHARD_VELOCITY = 250; - constexpr auto WINGED_MUTANT_BOMB_VELOCITY = 220; - - constexpr auto WINGED_MUTANT_WALK_TURN_RATE_MAX = ANGLE(2.0f); - constexpr auto WINGED_MUTANT_RUN_TURN_RATE_MAX = ANGLE(6.0f); - - const auto WingedMutantBiteLeftHand = CreatureBiteInfo(Vector3(0, 0, 0), 7); - const auto WingedMutantBiteRightHand = CreatureBiteInfo(Vector3(0, 0, 0), 10); - const auto WingedMutantRocketBite = CreatureBiteInfo(Vector3(0, 200, 20), 6); - const auto WingedMutantShardBite = CreatureBiteInfo(Vector3(0, 200, 20), 9); - const auto WingedMutantHeadJoints = std::vector{ 3 }; - const auto WingedMutantHandsJoints = std::vector{ 7, 10 }; - const auto WingedMutantWingsJoints = std::vector{ 15, 16, 17, 18, 19, 20 }; - - enum WingedMutantState - { - // No state 0. - WMUTANT_STATE_IDLE = 1, - WMUTANT_STATE_WALK_FORWARD = 2, - WMUTANT_STATE_RUN_FORWARD = 3, - WMUTANT_STATE_IDLE_JUMP_ATTACK = 4, - WMUTANT_STATE_DEATH = 5, - WMUTANT_STATE_POSE = 6, - WMUTANT_STATE_RUN_JUMP_ATTACK = 7, - WMUTANT_STATE_SWIPE_ATTACK = 8, - WMUTANT_STATE_AIM_DART = 9, - WMUTANT_STATE_AIM_BOMB = 10, - WMUTANT_STATE_SHOOT = 11, - WMUTANT_STATE_INACTIVE = 12, - WMUTANT_STATE_FLY = 13, - }; - - enum WingedMutantAnim - { - WMUTANT_ANIM_INACTIVE = 0, - WMUTANT_ANIM_INACTIVE_TO_IDLE = 1, - WMUTANT_ANIM_IDLE = 2, - WMUTANT_ANIM_IDLE_TO_RUN = 3, - WMUTANT_ANIM_RUN_FORWARD = 4, - WMUTANT_ANIM_IDLE_JUMP_ATTACK_START = 5, - WMUTANT_ANIM_IDLE_JUMP_ATTACK_END = 6, - WMUTANT_ANIM_IDLE_TO_POSE = 7, - WMUTANT_ANIM_POSE = 8, - WMUTANT_ANIM_POSE_TO_IDLE = 9, - WMUTANT_ANIM_POSE_TO_WALK_FORWARD = 10, - WMUTANT_ANIM_WALK_FORWARD = 11, - WMUTANT_ANIM_WALK_FORWARD_TO_IDLE = 12, - WMUTANT_ANIM_WALK_FORWARD_TO_POSE = 13, - WMUTANT_ANIM_RUN_JUMP_ATTACK = 14, - WMUTANT_ANIM_IDLE_TO_AIM_1 = 15, - WMUTANT_ANIM_AIM_DART = 16, - WMUTANT_ANIM_SHOOT_DART = 17, - WMUTANT_ANIM_AIM_DART_TO_IDLE = 18, - WMUTANT_ANIM_IDLE_TO_AIM_BOMB = 19, - WMUTANT_ANIM_SHOOT_BOMB = 20, - WMUTANT_ANIM_RUN_FORWARD_TO_IDLE = 21, - WMUTANT_ANIM_AIM_BOMB_TO_IDLE = 22, - WMUTANT_ANIM_IDLE_TO_FLY = 23, - WMUTANT_ANIM_FLY = 24, - WMUTANT_ANIM_FLY_TO_IDLE = 25, - WMUTANT_ANIM_SWIPE_ATTACK = 26 - }; - - enum WingedMutantPathFinding - { - WMUTANT_PATH_GROUND = 1, - WMUTANT_PATH_AERIAL = 2 - }; - - // NOTE: Originally, winged mutants did not have OCBs. -- TokyoSU 5/8/2022 - enum WingedMutantOcb - { - WMUTANT_OCB_START_AERIAL = (1 << 0), - WMUTANT_OCB_START_INACTIVE = (1 << 1), - WMUTANT_OCB_START_POSE = (1 << 2), - WMUTANT_OCB_NO_WINGS = (1 << 3), - WMUTANT_OCB_DISABLE_DART_WEAPON = (1 << 4), - WMUTANT_OCB_DISABLE_BOMB_WEAPON = (1 << 5) - }; - - enum WingedMutantProjectileType - { - WMUTANT_PROJ_NONE, - WMUTANT_PROJ_DART, - WMUTANT_PROJ_BOMB - }; - - enum WingedMutantConfig - { - WMUTANT_CONF_CAN_FLY, - WMUTANT_CONF_PATHFINDING_MODE, - WMUTANT_CONF_PROJECTILE_MODE, - WMUTANT_CONF_NO_WINGS, - WMUTANT_CONF_DISABLE_DART_WEAPON, - WMUTANT_CONF_DISABLE_BOMB_WEAPON - }; - - static void SwitchPathfinding(CreatureInfo* creature, WingedMutantPathFinding path) - { - switch (path) - { - case WMUTANT_PATH_GROUND: - creature->LOT.Step = CLICK(1); - creature->LOT.Drop = -CLICK(1); - creature->LOT.Fly = NO_FLYING; - creature->LOT.Zone = ZoneType::Basic; - break; - - case WMUTANT_PATH_AERIAL: - creature->LOT.Step = BLOCK(20); - creature->LOT.Drop = -BLOCK(20); - creature->LOT.Fly = WINGED_MUTANT_FLY_VELOCITY; - creature->LOT.Zone = ZoneType::Flyer; - break; - } - } - - static WingedMutantProjectileType CanTargetLara(ItemInfo* item, CreatureInfo* creature, AI_INFO* AI) - { - if (Targetable(item, AI) && - (AI->zoneNumber != AI->enemyZone || AI->distance > WINGED_MUTANT_PROJECTILE_ATTACK_RANGE)) - { - if ((AI->angle > 0 && AI->angle < ANGLE(45.0f)) && - item->TestFlagField(WMUTANT_CONF_DISABLE_DART_WEAPON, false)) - { - return WMUTANT_PROJ_DART; - } - else if ((AI->angle < 0 && AI->angle > -ANGLE(45.0f)) && - item->TestFlagField(WMUTANT_CONF_DISABLE_BOMB_WEAPON, false)) - { - return WMUTANT_PROJ_BOMB; - } - } - - // Cannot be targeted. - return WMUTANT_PROJ_NONE; - } - - static void WingedInitOCB(ItemInfo* item, CreatureInfo* creature) - { - if (item->TestOcb(WMUTANT_OCB_START_AERIAL)) - { - SwitchPathfinding(creature, WMUTANT_PATH_AERIAL); - SetAnimation(item, WMUTANT_ANIM_FLY); - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_AERIAL); - } - else if (item->TestOcb(WMUTANT_OCB_START_INACTIVE)) - { - SwitchPathfinding(creature, WMUTANT_PATH_GROUND); - SetAnimation(item, WMUTANT_ANIM_INACTIVE); - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); - } - else if (item->TestOcb(WMUTANT_OCB_START_POSE)) - { - SwitchPathfinding(creature, WMUTANT_PATH_GROUND); - SetAnimation(item, WMUTANT_ANIM_INACTIVE); - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); - } - - // Remove unnecessary OCBs. - if (item->TestOcb(WMUTANT_OCB_START_AERIAL)) - item->RemoveOcb(WMUTANT_OCB_START_AERIAL); - - if (item->TestOcb(WMUTANT_OCB_START_INACTIVE)) - item->RemoveOcb(WMUTANT_OCB_START_INACTIVE); - - if (item->TestOcb(WMUTANT_OCB_START_POSE)) - item->RemoveOcb(WMUTANT_OCB_START_POSE); - } - - void InitializeWingedMutant(short itemNumber) - { - auto* item = &g_Level.Items[itemNumber]; - - InitializeCreature(itemNumber); - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); - item->SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_NONE); - - if (item->TestOcb(WMUTANT_OCB_NO_WINGS)) - { - item->SetFlagField(WMUTANT_CONF_CAN_FLY, false); - item->MeshBits.Clear(WingedMutantWingsJoints); - } - else - { - item->SetFlagField(WMUTANT_CONF_CAN_FLY, true); - } - - if (item->TestOcb(WMUTANT_OCB_DISABLE_BOMB_WEAPON)) - item->SetFlagField(WMUTANT_CONF_DISABLE_BOMB_WEAPON, true); - - if (item->TestOcb(WMUTANT_OCB_DISABLE_DART_WEAPON)) - item->SetFlagField(WMUTANT_CONF_DISABLE_DART_WEAPON, true); - - if (item->TestOcb(WMUTANT_OCB_DISABLE_BOMB_WEAPON)) - item->RemoveOcb(WMUTANT_OCB_DISABLE_BOMB_WEAPON); - - if (item->TestOcb(WMUTANT_OCB_DISABLE_DART_WEAPON)) - item->RemoveOcb(WMUTANT_OCB_DISABLE_DART_WEAPON); - - if (item->TestOcb(WMUTANT_OCB_NO_WINGS)) - item->RemoveOcb(WMUTANT_OCB_NO_WINGS); - } - - void WingedMutantControl(short itemNumber) - { - if (!CreatureActive(itemNumber)) - return; - - auto* item = &g_Level.Items[itemNumber]; - auto* creature = GetCreatureInfo(item); - - short angle = 0; - short head = 0; - short torso = 0; // Only when shooting. - - bool flyEnabled = item->TestFlagField(WMUTANT_CONF_CAN_FLY, true); - bool flyStatus = item->TestFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_AERIAL); - - WingedInitOCB(item, creature); - - if (item->HitPoints <= 0) - { - CreatureDie(itemNumber, true, BODY_DO_EXPLOSION | BODY_PART_EXPLODE | BODY_NO_SMOKE | BODY_NO_SHATTER_EFFECT); - - auto pos = item->Pose; - pos.Position.y -= CLICK(3); - TriggerExplosionSparks(pos.Position.x, pos.Position.y, pos.Position.z, 3, -2, 0, item->RoomNumber); - TriggerExplosionSparks(pos.Position.x, pos.Position.y, pos.Position.z, 3, -1, 0, item->RoomNumber); - TriggerShockwave(&pos, 48, 304, (GetRandomControl() & 0x1F) + 112, 128, 32, 32, 32, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); - - SoundEffect(SFX_TR1_ATLANTEAN_EXPLODE, &item->Pose); - return; - } - else - { - AI_INFO ai; - SwitchPathfinding(creature, WMUTANT_PATH_GROUND); - CreatureAIInfo(item, &ai); - - bool isSameZoneInGroundMode = (ai.zoneNumber == ai.enemyZone); - auto projectileType = CanTargetLara(item, creature, &ai); - - if (flyEnabled && item->Animation.ActiveState == WMUTANT_STATE_FLY) - { - SwitchPathfinding(creature, WMUTANT_PATH_AERIAL); - CreatureAIInfo(item, &ai); - } - - if (ai.ahead) - { - head = ai.angle; - } - else - { - head = 0; - torso = 0; - } - - GetCreatureMood(item, &ai, flyStatus); - CreatureMood(item, &ai, flyStatus); - angle = CreatureTurn(item, creature->MaxTurn); - - switch (item->Animation.ActiveState) - { - case WMUTANT_STATE_INACTIVE: - creature->MaxTurn = 0; - creature->Flags = 0; - - if (TargetVisible(item, &ai) || creature->HurtByLara) - item->Animation.TargetState = WMUTANT_STATE_IDLE; - - break; - - case WMUTANT_STATE_IDLE: - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PROJ_NONE); - creature->MaxTurn = 0; - creature->Flags = 0; - torso = 0; - - if (flyEnabled && !isSameZoneInGroundMode) - { - item->Animation.TargetState = WMUTANT_STATE_FLY; - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_AERIAL); - } - else if (item->TouchBits.Test(WingedMutantHeadJoints)) - { - item->Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; - } - else if (ai.bite && ai.distance < WINGED_MUTANT_IDLE_JUMP_ATTACK_RANGE) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE_JUMP_ATTACK; - } - else if (ai.bite && ai.distance < WINGED_MUTANT_SWIPE_ATTACK_RANGE) - { - item->Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; - } - else if (projectileType == WMUTANT_PROJ_DART) - { - item->Animation.TargetState = WMUTANT_STATE_AIM_DART; - } - else if (projectileType == WMUTANT_PROJ_BOMB) - { - item->Animation.TargetState = WMUTANT_STATE_AIM_BOMB; - } - else if (creature->Mood == MoodType::Bored || - (creature->Mood == MoodType::Stalk && ai.distance < WINGED_MUTANT_POSE_RANGE)) - { - item->Animation.TargetState = WMUTANT_STATE_POSE; - } - else - { - item->Animation.TargetState = WMUTANT_STATE_RUN_FORWARD; - } - - break; - - case WMUTANT_STATE_POSE: - creature->Flags = 0; - creature->MaxTurn = 0; - head = 0; // NOTE: Pose has animation for head. - - if (projectileType != WMUTANT_PROJ_NONE || (flyStatus && flyEnabled)) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - else if (creature->Mood == MoodType::Stalk) - { - if (ai.distance < WINGED_MUTANT_WALK_RANGE) - { - if (isSameZoneInGroundMode || - Random::TestProbability(WINGED_MUTANT_UNPOSE_CHANCE)) - { - item->Animation.TargetState = WMUTANT_STATE_WALK_FORWARD; - } - } - else - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - } - else if (creature->Mood == MoodType::Bored && Random::TestProbability(WINGED_MUTANT_UNPOSE_CHANCE)) - { - item->Animation.TargetState = WMUTANT_STATE_WALK_FORWARD; - } - else if (creature->Mood == MoodType::Attack || - creature->Mood == MoodType::Escape) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - - break; - - case WMUTANT_STATE_WALK_FORWARD: - creature->MaxTurn = WINGED_MUTANT_WALK_TURN_RATE_MAX; - creature->Flags = 0; - - if (projectileType != WMUTANT_PROJ_NONE || (flyStatus && flyEnabled)) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - else if (creature->Mood == MoodType::Attack || creature->Mood == MoodType::Escape) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - else if (creature->Mood == MoodType::Bored || - (creature->Mood == MoodType::Stalk && !isSameZoneInGroundMode)) - { - if (Random::TestProbability(WINGED_MUTANT_POSE_CHANCE)) - item->Animation.TargetState = WMUTANT_STATE_POSE; - } - else if (creature->Mood == MoodType::Stalk && - ai.distance > WINGED_MUTANT_WALK_RANGE) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - - break; - - case WMUTANT_STATE_RUN_FORWARD: - creature->MaxTurn = WINGED_MUTANT_RUN_TURN_RATE_MAX; - creature->Flags = 0; - - if (flyEnabled && !isSameZoneInGroundMode) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - else if (projectileType != WMUTANT_PROJ_NONE) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - else if (item->TouchBits.Test(WingedMutantHeadJoints)) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - else if (ai.bite && ai.distance < WINGED_MUTANT_RUN_JUMP_ATTACK_RANGE) - { - item->Animation.TargetState = WMUTANT_STATE_RUN_JUMP_ATTACK; - } - else if (ai.bite && ai.distance < WINGED_MUTANT_SWIPE_ATTACK_RANGE) - { - item->Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; - } - else if (ai.ahead && ai.distance < WINGED_MUTANT_SWIPE_ATTACK_RANGE) - { - item->Animation.TargetState = WMUTANT_STATE_SWIPE_ATTACK; - } - else if (creature->Mood == MoodType::Bored || - (creature->Mood == MoodType::Stalk && ai.distance < WINGED_MUTANT_POSE_RANGE)) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - - break; - - case WMUTANT_STATE_IDLE_JUMP_ATTACK: - if (item->Animation.RequiredState == NO_VALUE && - (item->TouchBits.Test(WingedMutantHandsJoints) || item->TouchBits.Test(WingedMutantHeadJoints)) && creature->Flags == 0) - { - DoDamage(creature->Enemy, WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE / 2); - CreatureEffect(item, WingedMutantBiteLeftHand, DoBloodSplat); - - DoDamage(creature->Enemy, WINGED_MUTANT_IDLE_JUMP_ATTACK_DAMAGE / 2); - CreatureEffect(item, WingedMutantBiteRightHand, DoBloodSplat); - - item->Animation.TargetState = WMUTANT_STATE_IDLE; - creature->Flags = 1; - } - - break; - - case WMUTANT_STATE_RUN_JUMP_ATTACK: - if (item->Animation.RequiredState == NO_VALUE && - (item->TouchBits.Test(WingedMutantHandsJoints) || item->TouchBits.Test(WingedMutantHeadJoints)) && creature->Flags == 0) - { - DoDamage(creature->Enemy, WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE / 2); - CreatureEffect(item, WingedMutantBiteLeftHand, DoBloodSplat); - - DoDamage(creature->Enemy, WINGED_MUTANT_RUN_JUMP_ATTACK_DAMAGE / 2); - CreatureEffect(item, WingedMutantBiteRightHand, DoBloodSplat); - - item->Animation.TargetState = WMUTANT_STATE_RUN_FORWARD; - creature->Flags = 1; - } - - break; - - case WMUTANT_STATE_SWIPE_ATTACK: - if (item->Animation.RequiredState == NO_VALUE && - item->TouchBits.Test(WingedMutantHandsJoints) && creature->Flags == 0) - { - DoDamage(creature->Enemy, WINGED_MUTANT_SWIPE_ATTACK_DAMAGE / 2); - CreatureEffect(item, WingedMutantBiteLeftHand, DoBloodSplat); - - DoDamage(creature->Enemy, WINGED_MUTANT_SWIPE_ATTACK_DAMAGE / 2); - CreatureEffect(item, WingedMutantBiteRightHand, DoBloodSplat); - - item->Animation.TargetState = WMUTANT_STATE_IDLE; - creature->Flags = 1; - } - - break; - - case WMUTANT_STATE_AIM_DART: - item->SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_DART); - creature->MaxTurn = 0; - creature->Flags = 0; - torso = ai.angle / 2; - - if (projectileType == WMUTANT_PROJ_DART) - { - item->Animation.TargetState = WMUTANT_STATE_SHOOT; - } - else - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - - break; - - case WMUTANT_STATE_AIM_BOMB: - item->SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_BOMB); - creature->MaxTurn = 0; - creature->Flags = 0; - torso = ai.angle / 2; - - if (projectileType == WMUTANT_PROJ_BOMB) - { - item->Animation.TargetState = WMUTANT_STATE_SHOOT; - } - else - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; - } - - break; - - case WMUTANT_STATE_SHOOT: - creature->MaxTurn = 0; - torso = ai.angle / 2; - - if (creature->Flags == 0) - { - if (projectileType == WMUTANT_PROJ_DART) - { - CreatureEffect2(item, WingedMutantShardBite, WINGED_MUTANT_SHARD_VELOCITY, torso, ShardGun); - } - else if (projectileType == WMUTANT_PROJ_BOMB) - { - CreatureEffect2(item, WingedMutantRocketBite, WINGED_MUTANT_BOMB_VELOCITY, torso, BombGun); - } - - creature->Flags = 1; - } - - item->SetFlagField(WMUTANT_CONF_PROJECTILE_MODE, WMUTANT_PROJ_NONE); - break; - - case WMUTANT_STATE_FLY: - if (creature->Mood != MoodType::Escape && isSameZoneInGroundMode) - { - item->Animation.TargetState = WMUTANT_STATE_IDLE; // Switch to ground mode. - item->Pose.Position.y = item->Floor; - item->SetFlagField(WMUTANT_CONF_PATHFINDING_MODE, WMUTANT_PATH_GROUND); - } - - break; - } - } - - CreatureJoint(item, 0, torso); - CreatureJoint(item, 1, head); - CreatureAnimation(itemNumber, angle, 0); - } -} diff --git a/TombEngine/Objects/TR1/tr1_objects.cpp b/TombEngine/Objects/TR1/tr1_objects.cpp index 3a051cd50..9801d446f 100644 --- a/TombEngine/Objects/TR1/tr1_objects.cpp +++ b/TombEngine/Objects/TR1/tr1_objects.cpp @@ -10,18 +10,18 @@ #include "Specific/level.h" // Creatures -#include "Objects/TR1/Entity/Cowboy.h" // OK -#include "Objects/TR1/Entity/Kold.h" // OK -#include "Objects/TR1/Entity/tr1_ape.h" // OK -#include "Objects/TR1/Entity/tr1_bear.h" // OK -#include "Objects/TR1/Entity/tr1_doppelganger.h" // OK -#include "Objects/TR1/Entity/tr1_natla.h" // OK -#include "Objects/TR1/Entity/tr1_giant_mutant.h" // OK -#include "Objects/TR1/Entity/tr1_wolf.h" // OK -#include "Objects/TR1/Entity/tr1_big_rat.h" // OK -#include "Objects/TR1/Entity/tr1_centaur.h" // OK -#include "Objects/TR1/Entity/tr1_winged_mutant.h" // OK -#include "Objects/TR1/Entity/SkateboardKid.h" // OK +#include "Objects/TR1/Entity/Centaur.h" +#include "Objects/TR1/Entity/Cowboy.h" +#include "Objects/TR1/Entity/Kold.h" +#include "Objects/TR1/Entity/SkateboardKid.h" +#include "Objects/TR1/Entity/WingedMutant.h" +#include "Objects/TR1/Entity/tr1_ape.h" +#include "Objects/TR1/Entity/tr1_bear.h" +#include "Objects/TR1/Entity/tr1_doppelganger.h" +#include "Objects/TR1/Entity/tr1_natla.h" +#include "Objects/TR1/Entity/tr1_giant_mutant.h" +#include "Objects/TR1/Entity/tr1_wolf.h" +#include "Objects/TR1/Entity/tr1_big_rat.h" #include "Objects/Utils/object_helper.h" // Traps @@ -149,7 +149,7 @@ static void StartEntity(ObjectInfo* obj) if (obj->loaded) { obj->Initialize = InitializeCreature; - obj->control = CentaurControl; + obj->control = ControlCentaur; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; obj->HitPoints = 120; @@ -165,7 +165,7 @@ static void StartEntity(ObjectInfo* obj) if (obj->loaded) { obj->Initialize = InitializeWingedMutant; - obj->control = WingedMutantControl; + obj->control = ControlWingedMutant; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; obj->pivotLength = 150; diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index b9a6701e9..6f8cf8200 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -483,18 +483,18 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + - - + @@ -991,18 +991,18 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + - - + From 3ad7b1f5de4552f1909fe6c3d7df1a1ce7ce795e Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 6 Aug 2024 22:09:58 +1000 Subject: [PATCH 243/410] Tidy up room struct --- TombEngine/Game/camera.cpp | 12 +-- TombEngine/Game/collision/Point.cpp | 4 +- TombEngine/Game/collision/collide_item.cpp | 8 +- TombEngine/Game/collision/collide_room.cpp | 58 +++++++-------- TombEngine/Game/collision/floordata.cpp | 46 ++++++------ TombEngine/Game/control/box.cpp | 22 +++--- TombEngine/Game/control/los.cpp | 2 +- TombEngine/Game/control/lot.cpp | 2 +- TombEngine/Game/control/volume.cpp | 4 +- TombEngine/Game/effects/bubble.cpp | 4 +- TombEngine/Game/effects/tomb4fx.cpp | 4 +- TombEngine/Game/items.cpp | 2 +- TombEngine/Game/room.cpp | 54 +++++++------- TombEngine/Game/room.h | 31 ++++---- TombEngine/Game/savegame.cpp | 30 ++++---- .../Objects/Generic/Doors/generic_doors.cpp | 16 ++-- .../Object/Pushable/PushableCollision.cpp | 4 +- .../Generic/Object/generic_trapdoor.cpp | 4 +- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 2 +- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 2 +- TombEngine/Objects/TR4/Entity/Wraith.cpp | 6 +- .../Objects/TR4/Entity/tr4_knight_templar.cpp | 2 +- .../Objects/TR5/Emitter/tr5_rats_emitter.cpp | 8 +- .../TR5/Emitter/tr5_spider_emitter.cpp | 4 +- .../Objects/TR5/Entity/tr5_gladiator.cpp | 2 +- TombEngine/Objects/TR5/Entity/tr5_larson.cpp | 6 +- .../Objects/TR5/Entity/tr5_roman_statue.cpp | 8 +- .../TR5/Object/tr5_twoblockplatform.cpp | 2 +- .../Objects/TR5/Shatter/tr5_smashobject.cpp | 8 +- TombEngine/Renderer/RendererCompatibility.cpp | 18 ++--- TombEngine/Renderer/RendererDrawMenu.cpp | 4 +- .../Internal/TEN/Objects/ObjectsHandler.h | 2 +- .../Internal/TEN/Objects/Room/RoomObject.cpp | 10 +-- TombEngine/Specific/level.cpp | 74 +++++++++---------- 34 files changed, 230 insertions(+), 235 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 431de8ce8..b6fe8b185 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -166,7 +166,7 @@ void LookCamera(ItemInfo& item, const CollisionInfo& coll) bool isInSwamp = TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber); auto basePos = Vector3i( item.Pose.Position.x, - isInSwamp ? g_Level.Rooms[item.RoomNumber].maxceiling : item.Pose.Position.y, + isInSwamp ? g_Level.Rooms[item.RoomNumber].TopHeight : item.Pose.Position.y, item.Pose.Position.z); // Define landmarks. @@ -343,7 +343,7 @@ void MoveCamera(GameVector* ideal, int speed) int y = Camera.pos.y; if (TestEnvironment(ENV_FLAG_SWAMP, Camera.pos.RoomNumber)) - y = g_Level.Rooms[Camera.pos.RoomNumber].y - CLICK(1); + y = g_Level.Rooms[Camera.pos.RoomNumber].Position.y - CLICK(1); auto pointColl = GetPointCollision(Vector3i(Camera.pos.x, y, Camera.pos.z), Camera.pos.RoomNumber); if (y < pointColl.GetCeilingHeight() || @@ -534,7 +534,7 @@ void ChaseCamera(ItemInfo* item) auto pointColl = GetPointCollision(Vector3i(Camera.target.x, Camera.target.y + CLICK(1), Camera.target.z), Camera.target.RoomNumber); if (TestEnvironment(ENV_FLAG_SWAMP, pointColl.GetRoomNumber())) - Camera.target.y = g_Level.Rooms[pointColl.GetRoomNumber()].maxceiling - CLICK(1); + Camera.target.y = g_Level.Rooms[pointColl.GetRoomNumber()].TopHeight - CLICK(1); int y = Camera.target.y; pointColl = GetPointCollision(Vector3i(Camera.target.x, y, Camera.target.z), Camera.target.RoomNumber); @@ -652,7 +652,7 @@ void CombatCamera(ItemInfo* item) auto pointColl = GetPointCollision(Vector3i(Camera.target.x, Camera.target.y + CLICK(1), Camera.target.z), Camera.target.RoomNumber); if (TestEnvironment(ENV_FLAG_SWAMP, pointColl.GetRoomNumber())) - Camera.target.y = g_Level.Rooms[pointColl.GetRoomNumber()].y - CLICK(1); + Camera.target.y = g_Level.Rooms[pointColl.GetRoomNumber()].Position.y - CLICK(1); pointColl = GetPointCollision(Camera.target.ToVector3i(), Camera.target.RoomNumber); Camera.target.RoomNumber = pointColl.GetRoomNumber(); @@ -1393,7 +1393,7 @@ bool CheckItemCollideCamera(ItemInfo* item) static std::vector FillCollideableItemList() { auto itemList = std::vector{}; - auto& roomList = g_Level.Rooms[Camera.pos.RoomNumber].neighbors; + auto& roomList = g_Level.Rooms[Camera.pos.RoomNumber].NeighborRoomNumbers; for (short i = 0; i < g_Level.NumItems; i++) { @@ -1443,7 +1443,7 @@ bool CheckStaticCollideCamera(MESH_INFO* mesh) std::vector FillCollideableStaticsList() { std::vector staticList; - auto& roomList = g_Level.Rooms[Camera.pos.RoomNumber].neighbors; + auto& roomList = g_Level.Rooms[Camera.pos.RoomNumber].NeighborRoomNumbers; for (int i : roomList) { diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index 45f1b3fc2..b7e49bdd2 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -57,7 +57,7 @@ namespace TEN::Collision::Point int roomNumber = roomNumberBelow.value_or(bottomSector->RoomNumber); auto& room = g_Level.Rooms[roomNumber]; - bottomSector = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); + bottomSector = Room::GetSector(&room, _position.x - room.Position.x, _position.z - room.Position.z); roomNumberBelow = bottomSector->GetNextRoomNumber(_position, true); } _bottomSector = bottomSector; @@ -78,7 +78,7 @@ namespace TEN::Collision::Point int roomNumber = roomNumberAbove.value_or(topSector->RoomNumber); auto& room = g_Level.Rooms[roomNumber]; - topSector = Room::GetSector(&room, _position.x - room.x, _position.z - room.z); + topSector = Room::GetSector(&room, _position.x - room.Position.x, _position.z - room.Position.z); roomNumberAbove = topSector->GetNextRoomNumber(_position, false); } _topSector = topSector; diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 077c77cc8..bcefa102c 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -123,7 +123,7 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, // Run through neighboring rooms. const auto& room = g_Level.Rooms[collidingItem.RoomNumber]; - for (int roomNumber : room.neighbors) + for (int roomNumber : room.NeighborRoomNumbers) { auto& neighborRoom = g_Level.Rooms[roomNumber]; if (!neighborRoom.Active()) @@ -307,7 +307,7 @@ void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll) // DrawDebugSphere(origin, 16, Vector4::One, RendererDebugPage::CollisionStats); - for (auto i : g_Level.Rooms[item->RoomNumber].neighbors) + for (auto i : g_Level.Rooms[item->RoomNumber].NeighborRoomNumbers) { if (!g_Level.Rooms[i].Active()) continue; @@ -940,7 +940,7 @@ void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll) { coll->HitTallObject = false; - for (auto i : g_Level.Rooms[item->RoomNumber].neighbors) + for (auto i : g_Level.Rooms[item->RoomNumber].NeighborRoomNumbers) { if (!g_Level.Rooms[i].Active()) continue; @@ -1809,7 +1809,7 @@ void DoObjectCollision(ItemInfo* item, CollisionInfo* coll) return; const auto& room = g_Level.Rooms[item->RoomNumber]; - for (int neighborRoomNumber : room.neighbors) + for (int neighborRoomNumber : room.NeighborRoomNumbers) { auto& neighborRoom = g_Level.Rooms[neighborRoomNumber]; if (!neighborRoom.Active()) diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index 04670f47a..d453e172e 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -1084,7 +1084,7 @@ int GetDistanceToFloor(int itemNumber, bool precise) int GetWaterSurface(int x, int y, int z, short roomNumber) { auto* room = &g_Level.Rooms[roomNumber]; - auto* sector = GetSector(room, x - room->x, z - room->z); + auto* sector = GetSector(room, x - room->Position.x, z - room->Position.z); if (TestEnvironment(ENV_FLAG_WATER, room)) { @@ -1094,7 +1094,7 @@ int GetWaterSurface(int x, int y, int z, short roomNumber) if (!TestEnvironment(ENV_FLAG_WATER, room)) return (sector->GetSurfaceHeight(x, z, false)); - sector = GetSector(room, x - room->x, z - room->z); + sector = GetSector(room, x - room->Position.x, z - room->Position.z); } return NO_HEIGHT; @@ -1107,7 +1107,7 @@ int GetWaterSurface(int x, int y, int z, short roomNumber) if (TestEnvironment(ENV_FLAG_WATER, room)) return (sector->GetSurfaceHeight(x, z, true)); - sector = GetSector(room, x - room->x, z - room->z); + sector = GetSector(room, x - room->Position.x, z - room->Position.z); } } @@ -1127,8 +1127,8 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) int adjoiningRoomNumber = NO_VALUE; do { - int xFloor = (x - room->x) / BLOCK(1); - int zFloor = (z - room->z) / BLOCK(1); + int xFloor = (x - room->Position.x) / BLOCK(1); + int zFloor = (z - room->Position.z) / BLOCK(1); if (zFloor <= 0) { @@ -1137,33 +1137,33 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) { xFloor = 1; } - else if (xFloor > (room->xSize - 2)) + else if (xFloor > (room->XSize - 2)) { - xFloor = room->xSize - 2; + xFloor = room->XSize - 2; } } - else if (zFloor >= (room->zSize - 1)) + else if (zFloor >= (room->ZSize - 1)) { - zFloor = room->zSize - 1; + zFloor = room->ZSize - 1; if (xFloor < 1) { xFloor = 1; } - else if (xFloor > (room->xSize - 2)) + else if (xFloor > (room->XSize - 2)) { - xFloor = room->xSize - 2; + xFloor = room->XSize - 2; } } else if (xFloor < 0) { xFloor = 0; } - else if (xFloor >= room->xSize) + else if (xFloor >= room->XSize) { - xFloor = room->xSize - 1; + xFloor = room->XSize - 1; } - sector = &room->floor[zFloor + (xFloor * room->zSize)]; + sector = &room->Sectors[zFloor + (xFloor * room->ZSize)]; adjoiningRoomNumber = sector->SidePortalRoomNumber; if (adjoiningRoomNumber != NO_VALUE) { @@ -1188,7 +1188,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) return (floorHeight - waterHeight); } - sector = GetSector(room, x - room->x, z - room->z); + sector = GetSector(room, x - room->Position.x, z - room->Position.z); } return DEEP_WATER; @@ -1207,7 +1207,7 @@ int GetWaterDepth(int x, int y, int z, short roomNumber) return (GetFloorHeight(sector, x, y, z) - waterHeight); } - sector = GetSector(room, x - room->x, z - room->z); + sector = GetSector(room, x - room->Position.x, z - room->Position.z); } return NO_HEIGHT; @@ -1227,8 +1227,8 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) int adjoiningRoomNumber = NO_VALUE; do { - int xBlock = (x - room->x) / BLOCK(1); - int zBlock = (z - room->z) / BLOCK(1); + int xBlock = (x - room->Position.x) / BLOCK(1); + int zBlock = (z - room->Position.z) / BLOCK(1); if (zBlock <= 0) { @@ -1237,33 +1237,33 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) { xBlock = 1; } - else if (xBlock > (room->xSize - 2)) + else if (xBlock > (room->XSize - 2)) { - xBlock = room->xSize - 2; + xBlock = room->XSize - 2; } } - else if (zBlock >= (room->zSize - 1)) + else if (zBlock >= (room->ZSize - 1)) { - zBlock = room->zSize - 1; + zBlock = room->ZSize - 1; if (xBlock < 1) { xBlock = 1; } - else if (xBlock > (room->xSize - 2)) + else if (xBlock > (room->XSize - 2)) { - xBlock = room->xSize - 2; + xBlock = room->XSize - 2; } } else if (xBlock < 0) { xBlock = 0; } - else if (xBlock >= room->xSize) + else if (xBlock >= room->XSize) { - xBlock = room->xSize - 1; + xBlock = room->XSize - 1; } - sector = &room->floor[zBlock + (xBlock * room->zSize)]; + sector = &room->Sectors[zBlock + (xBlock * room->ZSize)]; adjoiningRoomNumber = sector->SidePortalRoomNumber; if (adjoiningRoomNumber != NO_VALUE) @@ -1290,7 +1290,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) break; } - sector = GetSector(room, x - room->x, z - room->z); + sector = GetSector(room, x - room->Position.x, z - room->Position.z); } return sector->GetSurfaceHeight(Vector3i(x, y, z), false); @@ -1307,7 +1307,7 @@ int GetWaterHeight(int x, int y, int z, short roomNumber) break; } - sector = GetSector(room2, x - room2->x, z - room2->z); + sector = GetSector(room2, x - room2->Position.x, z - room2->Position.z); } return sector->GetSurfaceHeight(Vector3i(x, y, z), true); diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 701717f42..525a64209 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -368,17 +368,17 @@ namespace TEN::Collision::Floordata const auto& room = g_Level.Rooms[roomNumber]; // Calculate room grid coord. - auto roomGridCoord = Vector2i((x - room.x) / BLOCK(1), (z - room.z) / BLOCK(1)); - if (x < room.x) + auto roomGridCoord = Vector2i((x - room.Position.x) / BLOCK(1), (z - room.Position.z) / BLOCK(1)); + if (x < room.Position.x) roomGridCoord.x -= 1; - if (z < room.z) + if (z < room.Position.z) roomGridCoord.y -= 1; // Clamp room grid coord to room bounds (if applicable). if (clampToBounds) { - roomGridCoord.x = std::clamp(roomGridCoord.x, 0, room.xSize - 1); - roomGridCoord.y = std::clamp(roomGridCoord.y, 0, room.zSize - 1); + roomGridCoord.x = std::clamp(roomGridCoord.x, 0, room.XSize - 1); + roomGridCoord.y = std::clamp(roomGridCoord.y, 0, room.ZSize - 1); } return roomGridCoord; @@ -397,8 +397,8 @@ namespace TEN::Collision::Floordata const auto& room = g_Level.Rooms[roomNumber]; // Search area out of range; return empty vector. - if (xMax <= 0 || xMin >= (room.xSize - 1) || - xMax <= 0 || xMin >= (room.xSize - 1)) + if (xMax <= 0 || xMin >= (room.XSize - 1) || + xMax <= 0 || xMin >= (room.XSize - 1)) { return {}; } @@ -408,13 +408,13 @@ namespace TEN::Collision::Floordata for (int x = xMin; x <= xMax; x++) { // Test if out of room X range. - if (x <= 0 || x >= (room.xSize - 1)) + if (x <= 0 || x >= (room.XSize - 1)) continue; for (int z = zMin; z <= zMax; z++) { // Test if out of room Z range. - if (z <= 0 || z >= (room.zSize - 1)) + if (z <= 0 || z >= (room.ZSize - 1)) continue; roomGridCoords.push_back(Vector2i(x, z)); @@ -430,7 +430,7 @@ namespace TEN::Collision::Floordata // Run through neighbor rooms. auto& room = g_Level.Rooms[roomNumber]; - for (int neighborRoomNumber : room.neighbors) + for (int neighborRoomNumber : room.NeighborRoomNumbers) { // Collect neighbor sectors. auto roomGridCoords = GetNeighborRoomGridCoords(pos, neighborRoomNumber, searchDepth); @@ -446,8 +446,8 @@ namespace TEN::Collision::Floordata { auto& room = g_Level.Rooms[roomNumber]; - int sectorID = (room.zSize * roomGridCoord.x) + roomGridCoord.y; - return room.floor[sectorID]; + int sectorID = (room.ZSize * roomGridCoord.x) + roomGridCoord.y; + return room.Sectors[sectorID]; } FloorInfo& GetFloor(int roomNumber, int x, int z) @@ -831,18 +831,18 @@ namespace TEN::Collision::Floordata const auto& room = g_Level.Rooms[item.RoomNumber]; // Get projected AABB min and max of bridge OBB. - float xMin = floor((std::min(std::min(std::min(corners[0].x, corners[1].x), corners[4].x), corners[5].x) - room.x) / BLOCK(1)); - float zMin = floor((std::min(std::min(std::min(corners[0].z, corners[1].z), corners[4].z), corners[5].z) - room.z) / BLOCK(1)); - float xMax = ceil((std::max(std::max(std::max(corners[0].x, corners[1].x), corners[4].x), corners[5].x) - room.x) / BLOCK(1)); - float zMax = ceil((std::max(std::max(std::max(corners[0].z, corners[1].z), corners[4].z), corners[5].z) - room.z) / BLOCK(1)); + float xMin = floor((std::min(std::min(std::min(corners[0].x, corners[1].x), corners[4].x), corners[5].x) - room.Position.x) / BLOCK(1)); + float zMin = floor((std::min(std::min(std::min(corners[0].z, corners[1].z), corners[4].z), corners[5].z) - room.Position.z) / BLOCK(1)); + float xMax = ceil((std::max(std::max(std::max(corners[0].x, corners[1].x), corners[4].x), corners[5].x) - room.Position.x) / BLOCK(1)); + float zMax = ceil((std::max(std::max(std::max(corners[0].z, corners[1].z), corners[4].z), corners[5].z) - room.Position.z) / BLOCK(1)); // Run through sectors enclosed in projected bridge AABB. - for (int x = 0; x < room.xSize; x++) + for (int x = 0; x < room.XSize; x++) { - for (int z = 0; z < room.zSize; z++) + for (int z = 0; z < room.ZSize; z++) { - float pX = (room.x + BLOCK(x)) + BLOCK(0.5f); - float pZ = (room.z + BLOCK(z)) + BLOCK(0.5f); + float pX = (room.Position.x + BLOCK(x)) + BLOCK(0.5f); + float pZ = (room.Position.z + BLOCK(z)) + BLOCK(0.5f); float offX = pX - item.Pose.Position.x; float offZ = pZ - item.Pose.Position.z; @@ -911,7 +911,7 @@ namespace TEN::Collision::Floordata // Run through neighboring rooms. const auto& room = g_Level.Rooms[item.RoomNumber]; - for (int neighborRoomNumber : room.neighbors) + for (int neighborRoomNumber : room.NeighborRoomNumbers) { const auto& neighborRoom = g_Level.Rooms[neighborRoomNumber]; @@ -919,8 +919,8 @@ namespace TEN::Collision::Floordata auto roomGridCoords = GetNeighborRoomGridCoords(item.Pose.Position, neighborRoomNumber, SECTOR_SEARCH_DEPTH); for (const auto& roomGridCoord : roomGridCoords) { - pos.x = BLOCK(roomGridCoord.x) + neighborRoom.x; - pos.z = BLOCK(roomGridCoord.y) + neighborRoom.z; + pos.x = BLOCK(roomGridCoord.x) + neighborRoom.Position.x; + pos.z = BLOCK(roomGridCoord.y) + neighborRoom.Position.z; pointColl = GetPointCollision(pos, neighborRoomNumber); pos.y = pointColl.GetFloorHeight(); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 453435568..a99729502 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -154,13 +154,13 @@ bool SameZone(CreatureInfo* creature, ItemInfo* target) auto* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); auto& roomSource = g_Level.Rooms[item.RoomNumber]; - auto& boxSource = GetSector(&roomSource, item.Pose.Position.x - roomSource.x, item.Pose.Position.z - roomSource.z)->PathfindingBoxID; + auto& boxSource = GetSector(&roomSource, item.Pose.Position.x - roomSource.Position.x, item.Pose.Position.z - roomSource.Position.z)->PathfindingBoxID; if (boxSource == NO_VALUE) return false; item.BoxNumber = boxSource; auto& roomTarget = g_Level.Rooms[target->RoomNumber]; - auto& boxTarget = GetSector(&roomTarget, target->Pose.Position.x - roomTarget.x, target->Pose.Position.z - roomTarget.z)->PathfindingBoxID; + auto& boxTarget = GetSector(&roomTarget, target->Pose.Position.x - roomTarget.Position.x, target->Pose.Position.z - roomTarget.Position.z)->PathfindingBoxID; if (boxTarget == NO_VALUE) return false; target->BoxNumber = boxTarget; @@ -1460,9 +1460,9 @@ void FindAITargetObject(CreatureInfo* creature, int objectNumber, int ocb, bool int* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); auto* room = &g_Level.Rooms[item.RoomNumber]; - item.BoxNumber = GetSector(room, item.Pose.Position.x - room->x, item.Pose.Position.z - room->z)->PathfindingBoxID; + item.BoxNumber = GetSector(room, item.Pose.Position.x - room->Position.x, item.Pose.Position.z - room->Position.z)->PathfindingBoxID; room = &g_Level.Rooms[aiObject.roomNumber]; - aiObject.boxNumber = GetSector(room, aiObject.pos.Position.x - room->x, aiObject.pos.Position.z - room->z)->PathfindingBoxID; + aiObject.boxNumber = GetSector(room, aiObject.pos.Position.x - room->Position.x, aiObject.pos.Position.z - room->Position.z)->PathfindingBoxID; if (item.BoxNumber == NO_VALUE || aiObject.boxNumber == NO_VALUE) return; @@ -1504,7 +1504,7 @@ int TargetReachable(ItemInfo* item, ItemInfo* enemy) { const auto& creature = *GetCreatureInfo(item); auto& room = g_Level.Rooms[enemy->RoomNumber]; - auto* floor = GetSector(&room, enemy->Pose.Position.x - room.x, enemy->Pose.Position.z - room.z); + auto* floor = GetSector(&room, enemy->Pose.Position.x - room.Position.x, enemy->Pose.Position.z - room.Position.z); // NEW: Only update enemy box number if it is actually reachable by the enemy. // This prevents enemies from running to the player and attacking nothing when they are hanging or shimmying. -- Lwmte, 27.06.22 @@ -1545,7 +1545,7 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) auto* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); auto* room = &g_Level.Rooms[item->RoomNumber]; - item->BoxNumber = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z)->PathfindingBoxID; + item->BoxNumber = GetSector(room, item->Pose.Position.x - room->Position.x, item->Pose.Position.z - room->Position.z)->PathfindingBoxID; AI->zoneNumber = zone[item->BoxNumber]; enemy->BoxNumber = TargetReachable(item, enemy); @@ -2129,14 +2129,14 @@ void AdjustStopperFlag(ItemInfo* item, int direction) int z = item->Pose.Position.z; auto* room = &g_Level.Rooms[item->RoomNumber]; - auto* floor = GetSector(room, x - room->x, z - room->z); + auto* floor = GetSector(room, x - room->Position.x, z - room->Position.z); floor->Stopper = !floor->Stopper; x = item->Pose.Position.x + BLOCK(1) * phd_sin(direction); z = item->Pose.Position.z + BLOCK(1) * phd_cos(direction); room = &g_Level.Rooms[GetPointCollision(Vector3i(x, item->Pose.Position.y, z), item->RoomNumber).GetRoomNumber()]; - floor = GetSector(room, x - room->x, z - room->z); + floor = GetSector(room, x - room->Position.x, z - room->Position.z); floor->Stopper = !floor->Stopper; } @@ -2151,11 +2151,11 @@ void InitializeItemBoxData() { for (const auto& mesh : room.mesh) { - long index = ((mesh.pos.Position.z - room.z) / BLOCK(1)) + room.zSize * ((mesh.pos.Position.x - room.x) / BLOCK(1)); - if (index > room.floor.size()) + long index = ((mesh.pos.Position.z - room.Position.z) / BLOCK(1)) + room.ZSize * ((mesh.pos.Position.x - room.Position.x) / BLOCK(1)); + if (index > room.Sectors.size()) continue; - auto* floor = &room.floor[index]; + auto* floor = &room.Sectors[index]; if (floor->PathfindingBoxID == NO_VALUE) continue; diff --git a/TombEngine/Game/control/los.cpp b/TombEngine/Game/control/los.cpp index 2c0ea4ec6..d527584ce 100644 --- a/TombEngine/Game/control/los.cpp +++ b/TombEngine/Game/control/los.cpp @@ -784,7 +784,7 @@ std::optional GetStaticObjectLos(const Vector3& origin, int roomNumber, { // Run through neighbor rooms. const auto& room = g_Level.Rooms[roomNumber]; - for (int neighborRoomNumber : room.neighbors) + for (int neighborRoomNumber : room.NeighborRoomNumbers) { // Get neighbor room. const auto& neighborRoom = g_Level.Rooms[neighborRoomNumber]; diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 74a9b7771..cff68ce9d 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -240,7 +240,7 @@ void CreateZone(ItemInfo* item) auto* creature = GetCreatureInfo(item); auto* room = &g_Level.Rooms[item->RoomNumber]; - item->BoxNumber = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z)->PathfindingBoxID; + item->BoxNumber = GetSector(room, item->Pose.Position.x - room->Position.x, item->Pose.Position.z - room->Position.z)->PathfindingBoxID; if (creature->LOT.Fly) { diff --git a/TombEngine/Game/control/volume.cpp b/TombEngine/Game/control/volume.cpp index 10bcdfe8a..5968dd206 100644 --- a/TombEngine/Game/control/volume.cpp +++ b/TombEngine/Game/control/volume.cpp @@ -139,14 +139,14 @@ namespace TEN::Control::Volumes if (roomNumber == NO_VALUE) return; - for (int currentRoomIndex : g_Level.Rooms[roomNumber].neighbors) + for (int currentRoomIndex : g_Level.Rooms[roomNumber].NeighborRoomNumbers) { auto& room = g_Level.Rooms[currentRoomIndex]; if (!room.Active()) continue; - for (auto& volume : room.triggerVolumes) + for (auto& volume : room.TriggerVolumes) { if (!volume.Enabled) continue; diff --git a/TombEngine/Game/effects/bubble.cpp b/TombEngine/Game/effects/bubble.cpp index 7a51a81b3..655307d9e 100644 --- a/TombEngine/Game/effects/bubble.cpp +++ b/TombEngine/Game/effects/bubble.cpp @@ -158,7 +158,7 @@ namespace TEN::Effects::Bubble { // Hit water surface; spawn ripple. SpawnRipple( - Vector3(bubble.Position.x, g_Level.Rooms[prevRoomNumber].maxceiling, bubble.Position.z), + Vector3(bubble.Position.x, g_Level.Rooms[prevRoomNumber].TopHeight, bubble.Position.z), roomNumber, ((bubble.SizeMax.x + bubble.SizeMax.y) / 2) * 0.5f, (int)RippleFlags::SlowFade); @@ -168,7 +168,7 @@ namespace TEN::Effects::Bubble } // Hit ceiling. NOTE: This is a hacky check. New collision fetching should provide fast info on a need-to-know basis. else if (bubble.RoomNumber == prevRoomNumber && - bubble.Position.y <= g_Level.Rooms[prevRoomNumber].maxceiling) + bubble.Position.y <= g_Level.Rooms[prevRoomNumber].TopHeight) { bubble.Life = 0.0f; continue; diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 2d128dc87..3b553395a 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -993,10 +993,10 @@ void UpdateGunShells() !TestEnvironment(ENV_FLAG_WATER, prevRoomNumber)) { - SpawnSplashDrips(Vector3(gunshell->pos.Position.x, g_Level.Rooms[gunshell->roomNumber].maxceiling, gunshell->pos.Position.z), gunshell->roomNumber, 3, true); + SpawnSplashDrips(Vector3(gunshell->pos.Position.x, g_Level.Rooms[gunshell->roomNumber].TopHeight, gunshell->pos.Position.z), gunshell->roomNumber, 3, true); //AddWaterSparks(gs->pos.Position.x, g_Level.Rooms[gs->roomNumber].maxceiling, gs->pos.Position.z, 8); SpawnRipple( - Vector3(gunshell->pos.Position.x, g_Level.Rooms[gunshell->roomNumber].maxceiling, gunshell->pos.Position.z), + Vector3(gunshell->pos.Position.x, g_Level.Rooms[gunshell->roomNumber].TopHeight, gunshell->pos.Position.z), gunshell->roomNumber, Random::GenerateFloat(8.0f, 12.0f), (int)RippleFlags::SlowFade); diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index bd3631e8b..2c9ffd758 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -584,7 +584,7 @@ void InitializeItem(short itemNumber) item->NextItem = room->itemNumber; room->itemNumber = itemNumber; - FloorInfo* floor = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z); + FloorInfo* floor = GetSector(room, item->Pose.Position.x - room->Position.x, item->Pose.Position.z - room->Position.z); item->Floor = floor->GetSurfaceHeight(item->Pose.Position.x, item->Pose.Position.z, true); item->BoxNumber = floor->PathfindingBoxID; diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index 24f6fe3df..405a46c2d 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -32,8 +32,8 @@ bool ROOM_INFO::Active() const // Since engine swaps whole room memory block but substitutes flippedRoom, // must check both original room number and flippedRoom equality, // as well as NO_VALUE if checking non-flipped rooms. - return (!FlipStats[flipNumber] && flippedRoom != index && flippedRoom != NO_VALUE) || - ( FlipStats[flipNumber] && flippedRoom == index); + return (!FlipStats[flipNumber] && flippedRoom != RoomNumber && flippedRoom != NO_VALUE) || + ( FlipStats[flipNumber] && flippedRoom == RoomNumber); } static void AddRoomFlipItems(const ROOM_INFO& room) @@ -105,11 +105,11 @@ void DoFlipMap(int group) g_Renderer.FlipRooms(roomNumber, room.flippedRoom); // Update active room sectors. - for (auto& sector : room.floor) + for (auto& sector : room.Sectors) sector.RoomNumber = roomNumber; // Update flipped room sectors. - for (auto& sector : flippedRoom.floor) + for (auto& sector : flippedRoom.Sectors) sector.RoomNumber = room.flippedRoom; } } @@ -158,9 +158,9 @@ int IsRoomOutside(int x, int y, int z) int roomNumber = OutsideRoomTable[xTable][zTable][i]; const auto& room = g_Level.Rooms[roomNumber]; - if ((x > (room.x + BLOCK(1)) && x < (room.x + (room.xSize - 1) * BLOCK(1))) && - (y > room.maxceiling && y < room.minfloor) && - (z > (room.z + BLOCK(1)) && z < (room.z + (room.zSize - 1) * BLOCK(1)))) + if ((x > (room.Position.x + BLOCK(1)) && x < (room.Position.x + (room.XSize - 1) * BLOCK(1))) && + (y > room.TopHeight && y < room.BottomHeight) && + (z > (room.Position.z + BLOCK(1)) && z < (room.Position.z + (room.ZSize - 1) * BLOCK(1)))) { auto pointColl = GetPointCollision(Vector3i(x, y, z), roomNumber); @@ -188,14 +188,14 @@ namespace TEN::Collision::Room // TODO: Can use floordata's GetRoomGridCoord()? FloorInfo* GetSector(ROOM_INFO* room, int x, int z) { - int sectorX = std::clamp(x / BLOCK(1), 0, room->xSize - 1); - int sectorZ = std::clamp(z / BLOCK(1), 0, room->zSize - 1); + int sectorX = std::clamp(x / BLOCK(1), 0, room->XSize - 1); + int sectorZ = std::clamp(z / BLOCK(1), 0, room->ZSize - 1); - int sectorID = sectorZ + (sectorX * room->zSize); - if (sectorID > room->floor.size()) + int sectorID = sectorZ + (sectorX * room->ZSize); + if (sectorID > room->Sectors.size()) return nullptr; - return &room->floor[sectorID]; + return &room->Sectors[sectorID]; } } @@ -219,9 +219,9 @@ bool IsPointInRoom(const Vector3i& pos, int roomNumber) { const auto& room = g_Level.Rooms[roomNumber]; - if (pos.z >= (room.z + BLOCK(1)) && pos.z <= (room.z + BLOCK(room.zSize - 1)) && - pos.y <= room.minfloor && pos.y > room.maxceiling && - pos.x >= (room.x + BLOCK(1)) && pos.x <= (room.x + BLOCK(room.xSize - 1))) + if (pos.z >= (room.Position.z + BLOCK(1)) && pos.z <= (room.Position.z + BLOCK(room.ZSize - 1)) && + pos.y <= room.BottomHeight && pos.y > room.TopHeight && + pos.x >= (room.Position.x + BLOCK(1)) && pos.x <= (room.Position.x + BLOCK(room.XSize - 1))) { return true; } @@ -234,7 +234,7 @@ int FindRoomNumber(const Vector3i& pos, int startRoomNumber) if (startRoomNumber != NO_VALUE && startRoomNumber < g_Level.Rooms.size()) { const auto& room = g_Level.Rooms[startRoomNumber]; - for (int neighborRoomNumber : room.neighbors) + for (int neighborRoomNumber : room.NeighborRoomNumbers) { const auto& neighborRoom = g_Level.Rooms[neighborRoomNumber]; if (neighborRoomNumber != startRoomNumber && neighborRoom.Active() && @@ -258,15 +258,15 @@ Vector3i GetRoomCenter(int roomNumber) { const auto& room = g_Level.Rooms[roomNumber]; - int halfLength = BLOCK(room.xSize) / 2; - int halfDepth = BLOCK(room.zSize) / 2; - int halfHeight = (room.maxceiling - room.minfloor) / 2; + int halfLength = BLOCK(room.XSize) / 2; + int halfDepth = BLOCK(room.ZSize) / 2; + int halfHeight = (room.TopHeight - room.BottomHeight) / 2; // Calculate and return center. return Vector3i( - room.x + halfLength, - room.minfloor + halfHeight, - room.z + halfDepth); + room.Position.x + halfLength, + room.BottomHeight + halfHeight, + room.Position.z + halfDepth); } static std::vector GetNeighborRoomNumbers(int roomNumber, unsigned int searchDepth, std::vector& visitedRoomNumbers = std::vector{}) @@ -316,7 +316,7 @@ void InitializeNeighborRoomList() for (int roomNumber = 0; roomNumber < g_Level.Rooms.size(); roomNumber++) { auto& room = g_Level.Rooms[roomNumber]; - room.neighbors = GetNeighborRoomNumbers(roomNumber, NEIGHBOR_ROOM_SEARCH_DEPTH); + room.NeighborRoomNumbers = GetNeighborRoomNumbers(roomNumber, NEIGHBOR_ROOM_SEARCH_DEPTH); } // Add flipped variations of itself. @@ -326,11 +326,11 @@ void InitializeNeighborRoomList() if (room.flippedRoom == NO_VALUE) continue; - if (!Contains(room.neighbors, room.flippedRoom)) - room.neighbors.push_back(room.flippedRoom); + if (!Contains(room.NeighborRoomNumbers, room.flippedRoom)) + room.NeighborRoomNumbers.push_back(room.flippedRoom); auto& flippedRoom = g_Level.Rooms[room.flippedRoom]; - if (!Contains(flippedRoom.neighbors, roomNumber)) - flippedRoom.neighbors.push_back(roomNumber); + if (!Contains(flippedRoom.NeighborRoomNumbers, roomNumber)) + flippedRoom.NeighborRoomNumbers.push_back(roomNumber); } } diff --git a/TombEngine/Game/room.h b/TombEngine/Game/room.h index f073ba80a..4a111e3fa 100644 --- a/TombEngine/Game/room.h +++ b/TombEngine/Game/room.h @@ -87,31 +87,32 @@ struct MESH_INFO struct ROOM_INFO { - int index; - int x; - int y; - int z; - int minfloor; - int maxceiling; - int xSize; - int zSize; + int RoomNumber = 0; + std::string Name = {}; + std::vector Tags = {}; + + Vector3i Position = Vector3i::Zero; + int BottomHeight = 0; + int TopHeight = 0; + int XSize = 0; + int ZSize = 0; + Vector3 ambient; - int flippedRoom; int flags; int meshEffect; ReverbType reverbType; + int flippedRoom; int flipNumber; short itemNumber; short fxNumber; bool boundActive; - std::string name = {}; - std::vector tags = {}; + std::vector NeighborRoomNumbers = {}; - std::vector floor = {}; + std::vector Sectors = {}; std::vector lights = {}; - std::vector mesh = {}; - std::vector triggerVolumes = {}; + std::vector mesh = {}; // Statics + std::vector TriggerVolumes = {}; std::vector positions = {}; std::vector normals = {}; @@ -120,8 +121,6 @@ struct ROOM_INFO std::vector buckets = {}; std::vector doors = {}; - std::vector neighbors = {}; - bool Active() const; }; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 9c821dd10..221d50862 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -544,11 +544,11 @@ const std::vector SaveGame::Build() std::vector> rooms; for (auto& room : g_Level.Rooms) { - auto nameOffset = fbb.CreateString(room.name); + auto nameOffset = fbb.CreateString(room.Name); Save::RoomBuilder serializedInfo{ fbb }; serializedInfo.add_name(nameOffset); - serializedInfo.add_index(room.index); + serializedInfo.add_index(room.RoomNumber); serializedInfo.add_reverb_type((int)room.reverbType); serializedInfo.add_flags(room.flags); auto serializedInfoOffset = serializedInfo.Finish(); @@ -991,14 +991,14 @@ const std::vector SaveGame::Build() staticMesh.add_flags(room->mesh[j].flags); staticMesh.add_hit_points(room->mesh[j].HitPoints); - staticMesh.add_room_number(room->index); + staticMesh.add_room_number(room->RoomNumber); staticMesh.add_number(j); staticMeshes.push_back(staticMesh.Finish()); } - for (int j = 0; j < room->triggerVolumes.size(); j++) + for (int j = 0; j < room->TriggerVolumes.size(); j++) { - auto& currVolume = room->triggerVolumes[j]; + auto& currVolume = room->TriggerVolumes[j]; std::vector> queue; for (int k = 0; k < currVolume.StateQueue.size(); k++) @@ -1022,7 +1022,7 @@ const std::vector SaveGame::Build() auto nameOffset = fbb.CreateString(currVolume.Name); Save::VolumeBuilder volume{ fbb }; - volume.add_room_number(room->index); + volume.add_room_number(room->RoomNumber); volume.add_number(j); volume.add_name(nameOffset); volume.add_enabled(currVolume.Enabled); @@ -2155,7 +2155,7 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) for (int i = 0; i < s->rooms()->size(); i++) { auto room = s->rooms()->Get(i); - g_Level.Rooms[room->index()].name = room->name()->str(); + g_Level.Rooms[room->index()].Name = room->name()->str(); g_Level.Rooms[room->index()].flags = room->flags(); g_Level.Rooms[room->index()].reverbType = (ReverbType)room->reverb_type(); } @@ -2191,18 +2191,18 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) auto room = &g_Level.Rooms[volume->room_number()]; int number = volume->number(); - room->triggerVolumes[number].Enabled = volume->enabled(); - room->triggerVolumes[number].Name = volume->name()->str(); - room->triggerVolumes[number].Box.Center = - room->triggerVolumes[number].Sphere.Center = ToVector3(volume->position()); - room->triggerVolumes[number].Box.Orientation = ToVector4(volume->rotation()); - room->triggerVolumes[number].Box.Extents = ToVector3(volume->scale()); - room->triggerVolumes[number].Sphere.Radius = room->triggerVolumes[number].Box.Extents.x; + room->TriggerVolumes[number].Enabled = volume->enabled(); + room->TriggerVolumes[number].Name = volume->name()->str(); + room->TriggerVolumes[number].Box.Center = + room->TriggerVolumes[number].Sphere.Center = ToVector3(volume->position()); + room->TriggerVolumes[number].Box.Orientation = ToVector4(volume->rotation()); + room->TriggerVolumes[number].Box.Extents = ToVector3(volume->scale()); + room->TriggerVolumes[number].Sphere.Radius = room->TriggerVolumes[number].Box.Extents.x; for (int j = 0; j < volume->queue()->size(); j++) { auto state = volume->queue()->Get(j); - room->triggerVolumes[number].StateQueue.push_back( + room->TriggerVolumes[number].StateQueue.push_back( VolumeState { (VolumeStateStatus)state->status(), diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index 84bc395df..cc1016f63 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -77,7 +77,7 @@ namespace TEN::Entities::Doors xOffset = BLOCK(1); auto* r = &g_Level.Rooms[doorItem->RoomNumber]; - doorData->d1.floor = GetSector(r, doorItem->Pose.Position.x - r->x + xOffset, doorItem->Pose.Position.z - r->z + zOffset); + doorData->d1.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x + xOffset, doorItem->Pose.Position.z - r->Position.z + zOffset); auto roomNumber = doorData->d1.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) @@ -85,7 +85,7 @@ namespace TEN::Entities::Doors else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->PathfindingBoxID; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->Position.x + xOffset, doorItem->Pose.Position.z - b->Position.z + zOffset)->PathfindingBoxID; } doorData->d1.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; @@ -94,7 +94,7 @@ namespace TEN::Entities::Doors if (r->flippedRoom != -1) { r = &g_Level.Rooms[r->flippedRoom]; - doorData->d1flip.floor = GetSector(r, doorItem->Pose.Position.x - r->x + xOffset, doorItem->Pose.Position.z - r->z + zOffset); + doorData->d1flip.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x + xOffset, doorItem->Pose.Position.z - r->Position.z + zOffset); roomNumber = doorData->d1flip.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) @@ -102,7 +102,7 @@ namespace TEN::Entities::Doors else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x + xOffset, doorItem->Pose.Position.z - b->z + zOffset)->PathfindingBoxID; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->Position.x + xOffset, doorItem->Pose.Position.z - b->Position.z + zOffset)->PathfindingBoxID; } doorData->d1flip.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; @@ -124,7 +124,7 @@ namespace TEN::Entities::Doors else { r = &g_Level.Rooms[twoRoom]; - doorData->d2.floor = GetSector(r, doorItem->Pose.Position.x - r->x, doorItem->Pose.Position.z - r->z); + doorData->d2.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x, doorItem->Pose.Position.z - r->Position.z); roomNumber = doorData->d2.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) @@ -132,7 +132,7 @@ namespace TEN::Entities::Doors else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->PathfindingBoxID; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->Position.x, doorItem->Pose.Position.z - b->Position.z)->PathfindingBoxID; } doorData->d2.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; @@ -141,7 +141,7 @@ namespace TEN::Entities::Doors if (r->flippedRoom != -1) { r = &g_Level.Rooms[r->flippedRoom]; - doorData->d2flip.floor = GetSector(r, doorItem->Pose.Position.x - r->x, doorItem->Pose.Position.z - r->z); + doorData->d2flip.floor = GetSector(r, doorItem->Pose.Position.x - r->Position.x, doorItem->Pose.Position.z - r->Position.z); roomNumber = doorData->d2flip.floor->SidePortalRoomNumber; if (roomNumber == NO_VALUE) @@ -149,7 +149,7 @@ namespace TEN::Entities::Doors else { auto* b = &g_Level.Rooms[roomNumber]; - boxNumber = GetSector(b, doorItem->Pose.Position.x - b->x, doorItem->Pose.Position.z - b->z)->PathfindingBoxID; + boxNumber = GetSector(b, doorItem->Pose.Position.x - b->Position.x, doorItem->Pose.Position.z - b->Position.z)->PathfindingBoxID; } doorData->d2flip.block = (boxNumber != NO_VALUE && g_Level.PathfindingBoxes[boxNumber].flags & BLOCKABLE) ? boxNumber : NO_VALUE; diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index c1ffac6ce..6314342b7 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -315,7 +315,7 @@ namespace TEN::Entities::Generic waterHeight = pointColl.GetWaterSurfaceHeight(); if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) - waterHeight = g_Level.Rooms[item.RoomNumber].maxceiling; + waterHeight = g_Level.Rooms[item.RoomNumber].TopHeight; AddPushableBridge(item); } @@ -324,7 +324,7 @@ namespace TEN::Entities::Generic waterHeight = pointColl.GetWaterSurfaceHeight(); if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) - waterHeight = g_Level.Rooms[item.RoomNumber].maxceiling; + waterHeight = g_Level.Rooms[item.RoomNumber].TopHeight; } auto pushableColl = PushableCollisionData{}; diff --git a/TombEngine/Objects/Generic/Object/generic_trapdoor.cpp b/TombEngine/Objects/Generic/Object/generic_trapdoor.cpp index 940720209..f9fa318ab 100644 --- a/TombEngine/Objects/Generic/Object/generic_trapdoor.cpp +++ b/TombEngine/Objects/Generic/Object/generic_trapdoor.cpp @@ -187,8 +187,8 @@ namespace TEN::Entities::Generic ForcedFixedCamera.x = trapDoorItem->Pose.Position.x - phd_sin(trapDoorItem->Pose.Orientation.y) * 2048; ForcedFixedCamera.y = trapDoorItem->Pose.Position.y - 2048; - if (ForcedFixedCamera.y < g_Level.Rooms[trapDoorItem->RoomNumber].maxceiling) - ForcedFixedCamera.y = g_Level.Rooms[trapDoorItem->RoomNumber].maxceiling; + if (ForcedFixedCamera.y < g_Level.Rooms[trapDoorItem->RoomNumber].TopHeight) + ForcedFixedCamera.y = g_Level.Rooms[trapDoorItem->RoomNumber].TopHeight; ForcedFixedCamera.z = trapDoorItem->Pose.Position.z - phd_cos(trapDoorItem->Pose.Orientation.y) * 2048; ForcedFixedCamera.RoomNumber = trapDoorItem->RoomNumber; diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index c0e9dfdb0..242998432 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -998,7 +998,7 @@ namespace TEN::Entities::Vehicles void KayakToItemCollision(ItemInfo* kayakItem, ItemInfo* laraItem) { - for (auto i : g_Level.Rooms[kayakItem->RoomNumber].neighbors) + for (auto i : g_Level.Rooms[kayakItem->RoomNumber].NeighborRoomNumbers) { if (!g_Level.Rooms[i].Active()) continue; diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index 75de38a5e..118374c04 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -281,7 +281,7 @@ namespace TEN::Entities::Vehicles static void MinecartToEntityCollision(ItemInfo* minecartItem, ItemInfo* laraItem) { - for (auto i : g_Level.Rooms[minecartItem->RoomNumber].neighbors) + for (auto i : g_Level.Rooms[minecartItem->RoomNumber].NeighborRoomNumbers) { if (!g_Level.Rooms[i].Active()) continue; diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index 5ea720a34..9eccd1b87 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -229,13 +229,13 @@ namespace TEN::Entities::TR4 { const auto& room = g_Level.Rooms[LaraItem->RoomNumber]; - x = room.x + room.xSize * BLOCK(1) / 2 - item.Pose.Position.x; - z = room.z + room.zSize * BLOCK(1) / 2 - item.Pose.Position.z; + x = room.Position.x + room.XSize * BLOCK(1) / 2 - item.Pose.Position.x; + z = room.Position.z + room.ZSize * BLOCK(1) / 2 - item.Pose.Position.z; distance = SQUARE(x) + SQUARE(z); dy = abs((distance / MAX_VISIBILITY_DISTANCE) - CLICK(1)); //Prevent Wraiths to go below floor level - y = room.y + ((room.maxceiling - room.minfloor) / 4); + y = room.Position.y + ((room.TopHeight - room.BottomHeight) / 4); } dy = y - item.Pose.Position.y - dy - CLICK(0.5f); diff --git a/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp b/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp index 85fa39ed0..3ed121e7b 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_knight_templar.cpp @@ -186,7 +186,7 @@ namespace TEN::Entities::TR4 auto pos = GetJointPosition(item, LM_LINARM); auto& room = g_Level.Rooms[item->RoomNumber]; - auto& currentFloor = room.floor[(pos.z - room.z) / BLOCK(1) + (pos.x - room.x) / BLOCK(1) * room.zSize]; + auto& currentFloor = room.Sectors[(pos.z - room.Position.z) / BLOCK(1) + (pos.x - room.Position.x) / BLOCK(1) * room.ZSize]; if (currentFloor.Stopper) { diff --git a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp index f5bc962bb..87d86f3d2 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_rats_emitter.cpp @@ -266,7 +266,7 @@ void UpdateRats() if (TestEnvironment(ENV_FLAG_WATER, room)) { - rat->Pose.Position.y = room->maxceiling + 50; + rat->Pose.Position.y = room->TopHeight + 50; rat->Velocity = 16; rat->VerticalVelocity = 0; @@ -274,16 +274,16 @@ void UpdateRats() { if (!(GetRandomControl() & 0xF)) SpawnRipple( - Vector3(rat->Pose.Position.x, room->maxceiling, rat->Pose.Position.z), + Vector3(rat->Pose.Position.x, room->TopHeight, rat->Pose.Position.z), rat->RoomNumber, Random::GenerateFloat(48.0f, 52.0f), (int)RippleFlags::SlowFade); } else { - AddWaterSparks(rat->Pose.Position.x, room->maxceiling, rat->Pose.Position.z, 16); + AddWaterSparks(rat->Pose.Position.x, room->TopHeight, rat->Pose.Position.z, 16); SpawnRipple( - Vector3(rat->Pose.Position.x, room->maxceiling, rat->Pose.Position.z), + Vector3(rat->Pose.Position.x, room->TopHeight, rat->Pose.Position.z), rat->RoomNumber, Random::GenerateFloat(48.0f, 52.0f), (int)RippleFlags::SlowFade); diff --git a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp index b7d0d01ee..da1ca2e19 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_spider_emitter.cpp @@ -232,9 +232,9 @@ void UpdateSpiders() spider->VerticalVelocity = 0; } - if (spider->Pose.Position.y < g_Level.Rooms[spider->RoomNumber].maxceiling + 50) + if (spider->Pose.Position.y < g_Level.Rooms[spider->RoomNumber].TopHeight + 50) { - spider->Pose.Position.y = g_Level.Rooms[spider->RoomNumber].maxceiling + 50; + spider->Pose.Position.y = g_Level.Rooms[spider->RoomNumber].TopHeight + 50; spider->Pose.Orientation.y += -ANGLE(180.0f); spider->VerticalVelocity = 1; } diff --git a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp index 2e10b3cbc..cd8759512 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_gladiator.cpp @@ -337,7 +337,7 @@ namespace TEN::Entities::Creatures::TR5 auto pos = GetJointPosition(item, 16); - auto* floor = GetSector(room, pos.x - room->x, pos.z - room->z); + auto* floor = GetSector(room, pos.x - room->Position.x, pos.z - room->Position.z); if (floor->Stopper) { for (int i = 0; i < room->mesh.size(); i++) diff --git a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp index a9adcaf22..ec249ed98 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp @@ -363,9 +363,9 @@ namespace TEN::Entities::Creatures::TR5 auto* room = &g_Level.Rooms[roomNumber]; - int x = room->x + (creature->Tosspad / 256 & 0xFF) * BLOCK(1) + 512; - int y = room->minfloor + floorHeight; - int z = room->z + (creature->Tosspad & 0xFF) * BLOCK(1) + 512; + int x = room->Position.x + (creature->Tosspad / 256 & 0xFF) * BLOCK(1) + 512; + int y = room->BottomHeight + floorHeight; + int z = room->Position.z + (creature->Tosspad & 0xFF) * BLOCK(1) + 512; TestTriggers(x, y, z, roomNumber, true); diff --git a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp index 2e041645b..29dc8b0f3 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_roman_statue.cpp @@ -543,7 +543,7 @@ namespace TEN::Entities::Creatures::TR5 pos = GetJointPosition(item, 16); auto* room = &g_Level.Rooms[item->RoomNumber]; - FloorInfo* floor = GetSector(room, pos.x - room->x, pos.z - room->z); + FloorInfo* floor = GetSector(room, pos.x - room->Position.x, pos.z - room->Position.z); // If floor is stopped, then try to find static meshes and shatter them, activating heavy triggers below if (floor->Stopper) @@ -823,9 +823,9 @@ namespace TEN::Entities::Creatures::TR5 short floorHeight = item->ItemFlags[2] & 0xFF00; auto* room = &g_Level.Rooms[roomNumber]; - int x = room->x + (creature->Tosspad / 256 & 0xFF) * BLOCK(1) + 512; - int y = room->minfloor + floorHeight; - int z = room->z + (creature->Tosspad & 0xFF) * BLOCK(1) + 512; + int x = room->Position.x + (creature->Tosspad / 256 & 0xFF) * BLOCK(1) + 512; + int y = room->BottomHeight + floorHeight; + int z = room->Position.z + (creature->Tosspad & 0xFF) * BLOCK(1) + 512; TestTriggers(x, y, z, roomNumber, true); } diff --git a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp index 52cb85e20..a60aaede0 100644 --- a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp @@ -82,7 +82,7 @@ namespace TEN::Entities::Generic return; } - int distToPortal = *&g_Level.Rooms[item->RoomNumber].maxceiling - item->Pose.Position.y; + int distToPortal = *&g_Level.Rooms[item->RoomNumber].TopHeight - item->Pose.Position.y; if (distToPortal <= speed) UpdateBridgeItem(*item); diff --git a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp index 54f008213..eba80f23b 100644 --- a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp +++ b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp @@ -14,10 +14,10 @@ void InitializeSmashObject(short itemNumber) item->Flags = 0; item->MeshBits = 1; - auto* room = &g_Level.Rooms[item->RoomNumber]; + auto& room = g_Level.Rooms[item->RoomNumber]; // NOTE: Avoids crash when attempting to access Boxes[] array while box is equal to NO_VALUE. -- TokyoSU 2022.12.20 - FloorInfo* floor = GetSector(room, item->Pose.Position.x - room->x, item->Pose.Position.z - room->z); + FloorInfo* floor = GetSector(&room, item->Pose.Position.x - room.Position.x, item->Pose.Position.z - room.Position.z); if (floor->PathfindingBoxID == NO_VALUE) { TENLog("Smash object with ID " + std::to_string(itemNumber) + " may be inside a wall." , LogLevel::Warning); @@ -34,9 +34,9 @@ void SmashObject(short itemNumber) auto* item = &g_Level.Items[itemNumber]; auto* room = &g_Level.Rooms[item->RoomNumber]; - int sector = ((item->Pose.Position.z - room->z) / 1024) + room->zSize * ((item->Pose.Position.x - room->x) / 1024); + int sector = ((item->Pose.Position.z - room->Position.z) / 1024) + room->ZSize * ((item->Pose.Position.x - room->Position.z) / 1024); - auto* box = &g_Level.PathfindingBoxes[room->floor[sector].PathfindingBoxID]; + auto* box = &g_Level.PathfindingBoxes[room->Sectors[sector].PathfindingBoxID]; if (box->flags & 0x8000) box->flags &= ~BOX_BLOCKED; diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp index 4b22ff7e3..9a0b17e5e 100644 --- a/TombEngine/Renderer/RendererCompatibility.cpp +++ b/TombEngine/Renderer/RendererCompatibility.cpp @@ -212,14 +212,14 @@ namespace TEN::Renderer r->ItemsToDraw.reserve(MAX_ITEMS_DRAW); r->EffectsToDraw.reserve(MAX_ITEMS_DRAW); - Vector3 boxMin = Vector3(room.x + BLOCK(1), room.maxceiling - CLICK(1), room.z + BLOCK(1)); - Vector3 boxMax = Vector3(room.x + (room.xSize - 1) * BLOCK(1), room.minfloor + CLICK(1), room.z + (room.zSize - 1) * BLOCK(1)); + Vector3 boxMin = Vector3(room.Position.x + BLOCK(1), room.TopHeight - CLICK(1), room.Position.z + BLOCK(1)); + Vector3 boxMax = Vector3(room.Position.x + (room.XSize - 1) * BLOCK(1), room.BottomHeight + CLICK(1), room.Position.z + (room.ZSize - 1) * BLOCK(1)); Vector3 center = (boxMin + boxMax) / 2.0f; Vector3 extents = boxMax - center; r->BoundingBox = BoundingBox(center, extents); r->Neighbors.clear(); - for (int j : room.neighbors) + for (int j : room.NeighborRoomNumbers) if (g_Level.Rooms[j].Active()) r->Neighbors.push_back(j); @@ -238,9 +238,9 @@ namespace TEN::Renderer for (int k = 0; k < 4; k++) { door->AbsoluteVertices[k] = Vector4( - room.x + oldDoor->vertices[k].x, - room.y + oldDoor->vertices[k].y, - room.z + oldDoor->vertices[k].z, + room.Position.x + oldDoor->vertices[k].x, + room.Position.y + oldDoor->vertices[k].y, + room.Position.z + oldDoor->vertices[k].z, 1.0f); } } @@ -312,9 +312,9 @@ namespace TEN::Renderer Vertex* vertex = &_roomsVertices[lastVertex]; int index = poly.indices[k]; - vertex->Position.x = room.x + room.positions[index].x; - vertex->Position.y = room.y + room.positions[index].y; - vertex->Position.z = room.z + room.positions[index].z; + vertex->Position.x = room.Position.x + room.positions[index].x; + vertex->Position.y = room.Position.y + room.positions[index].y; + vertex->Position.z = room.Position.z + room.positions[index].z; bucket.Centre += vertex->Position; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index fc66d93c3..20486b776 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1225,8 +1225,8 @@ namespace TEN::Renderer PrintDebugMessage("RoomNumber: %d", LaraItem->RoomNumber); PrintDebugMessage("PathfindingBoxID: %d", LaraItem->BoxNumber); PrintDebugMessage("WaterSurfaceDist: %d", Lara.Context.WaterSurfaceDist); - PrintDebugMessage("Room Position: %d, %d, %d, %d", room.x, room.z, room.x + BLOCK(room.xSize), room.z + BLOCK(room.zSize)); - PrintDebugMessage("Room.y, minFloor, maxCeiling: %d, %d, %d ", room.y, room.minfloor, room.maxceiling); + PrintDebugMessage("Room Position: %d, %d, %d, %d", room.Position.z, room.Position.z, room.Position.z + BLOCK(room.XSize), room.Position.z + BLOCK(room.ZSize)); + PrintDebugMessage("Room.y, minFloor, maxCeiling: %d, %d, %d ", room.Position.y, room.BottomHeight, room.TopHeight); PrintDebugMessage("Camera Position: %d, %d, %d", Camera.pos.x, Camera.pos.y, Camera.pos.z); PrintDebugMessage("Camera LookAt: %d, %d, %d", Camera.target.x, Camera.target.y, Camera.target.z); PrintDebugMessage("Camera RoomNumber: %d", Camera.pos.RoomNumber); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h index a63c510a1..ef8703b88 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectsHandler.h @@ -111,7 +111,7 @@ private: auto room = std::get>(val).get(); - if (std::any_of(room.tags.begin(), room.tags.end(), + if (std::any_of(room.Tags.begin(), room.Tags.end(), [&tag](const std::string& value) { return value == tag; })) { rooms.push_back(GetByName(key)); diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp index 3ca57da71..a215f8563 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp @@ -104,7 +104,7 @@ void Room::SetReverbType(ReverbType reverb) std::string Room::GetName() const { - return m_room.name; + return m_room.Name; } void Room::SetName(const std::string& name) @@ -115,8 +115,8 @@ void Room::SetName(const std::string& name) // Remove old name if it already exists. if (s_callbackSetName(name, m_room)) { - s_callbackRemoveName(m_room.name); - m_room.name = name; + s_callbackRemoveName(m_room.Name); + m_room.Name = name; } else { @@ -144,10 +144,10 @@ void Room::SetFlag(RoomEnvFlags flag, bool value) bool Room::IsTagPresent(const std::string& tag) const { - if (m_room.tags.empty()) + if (m_room.Tags.empty()) return false; return std::any_of( - m_room.tags.begin(), m_room.tags.end(), + m_room.Tags.begin(), m_room.Tags.end(), [&tag](const std::string& value) { return (value == tag); }); } diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index 6a3caf420..a48f820e2 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -687,17 +687,17 @@ void ReadRooms() { auto& room = g_Level.Rooms.emplace_back(); - room.name = ReadString(); + room.Name = ReadString(); int tagCount = ReadInt32(); for (int j = 0; j < tagCount; j++) - room.tags.push_back(ReadString()); + room.Tags.push_back(ReadString()); - room.x = ReadInt32(); - room.y = 0; - room.z = ReadInt32(); - room.minfloor = ReadInt32(); - room.maxceiling = ReadInt32(); + room.Position.x = ReadInt32(); + room.Position.y = 0; + room.Position.z = ReadInt32(); + room.BottomHeight = ReadInt32(); + room.TopHeight = ReadInt32(); int vertexCount = ReadInt32(); @@ -769,14 +769,14 @@ void ReadRooms() for (int j = 0; j < portalCount; j++) LoadPortal(room); - room.zSize = ReadInt32(); - room.xSize = ReadInt32(); - auto roomPos = Vector2i(room.x, room.z); + room.ZSize = ReadInt32(); + room.XSize = ReadInt32(); + auto roomPos = Vector2i(room.Position.x, room.Position.z); - room.floor.reserve(room.zSize * room.xSize); - for (int x = 0; x < room.xSize; x++) + room.Sectors.reserve(room.XSize * room.ZSize); + for (int x = 0; x < room.XSize; x++) { - for (int z = 0; z < room.zSize; z++) + for (int z = 0; z < room.ZSize; z++) { auto sector = FloorInfo{}; @@ -820,17 +820,17 @@ void ReadRooms() sector.Flags.MarkTriggererActive = 0; // TODO: Needs to be written to and read from savegames. sector.Flags.MarkBeetle = ReadBool(); - room.floor.push_back(sector); + room.Sectors.push_back(sector); } } room.ambient = ReadVector3(); - int numLights = ReadInt32(); - room.lights.reserve(numLights); - for (int j = 0; j < numLights; j++) + int lightCount = ReadInt32(); + room.lights.reserve(lightCount); + for (int j = 0; j < lightCount; j++) { - ROOM_LIGHT light; + auto light = ROOM_LIGHT{}; light.x = ReadInt32(); light.y = ReadInt32(); @@ -852,9 +852,9 @@ void ReadRooms() room.lights.push_back(light); } - int numStatics = ReadInt32(); - room.mesh.reserve(numStatics); - for (int j = 0; j < numStatics; j++) + int staticCount = ReadInt32(); + room.mesh.reserve(staticCount); + for (int j = 0; j < staticCount; j++) { auto& mesh = room.mesh.emplace_back(); @@ -875,21 +875,17 @@ void ReadRooms() g_GameScriptEntities->AddName(mesh.Name, mesh); } - int numTriggerVolumes = ReadInt32(); - - // Reserve in advance so the vector doesn't resize itself and leave anything - // in the script name-to-reference map obsolete. - room.triggerVolumes.reserve(numTriggerVolumes); - for (int j = 0; j < numTriggerVolumes; j++) + int triggerVolumeCount = ReadInt32(); + room.TriggerVolumes.reserve(triggerVolumeCount); + for (int j = 0; j < triggerVolumeCount; j++) { - auto& volume = room.triggerVolumes.emplace_back(); + auto& volume = room.TriggerVolumes.emplace_back(); volume.Type = (VolumeType)ReadInt32(); - // NOTE: Braces are necessary to ensure correct value init order. - auto pos = Vector3{ ReadFloat(), ReadFloat(), ReadFloat() }; - auto orient = Quaternion{ ReadFloat(), ReadFloat(), ReadFloat(), ReadFloat() }; - auto scale = Vector3{ ReadFloat(), ReadFloat(), ReadFloat() }; + auto pos = ReadVector3(); + auto orient = ReadVector4(); + auto scale = ReadVector3(); volume.Enabled = ReadBool(); volume.DetectInAdjacentRooms = ReadBool(); @@ -897,7 +893,7 @@ void ReadRooms() volume.Name = ReadString(); volume.EventSetIndex = ReadInt32(); - volume.Box = BoundingOrientedBox(pos, scale, orient); + volume.Box = BoundingOrientedBox(pos, scale, orient); volume.Sphere = BoundingSphere(pos, scale.x); volume.StateQueue.reserve(VOLUME_STATE_QUEUE_SIZE); @@ -913,9 +909,9 @@ void ReadRooms() room.itemNumber = NO_VALUE; room.fxNumber = NO_VALUE; - room.index = i; + room.RoomNumber = i; - g_GameScriptEntities->AddName(room.name, room); + g_GameScriptEntities->AddName(room.Name, room); } } @@ -1543,17 +1539,17 @@ void BuildOutsideRoomsTable() { auto* room = &g_Level.Rooms[i]; - int rx = (room->x / BLOCK(1)); - int rz = (room->z / BLOCK(1)); + int rx = (room->Position.x / BLOCK(1)); + int rz = (room->Position.z / BLOCK(1)); for (int x = 0; x < OUTSIDE_SIZE; x++) { - if (x < (rx + 1) || x > (rx + room->xSize - 2)) + if (x < (rx + 1) || x > (rx + room->XSize - 2)) continue; for (int z = 0; z < OUTSIDE_SIZE; z++) { - if (z < (rz + 1) || z > (rz + room->zSize - 2)) + if (z < (rz + 1) || z > (rz + room->ZSize - 2)) continue; OutsideRoomTable[x][z].push_back(i); From 27b4e0c2ad1c7b9fcffc95aa41041b8c39abdc47 Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Wed, 7 Aug 2024 21:03:29 +0200 Subject: [PATCH 244/410] Fixed bomb freezing/crashing the game. - Improved centaur code. - Now centaur look and rotate the head and torso at the target. - Removed double ID_PROJ_BOMB init. - --- TombEngine/Game/missile.cpp | 2 ++ TombEngine/Objects/TR1/Entity/Centaur.cpp | 24 ++++++++++++++++------- TombEngine/Objects/TR1/tr1_objects.cpp | 4 ++-- TombEngine/Objects/game_object_ids.h | 2 +- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/TombEngine/Game/missile.cpp b/TombEngine/Game/missile.cpp index 2dba2b650..f77cc2a4e 100644 --- a/TombEngine/Game/missile.cpp +++ b/TombEngine/Game/missile.cpp @@ -66,6 +66,7 @@ void ControlMissile(short fxNumber) // Check whether something was hit. if (fx.pos.Position.y >= pointColl.GetFloorHeight() || fx.pos.Position.y <= pointColl.GetCeilingHeight() || + pointColl.IsWall() || hasHitPlayer) { if (fx.objectNumber == ID_KNIFETHROWER_KNIFE || @@ -111,6 +112,7 @@ void ControlMissile(short fxNumber) } KillEffect(fxNumber); + return; } if (pointColl.GetRoomNumber() != fx.roomNumber) diff --git a/TombEngine/Objects/TR1/Entity/Centaur.cpp b/TombEngine/Objects/TR1/Entity/Centaur.cpp index fa5ef2fdc..8a32afb8d 100644 --- a/TombEngine/Objects/TR1/Entity/Centaur.cpp +++ b/TombEngine/Objects/TR1/Entity/Centaur.cpp @@ -23,7 +23,7 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR1 { constexpr auto CENTAUR_REAR_DAMAGE = 200; - constexpr auto CENTAUR_REAR_RANGE = BLOCK(3 / 2.0f); + constexpr auto CENTAUR_REAR_RANGE = SQUARE(BLOCK(3 / 2.0f)); constexpr auto CENTAUR_REAR_CHANCE = 1 / 340.0f; constexpr auto CENTAUR_BOMB_VELOCITY = CLICK(1); @@ -60,6 +60,9 @@ namespace TEN::Entities::Creatures::TR1 short headingAngle = 0; short headYOrient = 0; + short headXOrient = 0; + short torsoYOrient = 0; + short torsoXOrient = 0; if (item.HitPoints <= 0) { @@ -72,22 +75,25 @@ namespace TEN::Entities::Creatures::TR1 CreatureAIInfo(&item, &ai); if (ai.ahead) + { headYOrient = ai.angle; + headXOrient = ai.xAngle; + torsoYOrient = ai.angle / 2; + torsoXOrient = ai.xAngle / 2; + } + GetCreatureMood(&item, &ai, true); CreatureMood(&item, &ai, true); - headingAngle = CreatureTurn(&item, CENTAUR_TURN_RATE_MAX); switch (item.Animation.ActiveState) { case CENTAUR_STATE_IDLE: - CreatureJoint(&item, 17, 0); - if (item.Animation.RequiredState != NO_VALUE) { item.Animation.TargetState = item.Animation.RequiredState; } - else if (ai.bite && ai.distance < pow(CENTAUR_REAR_RANGE, 2)) + else if (ai.bite && ai.distance < CENTAUR_REAR_RANGE) { item.Animation.TargetState = CENTAUR_STATE_RUN_FORWARD; } @@ -103,7 +109,9 @@ namespace TEN::Entities::Creatures::TR1 break; case CENTAUR_STATE_RUN_FORWARD: - if (ai.bite && ai.distance < pow(CENTAUR_REAR_RANGE, 2)) + torsoYOrient = 0; + torsoXOrient = 0; + if (ai.bite && ai.distance < CENTAUR_REAR_RANGE) { item.Animation.TargetState = CENTAUR_STATE_IDLE; item.Animation.RequiredState = CENTAUR_STATE_WARNING; @@ -160,8 +168,10 @@ namespace TEN::Entities::Creatures::TR1 } CreatureJoint(&item, 0, headYOrient); + CreatureJoint(&item, 1, -headXOrient); + CreatureJoint(&item, 2, torsoYOrient); + CreatureJoint(&item, 3, -torsoXOrient); CreatureAnimation(itemNumber, headingAngle, 0); - if (item.Status == ITEM_DEACTIVATED) { SoundEffect(SFX_TR1_ATLANTEAN_DEATH, &item.Pose); diff --git a/TombEngine/Objects/TR1/tr1_objects.cpp b/TombEngine/Objects/TR1/tr1_objects.cpp index 9801d446f..2f2eb4c49 100644 --- a/TombEngine/Objects/TR1/tr1_objects.cpp +++ b/TombEngine/Objects/TR1/tr1_objects.cpp @@ -157,7 +157,8 @@ static void StartEntity(ObjectInfo* obj) obj->radius = BLOCK(1 / 3.0f); obj->intelligent = true; obj->LotType = LotType::Blockable; - obj->SetBoneRotationFlags(10, ROT_X | ROT_Y); + obj->SetBoneRotationFlags(10, ROT_X | ROT_Y); // Torso + obj->SetBoneRotationFlags(17, ROT_X | ROT_Y); // Head obj->SetHitEffect(); } @@ -274,7 +275,6 @@ static void StartProjectiles(ObjectInfo* obj) { InitProjectile(obj, ControlMissile, ID_PROJ_SHARD); InitProjectile(obj, ControlMissile, ID_PROJ_BOMB); - InitProjectile(obj, ControlMissile, ID_PROJ_BOMB); } void InitializeTR1Objects() diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index f04d93296..6d2a47cf7 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -165,7 +165,7 @@ enum GAME_OBJECT_ID : short ID_GIANT_MUTANT = 225, // 226 ID_PROJ_SHARD = 227, - ID_PROJ_BOMB, + ID_PROJ_BOMB, ID_YETI, ID_BIRDMONSTER, ID_MARCO_BARTOLI, From 374c42b9fb02471595739a19645302d8332437d2 Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Thu, 8 Aug 2024 01:07:06 +0200 Subject: [PATCH 245/410] Raptor upgrade (#1346) * Upgrade raptor OCB 0: NORMAL: Like the original, change zone type to basic to avoid the raptor to try jumping pit when he cant anymore. OCB 1: ABLE_TO_JUMP: can jump pit, new behaviour. --- TombEngine/Game/control/box.cpp | 14 +- TombEngine/Game/misc.cpp | 23 +- TombEngine/Game/misc.h | 2 +- TombEngine/Objects/TR3/Entity/tr3_raptor.cpp | 239 ++++++++++++------- TombEngine/Objects/TR3/tr3_objects.cpp | 5 +- 5 files changed, 177 insertions(+), 106 deletions(-) diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index a99729502..6b765938f 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -2184,19 +2184,7 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) if (creature.Enemy == nullptr) return false; - float stepDist = 0.0f; - switch (jumpDistType) - { - default: - case JumpDistance::Block1: - stepDist = BLOCK(0.51f); - break; - - case JumpDistance::Block2: - stepDist = BLOCK(0.76f); - break; - } - + float stepDist = BLOCK(0.92f); int vPos = item.Pose.Position.y; auto pointCollA = GetPointCollision(item, item.Pose.Orientation.y, stepDist); auto pointCollB = GetPointCollision(item, item.Pose.Orientation.y, stepDist * 2); diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 6365f6209..2ac1a19cd 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -16,20 +16,31 @@ CreatureInfo* GetCreatureInfo(ItemInfo* item) return (CreatureInfo*)item->Data; } -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature) +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, std::vector ignoredItemIds) { float nearestDistance = INFINITY; for (int i = 0; i < g_Level.NumItems; i++) { auto* targetEntity = &g_Level.Items[i]; - - if (targetEntity == nullptr) + if (targetEntity == nullptr || (targetEntity->Index == item->Index)) // Ignore itself ! continue; - if (targetEntity != item && - targetEntity->HitPoints > 0 && - targetEntity->Status != ITEM_INVISIBLE) + bool checkPassed = true; + for (auto& itemId : ignoredItemIds) + { + if (itemId == ID_NO_OBJECT) // NOTE: if there is any ID_NO_OBJECT then ignore the other itemids and attack the target ! + { + checkPassed = true; // just-in-case checkPassed was false ! + break; + } + else if (targetEntity->ObjectNumber == itemId) + checkPassed = false; + } + + if ((targetEntity != item && + targetEntity->HitPoints > 0 && + targetEntity->Status != ITEM_INVISIBLE) && checkPassed) { float distance = Vector3i::Distance(item->Pose.Position, targetEntity->Pose.Position); if (distance < nearestDistance) diff --git a/TombEngine/Game/misc.h b/TombEngine/Game/misc.h index d3e4b6e65..a0666dfcb 100644 --- a/TombEngine/Game/misc.h +++ b/TombEngine/Game/misc.h @@ -18,5 +18,5 @@ enum LaraMeshMask }; CreatureInfo* GetCreatureInfo(ItemInfo* item); -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature); +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, std::vector ignoredItemIds = {ID_NO_OBJECT}); bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat); diff --git a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp index 77d4c0558..d4445fb30 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp @@ -1,6 +1,7 @@ #include "framework.h" #include "Objects/TR3/Entity/tr3_raptor.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/lot.h" @@ -14,6 +15,7 @@ #include "Specific/level.h" using namespace TEN::Math; +using namespace TEN::Collision::Point; namespace TEN::Entities::Creatures::TR3 { @@ -27,7 +29,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto RAPTOR_SWITCH_TARGET_CHANCE = 1.0f / 128; constexpr auto RAPTOR_WALK_TURN_RATE_MAX = ANGLE(2.0f); - constexpr auto RAPTOR_RUN_TURN_RATE_MAX = ANGLE(2.0f); + constexpr auto RAPTOR_RUN_TURN_RATE_MAX = ANGLE(4.0f); constexpr auto RAPTOR_ATTACK_TURN_RATE_MAX = ANGLE(2.0f); const auto RaptorBite = CreatureBiteInfo(Vector3(0, 66, 318), 22); @@ -43,7 +45,11 @@ namespace TEN::Entities::Creatures::TR3 RAPTOR_STATE_NONE = 5, RAPTOR_STATE_ROAR = 6, RAPTOR_STATE_RUN_BITE_ATTACK = 7, - RAPTOR_STATE_BITE_ATTACK = 8 + RAPTOR_STATE_BITE_ATTACK = 8, + RAPTOR_STATE_JUMP_START = 9, + RAPTOR_STATE_JUMP_2BLOCK = 10, + RAPTOR_STATE_JUMP_1BLOCK = 11, + RAPTOR_STATE_CLIMB = 12 }; enum RaptorAnim @@ -61,16 +67,27 @@ namespace TEN::Entities::Creatures::TR3 RAPTOR_ANIM_DEATH_2 = 10, RAPTOR_ANIM_JUMP_ATTACK_START = 11, RAPTOR_ANIM_JUMP_ATTACK_END = 12, - RAPTOR_ANIM_BITE_ATTACK = 13 + RAPTOR_ANIM_BITE_ATTACK = 13, + RAPTOR_ANIM_JUMP_START = 14, + RAPTOR_ANIM_JUMP_2BLOCK = 15, + RAPTOR_ANIM_JUMP_END = 16, + RAPTOR_ANIM_JUMP_1BLOCK = 17, + RAPTOR_ANIM_VAULT_2CLICK = 18, + RAPTOR_ANIM_VAULT_3CLICK = 19, + RAPTOR_ANIM_VAULT_4CLICK = 20, + RAPTOR_ANIM_VAULT_DROP_2CLICK = 21, + RAPTOR_ANIM_VAULT_DROP_3CLICK = 22, + RAPTOR_ANIM_VAULT_DROP_4CLICK = 23 }; - // TODO enum RaptorFlags { - + OCB_NORMAL_BEHAVIOUR = 0, + OCB_ABLE_TO_JUMP = 1 }; const std::array RaptorDeathAnims = { RAPTOR_ANIM_DEATH_1, RAPTOR_ANIM_DEATH_2, }; + const std::vector RaptorIgnoreObjects = { ID_RAPTOR, ID_COMPSOGNATHUS }; void RaptorControl(short itemNumber) { @@ -79,76 +96,70 @@ namespace TEN::Entities::Creatures::TR3 auto* item = &g_Level.Items[itemNumber]; auto* creature = GetCreatureInfo(item); - short angle = 0; short tilt = 0; short head = 0; short neck = 0; - if (item->HitPoints <= 0) + bool canJump = item->TestOcb(OCB_ABLE_TO_JUMP); + if (!canJump) + { + creature->LOT.Step = CLICK(1); + creature->LOT.Drop = -CLICK(2); + creature->LOT.Zone = ZoneType::Basic; + creature->LOT.CanJump = false; + } + + bool canJump1block = canJump && CanCreatureJump(*item, JumpDistance::Block1); + bool canJump2blocks = canJump && !canJump1block && CanCreatureJump(*item, JumpDistance::Block2); + + if (item->HitPoints <= 0 && item->Animation.ActiveState == RAPTOR_STATE_IDLE) // Require IDLE state. { if (item->Animation.ActiveState != RAPTOR_STATE_DEATH) + { SetAnimation(item, RaptorDeathAnims[Random::GenerateInt(0, (int)RaptorDeathAnims.size() - 1)]); + } } else { - if (creature->Enemy == nullptr || Random::TestProbability(RAPTOR_SWITCH_TARGET_CHANCE)) - { - ItemInfo* nearestItem = nullptr; - float minDistance = INFINITY; - - for (auto& currentCreature : ActiveCreatures) - { - if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) - continue; - - auto* targetItem = &g_Level.Items[currentCreature->ItemNumber]; - - int distance = Vector3i::Distance(item->Pose.Position, targetItem->Pose.Position); - if (distance < minDistance && item->HitPoints > 0) - { - nearestItem = targetItem; - minDistance = distance; - } - } - - if (nearestItem != nullptr && - (nearestItem->ObjectNumber != ID_RAPTOR || - (Random::TestProbability(1 / 30.0f) && minDistance < SQUARE(BLOCK(2))))) - { - creature->Enemy = nearestItem; - } - - int distance = Vector3i::Distance(item->Pose.Position, LaraItem->Pose.Position); - if (distance <= minDistance) - creature->Enemy = LaraItem; - } + // Raptor ignore other raptor and mini-raptor but target anything else (TRex is not ignored) ! + TargetNearestEntity(item, creature, RaptorIgnoreObjects); + AI_INFO ai; if (item->AIBits) GetAITarget(creature); + CreatureAIInfo(item, &ai); - AI_INFO AI; - CreatureAIInfo(item, &AI); - - if (AI.ahead) - head = AI.angle; - - GetCreatureMood(item, &AI, true); - CreatureMood(item, &AI, true); - + GetCreatureMood(item, &ai, true); + CreatureMood(item, &ai, true); if (creature->Mood == MoodType::Bored) creature->MaxTurn /= 2; angle = CreatureTurn(item, creature->MaxTurn); - neck = -angle * 6; + if (ai.ahead) + { + head = ai.angle; + neck = -angle * 6; + } switch (item->Animation.ActiveState) { case RAPTOR_STATE_IDLE: creature->MaxTurn = 0; + creature->LOT.IsJumping = false; creature->Flags &= ~1; - if (item->Animation.RequiredState != NO_VALUE) + if (canJump1block || canJump2blocks) + { + creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_JUMP_START); + if (canJump1block) + item->Animation.TargetState = RAPTOR_STATE_JUMP_1BLOCK; + else + item->Animation.TargetState = RAPTOR_STATE_JUMP_2BLOCK; + creature->LOT.IsJumping = true; + } + else if (item->Animation.RequiredState != NO_VALUE) item->Animation.TargetState = item->Animation.RequiredState; else if (creature->Flags & 2) { @@ -156,14 +167,14 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.TargetState = RAPTOR_STATE_ROAR; } else if (item->TouchBits.Test(RaptorAttackJoints) || - (AI.distance < RAPTOR_BITE_ATTACK_RANGE && AI.bite)) + (ai.distance < RAPTOR_BITE_ATTACK_RANGE && ai.bite)) { item->Animation.TargetState = RAPTOR_STATE_BITE_ATTACK; } - else if (AI.bite && AI.distance < RAPTOR_JUMP_ATTACK_RANGE) + else if (ai.bite && ai.distance < RAPTOR_JUMP_ATTACK_RANGE) item->Animation.TargetState = RAPTOR_STATE_JUMP_ATTACK; else if (creature->Mood == MoodType::Escape && - Lara.TargetEntity != item && AI.ahead && !item->HitStatus) + Lara.TargetEntity != item && ai.ahead && !item->HitStatus) { item->Animation.TargetState = RAPTOR_STATE_IDLE; } @@ -176,11 +187,26 @@ namespace TEN::Entities::Creatures::TR3 case RAPTOR_STATE_WALK_FORWARD: creature->MaxTurn = RAPTOR_WALK_TURN_RATE_MAX; + creature->LOT.IsJumping = false; creature->Flags &= ~1; - if (creature->Mood != MoodType::Bored) + if (item->HitPoints <= 0) + { item->Animation.TargetState = RAPTOR_STATE_IDLE; - else if (AI.ahead && Random::TestProbability(RAPTOR_ROAR_CHANCE)) + } + else if (canJump1block || canJump2blocks) + { + creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_JUMP_START); + if (canJump1block) + item->Animation.TargetState = RAPTOR_STATE_JUMP_1BLOCK; + else + item->Animation.TargetState = RAPTOR_STATE_JUMP_2BLOCK; + creature->LOT.IsJumping = true; + } + else if (creature->Mood != MoodType::Bored) + item->Animation.TargetState = RAPTOR_STATE_IDLE; + else if (ai.ahead && Random::TestProbability(RAPTOR_ROAR_CHANCE)) { item->Animation.TargetState = RAPTOR_STATE_IDLE; item->Animation.RequiredState = RAPTOR_STATE_ROAR; @@ -191,10 +217,25 @@ namespace TEN::Entities::Creatures::TR3 case RAPTOR_STATE_RUN_FORWARD: creature->MaxTurn = RAPTOR_RUN_TURN_RATE_MAX; + creature->LOT.IsJumping = false; creature->Flags &= ~1; tilt = angle; - if (item->TouchBits.Test(RaptorAttackJoints)) + if (item->HitPoints <= 0) + { + item->Animation.TargetState = RAPTOR_STATE_IDLE; + } + else if (canJump1block || canJump2blocks) + { + creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_JUMP_START); + if (canJump1block) + item->Animation.TargetState = RAPTOR_STATE_JUMP_1BLOCK; + else + item->Animation.TargetState = RAPTOR_STATE_JUMP_2BLOCK; + creature->LOT.IsJumping = true; + } + else if (item->TouchBits.Test(RaptorAttackJoints)) item->Animation.TargetState = RAPTOR_STATE_IDLE; else if (creature->Flags & 2) { @@ -202,24 +243,21 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.RequiredState = RAPTOR_STATE_ROAR; creature->Flags &= ~2; } - else if (AI.bite && AI.distance < RAPTOR_RUN_ATTACK_RANGE) + else if (ai.bite && ai.distance < RAPTOR_RUN_ATTACK_RANGE) { - if (item->Animation.TargetState == RAPTOR_STATE_RUN_FORWARD) - { - if (Random::TestProbability(0.25f)) - item->Animation.TargetState = RAPTOR_STATE_IDLE; - else - item->Animation.TargetState = RAPTOR_STATE_RUN_BITE_ATTACK; - } + if (Random::TestProbability(0.25f)) + item->Animation.TargetState = RAPTOR_STATE_IDLE; + else + item->Animation.TargetState = RAPTOR_STATE_RUN_BITE_ATTACK; } - else if (AI.ahead && creature->Mood != MoodType::Escape && + else if (ai.ahead && creature->Mood != MoodType::Escape && Random::TestProbability(RAPTOR_ROAR_CHANCE)) { item->Animation.TargetState = RAPTOR_STATE_IDLE; item->Animation.RequiredState = RAPTOR_STATE_ROAR; } else if (creature->Mood == MoodType::Bored || - (creature->Mood == MoodType::Escape && Lara.TargetEntity != item && AI.ahead)) + (creature->Mood == MoodType::Escape && Lara.TargetEntity != item && ai.ahead)) { item->Animation.TargetState = RAPTOR_STATE_IDLE; } @@ -230,9 +268,9 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; tilt = angle; - if (creature->Enemy->IsLara()) + if (creature->Enemy != nullptr) { - if (!(creature->Flags & 1) && + if (creature->Enemy->IsLara() && !(creature->Flags & 1) && item->TouchBits.Test(RaptorAttackJoints)) { DoDamage(creature->Enemy, RAPTOR_ATTACK_DAMAGE); @@ -244,10 +282,7 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.RequiredState = RAPTOR_STATE_IDLE; } - } - else - { - if (!(creature->Flags & 1) && creature->Enemy != nullptr) + else if (!(creature->Flags & 1)) { if (Vector3i::Distance(item->Pose.Position, creature->Enemy->Pose.Position) <= BLOCK(0.5f)) { @@ -267,9 +302,9 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; tilt = angle; - if (creature->Enemy->IsLara()) + if (creature->Enemy != nullptr) { - if (!(creature->Flags & 1) && + if (creature->Enemy->IsLara() && !(creature->Flags & 1) && item->TouchBits.Test(RaptorAttackJoints)) { DoDamage(creature->Enemy, RAPTOR_ATTACK_DAMAGE); @@ -281,10 +316,7 @@ namespace TEN::Entities::Creatures::TR3 item->Animation.RequiredState = RAPTOR_STATE_IDLE; } - } - else - { - if (!(creature->Flags & 1) && creature->Enemy != nullptr) + else if (!(creature->Flags & 1)) { if (Vector3i::Distance(item->Pose.Position, creature->Enemy->Pose.Position) <= BLOCK(0.5f)) { @@ -304,9 +336,9 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; tilt = angle; - if (creature->Enemy->IsLara()) + if (creature->Enemy != nullptr) { - if (!(creature->Flags & 1) && + if (creature->Enemy->IsLara() && !(creature->Flags & 1) && item->TouchBits.Test(RaptorAttackJoints)) { DoDamage(creature->Enemy, RAPTOR_ATTACK_DAMAGE); @@ -317,10 +349,7 @@ namespace TEN::Entities::Creatures::TR3 if (LaraItem->HitPoints <= 0) creature->Flags |= 2; } - } - else - { - if (!(creature->Flags & 1) && creature->Enemy != nullptr) + else if (!(creature->Flags & 1)) { if (Vector3i::Distance(item->Pose.Position, creature->Enemy->Pose.Position) <= BLOCK(0.5f)) { @@ -343,6 +372,48 @@ namespace TEN::Entities::Creatures::TR3 CreatureJoint(item, 1, head / 2); CreatureJoint(item, 2, neck); CreatureJoint(item, 3, neck); - CreatureAnimation(itemNumber, angle, tilt); + + if (item->Animation.ActiveState != RAPTOR_STATE_JUMP_2BLOCK && + item->Animation.ActiveState != RAPTOR_STATE_JUMP_1BLOCK && + item->Animation.ActiveState != RAPTOR_STATE_CLIMB && + item->Animation.ActiveState != RAPTOR_STATE_JUMP_START) + { + switch (CreatureVault(itemNumber, angle, 2, CLICK(2.5f))) + { + case 2: + SetAnimation(item, RAPTOR_ANIM_VAULT_2CLICK); + creature->MaxTurn = 0; + break; + + case 3: + SetAnimation(item, RAPTOR_ANIM_VAULT_3CLICK); + creature->MaxTurn = 0; + break; + + case 4: + SetAnimation(item, RAPTOR_ANIM_VAULT_4CLICK); + creature->MaxTurn = 0; + break; + + case -2: + SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_2CLICK); + creature->MaxTurn = 0; + break; + + case -3: + SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_3CLICK); + creature->MaxTurn = 0; + break; + + case -4: + SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_4CLICK); + creature->MaxTurn = 0; + break; + } + } + else + { + CreatureAnimation(itemNumber, angle, tilt); + } } } diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index 663f8de36..3a9525920 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -117,6 +117,7 @@ static void StartEntity(ObjectInfo* obj) obj->radius = 341; obj->pivotLength = 600; obj->intelligent = true; + obj->LotType = LotType::HumanPlusJump; obj->SetBoneRotationFlags(20, ROT_Y); obj->SetBoneRotationFlags(21, ROT_Y); obj->SetBoneRotationFlags(23, ROT_Y); @@ -365,7 +366,7 @@ static void StartEntity(ObjectInfo* obj) obj->SetBoneRotationFlags(7, ROT_X | ROT_Y); // Head. obj->SetHitEffect(); } - + obj = &Objects[ID_WASP_MUTANT]; if (obj->loaded) { @@ -380,7 +381,7 @@ static void StartEntity(ObjectInfo* obj) obj->LotType = LotType::Flyer; obj->SetHitEffect(); } - + obj = &Objects[ID_COMPSOGNATHUS]; if (obj->loaded) { From a46c1af417d5d5fae6e24a148fb45a51dcc331ad Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Thu, 8 Aug 2024 00:21:20 +0100 Subject: [PATCH 246/410] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d5be69a..3e4586b7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,11 +32,16 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Enhaced Rolling Spindle detection to avoid them going down through pits. * Enhaced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) * Enhaced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). +* Enhanced Raptor behaviour and handling. + - OCB 0: Classic Behaviour + - OCB 1: Can jump up to 4 clicks and across a gap up to 2 blocks wide + - You must use the download version found on the TombEngine website. * Add new sound conditions: quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. * Changed Water sound condition to ShallowWater. + ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() From 89c4b0b22d75c4cd558dfe7c0d99432c47eea913 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Thu, 8 Aug 2024 00:22:19 +0100 Subject: [PATCH 247/410] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e4586b7b..1643f7adc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed sentry gun joint rotation. * Fixed teeth spikes not triggering the player impale animation. * Fixed TR4 mine crash with OCB 1 when triggered. +* Fixed cases where Atlantean mutant's bombs cause the game to crash. ### Features/Amendments * Changed Rome Hammer to not hurt player whilst deactivated. From 29e65d0d2e89454bb8a096c2debc241128fb75b4 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 8 Aug 2024 21:57:12 +1000 Subject: [PATCH 248/410] Formatting; simplify --- CHANGELOG.md | 8 +- TombEngine/Game/misc.cpp | 36 +- TombEngine/Game/misc.h | 2 +- TombEngine/Objects/TR1/Entity/Centaur.cpp | 29 +- TombEngine/Objects/TR3/Entity/tr3_raptor.cpp | 385 ++++++++++--------- 5 files changed, 240 insertions(+), 220 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1643f7adc..7e8a2b14c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,11 +33,11 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Enhaced Rolling Spindle detection to avoid them going down through pits. * Enhaced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) * Enhaced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). -* Enhanced Raptor behaviour and handling. - - OCB 0: Classic Behaviour - - OCB 1: Can jump up to 4 clicks and across a gap up to 2 blocks wide +* Enhanced raptor behaviour and handling. + - OCB 0: Classic behaviour + - OCB 1: Can jump up/down up to 4 steps and jump across gaps up to 2 blocks wide. - You must use the download version found on the TombEngine website. -* Add new sound conditions: quicksand and Underwater. +* Add new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. * Changed Water sound condition to ShallowWater. diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 2ac1a19cd..3b6560b59 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -8,45 +8,35 @@ #include "Game/items.h" #include "Game/Setup.h" #include "Specific/level.h" +#include "Specific/trutils.h" using namespace TEN::Collision::Point; +using namespace TEN::Utils; CreatureInfo* GetCreatureInfo(ItemInfo* item) { return (CreatureInfo*)item->Data; } -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, std::vector ignoredItemIds) +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& ignoredObjectIds) { - float nearestDistance = INFINITY; - + float closestDist = INFINITY; for (int i = 0; i < g_Level.NumItems; i++) { - auto* targetEntity = &g_Level.Items[i]; - if (targetEntity == nullptr || (targetEntity->Index == item->Index)) // Ignore itself ! + auto* targetItem = &g_Level.Items[i]; + if (targetItem == nullptr || targetItem->Index == item->Index) continue; - bool checkPassed = true; - for (auto& itemId : ignoredItemIds) - { - if (itemId == ID_NO_OBJECT) // NOTE: if there is any ID_NO_OBJECT then ignore the other itemids and attack the target ! - { - checkPassed = true; // just-in-case checkPassed was false ! - break; - } - else if (targetEntity->ObjectNumber == itemId) - checkPassed = false; - } + if (Contains(ignoredObjectIds, targetItem->ObjectNumber)) + continue; - if ((targetEntity != item && - targetEntity->HitPoints > 0 && - targetEntity->Status != ITEM_INVISIBLE) && checkPassed) + if (targetItem != item && targetItem->HitPoints > 0 && targetItem->Status != ITEM_INVISIBLE) { - float distance = Vector3i::Distance(item->Pose.Position, targetEntity->Pose.Position); - if (distance < nearestDistance) + float dist = Vector3i::Distance(item->Pose.Position, targetItem->Pose.Position); + if (dist < closestDist) { - creature->Enemy = targetEntity; - nearestDistance = distance; + creature->Enemy = targetItem; + closestDist = dist; } } } diff --git a/TombEngine/Game/misc.h b/TombEngine/Game/misc.h index a0666dfcb..c3f2f9928 100644 --- a/TombEngine/Game/misc.h +++ b/TombEngine/Game/misc.h @@ -18,5 +18,5 @@ enum LaraMeshMask }; CreatureInfo* GetCreatureInfo(ItemInfo* item); -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, std::vector ignoredItemIds = {ID_NO_OBJECT}); +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& ignoredObjectIds = {}); bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat); diff --git a/TombEngine/Objects/TR1/Entity/Centaur.cpp b/TombEngine/Objects/TR1/Entity/Centaur.cpp index 8a32afb8d..9d4e99c67 100644 --- a/TombEngine/Objects/TR1/Entity/Centaur.cpp +++ b/TombEngine/Objects/TR1/Entity/Centaur.cpp @@ -59,10 +59,8 @@ namespace TEN::Entities::Creatures::TR1 auto& creature = *GetCreatureInfo(&item); short headingAngle = 0; - short headYOrient = 0; - short headXOrient = 0; - short torsoYOrient = 0; - short torsoXOrient = 0; + auto headOrient = EulerAngles::Identity; + auto torsoOrient = EulerAngles::Identity; if (item.HitPoints <= 0) { @@ -76,10 +74,10 @@ namespace TEN::Entities::Creatures::TR1 if (ai.ahead) { - headYOrient = ai.angle; - headXOrient = ai.xAngle; - torsoYOrient = ai.angle / 2; - torsoXOrient = ai.xAngle / 2; + headOrient.x = ai.xAngle; + headOrient.y = ai.angle; + torsoOrient.x = ai.xAngle / 2; + torsoOrient.y = ai.angle / 2; } GetCreatureMood(&item, &ai, true); @@ -109,8 +107,8 @@ namespace TEN::Entities::Creatures::TR1 break; case CENTAUR_STATE_RUN_FORWARD: - torsoYOrient = 0; - torsoXOrient = 0; + torsoOrient = EulerAngles::Identity; + if (ai.bite && ai.distance < CENTAUR_REAR_RANGE) { item.Animation.TargetState = CENTAUR_STATE_IDLE; @@ -149,7 +147,7 @@ namespace TEN::Entities::Creatures::TR1 if (item.Animation.RequiredState == NO_VALUE) { item.Animation.RequiredState = CENTAUR_STATE_AIM; - CreatureEffect2(&item, CentaurRocketBite, CENTAUR_BOMB_VELOCITY, headYOrient, BombGun); + CreatureEffect2(&item, CentaurRocketBite, CENTAUR_BOMB_VELOCITY, headOrient.y, BombGun); } break; @@ -167,11 +165,12 @@ namespace TEN::Entities::Creatures::TR1 } } - CreatureJoint(&item, 0, headYOrient); - CreatureJoint(&item, 1, -headXOrient); - CreatureJoint(&item, 2, torsoYOrient); - CreatureJoint(&item, 3, -torsoXOrient); + CreatureJoint(&item, 0, headOrient.y); + CreatureJoint(&item, 1, -headOrient.x); + CreatureJoint(&item, 2, torsoOrient.y); + CreatureJoint(&item, 3, -torsoOrient.x); CreatureAnimation(itemNumber, headingAngle, 0); + if (item.Status == ITEM_DEACTIVATED) { SoundEffect(SFX_TR1_ATLANTEAN_DEATH, &item.Pose); diff --git a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp index d4445fb30..f15ddf362 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp @@ -14,8 +14,8 @@ #include "Math/Math.h" #include "Specific/level.h" -using namespace TEN::Math; using namespace TEN::Collision::Point; +using namespace TEN::Math; namespace TEN::Entities::Creatures::TR3 { @@ -47,8 +47,8 @@ namespace TEN::Entities::Creatures::TR3 RAPTOR_STATE_RUN_BITE_ATTACK = 7, RAPTOR_STATE_BITE_ATTACK = 8, RAPTOR_STATE_JUMP_START = 9, - RAPTOR_STATE_JUMP_2BLOCK = 10, - RAPTOR_STATE_JUMP_1BLOCK = 11, + RAPTOR_STATE_JUMP_2_BLOCKS = 10, + RAPTOR_STATE_JUMP_1_BLOCK = 11, RAPTOR_STATE_CLIMB = 12 }; @@ -69,229 +69,260 @@ namespace TEN::Entities::Creatures::TR3 RAPTOR_ANIM_JUMP_ATTACK_END = 12, RAPTOR_ANIM_BITE_ATTACK = 13, RAPTOR_ANIM_JUMP_START = 14, - RAPTOR_ANIM_JUMP_2BLOCK = 15, + RAPTOR_ANIM_JUMP_2_BLOCKS = 15, RAPTOR_ANIM_JUMP_END = 16, - RAPTOR_ANIM_JUMP_1BLOCK = 17, - RAPTOR_ANIM_VAULT_2CLICK = 18, - RAPTOR_ANIM_VAULT_3CLICK = 19, - RAPTOR_ANIM_VAULT_4CLICK = 20, - RAPTOR_ANIM_VAULT_DROP_2CLICK = 21, - RAPTOR_ANIM_VAULT_DROP_3CLICK = 22, - RAPTOR_ANIM_VAULT_DROP_4CLICK = 23 + RAPTOR_ANIM_JUMP_1_BLOCK = 17, + RAPTOR_ANIM_VAULT_2_STEPS = 18, + RAPTOR_ANIM_VAULT_4_STEPS = 19, + RAPTOR_ANIM_VAULT_4_STEPS = 20, + RAPTOR_ANIM_VAULT_DROP_2_STEPS = 21, + RAPTOR_ANIM_VAULT_DROP_3_STEPS = 22, + RAPTOR_ANIM_VAULT_DROP_4_STEPS = 23 }; enum RaptorFlags { OCB_NORMAL_BEHAVIOUR = 0, - OCB_ABLE_TO_JUMP = 1 + OCB_ENABLE_JUMP = 1 }; const std::array RaptorDeathAnims = { RAPTOR_ANIM_DEATH_1, RAPTOR_ANIM_DEATH_2, }; - const std::vector RaptorIgnoreObjects = { ID_RAPTOR, ID_COMPSOGNATHUS }; + const std::vector RaptorIgnoredObjectIds = { ID_RAPTOR, ID_COMPSOGNATHUS }; void RaptorControl(short itemNumber) { if (!CreatureActive(itemNumber)) return; - auto* item = &g_Level.Items[itemNumber]; - auto* creature = GetCreatureInfo(item); - short angle = 0; - short tilt = 0; - short head = 0; - short neck = 0; + auto& item = g_Level.Items[itemNumber]; + auto& creature = *GetCreatureInfo(&item); - bool canJump = item->TestOcb(OCB_ABLE_TO_JUMP); + short headingAngle = 0; + short tiltAngle = 0; + short headYOrient = 0; + short neckYOrient = 0; + + bool canJump = item.TestOcb(OCB_ENABLE_JUMP); if (!canJump) { - creature->LOT.Step = CLICK(1); - creature->LOT.Drop = -CLICK(2); - creature->LOT.Zone = ZoneType::Basic; - creature->LOT.CanJump = false; + creature.LOT.Step = CLICK(1); + creature.LOT.Drop = -CLICK(2); + creature.LOT.Zone = ZoneType::Basic; + creature.LOT.CanJump = false; } - bool canJump1block = canJump && CanCreatureJump(*item, JumpDistance::Block1); - bool canJump2blocks = canJump && !canJump1block && CanCreatureJump(*item, JumpDistance::Block2); + bool canJump1block = (canJump && CanCreatureJump(item, JumpDistance::Block1)); + bool canJump2blocks = (canJump && !canJump1block && CanCreatureJump(item, JumpDistance::Block2)); - if (item->HitPoints <= 0 && item->Animation.ActiveState == RAPTOR_STATE_IDLE) // Require IDLE state. + // Require Idle state. + if (item.HitPoints <= 0 && item.Animation.ActiveState == RAPTOR_STATE_IDLE) { - if (item->Animation.ActiveState != RAPTOR_STATE_DEATH) - { + if (item.Animation.ActiveState != RAPTOR_STATE_DEATH) SetAnimation(item, RaptorDeathAnims[Random::GenerateInt(0, (int)RaptorDeathAnims.size() - 1)]); - } } else { - // Raptor ignore other raptor and mini-raptor but target anything else (TRex is not ignored) ! - TargetNearestEntity(item, creature, RaptorIgnoreObjects); + // NOTE: Ignores other small dinosaurs. + TargetNearestEntity(&item, &creature, RaptorIgnoredObjectIds); AI_INFO ai; - if (item->AIBits) - GetAITarget(creature); - CreatureAIInfo(item, &ai); + if (item.AIBits) + GetAITarget(&creature); + CreatureAIInfo(&item, &ai); - GetCreatureMood(item, &ai, true); - CreatureMood(item, &ai, true); - if (creature->Mood == MoodType::Bored) - creature->MaxTurn /= 2; + GetCreatureMood(&item, &ai, true); + CreatureMood(&item, &ai, true); + if (creature.Mood == MoodType::Bored) + creature.MaxTurn /= 2; - angle = CreatureTurn(item, creature->MaxTurn); + headingAngle = CreatureTurn(&item, creature.MaxTurn); if (ai.ahead) { - head = ai.angle; - neck = -angle * 6; + headYOrient = ai.angle; + neckYOrient = -headingAngle * 6; } - switch (item->Animation.ActiveState) + switch (item.Animation.ActiveState) { case RAPTOR_STATE_IDLE: - creature->MaxTurn = 0; - creature->LOT.IsJumping = false; - creature->Flags &= ~1; + creature.MaxTurn = 0; + creature.LOT.IsJumping = false; + creature.Flags &= ~1; if (canJump1block || canJump2blocks) { - creature->MaxTurn = 0; + creature.MaxTurn = 0; + creature.LOT.IsJumping = true; SetAnimation(item, RAPTOR_ANIM_JUMP_START); + if (canJump1block) - item->Animation.TargetState = RAPTOR_STATE_JUMP_1BLOCK; + { + item.Animation.TargetState = RAPTOR_STATE_JUMP_1_BLOCK; + } else - item->Animation.TargetState = RAPTOR_STATE_JUMP_2BLOCK; - creature->LOT.IsJumping = true; + { + item.Animation.TargetState = RAPTOR_STATE_JUMP_2_BLOCKS; + } } - else if (item->Animation.RequiredState != NO_VALUE) - item->Animation.TargetState = item->Animation.RequiredState; - else if (creature->Flags & 2) + else if (item.Animation.RequiredState != NO_VALUE) { - creature->Flags &= ~2; - item->Animation.TargetState = RAPTOR_STATE_ROAR; + item.Animation.TargetState = item.Animation.RequiredState; } - else if (item->TouchBits.Test(RaptorAttackJoints) || + else if (creature.Flags & 2) + { + creature.Flags &= ~2; + item.Animation.TargetState = RAPTOR_STATE_ROAR; + } + else if (item.TouchBits.Test(RaptorAttackJoints) || (ai.distance < RAPTOR_BITE_ATTACK_RANGE && ai.bite)) { - item->Animation.TargetState = RAPTOR_STATE_BITE_ATTACK; + item.Animation.TargetState = RAPTOR_STATE_BITE_ATTACK; } else if (ai.bite && ai.distance < RAPTOR_JUMP_ATTACK_RANGE) - item->Animation.TargetState = RAPTOR_STATE_JUMP_ATTACK; - else if (creature->Mood == MoodType::Escape && - Lara.TargetEntity != item && ai.ahead && !item->HitStatus) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.TargetState = RAPTOR_STATE_JUMP_ATTACK; + } + else if (creature.Mood == MoodType::Escape && + Lara.TargetEntity != &item && ai.ahead && !item.HitStatus) + { + item.Animation.TargetState = RAPTOR_STATE_IDLE; + } + else if (creature.Mood == MoodType::Bored) + { + item.Animation.TargetState = RAPTOR_STATE_WALK_FORWARD; } - else if (creature->Mood == MoodType::Bored) - item->Animation.TargetState = RAPTOR_STATE_WALK_FORWARD; else - item->Animation.TargetState = RAPTOR_STATE_RUN_FORWARD; + { + item.Animation.TargetState = RAPTOR_STATE_RUN_FORWARD; + } break; case RAPTOR_STATE_WALK_FORWARD: - creature->MaxTurn = RAPTOR_WALK_TURN_RATE_MAX; - creature->LOT.IsJumping = false; - creature->Flags &= ~1; + creature.MaxTurn = RAPTOR_WALK_TURN_RATE_MAX; + creature.LOT.IsJumping = false; + creature.Flags &= ~1; - if (item->HitPoints <= 0) + if (item.HitPoints <= 0) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.TargetState = RAPTOR_STATE_IDLE; } else if (canJump1block || canJump2blocks) { - creature->MaxTurn = 0; + creature.MaxTurn = 0; + creature.LOT.IsJumping = true; SetAnimation(item, RAPTOR_ANIM_JUMP_START); + if (canJump1block) - item->Animation.TargetState = RAPTOR_STATE_JUMP_1BLOCK; + { + item.Animation.TargetState = RAPTOR_STATE_JUMP_1_BLOCK; + } else - item->Animation.TargetState = RAPTOR_STATE_JUMP_2BLOCK; - creature->LOT.IsJumping = true; + { + item.Animation.TargetState = RAPTOR_STATE_JUMP_2_BLOCKS; + } + } + else if (creature.Mood != MoodType::Bored) + { + item.Animation.TargetState = RAPTOR_STATE_IDLE; } - else if (creature->Mood != MoodType::Bored) - item->Animation.TargetState = RAPTOR_STATE_IDLE; else if (ai.ahead && Random::TestProbability(RAPTOR_ROAR_CHANCE)) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; - item->Animation.RequiredState = RAPTOR_STATE_ROAR; - creature->Flags &= ~2; + item.Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.RequiredState = RAPTOR_STATE_ROAR; + creature.Flags &= ~2; } break; case RAPTOR_STATE_RUN_FORWARD: - creature->MaxTurn = RAPTOR_RUN_TURN_RATE_MAX; - creature->LOT.IsJumping = false; - creature->Flags &= ~1; - tilt = angle; + creature.MaxTurn = RAPTOR_RUN_TURN_RATE_MAX; + creature.LOT.IsJumping = false; + creature.Flags &= ~1; + tiltAngle = headingAngle; - if (item->HitPoints <= 0) + if (item.HitPoints <= 0) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.TargetState = RAPTOR_STATE_IDLE; } else if (canJump1block || canJump2blocks) { - creature->MaxTurn = 0; + creature.MaxTurn = 0; + creature.LOT.IsJumping = true; SetAnimation(item, RAPTOR_ANIM_JUMP_START); + if (canJump1block) - item->Animation.TargetState = RAPTOR_STATE_JUMP_1BLOCK; + { + item.Animation.TargetState = RAPTOR_STATE_JUMP_1_BLOCK; + } else - item->Animation.TargetState = RAPTOR_STATE_JUMP_2BLOCK; - creature->LOT.IsJumping = true; + { + item.Animation.TargetState = RAPTOR_STATE_JUMP_2_BLOCKS; + } } - else if (item->TouchBits.Test(RaptorAttackJoints)) - item->Animation.TargetState = RAPTOR_STATE_IDLE; - else if (creature->Flags & 2) + else if (item.TouchBits.Test(RaptorAttackJoints)) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; - item->Animation.RequiredState = RAPTOR_STATE_ROAR; - creature->Flags &= ~2; + item.Animation.TargetState = RAPTOR_STATE_IDLE; + } + else if (creature.Flags & 2) + { + item.Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.RequiredState = RAPTOR_STATE_ROAR; + creature.Flags &= ~2; } else if (ai.bite && ai.distance < RAPTOR_RUN_ATTACK_RANGE) { - if (Random::TestProbability(0.25f)) - item->Animation.TargetState = RAPTOR_STATE_IDLE; + if (Random::TestProbability(1 / 4.0f)) + { + item.Animation.TargetState = RAPTOR_STATE_IDLE; + } else - item->Animation.TargetState = RAPTOR_STATE_RUN_BITE_ATTACK; + { + item.Animation.TargetState = RAPTOR_STATE_RUN_BITE_ATTACK; + } } - else if (ai.ahead && creature->Mood != MoodType::Escape && + else if (ai.ahead && creature.Mood != MoodType::Escape && Random::TestProbability(RAPTOR_ROAR_CHANCE)) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; - item->Animation.RequiredState = RAPTOR_STATE_ROAR; + item.Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.RequiredState = RAPTOR_STATE_ROAR; } - else if (creature->Mood == MoodType::Bored || - (creature->Mood == MoodType::Escape && Lara.TargetEntity != item && ai.ahead)) + else if (creature.Mood == MoodType::Bored || + (creature.Mood == MoodType::Escape && Lara.TargetEntity != &item && ai.ahead)) { - item->Animation.TargetState = RAPTOR_STATE_IDLE; + item.Animation.TargetState = RAPTOR_STATE_IDLE; } break; case RAPTOR_STATE_JUMP_ATTACK: - creature->MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; - tilt = angle; + creature.MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; + tiltAngle = headingAngle; - if (creature->Enemy != nullptr) + if (creature.Enemy != nullptr) { - if (creature->Enemy->IsLara() && !(creature->Flags & 1) && - item->TouchBits.Test(RaptorAttackJoints)) + if (creature.Enemy->IsLara() && !(creature.Flags & 1) && + item.TouchBits.Test(RaptorAttackJoints)) { - DoDamage(creature->Enemy, RAPTOR_ATTACK_DAMAGE); - CreatureEffect(item, RaptorBite, DoBloodSplat); - creature->Flags |= 1; + DoDamage(creature.Enemy, RAPTOR_ATTACK_DAMAGE); + CreatureEffect(&item, RaptorBite, DoBloodSplat); + creature.Flags |= 1; if (LaraItem->HitPoints <= 0) - creature->Flags |= 2; + creature.Flags |= 2; - item->Animation.RequiredState = RAPTOR_STATE_IDLE; + item.Animation.RequiredState = RAPTOR_STATE_IDLE; } - else if (!(creature->Flags & 1)) + else if (!(creature.Flags & 1)) { - if (Vector3i::Distance(item->Pose.Position, creature->Enemy->Pose.Position) <= BLOCK(0.5f)) + if (Vector3i::Distance(item.Pose.Position, creature.Enemy->Pose.Position) <= BLOCK(0.5f)) { - if (creature->Enemy->HitPoints <= 0) - creature->Flags |= 2; + if (creature.Enemy->HitPoints <= 0) + creature.Flags |= 2; - DoDamage(creature->Enemy, 25); - CreatureEffect(item, RaptorBite, DoBloodSplat); - creature->Flags |= 1; + DoDamage(creature.Enemy, 25); + CreatureEffect(&item, RaptorBite, DoBloodSplat); + creature.Flags |= 1; } } } @@ -299,33 +330,33 @@ namespace TEN::Entities::Creatures::TR3 break; case RAPTOR_STATE_BITE_ATTACK: - creature->MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; - tilt = angle; + creature.MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; + tiltAngle = headingAngle; - if (creature->Enemy != nullptr) + if (creature.Enemy != nullptr) { - if (creature->Enemy->IsLara() && !(creature->Flags & 1) && - item->TouchBits.Test(RaptorAttackJoints)) + if (creature.Enemy->IsLara() && !(creature.Flags & 1) && + item.TouchBits.Test(RaptorAttackJoints)) { - DoDamage(creature->Enemy, RAPTOR_ATTACK_DAMAGE); - CreatureEffect(item, RaptorBite, DoBloodSplat); - creature->Flags |= 1; + DoDamage(creature.Enemy, RAPTOR_ATTACK_DAMAGE); + CreatureEffect(&item, RaptorBite, DoBloodSplat); + creature.Flags |= 1; if (LaraItem->HitPoints <= 0) - creature->Flags |= 2; + creature.Flags |= 2; - item->Animation.RequiredState = RAPTOR_STATE_IDLE; + item.Animation.RequiredState = RAPTOR_STATE_IDLE; } - else if (!(creature->Flags & 1)) + else if (!(creature.Flags & 1)) { - if (Vector3i::Distance(item->Pose.Position, creature->Enemy->Pose.Position) <= BLOCK(0.5f)) + if (Vector3i::Distance(item.Pose.Position, creature.Enemy->Pose.Position) <= BLOCK(0.5f)) { - if (creature->Enemy->HitPoints <= 0) - creature->Flags |= 2; + if (creature.Enemy->HitPoints <= 0) + creature.Flags |= 2; - DoDamage(creature->Enemy, 25); - CreatureEffect(item, RaptorBite, DoBloodSplat); - creature->Flags |= 1; + DoDamage(creature.Enemy, 25); + CreatureEffect(&item, RaptorBite, DoBloodSplat); + creature.Flags |= 1; } } } @@ -333,32 +364,32 @@ namespace TEN::Entities::Creatures::TR3 break; case RAPTOR_STATE_RUN_BITE_ATTACK: - creature->MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; - tilt = angle; + creature.MaxTurn = RAPTOR_ATTACK_TURN_RATE_MAX; + tiltAngle = headingAngle; - if (creature->Enemy != nullptr) + if (creature.Enemy != nullptr) { - if (creature->Enemy->IsLara() && !(creature->Flags & 1) && - item->TouchBits.Test(RaptorAttackJoints)) + if (creature.Enemy->IsLara() && !(creature.Flags & 1) && + item.TouchBits.Test(RaptorAttackJoints)) { - DoDamage(creature->Enemy, RAPTOR_ATTACK_DAMAGE); - CreatureEffect(item, RaptorBite, DoBloodSplat); - item->Animation.RequiredState = RAPTOR_STATE_RUN_FORWARD; - creature->Flags |= 1; + DoDamage(creature.Enemy, RAPTOR_ATTACK_DAMAGE); + CreatureEffect(&item, RaptorBite, DoBloodSplat); + item.Animation.RequiredState = RAPTOR_STATE_RUN_FORWARD; + creature.Flags |= 1; if (LaraItem->HitPoints <= 0) - creature->Flags |= 2; + creature.Flags |= 2; } - else if (!(creature->Flags & 1)) + else if (!(creature.Flags & 1)) { - if (Vector3i::Distance(item->Pose.Position, creature->Enemy->Pose.Position) <= BLOCK(0.5f)) + if (Vector3i::Distance(item.Pose.Position, creature.Enemy->Pose.Position) <= BLOCK(0.5f)) { - if (creature->Enemy->HitPoints <= 0) - creature->Flags |= 2; + if (creature.Enemy->HitPoints <= 0) + creature.Flags |= 2; - DoDamage(creature->Enemy, 25); - CreatureEffect(item, RaptorBite, DoBloodSplat); - creature->Flags |= 1; + DoDamage(creature.Enemy, 25); + CreatureEffect(&item, RaptorBite, DoBloodSplat); + creature.Flags |= 1; } } } @@ -367,53 +398,53 @@ namespace TEN::Entities::Creatures::TR3 } } - CreatureTilt(item, tilt); - CreatureJoint(item, 0, head / 2); - CreatureJoint(item, 1, head / 2); - CreatureJoint(item, 2, neck); - CreatureJoint(item, 3, neck); + CreatureTilt(&item, tiltAngle); + CreatureJoint(&item, 0, headYOrient / 2); + CreatureJoint(&item, 1, headYOrient / 2); + CreatureJoint(&item, 2, neckYOrient); + CreatureJoint(&item, 3, neckYOrient); - if (item->Animation.ActiveState != RAPTOR_STATE_JUMP_2BLOCK && - item->Animation.ActiveState != RAPTOR_STATE_JUMP_1BLOCK && - item->Animation.ActiveState != RAPTOR_STATE_CLIMB && - item->Animation.ActiveState != RAPTOR_STATE_JUMP_START) + if (item.Animation.ActiveState != RAPTOR_STATE_JUMP_2_BLOCKS && + item.Animation.ActiveState != RAPTOR_STATE_JUMP_1_BLOCK && + item.Animation.ActiveState != RAPTOR_STATE_CLIMB && + item.Animation.ActiveState != RAPTOR_STATE_JUMP_START) { - switch (CreatureVault(itemNumber, angle, 2, CLICK(2.5f))) + switch (CreatureVault(itemNumber, headingAngle, 2, CLICK(2.5f))) { case 2: - SetAnimation(item, RAPTOR_ANIM_VAULT_2CLICK); - creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_VAULT_2_STEPS); + creature.MaxTurn = 0; break; case 3: - SetAnimation(item, RAPTOR_ANIM_VAULT_3CLICK); - creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_VAULT_4_STEPS); + creature.MaxTurn = 0; break; case 4: - SetAnimation(item, RAPTOR_ANIM_VAULT_4CLICK); - creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_VAULT_4_STEPS); + creature.MaxTurn = 0; break; case -2: - SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_2CLICK); - creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_2_STEPS); + creature.MaxTurn = 0; break; case -3: - SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_3CLICK); - creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_3_STEPS); + creature.MaxTurn = 0; break; case -4: - SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_4CLICK); - creature->MaxTurn = 0; + SetAnimation(item, RAPTOR_ANIM_VAULT_DROP_4_STEPS); + creature.MaxTurn = 0; break; } } else { - CreatureAnimation(itemNumber, angle, tilt); + CreatureAnimation(itemNumber, headingAngle, tiltAngle); } } } From 9ae935b8bb3aff89b18621fcfeff539f1bb7eb16 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 8 Aug 2024 22:12:50 +1000 Subject: [PATCH 249/410] Extend functionality of TargetNearestEntity() --- TombEngine/Game/misc.cpp | 17 +++++++++-------- TombEngine/Game/misc.h | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 3b6560b59..1d7ea6785 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -18,25 +18,26 @@ CreatureInfo* GetCreatureInfo(ItemInfo* item) return (CreatureInfo*)item->Data; } -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& ignoredObjectIds) +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds, bool ignoreKeyObjectIds) { - float closestDist = INFINITY; - for (int i = 0; i < g_Level.NumItems; i++) + float closestDistSqr = INFINITY; + for (int itemNumber = 0; itemNumber < g_Level.NumItems; itemNumber++) { - auto* targetItem = &g_Level.Items[i]; + auto* targetItem = &g_Level.Items[itemNumber]; if (targetItem == nullptr || targetItem->Index == item->Index) continue; - if (Contains(ignoredObjectIds, targetItem->ObjectNumber)) + // Ignore or specifically target key object IDs. + if (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem->ObjectNumber) : !Contains(keyObjectIds, targetItem->ObjectNumber)) continue; if (targetItem != item && targetItem->HitPoints > 0 && targetItem->Status != ITEM_INVISIBLE) { - float dist = Vector3i::Distance(item->Pose.Position, targetItem->Pose.Position); - if (dist < closestDist) + float distSqr = Vector3i::DistanceSquared(item->Pose.Position, targetItem->Pose.Position); + if (distSqr < closestDistSqr) { creature->Enemy = targetItem; - closestDist = dist; + closestDistSqr = distSqr; } } } diff --git a/TombEngine/Game/misc.h b/TombEngine/Game/misc.h index c3f2f9928..54defb43e 100644 --- a/TombEngine/Game/misc.h +++ b/TombEngine/Game/misc.h @@ -18,5 +18,5 @@ enum LaraMeshMask }; CreatureInfo* GetCreatureInfo(ItemInfo* item); -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& ignoredObjectIds = {}); +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds = {}, bool ignoreKeyObjectIds = true); bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat); From 943c552627409be7dc395d1d43e539dd8fc542df Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 8 Aug 2024 22:22:32 +1000 Subject: [PATCH 250/410] Rename raptor files --- .../TR3/Entity/{tr3_raptor.cpp => Raptor.cpp} | 2 +- .../TR3/Entity/{tr3_raptor.h => Raptor.h} | 0 TombEngine/Objects/TR3/tr3_objects.cpp | 42 +++++++++---------- TombEngine/TombEngine.vcxproj | 4 +- 4 files changed, 24 insertions(+), 24 deletions(-) rename TombEngine/Objects/TR3/Entity/{tr3_raptor.cpp => Raptor.cpp} (99%) rename TombEngine/Objects/TR3/Entity/{tr3_raptor.h => Raptor.h} (100%) diff --git a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp b/TombEngine/Objects/TR3/Entity/Raptor.cpp similarity index 99% rename from TombEngine/Objects/TR3/Entity/tr3_raptor.cpp rename to TombEngine/Objects/TR3/Entity/Raptor.cpp index f15ddf362..24b391593 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/Raptor.cpp @@ -1,5 +1,5 @@ #include "framework.h" -#include "Objects/TR3/Entity/tr3_raptor.h" +#include "Objects/TR3/Entity/Raptor.h" #include "Game/collision/Point.h" #include "Game/control/box.h" diff --git a/TombEngine/Objects/TR3/Entity/tr3_raptor.h b/TombEngine/Objects/TR3/Entity/Raptor.h similarity index 100% rename from TombEngine/Objects/TR3/Entity/tr3_raptor.h rename to TombEngine/Objects/TR3/Entity/Raptor.h diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index 3a9525920..5dadc08b3 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -8,28 +8,28 @@ #include "Specific/level.h" // Creatures -#include "Objects/TR3/Entity/Compsognathus.h" // OK -#include "Objects/TR3/Entity/Lizard.h" // OK -#include "Objects/TR3/Entity/PunaBoss.h" // OK -#include "Objects/TR3/Entity/Shiva.h" // OK -#include "Objects/TR3/Entity/SophiaLeigh.h" // OK +#include "Objects/TR3/Entity/Compsognathus.h" +#include "Objects/TR3/Entity/Lizard.h" +#include "Objects/TR3/Entity/PunaBoss.h" +#include "Objects/TR3/Entity/Raptor.h" +#include "Objects/TR3/Entity/Shiva.h" +#include "Objects/TR3/Entity/SophiaLeigh.h" #include "Objects/TR3/Entity/TwinAutoGun.h" -#include "Objects/TR3/Entity/WaspMutant.h" // OK -#include "Objects/TR3/Entity/Winston.h" // OK -#include "Objects/TR3/Entity/tr3_tony.h" // OK -#include "Objects/TR3/Entity/tr3_civvy.h" // OK -#include "Objects/TR3/Entity/tr3_claw_mutant.h" // OK -#include "Objects/TR3/Entity/tr3_cobra.h" // OK -#include "Objects/TR3/Entity/FishSwarm.h" // OK -#include "Objects/TR3/Entity/tr3_flamethrower.h" // OK -#include "Objects/TR3/Entity/tr3_monkey.h" // OK -#include "Objects/TR3/Entity/tr3_mp_gun.h" // OK -#include "Objects/TR3/Entity/tr3_mp_stick.h" // OK -#include "Objects/TR3/Entity/tr3_raptor.h" // OK -#include "Objects/TR3/Entity/tr3_scuba_diver.h" // OK -#include "Objects/TR3/Entity/tr3_tiger.h" // OK -#include "Objects/TR3/Entity/tr3_trex.h" // OK -#include "Objects/TR3/Entity/tr3_tribesman.h" // OK +#include "Objects/TR3/Entity/WaspMutant.h" +#include "Objects/TR3/Entity/Winston.h" +#include "Objects/TR3/Entity/tr3_tony.h" +#include "Objects/TR3/Entity/tr3_civvy.h" +#include "Objects/TR3/Entity/tr3_claw_mutant.h" +#include "Objects/TR3/Entity/tr3_cobra.h" +#include "Objects/TR3/Entity/FishSwarm.h" +#include "Objects/TR3/Entity/tr3_flamethrower.h" +#include "Objects/TR3/Entity/tr3_monkey.h" +#include "Objects/TR3/Entity/tr3_mp_gun.h" +#include "Objects/TR3/Entity/tr3_mp_stick.h" +#include "Objects/TR3/Entity/tr3_scuba_diver.h" +#include "Objects/TR3/Entity/tr3_tiger.h" +#include "Objects/TR3/Entity/tr3_trex.h" +#include "Objects/TR3/Entity/tr3_tribesman.h" // Effects #include "Objects/Effects/Boss.h" diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 6f8cf8200..67efb3876 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -531,6 +531,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -542,7 +543,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -1037,6 +1037,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -1046,7 +1047,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - From 587ce7d55113f3ae84442b51a490cc63e775b7a2 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 8 Aug 2024 22:23:30 +1000 Subject: [PATCH 251/410] Remove magic number --- TombEngine/Objects/TR3/Entity/Raptor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Objects/TR3/Entity/Raptor.cpp b/TombEngine/Objects/TR3/Entity/Raptor.cpp index 24b391593..6710ad9b3 100644 --- a/TombEngine/Objects/TR3/Entity/Raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/Raptor.cpp @@ -21,7 +21,7 @@ namespace TEN::Entities::Creatures::TR3 { constexpr auto RAPTOR_ATTACK_DAMAGE = 100; - constexpr auto RAPTOR_BITE_ATTACK_RANGE = SQUARE(585); + constexpr auto RAPTOR_BITE_ATTACK_RANGE = SQUARE(BLOCK(0.6f)); constexpr auto RAPTOR_JUMP_ATTACK_RANGE = SQUARE(BLOCK(1.5f)); constexpr auto RAPTOR_RUN_ATTACK_RANGE = SQUARE(BLOCK(1.5f)); From 77af7e9e223bf535affe9d99e698636963c7872e Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 8 Aug 2024 22:28:52 +1000 Subject: [PATCH 252/410] Update Raptor.cpp --- TombEngine/Objects/TR3/Entity/Raptor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Objects/TR3/Entity/Raptor.cpp b/TombEngine/Objects/TR3/Entity/Raptor.cpp index 6710ad9b3..084fee14a 100644 --- a/TombEngine/Objects/TR3/Entity/Raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/Raptor.cpp @@ -73,7 +73,7 @@ namespace TEN::Entities::Creatures::TR3 RAPTOR_ANIM_JUMP_END = 16, RAPTOR_ANIM_JUMP_1_BLOCK = 17, RAPTOR_ANIM_VAULT_2_STEPS = 18, - RAPTOR_ANIM_VAULT_4_STEPS = 19, + RAPTOR_ANIM_VAULT_3_STEPS = 19, RAPTOR_ANIM_VAULT_4_STEPS = 20, RAPTOR_ANIM_VAULT_DROP_2_STEPS = 21, RAPTOR_ANIM_VAULT_DROP_3_STEPS = 22, @@ -417,7 +417,7 @@ namespace TEN::Entities::Creatures::TR3 break; case 3: - SetAnimation(item, RAPTOR_ANIM_VAULT_4_STEPS); + SetAnimation(item, RAPTOR_ANIM_VAULT_3_STEPS); creature.MaxTurn = 0; break; From 046e0b26accc0ee98270363b40ac3c188a303381 Mon Sep 17 00:00:00 2001 From: Jakub <80340234+Jakub768@users.noreply.github.com> Date: Sun, 11 Aug 2024 09:57:43 +0100 Subject: [PATCH 253/410] Update AUTHORS.md --- AUTHORS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS.md b/AUTHORS.md index 69085982d..d7122440f 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -20,7 +20,8 @@ This is the credit list of **all** the people who contributed to TombEngine in a - TokyoSU (entity and vehicle decompilation) - Tomo (general coding, bug fixing) - Troye (general coding, refactoring) -- WolfCheese (general coding) +- Nickelony (general coding) +- JesseG, aka WolfCheese (general coding) ## Testers - Adngel From 0628affb69bf332d0703d43ee495dbf29dd11dd7 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 11 Aug 2024 09:59:56 +0100 Subject: [PATCH 254/410] Rework menu option looping (#1393) * Remove menu loop * Update CHANGELOG.md * Update config * Implement new menu logic * Remove mouse smoothing * Update Input.cpp * Allow 3 options for menu looping * Name adjustment * Rename RegKey * String key rename * General refactors * Change default menu looping mode * Update configuration.h --------- Co-authored-by: Sezz --- CHANGELOG.md | 3 +- Scripts/SystemStrings.lua | 5 +- TombEngine/Game/gui.cpp | 292 ++++++------------ TombEngine/Game/gui.h | 3 + TombEngine/Renderer/RendererDrawMenu.cpp | 61 ++-- .../Scripting/Internal/LanguageScript.h | 7 +- TombEngine/Specific/Input/Input.cpp | 5 +- TombEngine/Specific/configuration.cpp | 18 +- TombEngine/Specific/configuration.h | 41 ++- 9 files changed, 182 insertions(+), 253 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e8a2b14c..624420851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. * Changed Water sound condition to ShallowWater. - +* Added option to enable or disable menu option looping. +* Menu scrolling using held inputs will stop at the last option until a new input is made. ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. diff --git a/Scripts/SystemStrings.lua b/Scripts/SystemStrings.lua index 23f4c749b..29ae938c4 100644 --- a/Scripts/SystemStrings.lua +++ b/Scripts/SystemStrings.lua @@ -80,8 +80,11 @@ local strings = low = { "Low" }, medium = { "Medium" }, menu_actions = { "Menu Actions" }, + menu_option_looping = { "Menu Option Looping" }, + menu_option_looping_all_menus = { "All Menus" }, + menu_option_looping_disabled = { "Disabled" }, + menu_option_looping_save_load_only = { "Save/Load Only" }, mouse_sensitivity = { "Mouse Sensitivity" }, - mouse_smoothing = { "Mouse Smoothing" }, music_volume = { "Music Volume" }, new_game = { "New Game" }, none = { "None" }, diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index baf36f0e6..586dd8dfc 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -173,7 +173,7 @@ namespace TEN::Gui return ((IsReleased(In::Select) || IsReleased(In::Action)) && CanSelect()); } } - + bool GuiController::GuiIsDeselected() const { return ((IsClicked(In::Deselect) || IsClicked(In::Draw)) && CanDeselect()); @@ -354,21 +354,7 @@ namespace TEN::Gui MenuToDisplay == Menu::SelectLevel || MenuToDisplay == Menu::Options) { - if (GuiIsPulsed(In::Forward)) - { - SelectedOption = (SelectedOption <= 0) ? OptionCount : (SelectedOption - 1); - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } - - if (GuiIsPulsed(In::Back)) - { - if (SelectedOption < OptionCount) - SelectedOption++; - else - SelectedOption -= OptionCount; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } + SelectedOption = GetLoopedSelectedOption(SelectedOption, OptionCount, g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus); if (GuiIsDeselected() && MenuToDisplay != Menu::Title) { @@ -577,25 +563,7 @@ namespace TEN::Gui } } - if (GuiIsPulsed(In::Forward)) - { - if (SelectedOption <= 0) - SelectedOption += OptionCount; - else - SelectedOption--; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } - - if (GuiIsPulsed(In::Back)) - { - if (SelectedOption < OptionCount) - SelectedOption++; - else - SelectedOption -= OptionCount; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } + SelectedOption = GetLoopedSelectedOption(SelectedOption, OptionCount, g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus); if (GuiIsSelected()) { @@ -612,7 +580,7 @@ namespace TEN::Gui SaveConfiguration(); // Reset screen and go back. - g_Renderer.ChangeScreenResolution(CurrentSettings.Configuration.ScreenWidth, CurrentSettings.Configuration.ScreenHeight, + g_Renderer.ChangeScreenResolution(CurrentSettings.Configuration.ScreenWidth, CurrentSettings.Configuration.ScreenHeight, CurrentSettings.Configuration.EnableWindowedMode); MenuToDisplay = fromPauseMenu ? Menu::Pause : Menu::Options; @@ -743,25 +711,7 @@ namespace TEN::Gui } else { - if (GuiIsPulsed(In::Forward)) - { - if (SelectedOption <= 0) - SelectedOption += OptionCount; - else - SelectedOption--; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } - - if (GuiIsPulsed(In::Back)) - { - if (SelectedOption < OptionCount) - SelectedOption++; - else - SelectedOption -= OptionCount; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } + SelectedOption = GetLoopedSelectedOption(SelectedOption, OptionCount, g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus); // HACK: Menu screen scroll. if (GuiIsPulsed(In::Left) || GuiIsPulsed(In::Right)) @@ -893,8 +843,9 @@ namespace TEN::Gui TargetHighlighter, ToggleRumble, ThumbstickCameraControl, + MouseSensitivity, - MouseSmoothing, + MenuOptionLooping, Apply, Cancel, @@ -929,7 +880,7 @@ namespace TEN::Gui SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableAutoMonkeySwingJump = !CurrentSettings.Configuration.EnableAutoMonkeySwingJump; break; - + case OtherSettingsOption::Subtitles: SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableSubtitles = !CurrentSettings.Configuration.EnableSubtitles; @@ -944,7 +895,7 @@ namespace TEN::Gui SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableTargetHighlighter = !CurrentSettings.Configuration.EnableTargetHighlighter; break; - + case OtherSettingsOption::ToggleRumble: SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); CurrentSettings.Configuration.EnableRumble = !CurrentSettings.Configuration.EnableRumble; @@ -1000,14 +951,23 @@ namespace TEN::Gui break; - case OtherSettingsOption::MouseSmoothing: - if (CurrentSettings.Configuration.MouseSmoothing > MOUSE_SMOOTHING_MIN) - { - CurrentSettings.Configuration.MouseSmoothing -= 1; - if (CurrentSettings.Configuration.MouseSmoothing < MOUSE_SMOOTHING_MIN) - CurrentSettings.Configuration.MouseSmoothing = MOUSE_SMOOTHING_MIN; + case OtherSettingsOption::MenuOptionLooping: + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + switch (CurrentSettings.Configuration.MenuOptionLoopingMode) + { + default: + case MenuOptionLoopingMode::AllMenus: + CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::Disabled; + break; + + case MenuOptionLoopingMode::SaveLoadOnly: + CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::AllMenus; + break; + + case MenuOptionLoopingMode::Disabled: + CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::SaveLoadOnly; + break; } break; @@ -1063,14 +1023,23 @@ namespace TEN::Gui break; - case OtherSettingsOption::MouseSmoothing: - if (CurrentSettings.Configuration.MouseSmoothing < MOUSE_SMOOTHING_MAX) + case OtherSettingsOption::MenuOptionLooping: + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + + switch (CurrentSettings.Configuration.MenuOptionLoopingMode) { - CurrentSettings.Configuration.MouseSmoothing += 1; - if (CurrentSettings.Configuration.MouseSmoothing > MOUSE_SMOOTHING_MAX) - CurrentSettings.Configuration.MouseSmoothing = MOUSE_SMOOTHING_MAX; + default: + case MenuOptionLoopingMode::AllMenus: + CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::SaveLoadOnly; + break; - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + case MenuOptionLoopingMode::SaveLoadOnly: + CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::Disabled; + break; + + case MenuOptionLoopingMode::Disabled: + CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::AllMenus; + break; } break; @@ -1083,33 +1052,7 @@ namespace TEN::Gui } } - if (GuiIsPulsed(In::Forward)) - { - if (SelectedOption <= 0) - { - SelectedOption += OptionCount; - } - else - { - SelectedOption--; - } - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } - - if (GuiIsPulsed(In::Back)) - { - if (SelectedOption < OptionCount) - { - SelectedOption++; - } - else - { - SelectedOption -= OptionCount; - } - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } + SelectedOption = GetLoopedSelectedOption(SelectedOption, OptionCount, g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus); if (GuiIsSelected()) { @@ -1191,25 +1134,7 @@ namespace TEN::Gui if (MenuToDisplay == Menu::Pause || MenuToDisplay == Menu::Options) { - if (GuiIsPulsed(In::Forward)) - { - if (SelectedOption <= 0) - SelectedOption += OptionCount; - else - SelectedOption--; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } - - if (GuiIsPulsed(In::Back)) - { - if (SelectedOption < OptionCount) - SelectedOption++; - else - SelectedOption -= OptionCount; - - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - } + SelectedOption = GetLoopedSelectedOption(SelectedOption, OptionCount, g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus); } if (GuiIsDeselected() || IsClicked(In::Pause)) @@ -1409,7 +1334,7 @@ namespace TEN::Gui if (Rings[(int)RingTypes::Ammo].RingActive) return; - + AmmoObjectList[0].Orientation = EulerAngles::Identity; AmmoObjectList[1].Orientation = EulerAngles::Identity; AmmoObjectList[2].Orientation = EulerAngles::Identity; @@ -1903,7 +1828,7 @@ namespace TEN::Gui { Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].GetCount() / 6; } - + Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); Ammo.AmountHKAmmo1 = lara->Weapons[(int)LaraWeaponType::HK].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::HK].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); @@ -2108,7 +2033,7 @@ namespace TEN::Gui { player.Control.HandStatus = HandStatus::WeaponDraw; } - + InventoryItemChosen = NO_VALUE; return; } @@ -2515,51 +2440,10 @@ namespace TEN::Gui !invRing.ObjectListMovement && !ammoRing.ObjectListMovement) { + CurrentSelectedOption = GetLoopedSelectedOption(CurrentSelectedOption, n - 1, g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus); + if (AmmoActive) - { - if (GuiIsPulsed(In::Forward)) - { - if (CurrentSelectedOption <= 0) - CurrentSelectedOption = n - 1; - else - CurrentSelectedOption--; - - SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); - } - - if (GuiIsPulsed(In::Back)) - { - if (CurrentSelectedOption >= (n - 1)) - CurrentSelectedOption = 0; - else - CurrentSelectedOption++; - - SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); - } - *CurrentAmmoType = CurrentSelectedOption; - } - else - { - if (GuiIsPulsed(In::Forward)) - { - if (CurrentSelectedOption <= 0) - CurrentSelectedOption = n - 1; - else - CurrentSelectedOption--; - - SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); - } - else if (GuiIsPulsed(In::Back)) - { - if (CurrentSelectedOption >= (n - 1)) - CurrentSelectedOption = 0; - else - CurrentSelectedOption++; - - SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); - } - } if (GuiIsSelected(false)) { @@ -2719,7 +2603,7 @@ namespace TEN::Gui { if (!AmmoSelectorFlag) return; - + int xPos = (2 * PHD_CENTER_X - OBJLIST_SPACING) / 2; if (NumAmmoSlots == 2) xPos -= OBJLIST_SPACING / 2; @@ -2767,7 +2651,7 @@ namespace TEN::Gui // CHECK: AmmoSelectorFadeVal is never true and therefore the string is never printed. //if (AmmoSelectorFadeVal) g_Renderer.AddString(PHD_CENTER_X, 380, &invTextBuffer[0], PRINTSTRING_COLOR_YELLOW, (int)PrintStringFlags::Center | (int)PrintStringFlags::Outline); - + if (n == *CurrentAmmoType) g_Renderer.DrawObjectIn2DSpace(objectNumber, Vector2(x, y), AmmoObjectList[n].Orientation, scaler); else @@ -3459,27 +3343,49 @@ namespace TEN::Gui return SelectedSaveSlot; } - LoadResult GuiController::DoLoad() + int GuiController::GetLoopedSelectedOption(int selectedOption, int optionCount, bool canLoop) { - if (GuiIsPulsed(In::Back)) - { - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - - if (SelectedSaveSlot == (SAVEGAME_MAX - 1)) - SelectedSaveSlot -= SAVEGAME_MAX - 1; - else - SelectedSaveSlot++; - } - if (GuiIsPulsed(In::Forward)) { - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - - if (SelectedSaveSlot == 0) - SelectedSaveSlot += SAVEGAME_MAX - 1; + if (selectedOption <= 0) + { + if (IsClicked(In::Forward) && canLoop) + { + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + return optionCount; + } + } else - SelectedSaveSlot--; + { + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + return (selectedOption - 1); + } } + else if (GuiIsPulsed(In::Back)) + { + if (selectedOption >= optionCount) + { + if (IsClicked(In::Back) && canLoop) + { + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + return 0; + } + } + else + { + SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); + return (selectedOption + 1); + } + } + + return selectedOption; + } + + LoadResult GuiController::DoLoad() + { + bool canLoop = g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::SaveLoadOnly || + g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus; + SelectedSaveSlot = GetLoopedSelectedOption(SelectedSaveSlot, SAVEGAME_MAX - 1, canLoop); if (GuiIsSelected()) { @@ -3501,25 +3407,9 @@ namespace TEN::Gui bool GuiController::DoSave() { - if (GuiIsPulsed(In::Back)) - { - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - - if (SelectedSaveSlot == (SAVEGAME_MAX - 1)) - SelectedSaveSlot -= SAVEGAME_MAX - 1; - else - SelectedSaveSlot++; - } - - if (GuiIsPulsed(In::Forward)) - { - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - - if (SelectedSaveSlot == 0) - SelectedSaveSlot += SAVEGAME_MAX - 1; - else - SelectedSaveSlot--; - } + bool canLoop = g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::SaveLoadOnly || + g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus; + SelectedSaveSlot = GetLoopedSelectedOption(SelectedSaveSlot, SAVEGAME_MAX - 1, canLoop); if (GuiIsSelected()) { @@ -3569,7 +3459,7 @@ namespace TEN::Gui return true; } } - else + else { // Small one isn't empty and the big one isn't full. if (lara->Inventory.SmallWaterskin != 1 && bigCapacity) diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h index bf4a4baea..aa1f88882 100644 --- a/TombEngine/Game/gui.h +++ b/TombEngine/Game/gui.h @@ -184,6 +184,7 @@ namespace TEN::Gui void UseItem(ItemInfo& item, int objectNumber); // Getters + const InventoryRing& GetRing(RingTypes ringType); int GetSelectedOption(); Menu GetMenuToDisplay(); @@ -193,8 +194,10 @@ namespace TEN::Gui int GetLastInventoryItem(); SettingsData& GetCurrentSettings(); int GetLoadSaveSelection(); + int GetLoopedSelectedOption(int selectedOption, int optionCount, bool canLoop); // Setters + void SetSelectedOption(int menu); void SetMenuToDisplay(Menu menu); void SetInventoryMode(InventoryMode mode); diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 20486b776..2bdfee90b 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -38,7 +38,7 @@ namespace TEN::Renderer constexpr auto MenuVerticalLineSpacing = 30; constexpr auto MenuVerticalNarrowLineSpacing = 24; constexpr auto MenuVerticalBlockSpacing = 50; - + // Vertical menu positioning templates constexpr auto MenuVerticalControls = 30; constexpr auto MenuVerticalDisplaySettings = 160; @@ -65,10 +65,25 @@ namespace TEN::Renderer // Helper functions to construct string flags inline int SF(bool selected = false) { return (int)PrintStringFlags::Outline | (selected ? (int)PrintStringFlags::Blink : 0); } inline int SF_Center(bool selected = false) { return (int)PrintStringFlags::Outline | (int)PrintStringFlags::Center | (selected ? (int)PrintStringFlags::Blink : 0); } - + // Helper functions to get specific generic strings - inline const char* Str_Enabled(bool enabled = false) { return g_GameFlow->GetString(enabled ? STRING_ENABLED : STRING_DISABLED); } - inline const char* Str_LoadSave(bool save = false) { return g_GameFlow->GetString(save ? STRING_SAVE_GAME : STRING_LOAD_GAME); } + inline const std::string Str_Enabled(bool enabled = false) { return g_GameFlow->GetString(enabled ? STRING_ENABLED : STRING_DISABLED); } + inline const std::string Str_LoadSave(bool save = false) { return g_GameFlow->GetString(save ? STRING_SAVE_GAME : STRING_LOAD_GAME); } + inline const std::string Str_MenuOptionLoopingMode(MenuOptionLoopingMode loopingMode) + { + switch (loopingMode) + { + default: + case MenuOptionLoopingMode::AllMenus: + return g_GameFlow->GetString(STRING_MENU_OPT_LOOP_ALL_MENUS); + + case MenuOptionLoopingMode::SaveLoadOnly: + return g_GameFlow->GetString(STRING_MENU_OPT_LOOP_SAVE_LOAD_ONLY); + + case MenuOptionLoopingMode::Disabled: + return g_GameFlow->GetString(STRING_MENU_OPT_LOOP_DISABLED); + } + } // These bars are only used in menus. TEN::Renderer::RendererHudBar* g_MusicVolumeBar = nullptr; @@ -235,7 +250,7 @@ namespace TEN::Renderer AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_AUTO_MONKEY_SWING_JUMP), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 4)); AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAutoMonkeySwingJump), PRINTSTRING_COLOR_WHITE, SF(titleOption == 4)); GetNextLinePosition(&y); - + // Auto targeting AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_AUTO_TARGETING), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 5)); AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAutoTargeting), PRINTSTRING_COLOR_WHITE, SF(titleOption == 5)); @@ -245,7 +260,7 @@ namespace TEN::Renderer AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_TARGET_HIGHLIGHTER), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 6)); AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableTargetHighlighter), PRINTSTRING_COLOR_WHITE, SF(titleOption == 6)); GetNextLinePosition(&y); - + // Vibration AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_RUMBLE), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 7)); AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableRumble), PRINTSTRING_COLOR_WHITE, SF(titleOption == 7)); @@ -261,9 +276,9 @@ namespace TEN::Renderer AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSensitivity).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 9)); GetNextLinePosition(&y); - // Mouse smoothing - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MOUSE_SMOOTHING), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 10)); - AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSmoothing).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 10)); + // Menu option looping + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MENU_OPT_LOOP), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 10)); + AddString(MenuRightSideEntry, y, Str_MenuOptionLoopingMode(g_Gui.GetCurrentSettings().Configuration.MenuOptionLoopingMode), PRINTSTRING_COLOR_WHITE, SF(titleOption == 10)); GetNextBlockPosition(&y); // Apply @@ -605,7 +620,7 @@ namespace TEN::Renderer char stringBuffer[255]; // Title - AddString(MenuCenterEntry, MenuVerticalNarrowLineSpacing, Str_LoadSave(g_Gui.GetInventoryMode() == InventoryMode::Save), + AddString(MenuCenterEntry, MenuVerticalNarrowLineSpacing, Str_LoadSave(g_Gui.GetInventoryMode() == InventoryMode::Save), PRINTSTRING_COLOR_ORANGE, SF_Center()); GetNextBlockPosition(&y); @@ -798,7 +813,7 @@ namespace TEN::Renderer { if (meshBits && !(meshBits & (1 << n))) continue; - + auto* mesh = (*moveableObject).ObjectMeshes[n]; // HACK: Rotate compass needle. @@ -823,7 +838,7 @@ namespace TEN::Renderer _cbItem.UpdateData(_stItem, _context.Get()); BindConstantBufferVS(ConstantBufferRegister::Item, _cbItem.get()); BindConstantBufferPS(ConstantBufferRegister::Item, _cbItem.get()); - + for (const auto& bucket : mesh->Buckets) { if (bucket.NumVertices == 0) @@ -835,10 +850,10 @@ namespace TEN::Renderer BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - + if (bucket.BlendMode != BlendMode::Opaque) Renderer::SetBlendMode(bucket.BlendMode, true); - + SetAlphaTest( (bucket.BlendMode == BlendMode::AlphaTest) ? AlphaTestMode::GreatherThan : AlphaTestMode::None, ALPHA_TEST_THRESHOLD); @@ -1104,9 +1119,9 @@ namespace TEN::Renderer { _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); - + RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 0.5f); - + _swapChain->Present(0, 0); } @@ -1171,14 +1186,14 @@ namespace TEN::Renderer PrintDebugMessage(" CheckPortal() calls: %d", _numCheckPortalCalls); PrintDebugMessage(" GetVisibleRooms() calls: %d", _numGetVisibleRoomsCalls); PrintDebugMessage(" Dot products: %d", _numDotProducts); - - _spriteBatch->Begin(SpriteSortMode_Deferred, _renderStates->Opaque()); + + _spriteBatch->Begin(SpriteSortMode_Deferred, _renderStates->Opaque()); rect.left = _screenWidth - thumbWidth; rect.top = thumbY; rect.right = rect.left+ thumbWidth; rect.bottom = rect.top+thumbWidth / aspectRatio; - + _spriteBatch->Draw(_normalsRenderTarget.ShaderResourceView.Get(), rect); thumbY += thumbWidth / aspectRatio; @@ -1194,7 +1209,7 @@ namespace TEN::Renderer _spriteBatch->Draw(_SSAOBlurredRenderTarget.ShaderResourceView.Get(), rect); thumbY += thumbWidth / aspectRatio; - + if (g_Configuration.AntialiasingMode > AntialiasingMode::Low) { rect.left = _screenWidth - thumbWidth; @@ -1265,7 +1280,7 @@ namespace TEN::Renderer if (action.IsReleased()) releasedActions.Set((int)action.GetID()); } - + PrintDebugMessage("INPUT STATS"); PrintDebugMessage(("Clicked actions: " + clickedActions.ToString()).c_str()); PrintDebugMessage(("Held actions: " + heldActions.ToString()).c_str()); @@ -1288,12 +1303,12 @@ namespace TEN::Renderer PrintDebugMessage("Front left ceil: %d", LaraCollision.FrontLeft.Ceiling); PrintDebugMessage("Front right ceil: %d", LaraCollision.FrontRight.Ceiling); break; - + case RendererDebugPage::PathfindingStats: PrintDebugMessage("PATHFINDING STATS"); PrintDebugMessage("BoxNumber: %d", LaraItem->BoxNumber); break; - + case RendererDebugPage::WireframeMode: PrintDebugMessage("WIREFRAME MODE"); break; diff --git a/TombEngine/Scripting/Internal/LanguageScript.h b/TombEngine/Scripting/Internal/LanguageScript.h index 5eb728917..f3093bcb8 100644 --- a/TombEngine/Scripting/Internal/LanguageScript.h +++ b/TombEngine/Scripting/Internal/LanguageScript.h @@ -11,7 +11,7 @@ #define STRING_LOAD_GAME "load_game" #define STRING_SAVE_GAME "save_game" #define STRING_EXIT_GAME "exit_game" -#define STRING_EXIT_TO_TITLE "exit_to_title" +#define STRING_EXIT_TO_TITLE "exit_to_title" #define STRING_OPTIONS "options" #define STRING_UZIS "uzis" #define STRING_PISTOLS "pistols" @@ -86,8 +86,11 @@ #define STRING_RUMBLE "rumble" #define STRING_THUMBSTICK_CAMERA "thumbstick_camera" #define STRING_SUBTITLES "subtitles" +#define STRING_MENU_OPT_LOOP "menu_option_looping" +#define STRING_MENU_OPT_LOOP_ALL_MENUS "menu_option_looping_all_menus" +#define STRING_MENU_OPT_LOOP_DISABLED "menu_option_looping_disabled" +#define STRING_MENU_OPT_LOOP_SAVE_LOAD_ONLY "menu_option_looping_save_load_only" #define STRING_MOUSE_SENSITIVITY "mouse_sensitivity" -#define STRING_MOUSE_SMOOTHING "mouse_smoothing" #define STRING_ACTIONS_FORWARD "actions_forward" #define STRING_ACTIONS_BACKWARD "actions_backward" #define STRING_ACTIONS_LEFT "actions_left" diff --git a/TombEngine/Specific/Input/Input.cpp b/TombEngine/Specific/Input/Input.cpp index c93607644..80b8cd0b6 100644 --- a/TombEngine/Specific/Input/Input.cpp +++ b/TombEngine/Specific/Input/Input.cpp @@ -463,10 +463,9 @@ namespace TEN::Input (((rawAxes.x - -DISPLAY_SPACE_RES.x) * 2) / (DISPLAY_SPACE_RES.x - -DISPLAY_SPACE_RES.x)) - 1.0f, (((rawAxes.y - -DISPLAY_SPACE_RES.y) * 2) / (DISPLAY_SPACE_RES.y - -DISPLAY_SPACE_RES.y)) - 1.0f); - // Apply sensitivity and smoothing. + // Apply sensitivity. float sensitivity = (g_Configuration.MouseSensitivity * 0.1f) + 0.4f; - float smoothing = 1.0f - (g_Configuration.MouseSmoothing * 0.1f); - normAxes *= sensitivity * smoothing; + normAxes *= sensitivity; // Set mouse axis values. AxisMap[(int)InputAxis::Mouse] = normAxes; diff --git a/TombEngine/Specific/configuration.cpp b/TombEngine/Specific/configuration.cpp index 8d479c44f..93945202f 100644 --- a/TombEngine/Specific/configuration.cpp +++ b/TombEngine/Specific/configuration.cpp @@ -257,7 +257,7 @@ bool SaveConfiguration() // Set Input keys. if (SetDWORDRegKey(inputKey, REGKEY_MOUSE_SENSITIVITY, g_Configuration.MouseSensitivity) != ERROR_SUCCESS || - SetDWORDRegKey(inputKey, REGKEY_MOUSE_SMOOTHING, g_Configuration.MouseSmoothing) != ERROR_SUCCESS) + SetDWORDRegKey(inputKey, REGKEY_ENABLE_MENU_OPTION_LOOPING, (int)g_Configuration.MenuOptionLoopingMode) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -330,7 +330,7 @@ void InitDefaultConfiguration() g_Configuration.EnableThumbstickCamera = false; g_Configuration.MouseSensitivity = GameConfiguration::DEFAULT_MOUSE_SENSITIVITY; - g_Configuration.MouseSmoothing = GameConfiguration::DEFAULT_MOUSE_SMOOTHING; + g_Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::SaveLoadOnly; g_Configuration.SupportedScreenResolutions = GetAllSupportedScreenResolutions(); g_Configuration.AdapterName = g_Renderer.GetDefaultAdapterName(); @@ -444,14 +444,14 @@ bool LoadConfiguration() } DWORD mouseSensitivity = GameConfiguration::DEFAULT_MOUSE_SENSITIVITY; - DWORD mouseSmoothing = GameConfiguration::DEFAULT_MOUSE_SMOOTHING; + DWORD menuOptionLoopingMode = (DWORD)MenuOptionLoopingMode::SaveLoadOnly; // Load Input keys. HKEY inputKey = NULL; if (RegOpenKeyExA(rootKey, REGKEY_INPUT, 0, KEY_READ, &inputKey) == ERROR_SUCCESS) { if (GetDWORDRegKey(inputKey, REGKEY_MOUSE_SENSITIVITY, &mouseSensitivity, GameConfiguration::DEFAULT_MOUSE_SENSITIVITY) != ERROR_SUCCESS || - GetDWORDRegKey(inputKey, REGKEY_MOUSE_SMOOTHING, &mouseSmoothing, GameConfiguration::DEFAULT_MOUSE_SMOOTHING) != ERROR_SUCCESS) + GetDWORDRegKey(inputKey, REGKEY_ENABLE_MENU_OPTION_LOOPING, &menuOptionLoopingMode, (DWORD)MenuOptionLoopingMode::SaveLoadOnly) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -519,7 +519,7 @@ bool LoadConfiguration() g_Configuration.EnableThumbstickCamera = enableThumbstickCamera; g_Configuration.MouseSensitivity = mouseSensitivity; - g_Configuration.MouseSmoothing = mouseSmoothing; + g_Configuration.MenuOptionLoopingMode = (MenuOptionLoopingMode)menuOptionLoopingMode; // Set legacy variables. SetVolumeTracks(musicVolume); @@ -558,10 +558,10 @@ LONG GetDWORDRegKey(HKEY hKey, LPCSTR strValueName, DWORD* nValue, DWORD nDefaul NULL, reinterpret_cast(&nResult), &dwBufferSize); - + if (ERROR_SUCCESS == nError) *nValue = nResult; - + return nError; } @@ -570,10 +570,10 @@ LONG GetBoolRegKey(HKEY hKey, LPCSTR strValueName, bool* bValue, bool bDefaultVa DWORD nDefValue((bDefaultValue) ? 1 : 0); DWORD nResult(nDefValue); LONG nError = GetDWORDRegKey(hKey, strValueName, &nResult, nDefValue); - + if (ERROR_SUCCESS == nError) *bValue = (nResult != 0); - + return nError; } diff --git a/TombEngine/Specific/configuration.h b/TombEngine/Specific/configuration.h index ab3694e01..0ab9c10ee 100644 --- a/TombEngine/Specific/configuration.h +++ b/TombEngine/Specific/configuration.h @@ -7,6 +7,7 @@ using namespace TEN::Input; using namespace TEN::Math; // Directories + constexpr auto REGKEY_ROOT = "Software\\TombEngine\\1.1.0"; constexpr auto REGKEY_GRAPHICS = "Graphics"; constexpr auto REGKEY_SOUND = "Sound"; @@ -14,6 +15,7 @@ constexpr auto REGKEY_GAMEPLAY = "Gameplay"; constexpr auto REGKEY_INPUT = "Input"; // Graphics keys + constexpr auto REGKEY_SCREEN_WIDTH = "ScreenWidth"; constexpr auto REGKEY_SCREEN_HEIGHT = "ScreenHeight"; constexpr auto REGKEY_ENABLE_WINDOWED_MODE = "EnableWindowedMode"; @@ -25,6 +27,7 @@ constexpr auto REGKEY_ANTIALIASING_MODE = "AntialiasingMode"; constexpr auto REGKEY_AMBIENT_OCCLUSION = "AmbientOcclusion"; // Sound keys + constexpr auto REGKEY_SOUND_DEVICE = "SoundDevice"; constexpr auto REGKEY_ENABLE_SOUND = "EnableSound"; constexpr auto REGKEY_ENABLE_REVERB = "EnableReverb"; @@ -32,6 +35,7 @@ constexpr auto REGKEY_MUSIC_VOLUME = "MusicVolume"; constexpr auto REGKEY_SFX_VOLUME = "SfxVolume"; // Gameplay keys + constexpr auto REGKEY_ENABLE_SUBTITLES = "EnableSubtitles"; constexpr auto REGKEY_ENABLE_AUTO_MONKEY_JUMP = "EnableAutoMonkeySwingJump"; constexpr auto REGKEY_ENABLE_AUTO_TARGETING = "EnableAutoTargeting"; @@ -40,17 +44,25 @@ constexpr auto REGKEY_ENABLE_RUMBLE = "EnableRumble"; constexpr auto REGKEY_ENABLE_THUMBSTICK_CAMERA = "EnableThumbstickCamera"; // Input keys -constexpr auto REGKEY_MOUSE_SENSITIVITY = "MouseSensitivity"; -constexpr auto REGKEY_MOUSE_SMOOTHING = "MouseSmoothing"; -struct GameConfiguration +constexpr auto REGKEY_MOUSE_SENSITIVITY = "MouseSensitivity"; +constexpr auto REGKEY_ENABLE_MENU_OPTION_LOOPING = "EnableMenuOptionLooping"; + +enum class MenuOptionLoopingMode +{ + AllMenus, + SaveLoadOnly, + Disabled +}; + +struct GameConfiguration { static constexpr auto DEFAULT_SHADOW_MAP_SIZE = 1024; static constexpr auto DEFAULT_SHADOW_BLOBS_MAX = 16; static constexpr auto DEFAULT_MOUSE_SENSITIVITY = 6; - static constexpr auto DEFAULT_MOUSE_SMOOTHING = 1; // Graphics + int ScreenWidth = 0; int ScreenHeight = 0; bool EnableWindowedMode = false; @@ -62,6 +74,7 @@ struct GameConfiguration AntialiasingMode AntialiasingMode = AntialiasingMode::None; // Sound + int SoundDevice = 0; bool EnableSound = false; bool EnableReverb = false; @@ -69,17 +82,19 @@ struct GameConfiguration int SfxVolume = 0; // Gameplay - bool EnableSubtitles = false; - bool EnableAutoMonkeySwingJump = false; - bool EnableAutoTargeting = false; - bool EnableTargetHighlighter = false; - bool EnableRumble = false; - bool EnableThumbstickCamera = false; + + bool EnableSubtitles = false; + bool EnableAutoMonkeySwingJump = false; + bool EnableAutoTargeting = false; + bool EnableTargetHighlighter = false; + bool EnableRumble = false; + bool EnableThumbstickCamera = false; // Input - int MouseSensitivity = DEFAULT_MOUSE_SENSITIVITY; - int MouseSmoothing = DEFAULT_MOUSE_SMOOTHING; - std::vector Bindings = {}; + + int MouseSensitivity = DEFAULT_MOUSE_SENSITIVITY; + MenuOptionLoopingMode MenuOptionLoopingMode = MenuOptionLoopingMode::SaveLoadOnly; + std::vector Bindings = {}; std::vector SupportedScreenResolutions = {}; std::string AdapterName = {}; From b9b99af3d2150af18983e6114f73e2c7d4e1786a Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Sun, 11 Aug 2024 17:48:52 +0200 Subject: [PATCH 255/410] Seal Mutant Port (#1392) * begin mutant crawler import * progress. * Update MutantCrawler.cpp * Done seal mutant. - Changed how ThrowPoison color worked. The old function didn't really reflect the correct color. * Update CHANGELOG.md * Improve ThrowSealMutantGas * Add ID_SEAL_MUTANT scripting ID * Update ObjectIDs.h * Remove IsLaraCrouching() * Use correct data types for poison effect * Use references, not pointers * Use proper spacing * Use const * Remove magic numbers, ordering, const, etc * Remove pointless CreatureBiteInfo constructor; remove global constants;; etc * Formatting, cleanup * Replace GetRandomControl() usage * Comment * Update CHANGELOG.md * rename variable * demagic numbers * Define constants * Remove anim data checks * Update poison gas spawn function * Update tr3_flamethrower.cpp * Update SealMutant.cpp * Update seal mutant * Update seal light * Update SealMutant.cpp * Minor changes * Update sealMutant * Update effects.h * Update flamethrower to have lara as target too. * Revert feffects from int to uchar * Cleanup --------- Co-authored-by: Kubsy Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Co-authored-by: Sezz Co-authored-by: Jakub <80340234+Jakub768@users.noreply.github.com> Co-authored-by: Jakub --- CHANGELOG.md | 3 + Documentation/doc/4 enums/Objects.ObjID.html | 3 +- TombEngine/Game/control/control.cpp | 1 + TombEngine/Game/effects/tomb4fx.cpp | 68 ++-- TombEngine/Game/effects/tomb4fx.h | 8 +- TombEngine/Game/itemdata/creature_info.h | 6 - TombEngine/Game/people.cpp | 4 +- TombEngine/Objects/TR3/Entity/Lizard.cpp | 21 +- TombEngine/Objects/TR3/Entity/SealMutant.cpp | 331 ++++++++++++++++++ TombEngine/Objects/TR3/Entity/SealMutant.h | 7 + TombEngine/Objects/TR3/Entity/TwinAutoGun.cpp | 4 +- .../Objects/TR3/Entity/tr3_flamethrower.cpp | 38 +- TombEngine/Objects/TR3/tr3_objects.cpp | 19 +- TombEngine/Objects/game_object_ids.h | 4 +- .../Internal/TEN/Objects/ObjectIDs.h | 4 +- TombEngine/TombEngine.vcxproj | 2 + 16 files changed, 428 insertions(+), 95 deletions(-) create mode 100644 TombEngine/Objects/TR3/Entity/SealMutant.cpp create mode 100644 TombEngine/Objects/TR3/Entity/SealMutant.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 624420851..9b441efee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): - OCB 0: Classic behaviour - OCB 1: Can jump up/down up to 4 steps and jump across gaps up to 2 blocks wide. - You must use the download version found on the TombEngine website. +* Added TR3 seal mutant. + - OCB 0: Normal enemy behaviour. (TR3 RX-Tech mines level) + - OCB 1: Trap like behaviour. (TR3 Antarctica level) * Add new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 9372f1014..9068ee709 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -357,7 +357,7 @@ WASP_MUTANT SKATEBOARD SKATEBOARD_KID WINSTON -ARMY_WINSTON +SEAL_MUTANT SPRINGBOARD ROLLING_SPINDLE DISK_SHOOTER @@ -943,6 +943,7 @@ MESHSWAP_ROMAN_GOD1 MESHSWAP_ROMAN_GOD2 MESHSWAP_MONKEY_MEDIPACK MESHSWAP_MONKEY_KEY +MESHSWAP_WINSTON_ARMY_OUTFIT ANIMATING1 ANIMATING2 ANIMATING3 diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 026ff78ff..6aaa1d01b 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -397,6 +397,7 @@ void KillMoveEffects() ItemNewRoomNo = 0; } +// NOTE: No one should use this ever again. int GetRandomControl() { return Random::GenerateInt(); diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 3b553395a..f5bf359da 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -256,30 +256,23 @@ void TriggerPilotFlame(int itemNumber, int nodeIndex) spark->dSize = size; } -Particle* SetupPoisonSpark(Vector3 color) +static Particle& SetupPoisonParticle(const Color& colorStart, const Color& colorEnd) { - auto* spark = GetFreeParticle(); + auto& part = *GetFreeParticle(); + part.sR = std::clamp(colorStart.x * UCHAR_MAX, 0, UCHAR_MAX); + part.sG = std::clamp(colorStart.y * UCHAR_MAX, 0, UCHAR_MAX); + part.sB = std::clamp(colorStart.z * UCHAR_MAX, 0, UCHAR_MAX); + part.dR = std::clamp(colorEnd.x * UCHAR_MAX, 0, UCHAR_MAX); + part.dG = std::clamp(colorEnd.y * UCHAR_MAX, 0, UCHAR_MAX); + part.dB = std::clamp(colorEnd.z * UCHAR_MAX, 0, UCHAR_MAX); + part.colFadeSpeed = 14; + part.fadeToBlack = 8; + part.blendMode = BlendMode::Screen; - bool rMax = color.x > color.y && color.x > color.z; - bool gMax = color.y > color.x && color.y > color.z; - bool bMax = color.z > color.x && color.z > color.y; - - char seed = (GetRandomControl() & 0x1F) + 220; - - spark->sR = (rMax ? seed : 255) * (color.x * 0.4); - spark->sG = (gMax ? seed : 255) * (color.y * 0.4); - spark->sB = (bMax ? seed : 255) * (color.z * 0.4); - spark->dR = 255 * color.x; - spark->dG = 255 * color.y; - spark->dB = 255 * color.z; - spark->colFadeSpeed = 14; - spark->fadeToBlack = 8; - spark->blendMode = BlendMode::Screen; - - return spark; + return part; } -Particle* SetupFireSpark() +static Particle* SetupFireSpark() { auto* spark = GetFreeParticle(); @@ -296,19 +289,20 @@ Particle* SetupFireSpark() return spark; } -void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector3i offset, Vector3i vel) +static void AttachAndCreateSpark(Particle* spark, const ItemInfo* item, int meshID, Vector3i offset, Vector3i vel, int spriteID = 0) { - auto pos1 = GetJointPosition(item, meshIndex, Vector3i(-4, -30, -4) + offset); + auto pos1 = GetJointPosition(*item, meshID, Vector3i(-4, -30, -4) + offset); spark->x = (GetRandomControl() & 0x1F) + pos1.x - 16; spark->y = (GetRandomControl() & 0x1F) + pos1.y - 16; spark->z = (GetRandomControl() & 0x1F) + pos1.z - 16; - auto pos2 = GetJointPosition(item, meshIndex, Vector3i(-4, -30, -4) + offset + vel); + auto pos2 = GetJointPosition(*item, meshID, Vector3i(-4, -30, -4) + offset + vel); int v = (GetRandomControl() & 0x3F) + 192; spark->life = spark->sLife = v / 6; + spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + spriteID; spark->xVel = v * (pos2.x - pos1.x) / 10; spark->yVel = v * (pos2.y - pos1.y) / 10; @@ -327,39 +321,39 @@ void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector spark->on = 1; } -void ThrowFire(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel) +void ThrowFire(int itemNumber, int meshID, const Vector3i& offset, const Vector3i& vel, int spriteID) { auto& item = g_Level.Items[itemNumber]; for (int i = 0; i < 3; i++) { - auto& spark = *SetupFireSpark(); - AttachAndCreateSpark(&spark, &item, meshIndex, offset, vel); + auto& part = *SetupFireSpark(); + AttachAndCreateSpark(&part, &item, meshID, offset, vel, spriteID); - spark.flags = SP_FIRE | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; + part.flags = SP_FIRE | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; } } -void ThrowFire(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel) +void ThrowFire(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, int spriteID) { - ThrowFire(itemNumber, bite.BoneID, bite.Position, vel); + ThrowFire(itemNumber, bite.BoneID, bite.Position, vel, spriteID); } -void ThrowPoison(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel, const Vector3& color) +void ThrowPoison(const ItemInfo& item, int boneID, const Vector3& offset, const Vector3& vel, const Color& colorStart, const Color& colorEnd, int spriteID) { - auto* item = &g_Level.Items[itemNumber]; + constexpr auto COUNT = 2; - for (int i = 0; i < 2; i++) + for (int i = 0; i < COUNT; i++) { - auto* spark = SetupPoisonSpark(color); - AttachAndCreateSpark(spark, item, meshIndex, offset, vel); - spark->flags = SP_POISON | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; + auto& part = SetupPoisonParticle(colorStart, colorEnd); + AttachAndCreateSpark(&part, &item, boneID, offset, vel, spriteID); + part.flags = SP_POISON | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; } } -void ThrowPoison(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, const Vector3& color) +void ThrowPoison(const ItemInfo& item, const CreatureBiteInfo& bite, const Vector3& vel, const Color& colorStart, const Color& colorEnd, int spriteID) { - ThrowPoison(itemNumber, bite.BoneID, bite.Position, vel, color); + ThrowPoison(item, bite.BoneID, bite.Position, vel, colorStart, colorEnd, spriteID); } void UpdateFireProgress() diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index ae58bd055..4281e0de5 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -230,10 +230,10 @@ void TriggerGlobalStaticFlame(); void TriggerGlobalFireSmoke(); void TriggerGlobalFireFlame(); void TriggerPilotFlame(int itemNumber, int nodeIndex); -void ThrowFire(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel); -void ThrowFire(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel); -void ThrowPoison(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel, const Vector3& color); -void ThrowPoison(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, const Vector3& color); +void ThrowFire(int itemNumber, int meshID, const Vector3i& offset, const Vector3i& vel, int spriteID = 0); +void ThrowFire(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, int spriteID = 0); +void ThrowPoison(const ItemInfo& item, int boneID, const Vector3& offset, const Vector3& vel, const Color& colorStart, const Color& colorEnd, int spriteID = 0); +void ThrowPoison(const ItemInfo& item, const CreatureBiteInfo& bite, const Vector3& vel, const Color& colorStart, const Color& colorEnd, int spriteID = 0); void UpdateFireProgress(); void ClearFires(); void AddFire(int x, int y, int z, short roomNum, float size, short fade); diff --git a/TombEngine/Game/itemdata/creature_info.h b/TombEngine/Game/itemdata/creature_info.h index 206e3ded2..f2ba55346 100644 --- a/TombEngine/Game/itemdata/creature_info.h +++ b/TombEngine/Game/itemdata/creature_info.h @@ -83,12 +83,6 @@ struct CreatureBiteInfo Position = pos; BoneID = boneID; } - - CreatureBiteInfo(float x, float y, float z, int boneID) - { - Position = Vector3(x, y, z); - BoneID = boneID; - } }; struct CreatureMuzzleFlashInfo diff --git a/TombEngine/Game/people.cpp b/TombEngine/Game/people.cpp index acbf086f1..ff9c24d7e 100644 --- a/TombEngine/Game/people.cpp +++ b/TombEngine/Game/people.cpp @@ -169,8 +169,8 @@ bool TargetVisible(ItemInfo* item, AI_INFO* ai, float maxAngleInDegrees) auto target = GameVector( enemy->Pose.Position.x, enemy->Pose.Position.y + ((((bounds.Y1 * 2) + bounds.Y1) + bounds.Y2) / 4), - enemy->Pose.Position.z, - enemy->RoomNumber); // TODO: Check why this line didn't exist before. -- TokyoSU, 10/8/2022 + enemy->Pose.Position.z); + return LOS(&origin, &target); } diff --git a/TombEngine/Objects/TR3/Entity/Lizard.cpp b/TombEngine/Objects/TR3/Entity/Lizard.cpp index a57c724a0..ee5ba0347 100644 --- a/TombEngine/Objects/TR3/Entity/Lizard.cpp +++ b/TombEngine/Objects/TR3/Entity/Lizard.cpp @@ -72,14 +72,17 @@ namespace TEN::Entities::Creatures::TR3 (g_Level.PathfindingBoxes[creature.Enemy->BoxNumber].flags & BLOCKABLE)); } - static void SpawnLizardGas(int itemNumber, const CreatureBiteInfo& bite, int speed) + static void SpawnLizardGas(const ItemInfo& item, const CreatureBiteInfo& bite, float vel) { - constexpr auto THROW_COUNT = 2; + constexpr auto THROW_COUNT = 3; + auto velVector = Vector3(0.0f, -100.0f, vel * 4); for (int i = 0; i < THROW_COUNT; i++) - ThrowPoison(itemNumber, bite, Vector3i(0.0f, -100.0f, speed << 2), Vector3(0.0f, 1.0f, 0.0f)); - - ThrowPoison(itemNumber, bite, Vector3i(0.0f, -100.0f, speed << 1), Vector3(0.0f, 1.0f, 0.0f)); + { + auto colorStart = Color(0.0f, Random::GenerateFloat(0.25f, 0.5f), 0.1f); + auto colorEnd = Color(0.0f, Random::GenerateFloat(0.1f, 0.2f), 0.1f); + ThrowPoison(item, bite, velVector, colorStart, colorEnd); + } } void LizardControl(short itemNumber) @@ -319,9 +322,13 @@ namespace TEN::Entities::Creatures::TR3 creature.Flags += 2; if (creature.Flags < 24) - SpawnLizardGas(itemNumber, LizardGasBite, creature.Flags); + { + SpawnLizardGas(item, LizardGasBite, creature.Flags); + } else - SpawnLizardGas(itemNumber, LizardGasBite, (GetRandomControl() & 15) + 8); + { + SpawnLizardGas(item, LizardGasBite, (GetRandomControl() & 15) + 8); + } } if (TestAnimFrame(item, 28)) diff --git a/TombEngine/Objects/TR3/Entity/SealMutant.cpp b/TombEngine/Objects/TR3/Entity/SealMutant.cpp new file mode 100644 index 000000000..87b2b46d7 --- /dev/null +++ b/TombEngine/Objects/TR3/Entity/SealMutant.cpp @@ -0,0 +1,331 @@ +#include "framework.h" + +#include "Game/animation.h" +#include "Game/control/box.h" +#include "Game/effects/effects.h" +#include "Game/effects/tomb4fx.h" +#include "Game/Lara/lara.h" +#include "Game/Lara/lara_helpers.h" +#include "Game/misc.h" +#include "Game/people.h" +#include "Game/Setup.h" +#include "Math/Math.h" +#include "Objects/Effects/enemy_missile.h" + +using namespace TEN::Math; + +// NOTES: +// ItemFlags[0]: Sprite ID for poison effect. + +namespace TEN::Entities::Creatures::TR3 +{ + constexpr auto SEAL_MUTANT_ATTACK_DAMAGE = 1; + + constexpr auto SEAL_MUTANT_ALERT_RANGE = SQUARE(BLOCK(1)); + constexpr auto SEAL_MUTANT_ATTACK_RANGE = SQUARE(BLOCK(1.5f)); + + constexpr auto SEAL_MUTANT_WALK_TURN_RATE = ANGLE(3.0f); + + constexpr auto SEAL_MUTANT_FLAME_LIGHT_Y_OFFSET = CLICK(2); + constexpr auto SEAL_MUTANT_BURN_END_TIME = 16; + + const auto SealMutantGasBite = CreatureBiteInfo(Vector3(0.0f, 48.0f, 140.0f), 10); + const auto SealMutantAttackTargetObjectIds = { ID_LARA, ID_FLAMETHROWER_BADDY, ID_WORKER_FLAMETHROWER }; + + enum SealMutantState + { + SEAL_MUTANT_STATE_IDLE = 0, + SEAL_MUTANT_STATE_WALK = 1, + SEAL_MUTANT_STATE_ATTACK = 2, + SEAL_MUTANT_STATE_DEATH = 3, + SEAL_MUTANT_STATE_TRAP = 4 + }; + + enum SealMutantAnim + { + SEAL_MUTANT_ANIM_IDLE = 0, + SEAL_MUTANT_ANIM_IDLE_TO_WALK = 1, + SEAL_MUTANT_ANIM_WALK = 2, + SEAL_MUTANT_ANIM_WALK_TO_IDLE = 3, + SEAL_MUTANT_ANIM_ATTACK = 4, + SEAL_MUTANT_ANIM_DEATH = 5, + SEAL_MUTANT_ANIM_TRAP = 6 + }; + + enum SealMutantItemFlags + { + IF_SEAL_MUTANT_FLAME_TIMER = 0 + }; + + enum SealMutantOcb + { + OCB_NORMAL_BEHAVIOUR = 0, + OCB_TRAP = 1 + }; + + static void SpawnSealMutantPoisonGas(ItemInfo& item, float vel) + { + constexpr auto GAS_COUNT = 2; + constexpr auto VEL_MULT = 5.0f; + constexpr auto PLAYER_CROUCH_GRAVITY = 32.0f; + + auto& creature = *GetCreatureInfo(&item); + + // HACK. + float gravity = 0.0f; + if (creature.Enemy != nullptr) + { + if (creature.Enemy->IsLara()) + { + const auto& player = GetLaraInfo(*creature.Enemy); + if (player.Control.IsLow) + gravity = PLAYER_CROUCH_GRAVITY; + } + else + { + DoDamage(creature.Enemy, SEAL_MUTANT_ATTACK_DAMAGE); + } + } + + auto velVector = Vector3(0.0f, gravity, vel * VEL_MULT); + auto colorStart = Color(Random::GenerateFloat(0.25f, 0.5f), Random::GenerateFloat(0.25f, 0.5f), 0.1f); + auto colorEnd = Color(Random::GenerateFloat(0.05f, 0.1f), Random::GenerateFloat(0.05f, 0.1f), 0.0f); + + for (int i = 0; i < GAS_COUNT; i++) + ThrowPoison(item, SealMutantGasBite, velVector, colorStart, colorEnd, item.ItemFlags[0]); + } + + void InitializeSealMutant(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + item.ItemFlags[0] = 0; + InitializeCreature(itemNumber); + } + + void ControlSealMutant(short itemNumber) + { + if (!CreatureActive(itemNumber)) + return; + + auto& item = g_Level.Items[itemNumber]; + auto& creature = *GetCreatureInfo(&item); + + short headingAngle = 0; + auto headOrient = EulerAngles::Identity; + auto torsoOrient = EulerAngles::Identity; + + float gasVel = 0.0f; + + if (item.TestOcb(OCB_TRAP)) + { + if (item.Animation.ActiveState != SEAL_MUTANT_STATE_TRAP) + { + SetAnimation(item, SEAL_MUTANT_ANIM_TRAP); + } + else if (TestAnimFrameRange(item, 1, 124)) + { + const auto& anim = GetAnimData(item.Animation.AnimNumber); + + gasVel = item.Animation.FrameNumber - (anim.frameBase + 1); + if (gasVel > 24.0f) + { + gasVel = item.Animation.FrameNumber - (anim.frameEnd - 8); + if (gasVel <= 0.0f) + gasVel = 1.0f; + + if (gasVel > 24.0f) + gasVel = Random::GenerateFloat(8.0f, 24.0f); + + SpawnSealMutantPoisonGas(item, gasVel); + } + } + + CreatureAnimation(itemNumber, 0, 0); + return; + } + + if (item.GetFlagField(IF_SEAL_MUTANT_FLAME_TIMER) > 80) + item.HitPoints = 0; + + if (item.HitPoints <= 0) + { + const auto& anim = GetAnimData(item.Animation.AnimNumber); + + if (item.Animation.ActiveState != SEAL_MUTANT_STATE_DEATH) + { + SetAnimation(item, SEAL_MUTANT_ANIM_DEATH); + } + else if (item.GetFlagField(IF_SEAL_MUTANT_FLAME_TIMER) > 80) + { + for (int boneID = 9; boneID < 17; boneID++) + { + auto pos = GetJointPosition(item, boneID); + TriggerFireFlame(pos.x, pos.y, pos.z, FlameType::Medium); + } + + int burnTimer = item.Animation.FrameNumber - anim.frameBase; + if (burnTimer > SEAL_MUTANT_BURN_END_TIME) + { + burnTimer = item.Animation.FrameNumber - anim.frameEnd; + if (burnTimer > SEAL_MUTANT_BURN_END_TIME) + burnTimer = SEAL_MUTANT_BURN_END_TIME; + } + + if (burnTimer != SEAL_MUTANT_BURN_END_TIME) + { + auto pos = GetJointPosition(item, SealMutantGasBite.BoneID, Vector3(0.0f, -SEAL_MUTANT_FLAME_LIGHT_Y_OFFSET, 0.0f)); + auto color = Color(Random::GenerateFloat(0.75f, 1.0f), Random::GenerateFloat(0.4f, 0.5f), Random::GenerateFloat(0.0f, 0.25f)); + float falloff = Random::GenerateFloat(0.03f, 0.04f); + TriggerDynamicLight(pos.ToVector3(), color, falloff); + } + } + else if (TestAnimFrameRange(item, 1, 124)) + { + gasVel = item.Animation.FrameNumber - (anim.frameBase + 1); + if (gasVel > 24.0f) + { + gasVel = item.Animation.FrameNumber - (anim.frameEnd - 8); + if (gasVel <= 0.0f) + gasVel = 1.0f; + + if (gasVel > 24.0f) + gasVel = Random::GenerateFloat(16.0f, 24.0f); + + SpawnSealMutantPoisonGas(item, gasVel); + } + } + } + else + { + if (item.AIBits) + { + GetAITarget(&creature); + } + else + { + TargetNearestEntity(&item, &creature, SealMutantAttackTargetObjectIds, false); + } + + AI_INFO ai; + CreatureAIInfo(&item, &ai); + + GetCreatureMood(&item, &ai, ai.zoneNumber == ai.enemyZone); + if (creature.Enemy != nullptr && creature.Enemy->IsLara()) + { + const auto& player = GetLaraInfo(*creature.Enemy); + if (player.Status.Poison >= LARA_POISON_MAX) + creature.Mood = MoodType::Escape; + } + + CreatureMood(&item, &ai, ai.zoneNumber == ai.enemyZone); + headingAngle = CreatureTurn(&item, creature.MaxTurn); + + auto* target = creature.Enemy; + creature.Enemy = LaraItem; + if (ai.distance < SEAL_MUTANT_ALERT_RANGE || item.HitStatus || TargetVisible(&item, &ai)) + AlertAllGuards(itemNumber); + + creature.Enemy = target; + + switch (item.Animation.ActiveState) + { + case SEAL_MUTANT_STATE_IDLE: + creature.MaxTurn = 0; + creature.Flags = 0; + headOrient.x = -ai.xAngle; + headOrient.y = ai.angle; + torsoOrient.x = 0; + torsoOrient.z = 0; + + if (item.AIBits & GUARD) + { + item.Animation.TargetState = SEAL_MUTANT_STATE_IDLE; + headOrient.x = 0; + headOrient.y = AIGuard(&creature); + } + else if (item.AIBits & PATROL1) + { + item.Animation.TargetState = SEAL_MUTANT_STATE_WALK; + headOrient.x = 0; + headOrient.y = 0; + } + else if (creature.Mood == MoodType::Escape) + { + item.Animation.TargetState = SEAL_MUTANT_STATE_WALK; + } + else if (Targetable(&item, &ai) && ai.distance < SEAL_MUTANT_ATTACK_RANGE) + { + item.Animation.TargetState = SEAL_MUTANT_STATE_ATTACK; + } + else if (item.Animation.RequiredState != NO_VALUE) + { + item.Animation.TargetState = item.Animation.RequiredState; + } + else + { + item.Animation.TargetState = SEAL_MUTANT_STATE_WALK; + } + + break; + + case SEAL_MUTANT_STATE_WALK: + creature.MaxTurn = SEAL_MUTANT_WALK_TURN_RATE; + + if (ai.ahead) + { + headOrient.x = -ai.xAngle; + headOrient.y = ai.angle; + } + + if (item.AIBits & PATROL1) + { + item.Animation.TargetState = SEAL_MUTANT_STATE_WALK; + headOrient.y = 0; + } + else if (Targetable(&item, &ai) && ai.distance < SEAL_MUTANT_ATTACK_RANGE) + { + item.Animation.TargetState = SEAL_MUTANT_STATE_IDLE; + } + + break; + + case SEAL_MUTANT_STATE_ATTACK: + if (ai.ahead) + { + headOrient.x = -ai.xAngle; + headOrient.y = ai.angle; + torsoOrient.x = -ai.xAngle / 2; + torsoOrient.z = ai.angle / 2; + } + + if (TestAnimFrameRange(item, 35, 58)) + { + if (creature.Flags < 24) + creature.Flags += 3; + + gasVel = 0.0f; + if (creature.Flags < 24.0f) + { + gasVel = creature.Flags; + } + else + { + gasVel = Random::GenerateFloat(16.0f, 24.0f); + } + + SpawnSealMutantPoisonGas(item, gasVel); + if (creature.Enemy != nullptr && !creature.Enemy->IsLara()) + creature.Enemy->HitStatus = true; + } + + break; + } + } + + CreatureJoint(&item, 0, torsoOrient.z); + CreatureJoint(&item, 1, torsoOrient.x); + CreatureJoint(&item, 2, headOrient.y); + CreatureAnimation(itemNumber, headingAngle, 0); + } +} diff --git a/TombEngine/Objects/TR3/Entity/SealMutant.h b/TombEngine/Objects/TR3/Entity/SealMutant.h new file mode 100644 index 000000000..7dc7c3fa1 --- /dev/null +++ b/TombEngine/Objects/TR3/Entity/SealMutant.h @@ -0,0 +1,7 @@ +#pragma once + +namespace TEN::Entities::Creatures::TR3 +{ + void InitializeSealMutant(short itemNumber); + void ControlSealMutant(short itemNumber); +} diff --git a/TombEngine/Objects/TR3/Entity/TwinAutoGun.cpp b/TombEngine/Objects/TR3/Entity/TwinAutoGun.cpp index 67cd6c0f5..e944f5062 100644 --- a/TombEngine/Objects/TR3/Entity/TwinAutoGun.cpp +++ b/TombEngine/Objects/TR3/Entity/TwinAutoGun.cpp @@ -21,8 +21,8 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto TWIN_AUTO_GUN_SHOT_DAMAGE = 5; constexpr auto TWIN_AUTO_GUN_HIT_POINTS_MAX = 28; - const auto TwinAutoGunLeftBite = CreatureBiteInfo(110, -30, 530, 2); - const auto TwinAutoGunRightBite = CreatureBiteInfo(-110, -30, 530, 2); + const auto TwinAutoGunLeftBite = CreatureBiteInfo(Vector3(110.0f, -30.0f, 530.0f), 2); + const auto TwinAutoGunRightBite = CreatureBiteInfo(Vector3(-110.0f, -30.0f, 530.0f), 2); enum TwinAutoGunAnim { diff --git a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp index 57d37d488..15cc2f64b 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp @@ -28,6 +28,7 @@ namespace TEN::Entities::Creatures::TR3 constexpr auto FLAMETHROWER_WALK_TURN_RATE_MAX = ANGLE(5.0f); const auto FlamethrowerBite = CreatureBiteInfo(Vector3(0, 340, 64), 7); + const auto FlamethrowerTargetIds = { ID_LARA, ID_SEAL_MUTANT }; // TODO enum FlamethrowerState @@ -94,30 +95,7 @@ namespace TEN::Entities::Creatures::TR3 } else { - creature->Enemy = nullptr; - - ItemInfo* target = nullptr; - int minDistance = INT_MAX; - - for (auto& currentCreature : ActiveCreatures) - { - if (currentCreature->ItemNumber == NO_VALUE || currentCreature->ItemNumber == itemNumber) - continue; - - target = &g_Level.Items[currentCreature->ItemNumber]; - if (target->ObjectNumber == ID_LARA || target->HitPoints <= 0 || target->ObjectNumber == ID_FLAMETHROWER_BADDY) - continue; - - int x = target->Pose.Position.x - item->Pose.Position.x; - int z = target->Pose.Position.z - item->Pose.Position.z; - - int distance = SQUARE(z) + SQUARE(x); - if (distance < minDistance) - { - creature->Enemy = target; - minDistance = distance; - } - } + TargetNearestEntity(item, creature, FlamethrowerTargetIds, false); } AI_INFO AI; @@ -311,10 +289,8 @@ namespace TEN::Entities::Creatures::TR3 else { ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, (Random::GenerateInt() & 63) + 12, 0)); - if (realEnemy) - { - /*code*/ - } + if (realEnemy && realEnemy->ObjectNumber == ID_SEAL_MUTANT) + realEnemy->ItemFlags[0]++; } SoundEffect(SFX_TR4_FLAME_EMITTER, &item->Pose); @@ -345,10 +321,8 @@ namespace TEN::Entities::Creatures::TR3 else { ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, (GetRandomControl() & 63) + 12, 0)); - if (realEnemy) - { - /*code*/ - } + if (realEnemy && realEnemy->ObjectNumber == ID_SEAL_MUTANT) + realEnemy->ItemFlags[0]++; } SoundEffect(SFX_TR4_FLAME_EMITTER, &item->Pose); diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index 5dadc08b3..f5909af7d 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -11,9 +11,10 @@ #include "Objects/TR3/Entity/Compsognathus.h" #include "Objects/TR3/Entity/Lizard.h" #include "Objects/TR3/Entity/PunaBoss.h" -#include "Objects/TR3/Entity/Raptor.h" +#include "Objects/TR3/Entity/SealMutant.h" #include "Objects/TR3/Entity/Shiva.h" #include "Objects/TR3/Entity/SophiaLeigh.h" +#include "Objects/TR3/Entity/Raptor.h" #include "Objects/TR3/Entity/TwinAutoGun.h" #include "Objects/TR3/Entity/WaspMutant.h" #include "Objects/TR3/Entity/Winston.h" @@ -413,6 +414,22 @@ static void StartEntity(ObjectInfo* obj) obj->SetHitEffect(); } + obj = &Objects[ID_SEAL_MUTANT]; + if (obj->loaded) + { + obj->Initialize = InitializeSealMutant; + obj->collision = CreatureCollision; + obj->control = ControlSealMutant; + obj->shadowType = ShadowMode::All; + obj->HitPoints = 50; + obj->radius = 204; + obj->pivotLength = 0; + obj->intelligent = true; + obj->SetBoneRotationFlags(8, ROT_X | ROT_Z); // Torso X/Z + obj->SetBoneRotationFlags(9, ROT_Y); // Head + obj->SetHitEffect(); + } + obj = &Objects[ID_WINSTON]; if (obj->loaded) { diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index 6d2a47cf7..21132980f 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -232,10 +232,10 @@ enum GAME_OBJECT_ID : short ID_CLAW_MUTANT, ID_WASP_MUTANT, ID_TWIN_AUTO_GUN, - ID_SKATEBOARD = 296, + ID_SKATEBOARD, ID_SKATEBOARD_KID, ID_WINSTON, - //299 + ID_SEAL_MUTANT, ID_SPRINGBOARD = 320, ID_ROLLING_SPINDLE, diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index 351402296..6a9209f5d 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -239,7 +239,7 @@ The following constants are inside ObjID. SKATEBOARD SKATEBOARD_KID WINSTON - ARMY_WINSTON + SEAL_MUTANT SPRINGBOARD ROLLING_SPINDLE DISK_SHOOTER @@ -825,6 +825,7 @@ The following constants are inside ObjID. MESHSWAP_ROMAN_GOD2 MESHSWAP_MONKEY_MEDIPACK MESHSWAP_MONKEY_KEY + MESHSWAP_WINSTON_ARMY_OUTFIT ANIMATING1 ANIMATING2 ANIMATING3 @@ -1415,6 +1416,7 @@ static const std::unordered_map kObjIDs { { "SKATEBOARD", ID_SKATEBOARD }, { "SKATEBOARD_KID", ID_SKATEBOARD_KID }, { "WINSTON", ID_WINSTON }, + { "SEAL_MUTANT", ID_SEAL_MUTANT }, { "SPRINGBOARD", ID_SPRINGBOARD }, { "ROLLING_SPINDLE", ID_ROLLING_SPINDLE }, { "DISK_SHOOTER", ID_DISK_SHOOTER }, diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 67efb3876..aa6f981f4 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -530,6 +530,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -1036,6 +1037,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + From f2c52e61aac9f40270e511fb195d8b9482673cbe Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 11 Aug 2024 17:20:09 +0100 Subject: [PATCH 256/410] Add "Lara's Home" menu entry (#1394) * Add "Lara's Home" menu entry * Minor things * Move home_level into Strings.lua * Lara's Home -> Home Level --------- Co-authored-by: Sezz --- CHANGELOG.md | 2 + Documentation/doc/1 modules/Flow.html | 26 ++++++++ Scripts/Strings.lua | 2 +- TombEngine/Game/control/control.cpp | 4 ++ TombEngine/Game/control/control.h | 1 + TombEngine/Game/gui.cpp | 48 +++++++++++--- TombEngine/Game/gui.h | 1 + TombEngine/Renderer/RendererDrawMenu.cpp | 16 ++++- .../Include/Flow/ScriptInterfaceFlowHandler.h | 1 + .../Scripting/Internal/LanguageScript.h | 2 +- .../Scripting/Internal/ReservedScriptNames.h | 1 + .../Internal/TEN/Flow/FlowHandler.cpp | 64 ++++++++++++------- .../Scripting/Internal/TEN/Flow/FlowHandler.h | 19 +++--- 13 files changed, 142 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b441efee..78d54106a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,10 +46,12 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Changed Water sound condition to ShallowWater. * Added option to enable or disable menu option looping. * Menu scrolling using held inputs will stop at the last option until a new input is made. +* Added the ability to display "Lara's Home" entry in the main menu. ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() +* Added Flow.EnableHomeLevel() * Removed anims.monkeyAutoJump. It is now a player menu configuration. * Fixed Volume:GetActive() method diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index 46af015e4..9f3a108d4 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -129,6 +129,10 @@ scripts too.

    + + + + @@ -361,6 +365,28 @@ Must be true or false + +
    + + EnableHomeLevel(enabled) +
    +
    + Enable or disable Home Level entry in the main menu. + + + +

    Parameters:

    +
      +
    • enabled + bool + true or false. +
    • +
    + + + + +
    diff --git a/Scripts/Strings.lua b/Scripts/Strings.lua index a7f6a7678..64b06d34e 100644 --- a/Scripts/Strings.lua +++ b/Scripts/Strings.lua @@ -58,7 +58,7 @@ local strings = -- Level name strings - lara_home = { "Lara's Home" }, + home_level = { "Home Level" }, test_level = { "Test Level" }, title = { "Title" }, } diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 6aaa1d01b..5509c4383 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -579,6 +579,10 @@ GameStatus DoGameLoop(int levelIndex) status = GameStatus::NewGame; break; + case InventoryResult::HomeLevel: + status = GameStatus::HomeLevel; + break; + case InventoryResult::LoadGame: status = GameStatus::LoadGame; break; diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index 45cab275e..168fd06d7 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -17,6 +17,7 @@ enum class GameStatus { Normal, NewGame, + HomeLevel, LoadGame, SaveGame, ExitToTitle, diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 586dd8dfc..72b675237 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -281,14 +281,17 @@ namespace TEN::Gui enum TitleOption { NewGame, + HomeLevel, LoadGame, Options, - ExitGame + ExitGame, + + Count }; - static const int numTitleOptions = 3; - static const int numLoadGameOptions = SAVEGAME_MAX - 1; - static const int numOptionsOptions = 2; + constexpr auto TITLE_OPTION_COUNT = TitleOption::Count - 1; + constexpr auto LOAD_GAME_OPTION_COUNT = SAVEGAME_MAX - 1; + constexpr auto OPTION_OPTION_COUNT = 2; static int selectedOptionBackup; auto inventoryResult = InventoryResult::None; @@ -300,20 +303,31 @@ namespace TEN::Gui switch (MenuToDisplay) { case Menu::Title: - OptionCount = g_GameFlow->IsLoadSaveEnabled() ? numTitleOptions : (numTitleOptions - 1); + OptionCount = TITLE_OPTION_COUNT; + + if (!g_GameFlow->IsHomeLevelEnabled()) + OptionCount--; + + if (!g_GameFlow->IsLoadSaveEnabled()) + OptionCount--; + break; case Menu::SelectLevel: inventoryResult = InventoryResult::None; OptionCount = g_GameFlow->GetNumLevels() - 2; + + if (g_GameFlow->IsHomeLevelEnabled()) + OptionCount--; + break; case Menu::LoadGame: - OptionCount = numLoadGameOptions; + OptionCount = LOAD_GAME_OPTION_COUNT; break; case Menu::Options: - OptionCount = numOptionsOptions; + OptionCount = OPTION_OPTION_COUNT; break; case Menu::Display: @@ -369,9 +383,14 @@ namespace TEN::Gui if (MenuToDisplay == Menu::Title) { - // Skip load game entry if loading and saving is disabled. int realSelectedOption = SelectedOption; - if (!g_GameFlow->IsLoadSaveEnabled() && SelectedOption > TitleOption::NewGame) + + // Skip Home Level entry if home level is disabled. + if (!g_GameFlow->IsHomeLevelEnabled() && realSelectedOption > TitleOption::NewGame) + realSelectedOption++; + + // Skip Load Game entry if loading and saving is disabled. + if (!g_GameFlow->IsLoadSaveEnabled() && realSelectedOption > TitleOption::HomeLevel) realSelectedOption++; switch (realSelectedOption) @@ -390,6 +409,10 @@ namespace TEN::Gui break; + case TitleOption::HomeLevel: + inventoryResult = InventoryResult::HomeLevel; + break; + case TitleOption::LoadGame: selectedOptionBackup = SelectedOption; SelectedOption = 0; @@ -410,8 +433,13 @@ namespace TEN::Gui } else if (MenuToDisplay == Menu::SelectLevel) { - // Level 0 is the title level, so increment the option by 1 to offset it. + // Level 0 is Title Level; increment option to offset it. g_GameFlow->SelectedLevelForNewGame = SelectedOption + 1; + + // Level 1 reserved for Home Level; increment option if enabled to offset it. + if (g_GameFlow->IsHomeLevelEnabled()) + g_GameFlow->SelectedLevelForNewGame++; + MenuToDisplay = Menu::Title; SelectedOption = 0; inventoryResult = InventoryResult::NewGameSelectedLevel; diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h index aa1f88882..3dda2f61c 100644 --- a/TombEngine/Game/gui.h +++ b/TombEngine/Game/gui.h @@ -30,6 +30,7 @@ namespace TEN::Gui None, UseItem, NewGame, + HomeLevel, LoadGame, SaveGame, ExitGame, diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 2bdfee90b..5cf475445 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -508,6 +508,14 @@ namespace TEN::Renderer GetNextLinePosition(&y); selectedOption++; + // Home Level + if (g_GameFlow->IsHomeLevelEnabled()) + { + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_HOME_LEVEL), PRINTSTRING_COLOR_WHITE, SF_Center(titleOption == selectedOption)); + GetNextLinePosition(&y); + selectedOption++; + } + // Load game if (g_GameFlow->IsLoadSaveEnabled()) { @@ -538,13 +546,15 @@ namespace TEN::Renderer AddString(MenuCenterEntry, 26, g_GameFlow->GetString(STRING_SELECT_LEVEL), PRINTSTRING_COLOR_ORANGE, SF_Center()); GetNextBlockPosition(&y); - // Level listing (starts with 1 because 0 is always title) - for (int i = 1; i < g_GameFlow->GetNumLevels(); i++, selectedOption++) + // Level 0 is always Title Level and level 1 might be Home Level. + for (int i = (g_GameFlow->IsHomeLevelEnabled() ? 2 : 1); i < g_GameFlow->GetNumLevels(); i++, selectedOption++) { - AddString(MenuCenterEntry, y, g_GameFlow->GetString(g_GameFlow->GetLevel(i)->NameStringKey.c_str()), + AddString( + MenuCenterEntry, y, g_GameFlow->GetString(g_GameFlow->GetLevel(i)->NameStringKey.c_str()), PRINTSTRING_COLOR_WHITE, SF_Center(titleOption == selectedOption)); GetNextNarrowLinePosition(&y); } + break; case Menu::Options: diff --git a/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h b/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h index 5c679f359..4a3f67354 100644 --- a/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h +++ b/TombEngine/Scripting/Include/Flow/ScriptInterfaceFlowHandler.h @@ -35,6 +35,7 @@ public: virtual bool IsMassPickupEnabled() const = 0; virtual bool IsPointFilterEnabled() const = 0; virtual bool IsLaraInTitleEnabled() const = 0; + virtual bool IsHomeLevelEnabled() const = 0; virtual bool IsLoadSaveEnabled() const = 0; virtual bool HasCrawlExtended() const = 0; virtual bool HasCrouchRoll() const = 0; diff --git a/TombEngine/Scripting/Internal/LanguageScript.h b/TombEngine/Scripting/Internal/LanguageScript.h index f3093bcb8..f3a320b03 100644 --- a/TombEngine/Scripting/Internal/LanguageScript.h +++ b/TombEngine/Scripting/Internal/LanguageScript.h @@ -3,7 +3,7 @@ // std::string ID macros #define STRING_WINDOW_TITLE "window_title" #define STRING_PASSPORT "passport" -#define STRING_LARA_HOME "lara_home" +#define STRING_HOME_LEVEL "home_level" #define STRING_CONTROLS "controls" #define STRING_DISPLAY "display" #define STRING_OTHER_SETTINGS "other_settings" diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 25c27763e..eafb807cf 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -223,6 +223,7 @@ static constexpr char ScriptReserved_EnableFlyCheat[] = "EnableFlyCheat"; static constexpr char ScriptReserved_EnableMassPickup[] = "EnableMassPickup"; static constexpr char ScriptReserved_EnableLaraInTitle[] = "EnableLaraInTitle"; static constexpr char ScriptReserved_EnableLevelSelect[] = "EnableLevelSelect"; +static constexpr char ScriptReserved_EnableHomeLevel[] = "EnableHomeLevel"; static constexpr char ScriptReserved_EnableLoadSave[] = "EnableLoadSave"; static constexpr char ScriptReserved_EnablePointFilter[] = "EnablePointFilter"; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp index 73dfe787c..5aebe1328 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp @@ -77,21 +77,23 @@ Must be true or false */ tableFlow.set_function(ScriptReserved_EnableLevelSelect, &FlowHandler::EnableLevelSelect, this); - /*** Enable or disable saving and loading of savegames. - @function EnableLoadSave - @tparam bool enabled true or false. - */ + /// Enable or disable Home Level entry in the main menu. + // @function EnableHomeLevel() + // @tparam bool enabled True or false. + tableFlow.set_function(ScriptReserved_EnableHomeLevel, &FlowHandler::EnableHomeLevel, this); + + /// Enable or disable saving and loading of savegames. + // @function EnableLoadSave() + // @tparam bool enabled True or false. tableFlow.set_function(ScriptReserved_EnableLoadSave, &FlowHandler::EnableLoadSave, this); /*** gameflow.lua or level scripts. @section FlowluaOrScripts */ -/*** Enable or disable DOZY mode (fly cheat). -Must be true or false -@function EnableFlyCheat -@tparam bool enabled true or false -*/ + /// Enable or disable the fly cheat. + // @function EnableFlyCheat() + // @tparam bool enabled True or false. tableFlow.set_function(ScriptReserved_EnableFlyCheat, &FlowHandler::EnableFlyCheat, this); /*** Enable or disable point texture filter. @@ -537,9 +539,9 @@ bool FlowHandler::IsFlyCheatEnabled() const return FlyCheat; } -void FlowHandler::EnableFlyCheat(bool flyCheat) +void FlowHandler::EnableFlyCheat(bool enable) { - FlyCheat = flyCheat; + FlyCheat = enable; } bool FlowHandler::IsPointFilterEnabled() const @@ -547,9 +549,9 @@ bool FlowHandler::IsPointFilterEnabled() const return PointFilter; } -void FlowHandler::EnablePointFilter(bool pointFilter) +void FlowHandler::EnablePointFilter(bool enable) { - PointFilter = pointFilter; + PointFilter = enable; } bool FlowHandler::IsMassPickupEnabled() const @@ -557,9 +559,9 @@ bool FlowHandler::IsMassPickupEnabled() const return MassPickup; } -void FlowHandler::EnableMassPickup(bool massPickup) +void FlowHandler::EnableMassPickup(bool enable) { - MassPickup = massPickup; + MassPickup = enable; } bool FlowHandler::IsLaraInTitleEnabled() const @@ -567,14 +569,24 @@ bool FlowHandler::IsLaraInTitleEnabled() const return LaraInTitle; } -void FlowHandler::EnableLaraInTitle(bool laraInTitle) +void FlowHandler::EnableLaraInTitle(bool enable) { - LaraInTitle = laraInTitle; + LaraInTitle = enable; } -void FlowHandler::EnableLevelSelect(bool levelSelect) +void FlowHandler::EnableLevelSelect(bool enable) { - LevelSelect = levelSelect; + LevelSelect = enable; +} + +bool FlowHandler::IsHomeLevelEnabled() const +{ + return HomeLevel; +} + +void FlowHandler::EnableHomeLevel(bool enable) +{ + HomeLevel = enable; } bool FlowHandler::IsLoadSaveEnabled() const @@ -582,9 +594,9 @@ bool FlowHandler::IsLoadSaveEnabled() const return LoadSave; } -void FlowHandler::EnableLoadSave(bool loadSave) +void FlowHandler::EnableLoadSave(bool enable) { - LoadSave = loadSave; + LoadSave = enable; } void FlowHandler::PrepareInventoryObjects() @@ -674,12 +686,20 @@ bool FlowHandler::DoFlow() break; case GameStatus::NewGame: - CurrentLevel = (SelectedLevelForNewGame != 0 ? SelectedLevelForNewGame : 1); + // NOTE: 0 reserved for title level and 1 reserved for home level. + CurrentLevel = (SelectedLevelForNewGame != 0) ? SelectedLevelForNewGame : (IsHomeLevelEnabled() ? 2 : 1); + RequiredStartPos = 0; SelectedLevelForNewGame = 0; InitializeGame = true; break; + case GameStatus::HomeLevel: + CurrentLevel = 1; + RequiredStartPos = 0; + InitializeGame = true; + break; + case GameStatus::LoadGame: // Load header of savegame to get level to load. SaveGame::LoadHeader(SelectedSaveGame, &header); diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h index 84b267d36..d9bd1ac84 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h @@ -30,10 +30,11 @@ public: int FogOutDistance = 0; bool LevelSelect = true; + bool HomeLevel = false; bool LoadSave = true; bool FlyCheat = true; bool PointFilter = false; - bool MassPickup = true; + bool MassPickup = true; bool LaraInTitle = false; bool DebugMode = false; @@ -74,17 +75,19 @@ public: void SetTitleScreenImagePath(const std::string& path); void SetTotalSecretCount(int secretsNumber); bool IsFlyCheatEnabled() const; - void EnableFlyCheat(bool flyCheat); + void EnableFlyCheat(bool enable); bool IsPointFilterEnabled() const; - void EnablePointFilter(bool pointFilter); - bool IsMassPickupEnabled() const; - void EnableMassPickup(bool massPickup); + void EnablePointFilter(bool enable); + bool IsMassPickupEnabled() const; + void EnableMassPickup(bool enable); bool IsLaraInTitleEnabled() const; - void EnableLaraInTitle(bool laraInTitle); + void EnableLaraInTitle(bool enable); bool IsLevelSelectEnabled() const; - void EnableLevelSelect(bool laraInTitle); + void EnableLevelSelect(bool enable); + bool IsHomeLevelEnabled() const; + void EnableHomeLevel(bool enable); bool IsLoadSaveEnabled() const; - void EnableLoadSave(bool loadSave); + void EnableLoadSave(bool enable); bool HasCrawlExtended() const override { return Anims.HasCrawlExtended; } bool HasCrouchRoll() const override { return Anims.HasCrouchRoll; } From 37f056bfaf93db856ddf360cebf51a7714d8eab2 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 12 Aug 2024 15:13:35 +1000 Subject: [PATCH 257/410] Add missing include --- TombEngine/Objects/TR3/Entity/SealMutant.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Objects/TR3/Entity/SealMutant.cpp b/TombEngine/Objects/TR3/Entity/SealMutant.cpp index 87b2b46d7..1d7198dee 100644 --- a/TombEngine/Objects/TR3/Entity/SealMutant.cpp +++ b/TombEngine/Objects/TR3/Entity/SealMutant.cpp @@ -1,4 +1,5 @@ #include "framework.h" +#include "Objects/TR3/Entity/SealMutant.h" #include "Game/animation.h" #include "Game/control/box.h" From a9c3474b1cc3ad1b337bc1dcf4f8531d8538093d Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:19:11 +0100 Subject: [PATCH 258/410] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d54106a..2edef0e20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,10 +36,11 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Enhanced raptor behaviour and handling. - OCB 0: Classic behaviour - OCB 1: Can jump up/down up to 4 steps and jump across gaps up to 2 blocks wide. - - You must use the download version found on the TombEngine website. + - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2 * Added TR3 seal mutant. - OCB 0: Normal enemy behaviour. (TR3 RX-Tech mines level) - OCB 1: Trap like behaviour. (TR3 Antarctica level) + - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Seal_Mutant.wad2 * Add new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. From 4258b27c0c574d24374d06cf3d014c086dca96b5 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Wed, 14 Aug 2024 00:52:48 +0100 Subject: [PATCH 259/410] Changelog typos --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2edef0e20..674b3fdee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,9 +30,9 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Features/Amendments * Changed Rome Hammer to not hurt player whilst deactivated. * Changed Statue with blade damage, from 20 to 200. -* Enhaced Rolling Spindle detection to avoid them going down through pits. -* Enhaced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) -* Enhaced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). +* Enhanced Rolling Spindle detection to avoid them going down through pits. +* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) +* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). * Enhanced raptor behaviour and handling. - OCB 0: Classic behaviour - OCB 1: Can jump up/down up to 4 steps and jump across gaps up to 2 blocks wide. From 079a2bfc001dada523b401d1aae98cc60c24981e Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 14 Aug 2024 16:09:42 +1000 Subject: [PATCH 260/410] Correct config --- TombEngine/Specific/configuration.cpp | 4 ++-- TombEngine/Specific/configuration.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/TombEngine/Specific/configuration.cpp b/TombEngine/Specific/configuration.cpp index 93945202f..07aaba43a 100644 --- a/TombEngine/Specific/configuration.cpp +++ b/TombEngine/Specific/configuration.cpp @@ -257,7 +257,7 @@ bool SaveConfiguration() // Set Input keys. if (SetDWORDRegKey(inputKey, REGKEY_MOUSE_SENSITIVITY, g_Configuration.MouseSensitivity) != ERROR_SUCCESS || - SetDWORDRegKey(inputKey, REGKEY_ENABLE_MENU_OPTION_LOOPING, (int)g_Configuration.MenuOptionLoopingMode) != ERROR_SUCCESS) + SetDWORDRegKey(inputKey, REGKEY_MENU_OPTION_LOOPING_MODE, (int)g_Configuration.MenuOptionLoopingMode) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -451,7 +451,7 @@ bool LoadConfiguration() if (RegOpenKeyExA(rootKey, REGKEY_INPUT, 0, KEY_READ, &inputKey) == ERROR_SUCCESS) { if (GetDWORDRegKey(inputKey, REGKEY_MOUSE_SENSITIVITY, &mouseSensitivity, GameConfiguration::DEFAULT_MOUSE_SENSITIVITY) != ERROR_SUCCESS || - GetDWORDRegKey(inputKey, REGKEY_ENABLE_MENU_OPTION_LOOPING, &menuOptionLoopingMode, (DWORD)MenuOptionLoopingMode::SaveLoadOnly) != ERROR_SUCCESS) + GetDWORDRegKey(inputKey, REGKEY_MENU_OPTION_LOOPING_MODE, &menuOptionLoopingMode, (DWORD)MenuOptionLoopingMode::SaveLoadOnly) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); diff --git a/TombEngine/Specific/configuration.h b/TombEngine/Specific/configuration.h index 0ab9c10ee..fadfc60ae 100644 --- a/TombEngine/Specific/configuration.h +++ b/TombEngine/Specific/configuration.h @@ -45,8 +45,8 @@ constexpr auto REGKEY_ENABLE_THUMBSTICK_CAMERA = "EnableThumbstickCamera"; // Input keys -constexpr auto REGKEY_MOUSE_SENSITIVITY = "MouseSensitivity"; -constexpr auto REGKEY_ENABLE_MENU_OPTION_LOOPING = "EnableMenuOptionLooping"; +constexpr auto REGKEY_MOUSE_SENSITIVITY = "MouseSensitivity"; +constexpr auto REGKEY_MENU_OPTION_LOOPING_MODE = "MenuOptionLoopingMode"; enum class MenuOptionLoopingMode { From dcfdae10da61fce00bc48f088277273e7a6d6b1d Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 14 Aug 2024 17:50:19 +1000 Subject: [PATCH 261/410] lara -> player in GUI --- TombEngine/Game/GuiObjects.cpp | 498 ++++++++++++++++----------------- TombEngine/Game/gui.cpp | 246 ++++++++-------- 2 files changed, 372 insertions(+), 372 deletions(-) diff --git a/TombEngine/Game/GuiObjects.cpp b/TombEngine/Game/GuiObjects.cpp index 62cccff81..0967e3a00 100644 --- a/TombEngine/Game/GuiObjects.cpp +++ b/TombEngine/Game/GuiObjects.cpp @@ -331,21 +331,21 @@ namespace TEN::Gui void CombineRevolverLasersight(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); if (flag) { - lara->Inventory.HasLasersight = true; - lara->Weapons[(int)LaraWeaponType::Revolver].HasLasersight = false; + player.Inventory.HasLasersight = true; + player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight = false; } else { - lara->Inventory.HasLasersight = false; - lara->Weapons[(int)LaraWeaponType::Revolver].HasLasersight = true; + player.Inventory.HasLasersight = false; + player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight = true; } - if (lara->Control.HandStatus != HandStatus::Free && - lara->Control.Weapon.GunType == LaraWeaponType::Revolver) + if (player.Control.HandStatus != HandStatus::Free && + player.Control.Weapon.GunType == LaraWeaponType::Revolver) { UndrawPistolMesh(*item, LaraWeaponType::Revolver, true); DrawPistolMeshes(*item, LaraWeaponType::Revolver); @@ -354,21 +354,21 @@ namespace TEN::Gui void CombineCrossbowLasersight(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); if (flag) { - lara->Inventory.HasLasersight = true; - lara->Weapons[(int)LaraWeaponType::Crossbow].HasLasersight = false; + player.Inventory.HasLasersight = true; + player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight = false; } else { - lara->Inventory.HasLasersight = false; - lara->Weapons[(int)LaraWeaponType::Crossbow].HasLasersight = true; + player.Inventory.HasLasersight = false; + player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight = true; } - if (lara->Control.HandStatus != HandStatus::Free && - lara->Control.Weapon.GunType == LaraWeaponType::Crossbow) + if (player.Control.HandStatus != HandStatus::Free && + player.Control.Weapon.GunType == LaraWeaponType::Crossbow) { UndrawShotgunMeshes(*item, LaraWeaponType::Crossbow); DrawShotgunMeshes(*item, LaraWeaponType::Crossbow); @@ -377,21 +377,21 @@ namespace TEN::Gui void CombineHKLasersight(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); if (flag) { - lara->Inventory.HasLasersight = true; - lara->Weapons[(int)LaraWeaponType::HK].HasLasersight = false; + player.Inventory.HasLasersight = true; + player.Weapons[(int)LaraWeaponType::HK].HasLasersight = false; } else { - lara->Inventory.HasLasersight = false; - lara->Weapons[(int)LaraWeaponType::HK].HasLasersight = true; + player.Inventory.HasLasersight = false; + player.Weapons[(int)LaraWeaponType::HK].HasLasersight = true; } - if (lara->Control.HandStatus != HandStatus::Free && - lara->Control.Weapon.GunType == LaraWeaponType::HK) + if (player.Control.HandStatus != HandStatus::Free && + player.Control.Weapon.GunType == LaraWeaponType::HK) { UndrawShotgunMeshes(*item, LaraWeaponType::HK); DrawShotgunMeshes(*item, LaraWeaponType::HK); @@ -400,514 +400,514 @@ namespace TEN::Gui void CombinePuzzleItem1(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[0] = false; - lara->Inventory.PuzzlesCombo[1] = false; - lara->Inventory.Puzzles[0] = true; + player.Inventory.PuzzlesCombo[0] = false; + player.Inventory.PuzzlesCombo[1] = false; + player.Inventory.Puzzles[0] = true; } void CombinePuzzleItem2(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[2] = false; - lara->Inventory.PuzzlesCombo[3] = false; - lara->Inventory.Puzzles[1] = true; + player.Inventory.PuzzlesCombo[2] = false; + player.Inventory.PuzzlesCombo[3] = false; + player.Inventory.Puzzles[1] = true; } void CombinePuzzleItem3(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[4] = false; - lara->Inventory.PuzzlesCombo[5] = false; - lara->Inventory.Puzzles[2] = true; + player.Inventory.PuzzlesCombo[4] = false; + player.Inventory.PuzzlesCombo[5] = false; + player.Inventory.Puzzles[2] = true; } void CombinePuzzleItem4(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[6] = false; - lara->Inventory.PuzzlesCombo[7] = false; - lara->Inventory.Puzzles[3] = true; + player.Inventory.PuzzlesCombo[6] = false; + player.Inventory.PuzzlesCombo[7] = false; + player.Inventory.Puzzles[3] = true; } void CombinePuzzleItem5(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[8] = false; - lara->Inventory.PuzzlesCombo[9] = false; - lara->Inventory.Puzzles[4] = true; + player.Inventory.PuzzlesCombo[8] = false; + player.Inventory.PuzzlesCombo[9] = false; + player.Inventory.Puzzles[4] = true; } void CombinePuzzleItem6(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[10] = false; - lara->Inventory.PuzzlesCombo[11] = false; - lara->Inventory.Puzzles[5] = true; + player.Inventory.PuzzlesCombo[10] = false; + player.Inventory.PuzzlesCombo[11] = false; + player.Inventory.Puzzles[5] = true; } void CombinePuzzleItem7(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[12] = false; - lara->Inventory.PuzzlesCombo[13] = false; - lara->Inventory.Puzzles[6] = true; + player.Inventory.PuzzlesCombo[12] = false; + player.Inventory.PuzzlesCombo[13] = false; + player.Inventory.Puzzles[6] = true; } void CombinePuzzleItem8(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[14] = false; - lara->Inventory.PuzzlesCombo[15] = false; - lara->Inventory.Puzzles[7] = true; + player.Inventory.PuzzlesCombo[14] = false; + player.Inventory.PuzzlesCombo[15] = false; + player.Inventory.Puzzles[7] = true; } void CombinePuzzleItem9(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[16] = false; - lara->Inventory.PuzzlesCombo[17] = false; - lara->Inventory.Puzzles[8] = true; + player.Inventory.PuzzlesCombo[16] = false; + player.Inventory.PuzzlesCombo[17] = false; + player.Inventory.Puzzles[8] = true; } void CombinePuzzleItem10(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[18] = false; - lara->Inventory.PuzzlesCombo[19] = false; - lara->Inventory.Puzzles[9] = true; + player.Inventory.PuzzlesCombo[18] = false; + player.Inventory.PuzzlesCombo[19] = false; + player.Inventory.Puzzles[9] = true; } void CombinePuzzleItem11(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[20] = false; - lara->Inventory.PuzzlesCombo[21] = false; - lara->Inventory.Puzzles[10] = true; + player.Inventory.PuzzlesCombo[20] = false; + player.Inventory.PuzzlesCombo[21] = false; + player.Inventory.Puzzles[10] = true; } void CombinePuzzleItem12(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[22] = false; - lara->Inventory.PuzzlesCombo[23] = false; - lara->Inventory.Puzzles[11] = true; + player.Inventory.PuzzlesCombo[22] = false; + player.Inventory.PuzzlesCombo[23] = false; + player.Inventory.Puzzles[11] = true; } void CombinePuzzleItem13(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[24] = false; - lara->Inventory.PuzzlesCombo[25] = false; - lara->Inventory.Puzzles[12] = true; + player.Inventory.PuzzlesCombo[24] = false; + player.Inventory.PuzzlesCombo[25] = false; + player.Inventory.Puzzles[12] = true; } void CombinePuzzleItem14(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[26] = false; - lara->Inventory.PuzzlesCombo[27] = false; - lara->Inventory.Puzzles[13] = true; + player.Inventory.PuzzlesCombo[26] = false; + player.Inventory.PuzzlesCombo[27] = false; + player.Inventory.Puzzles[13] = true; } void CombinePuzzleItem15(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[28] = false; - lara->Inventory.PuzzlesCombo[29] = false; - lara->Inventory.Puzzles[14] = true; + player.Inventory.PuzzlesCombo[28] = false; + player.Inventory.PuzzlesCombo[29] = false; + player.Inventory.Puzzles[14] = true; } void CombinePuzzleItem16(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.PuzzlesCombo[30] = false; - lara->Inventory.PuzzlesCombo[31] = false; - lara->Inventory.Puzzles[15] = true; + player.Inventory.PuzzlesCombo[30] = false; + player.Inventory.PuzzlesCombo[31] = false; + player.Inventory.Puzzles[15] = true; } void CombineKeyItem1(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[0] = true; - lara->Inventory.KeysCombo[0] = false; - lara->Inventory.KeysCombo[1] = false; + player.Inventory.Keys[0] = true; + player.Inventory.KeysCombo[0] = false; + player.Inventory.KeysCombo[1] = false; } void CombineKeyItem2(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[1] = true; - lara->Inventory.KeysCombo[2] = false; - lara->Inventory.KeysCombo[3] = false; + player.Inventory.Keys[1] = true; + player.Inventory.KeysCombo[2] = false; + player.Inventory.KeysCombo[3] = false; } void CombineKeyItem3(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[2] = true; - lara->Inventory.KeysCombo[4] = false; - lara->Inventory.KeysCombo[5] = false; + player.Inventory.Keys[2] = true; + player.Inventory.KeysCombo[4] = false; + player.Inventory.KeysCombo[5] = false; } void CombineKeyItem4(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[3] = true; - lara->Inventory.KeysCombo[6] = false; - lara->Inventory.KeysCombo[7] = false; + player.Inventory.Keys[3] = true; + player.Inventory.KeysCombo[6] = false; + player.Inventory.KeysCombo[7] = false; } void CombineKeyItem5(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[4] = true; - lara->Inventory.KeysCombo[8] = false; - lara->Inventory.KeysCombo[9] = false; + player.Inventory.Keys[4] = true; + player.Inventory.KeysCombo[8] = false; + player.Inventory.KeysCombo[9] = false; } void CombineKeyItem6(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[5] = true; - lara->Inventory.KeysCombo[10] = false; - lara->Inventory.KeysCombo[11] = false; + player.Inventory.Keys[5] = true; + player.Inventory.KeysCombo[10] = false; + player.Inventory.KeysCombo[11] = false; } void CombineKeyItem7(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[6] = true; - lara->Inventory.KeysCombo[12] = false; - lara->Inventory.KeysCombo[13] = false; + player.Inventory.Keys[6] = true; + player.Inventory.KeysCombo[12] = false; + player.Inventory.KeysCombo[13] = false; } void CombineKeyItem8(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[7] = true; - lara->Inventory.KeysCombo[14] = false; - lara->Inventory.KeysCombo[15] = false; + player.Inventory.Keys[7] = true; + player.Inventory.KeysCombo[14] = false; + player.Inventory.KeysCombo[15] = false; } void CombineKeyItem9(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[8] = true; - lara->Inventory.KeysCombo[16] = false; - lara->Inventory.KeysCombo[17] = false; + player.Inventory.Keys[8] = true; + player.Inventory.KeysCombo[16] = false; + player.Inventory.KeysCombo[17] = false; } void CombineKeyItem10(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[9] = true; - lara->Inventory.KeysCombo[18] = false; - lara->Inventory.KeysCombo[19] = false; + player.Inventory.Keys[9] = true; + player.Inventory.KeysCombo[18] = false; + player.Inventory.KeysCombo[19] = false; } void CombineKeyItem11(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[10] = true; - lara->Inventory.KeysCombo[20] = false; - lara->Inventory.KeysCombo[21] = false; + player.Inventory.Keys[10] = true; + player.Inventory.KeysCombo[20] = false; + player.Inventory.KeysCombo[21] = false; } void CombineKeyItem12(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[11] = true; - lara->Inventory.KeysCombo[22] = false; - lara->Inventory.KeysCombo[23] = false; + player.Inventory.Keys[11] = true; + player.Inventory.KeysCombo[22] = false; + player.Inventory.KeysCombo[23] = false; } void CombineKeyItem13(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[12] = true; - lara->Inventory.KeysCombo[24] = false; - lara->Inventory.KeysCombo[25] = false; + player.Inventory.Keys[12] = true; + player.Inventory.KeysCombo[24] = false; + player.Inventory.KeysCombo[25] = false; } void CombineKeyItem14(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[13] = true; - lara->Inventory.KeysCombo[26] = false; - lara->Inventory.KeysCombo[27] = false; + player.Inventory.Keys[13] = true; + player.Inventory.KeysCombo[26] = false; + player.Inventory.KeysCombo[27] = false; } void CombineKeyItem15(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[14] = true; - lara->Inventory.KeysCombo[28] = false; - lara->Inventory.KeysCombo[29] = false; + player.Inventory.Keys[14] = true; + player.Inventory.KeysCombo[28] = false; + player.Inventory.KeysCombo[29] = false; } void CombineKeyItem16(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Keys[15] = true; - lara->Inventory.KeysCombo[30] = false; - lara->Inventory.KeysCombo[31] = false; + player.Inventory.Keys[15] = true; + player.Inventory.KeysCombo[30] = false; + player.Inventory.KeysCombo[31] = false; } void CombinePickupItem1(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[0] = true; - lara->Inventory.PickupsCombo[0] = false; - lara->Inventory.PickupsCombo[1] = false; + player.Inventory.Pickups[0] = true; + player.Inventory.PickupsCombo[0] = false; + player.Inventory.PickupsCombo[1] = false; } void CombinePickupItem2(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[1] = true; - lara->Inventory.PickupsCombo[2] = false; - lara->Inventory.PickupsCombo[3] = false; + player.Inventory.Pickups[1] = true; + player.Inventory.PickupsCombo[2] = false; + player.Inventory.PickupsCombo[3] = false; } void CombinePickupItem3(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[2] = true; - lara->Inventory.PickupsCombo[4] = false; - lara->Inventory.PickupsCombo[5] = false; + player.Inventory.Pickups[2] = true; + player.Inventory.PickupsCombo[4] = false; + player.Inventory.PickupsCombo[5] = false; } void CombinePickupItem4(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[3] = true; - lara->Inventory.PickupsCombo[6] = false; - lara->Inventory.PickupsCombo[7] = false; + player.Inventory.Pickups[3] = true; + player.Inventory.PickupsCombo[6] = false; + player.Inventory.PickupsCombo[7] = false; } void CombinePickupItem5(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[4] = true; - lara->Inventory.PickupsCombo[8] = false; - lara->Inventory.PickupsCombo[9] = false; + player.Inventory.Pickups[4] = true; + player.Inventory.PickupsCombo[8] = false; + player.Inventory.PickupsCombo[9] = false; } void CombinePickupItem6(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[5] = true; - lara->Inventory.PickupsCombo[10] = false; - lara->Inventory.PickupsCombo[11] = false; + player.Inventory.Pickups[5] = true; + player.Inventory.PickupsCombo[10] = false; + player.Inventory.PickupsCombo[11] = false; } void CombinePickupItem7(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[6] = true; - lara->Inventory.PickupsCombo[12] = false; - lara->Inventory.PickupsCombo[13] = false; + player.Inventory.Pickups[6] = true; + player.Inventory.PickupsCombo[12] = false; + player.Inventory.PickupsCombo[13] = false; } void CombinePickupItem8(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[7] = true; - lara->Inventory.PickupsCombo[14] = false; - lara->Inventory.PickupsCombo[15] = false; + player.Inventory.Pickups[7] = true; + player.Inventory.PickupsCombo[14] = false; + player.Inventory.PickupsCombo[15] = false; } void CombinePickupItem9(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[8] = true; - lara->Inventory.PickupsCombo[16] = false; - lara->Inventory.PickupsCombo[17] = false; + player.Inventory.Pickups[8] = true; + player.Inventory.PickupsCombo[16] = false; + player.Inventory.PickupsCombo[17] = false; } void CombinePickupItem10(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[9] = true; - lara->Inventory.PickupsCombo[18] = false; - lara->Inventory.PickupsCombo[19] = false; + player.Inventory.Pickups[9] = true; + player.Inventory.PickupsCombo[18] = false; + player.Inventory.PickupsCombo[19] = false; } void CombinePickupItem11(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[10] = true; - lara->Inventory.PickupsCombo[20] = false; - lara->Inventory.PickupsCombo[21] = false; + player.Inventory.Pickups[10] = true; + player.Inventory.PickupsCombo[20] = false; + player.Inventory.PickupsCombo[21] = false; } void CombinePickupItem12(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[11] = true; - lara->Inventory.PickupsCombo[22] = false; - lara->Inventory.PickupsCombo[23] = false; + player.Inventory.Pickups[11] = true; + player.Inventory.PickupsCombo[22] = false; + player.Inventory.PickupsCombo[23] = false; } void CombinePickupItem13(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[12] = true; - lara->Inventory.PickupsCombo[24] = false; - lara->Inventory.PickupsCombo[25] = false; + player.Inventory.Pickups[12] = true; + player.Inventory.PickupsCombo[24] = false; + player.Inventory.PickupsCombo[25] = false; } void CombinePickupItem14(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[13] = true; - lara->Inventory.PickupsCombo[26] = false; - lara->Inventory.PickupsCombo[27] = false; + player.Inventory.Pickups[13] = true; + player.Inventory.PickupsCombo[26] = false; + player.Inventory.PickupsCombo[27] = false; } void CombinePickupItem15(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[14] = true; - lara->Inventory.PickupsCombo[28] = false; - lara->Inventory.PickupsCombo[29] = false; + player.Inventory.Pickups[14] = true; + player.Inventory.PickupsCombo[28] = false; + player.Inventory.PickupsCombo[29] = false; } void CombinePickupItem16(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Pickups[15] = true; - lara->Inventory.PickupsCombo[30] = false; - lara->Inventory.PickupsCombo[31] = false; + player.Inventory.Pickups[15] = true; + player.Inventory.PickupsCombo[30] = false; + player.Inventory.PickupsCombo[31] = false; } void CombineExamine1(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[0] = true; - lara->Inventory.ExaminesCombo[0] = false; - lara->Inventory.ExaminesCombo[1] = false; + player.Inventory.Examines[0] = true; + player.Inventory.ExaminesCombo[0] = false; + player.Inventory.ExaminesCombo[1] = false; } void CombineExamine2(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[1] = true; - lara->Inventory.ExaminesCombo[2] = false; - lara->Inventory.ExaminesCombo[3] = false; + player.Inventory.Examines[1] = true; + player.Inventory.ExaminesCombo[2] = false; + player.Inventory.ExaminesCombo[3] = false; } void CombineExamine3(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[2] = true; - lara->Inventory.ExaminesCombo[4] = false; - lara->Inventory.ExaminesCombo[5] = false; + player.Inventory.Examines[2] = true; + player.Inventory.ExaminesCombo[4] = false; + player.Inventory.ExaminesCombo[5] = false; } void CombineExamine4(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[3] = true; - lara->Inventory.ExaminesCombo[6] = false; - lara->Inventory.ExaminesCombo[7] = false; + player.Inventory.Examines[3] = true; + player.Inventory.ExaminesCombo[6] = false; + player.Inventory.ExaminesCombo[7] = false; } void CombineExamine5(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[4] = true; - lara->Inventory.ExaminesCombo[8] = false; - lara->Inventory.ExaminesCombo[9] = false; + player.Inventory.Examines[4] = true; + player.Inventory.ExaminesCombo[8] = false; + player.Inventory.ExaminesCombo[9] = false; } void CombineExamine6(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[5] = true; - lara->Inventory.ExaminesCombo[10] = false; - lara->Inventory.ExaminesCombo[11] = false; + player.Inventory.Examines[5] = true; + player.Inventory.ExaminesCombo[10] = false; + player.Inventory.ExaminesCombo[11] = false; } void CombineExamine7(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[6] = true; - lara->Inventory.ExaminesCombo[12] = false; - lara->Inventory.ExaminesCombo[13] = false; + player.Inventory.Examines[6] = true; + player.Inventory.ExaminesCombo[12] = false; + player.Inventory.ExaminesCombo[13] = false; } void CombineExamine8(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.Examines[7] = true; - lara->Inventory.ExaminesCombo[14] = false; - lara->Inventory.ExaminesCombo[15] = false; + player.Inventory.Examines[7] = true; + player.Inventory.ExaminesCombo[14] = false; + player.Inventory.ExaminesCombo[15] = false; } void CombineClockWorkBeetle(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - lara->Inventory.BeetleComponents |= BEETLECOMP_FLAG_BEETLE; // Get beetle. - lara->Inventory.BeetleComponents &= BEETLECOMP_FLAG_COMBO_1; // Remove combo 1. - lara->Inventory.BeetleComponents &= BEETLECOMP_FLAG_COMBO_2; // Remove combo 2. + player.Inventory.BeetleComponents |= BEETLECOMP_FLAG_BEETLE; // Get beetle. + player.Inventory.BeetleComponents &= BEETLECOMP_FLAG_COMBO_1; // Remove combo 1. + player.Inventory.BeetleComponents &= BEETLECOMP_FLAG_COMBO_2; // Remove combo 2. } } diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 72b675237..819c3f453 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -1503,7 +1503,7 @@ namespace TEN::Gui void GuiController::ConstructObjectList(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); Rings[(int)RingTypes::Inventory].NumObjectsInList = 0; @@ -1519,19 +1519,19 @@ namespace TEN::Gui if (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() != LaraType::Young) { - if (lara->Weapons[(int)LaraWeaponType::Pistol].Present) + if (player.Weapons[(int)LaraWeaponType::Pistol].Present) InsertObjectIntoList(INV_OBJECT_PISTOLS); else if (Ammo.AmountPistolsAmmo) InsertObjectIntoList(INV_OBJECT_PISTOLS_AMMO); - if (lara->Weapons[(int)LaraWeaponType::Uzi].Present) + if (player.Weapons[(int)LaraWeaponType::Uzi].Present) InsertObjectIntoList(INV_OBJECT_UZIS); else if (Ammo.AmountUziAmmo) InsertObjectIntoList(INV_OBJECT_UZI_AMMO); - if (lara->Weapons[(int)LaraWeaponType::Revolver].Present) + if (player.Weapons[(int)LaraWeaponType::Revolver].Present) { - if (lara->Weapons[(int)LaraWeaponType::Revolver].HasLasersight) + if (player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight) InsertObjectIntoList(INV_OBJECT_REVOLVER_LASER); else InsertObjectIntoList(INV_OBJECT_REVOLVER); @@ -1539,11 +1539,11 @@ namespace TEN::Gui else if (Ammo.AmountRevolverAmmo) InsertObjectIntoList(INV_OBJECT_REVOLVER_AMMO); - if (lara->Weapons[(int)LaraWeaponType::Shotgun].Present) + if (player.Weapons[(int)LaraWeaponType::Shotgun].Present) { InsertObjectIntoList(INV_OBJECT_SHOTGUN); - if (lara->Weapons[(int)LaraWeaponType::Shotgun].SelectedAmmo == WeaponAmmoType::Ammo2) + if (player.Weapons[(int)LaraWeaponType::Shotgun].SelectedAmmo == WeaponAmmoType::Ammo2) Ammo.CurrentShotGunAmmoType = 1; } else @@ -1555,33 +1555,33 @@ namespace TEN::Gui InsertObjectIntoList(INV_OBJECT_SHOTGUN_AMMO_2); } - if (lara->Weapons[(int)LaraWeaponType::HK].Present) + if (player.Weapons[(int)LaraWeaponType::HK].Present) { - if (lara->Weapons[(int)LaraWeaponType::HK].HasLasersight) + if (player.Weapons[(int)LaraWeaponType::HK].HasLasersight) InsertObjectIntoList(INV_OBJECT_HK_LASERSIGHT); else InsertObjectIntoList(INV_OBJECT_HK); - if (lara->Weapons[(int)LaraWeaponType::HK].WeaponMode == LaraWeaponTypeCarried::WTYPE_AMMO_2) + if (player.Weapons[(int)LaraWeaponType::HK].WeaponMode == LaraWeaponTypeCarried::WTYPE_AMMO_2) Ammo.CurrentHKAmmoType = 1; - if (lara->Weapons[(int)LaraWeaponType::HK].WeaponMode == LaraWeaponTypeCarried::WTYPE_AMMO_3) + if (player.Weapons[(int)LaraWeaponType::HK].WeaponMode == LaraWeaponTypeCarried::WTYPE_AMMO_3) Ammo.CurrentHKAmmoType = 2; } else if (Ammo.AmountHKAmmo1) InsertObjectIntoList(INV_OBJECT_HK_AMMO); - if (lara->Weapons[(int)LaraWeaponType::Crossbow].Present) + if (player.Weapons[(int)LaraWeaponType::Crossbow].Present) { - if (lara->Weapons[(int)LaraWeaponType::Crossbow].HasLasersight) + if (player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight) InsertObjectIntoList(INV_OBJECT_CROSSBOW_LASER); else InsertObjectIntoList(INV_OBJECT_CROSSBOW); - if (lara->Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo == WeaponAmmoType::Ammo2) + if (player.Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo == WeaponAmmoType::Ammo2) Ammo.CurrentCrossBowAmmoType = 1; - if (lara->Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo == WeaponAmmoType::Ammo3) + if (player.Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo == WeaponAmmoType::Ammo3) Ammo.CurrentCrossBowAmmoType = 2; } else @@ -1596,14 +1596,14 @@ namespace TEN::Gui InsertObjectIntoList(INV_OBJECT_CROSSBOW_AMMO_3); } - if (lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Present) + if (player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Present) { InsertObjectIntoList(INV_OBJECT_GRENADE_LAUNCHER); - if (lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo == WeaponAmmoType::Ammo2) + if (player.Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo == WeaponAmmoType::Ammo2) Ammo.CurrentGrenadeGunAmmoType = 1; - if (lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo == WeaponAmmoType::Ammo3) + if (player.Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo == WeaponAmmoType::Ammo3) Ammo.CurrentGrenadeGunAmmoType = 2; } else @@ -1618,107 +1618,107 @@ namespace TEN::Gui InsertObjectIntoList(INV_OBJECT_GRENADE_AMMO_3); } - if (lara->Weapons[(int)LaraWeaponType::RocketLauncher].Present) + if (player.Weapons[(int)LaraWeaponType::RocketLauncher].Present) InsertObjectIntoList(INV_OBJECT_ROCKET_LAUNCHER); else if (Ammo.AmountRocketsAmmo) InsertObjectIntoList(INV_OBJECT_ROCKET_AMMO); - if (lara->Weapons[(int)LaraWeaponType::HarpoonGun].Present) + if (player.Weapons[(int)LaraWeaponType::HarpoonGun].Present) InsertObjectIntoList(INV_OBJECT_HARPOON_GUN); else if (Ammo.AmountHarpoonAmmo) InsertObjectIntoList(INV_OBJECT_HARPOON_AMMO); - if (lara->Inventory.HasLasersight) + if (player.Inventory.HasLasersight) InsertObjectIntoList(INV_OBJECT_LASERSIGHT); - if (lara->Inventory.HasSilencer) + if (player.Inventory.HasSilencer) InsertObjectIntoList(INV_OBJECT_SILENCER); - if (lara->Inventory.HasBinoculars) + if (player.Inventory.HasBinoculars) InsertObjectIntoList(INV_OBJECT_BINOCULARS); - if (lara->Inventory.TotalFlares) + if (player.Inventory.TotalFlares) InsertObjectIntoList(INV_OBJECT_FLARES); } InsertObjectIntoList(INV_OBJECT_TIMEX);//every level has the timex? what's a good way to check?! - if (lara->Inventory.TotalSmallMedipacks) + if (player.Inventory.TotalSmallMedipacks) InsertObjectIntoList(INV_OBJECT_SMALL_MEDIPACK); - if (lara->Inventory.TotalLargeMedipacks) + if (player.Inventory.TotalLargeMedipacks) InsertObjectIntoList(INV_OBJECT_LARGE_MEDIPACK); - if (lara->Inventory.HasCrowbar) + if (player.Inventory.HasCrowbar) InsertObjectIntoList(INV_OBJECT_CROWBAR); - if (lara->Inventory.BeetleComponents) + if (player.Inventory.BeetleComponents) { - if (lara->Inventory.BeetleComponents & BEETLECOMP_FLAG_BEETLE) + if (player.Inventory.BeetleComponents & BEETLECOMP_FLAG_BEETLE) InsertObjectIntoList(INV_OBJECT_BEETLE); - if (lara->Inventory.BeetleComponents & BEETLECOMP_FLAG_COMBO_1) + if (player.Inventory.BeetleComponents & BEETLECOMP_FLAG_COMBO_1) InsertObjectIntoList(INV_OBJECT_BEETLE_PART1); - if (lara->Inventory.BeetleComponents & BEETLECOMP_FLAG_COMBO_2) + if (player.Inventory.BeetleComponents & BEETLECOMP_FLAG_COMBO_2) InsertObjectIntoList(INV_OBJECT_BEETLE_PART2); } - if (lara->Inventory.SmallWaterskin) - InsertObjectIntoList((lara->Inventory.SmallWaterskin - 1) + INV_OBJECT_SMALL_WATERSKIN_EMPTY); + if (player.Inventory.SmallWaterskin) + InsertObjectIntoList((player.Inventory.SmallWaterskin - 1) + INV_OBJECT_SMALL_WATERSKIN_EMPTY); - if (lara->Inventory.BigWaterskin) - InsertObjectIntoList((lara->Inventory.BigWaterskin - 1) + INV_OBJECT_BIG_WATERSKIN_EMPTY); + if (player.Inventory.BigWaterskin) + InsertObjectIntoList((player.Inventory.BigWaterskin - 1) + INV_OBJECT_BIG_WATERSKIN_EMPTY); for (int i = 0; i < NUM_PUZZLES; i++) { - if (lara->Inventory.Puzzles[i]) + if (player.Inventory.Puzzles[i]) InsertObjectIntoList(INV_OBJECT_PUZZLE1 + i); } for (int i = 0; i < NUM_PUZZLE_PIECES; i++) { - if (lara->Inventory.PuzzlesCombo[i]) + if (player.Inventory.PuzzlesCombo[i]) InsertObjectIntoList(INV_OBJECT_PUZZLE1_COMBO1 + i); } for (int i = 0; i < NUM_KEYS; i++) { - if (lara->Inventory.Keys[i]) + if (player.Inventory.Keys[i]) InsertObjectIntoList(INV_OBJECT_KEY1 + i); } for (int i = 0; i < NUM_KEY_PIECES; i++) { - if (lara->Inventory.KeysCombo[i]) + if (player.Inventory.KeysCombo[i]) InsertObjectIntoList(INV_OBJECT_KEY1_COMBO1 + i); } for (int i = 0; i < NUM_PICKUPS; i++) { - if (lara->Inventory.Pickups[i]) + if (player.Inventory.Pickups[i]) InsertObjectIntoList(INV_OBJECT_PICKUP1 + i); } for (int i = 0; i < NUM_PICKUPS_PIECES; i++) { - if (lara->Inventory.PickupsCombo[i]) + if (player.Inventory.PickupsCombo[i]) InsertObjectIntoList(INV_OBJECT_PICKUP1_COMBO1 + i); } for (int i = 0; i < NUM_EXAMINES; i++) { - if (lara->Inventory.Examines[i]) + if (player.Inventory.Examines[i]) InsertObjectIntoList(INV_OBJECT_EXAMINE1 + i); } for (int i = 0; i < NUM_EXAMINES_PIECES; i++) { - if (lara->Inventory.ExaminesCombo[i]) + if (player.Inventory.ExaminesCombo[i]) InsertObjectIntoList(INV_OBJECT_EXAMINE1_COMBO1 + i); } - if (lara->Inventory.Diary.Present) + if (player.Inventory.Diary.Present) InsertObjectIntoList(INV_OBJECT_DIARY); if (g_GameFlow->IsLoadSaveEnabled()) @@ -1739,7 +1739,7 @@ namespace TEN::Gui void GuiController::ConstructCombineObjectList(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); Rings[(int)RingTypes::Ammo].NumObjectsInList = 0; @@ -1748,73 +1748,73 @@ namespace TEN::Gui if (!(g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young)) { - if (lara->Weapons[(int)LaraWeaponType::Revolver].Present) + if (player.Weapons[(int)LaraWeaponType::Revolver].Present) { - if (lara->Weapons[(int)LaraWeaponType::Revolver].HasLasersight) + if (player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight) InsertObjectIntoList_v2(INV_OBJECT_REVOLVER_LASER); else InsertObjectIntoList_v2(INV_OBJECT_REVOLVER); } - if (lara->Weapons[(int)LaraWeaponType::HK].Present) + if (player.Weapons[(int)LaraWeaponType::HK].Present) { - if (lara->Weapons[(int)LaraWeaponType::HK].HasLasersight) + if (player.Weapons[(int)LaraWeaponType::HK].HasLasersight) InsertObjectIntoList_v2(INV_OBJECT_HK_LASERSIGHT); else InsertObjectIntoList_v2(INV_OBJECT_HK); } - if (lara->Weapons[(int)LaraWeaponType::Crossbow].Present) + if (player.Weapons[(int)LaraWeaponType::Crossbow].Present) { - if (lara->Weapons[(int)LaraWeaponType::Crossbow].HasLasersight) + if (player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight) InsertObjectIntoList_v2(INV_OBJECT_CROSSBOW_LASER); else InsertObjectIntoList_v2(INV_OBJECT_CROSSBOW); } - if (lara->Inventory.HasLasersight) + if (player.Inventory.HasLasersight) InsertObjectIntoList_v2(INV_OBJECT_LASERSIGHT); - if (lara->Inventory.HasSilencer) + if (player.Inventory.HasSilencer) InsertObjectIntoList_v2(INV_OBJECT_SILENCER); } - if (lara->Inventory.BeetleComponents) + if (player.Inventory.BeetleComponents) { - if (lara->Inventory.BeetleComponents & 2) + if (player.Inventory.BeetleComponents & 2) InsertObjectIntoList_v2(INV_OBJECT_BEETLE_PART1); - if (lara->Inventory.BeetleComponents & 4) + if (player.Inventory.BeetleComponents & 4) InsertObjectIntoList_v2(INV_OBJECT_BEETLE_PART2); } - if (lara->Inventory.SmallWaterskin) - InsertObjectIntoList_v2(lara->Inventory.SmallWaterskin - 1 + INV_OBJECT_SMALL_WATERSKIN_EMPTY); + if (player.Inventory.SmallWaterskin) + InsertObjectIntoList_v2(player.Inventory.SmallWaterskin - 1 + INV_OBJECT_SMALL_WATERSKIN_EMPTY); - if (lara->Inventory.BigWaterskin) - InsertObjectIntoList_v2(lara->Inventory.BigWaterskin - 1 + INV_OBJECT_BIG_WATERSKIN_EMPTY); + if (player.Inventory.BigWaterskin) + InsertObjectIntoList_v2(player.Inventory.BigWaterskin - 1 + INV_OBJECT_BIG_WATERSKIN_EMPTY); for (int i = 0; i < NUM_PUZZLE_PIECES; i++) { - if (lara->Inventory.PuzzlesCombo[i]) + if (player.Inventory.PuzzlesCombo[i]) InsertObjectIntoList_v2(INV_OBJECT_PUZZLE1_COMBO1 + i); } for (int i = 0; i < NUM_KEY_PIECES; i++) { - if (lara->Inventory.KeysCombo[i]) + if (player.Inventory.KeysCombo[i]) InsertObjectIntoList_v2(INV_OBJECT_KEY1_COMBO1 + i); } for (int i = 0; i < NUM_PICKUPS_PIECES; i++) { - if (lara->Inventory.PickupsCombo[i]) + if (player.Inventory.PickupsCombo[i]) InsertObjectIntoList_v2(INV_OBJECT_PICKUP1_COMBO1 + i); } for (int i = 0; i < NUM_EXAMINES_PIECES; i++) { - if (lara->Inventory.ExaminesCombo[i]) + if (player.Inventory.ExaminesCombo[i]) InsertObjectIntoList_v2(INV_OBJECT_EXAMINE1_COMBO1 + i); } @@ -1832,45 +1832,45 @@ namespace TEN::Gui void GuiController::InitializeInventory(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); AlterFOV(ANGLE(DEFAULT_FOV), false); - lara->Inventory.IsBusy = false; + player.Inventory.IsBusy = false; InventoryItemChosen = NO_VALUE; ItemUsed = false; - if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite()) + if (player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite()) { Ammo.AmountShotGunAmmo1 = -1; } else { - Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].GetCount() / 6; + Ammo.AmountShotGunAmmo1 = player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].GetCount() / 6; } - if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].HasInfinite()) + if (player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].HasInfinite()) { Ammo.AmountShotGunAmmo2 = -1; } else { - Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].GetCount() / 6; + Ammo.AmountShotGunAmmo2 = player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].GetCount() / 6; } - Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); - Ammo.AmountHKAmmo1 = lara->Weapons[(int)LaraWeaponType::HK].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::HK].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountCrossBowAmmo1 = lara->Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountCrossBowAmmo2 = lara->Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); - Ammo.AmountCrossBowAmmo3 = lara->Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo3].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo3].GetCount(); - Ammo.AmountUziAmmo = lara->Weapons[(int)LaraWeaponType::Uzi].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Uzi].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountRevolverAmmo = lara->Weapons[(int)LaraWeaponType::Revolver].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Revolver].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountPistolsAmmo = lara->Weapons[(int)LaraWeaponType::Pistol].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Pistol].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountRocketsAmmo = lara->Weapons[(int)LaraWeaponType::RocketLauncher].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::RocketLauncher].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountHarpoonAmmo = lara->Weapons[(int)LaraWeaponType::HarpoonGun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite()? -1 : lara->Weapons[(int)LaraWeaponType::HarpoonGun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountGrenadeAmmo1 = lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); - Ammo.AmountGrenadeAmmo2 = lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); - Ammo.AmountGrenadeAmmo3 = lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo3].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo3].GetCount(); + Ammo.AmountShotGunAmmo1 = player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountShotGunAmmo2 = player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); + Ammo.AmountHKAmmo1 = player.Weapons[(int)LaraWeaponType::HK].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::HK].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountCrossBowAmmo1 = player.Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountCrossBowAmmo2 = player.Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); + Ammo.AmountCrossBowAmmo3 = player.Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo3].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Crossbow].Ammo[(int)WeaponAmmoType::Ammo3].GetCount(); + Ammo.AmountUziAmmo = player.Weapons[(int)LaraWeaponType::Uzi].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Uzi].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountRevolverAmmo = player.Weapons[(int)LaraWeaponType::Revolver].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Revolver].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountPistolsAmmo = player.Weapons[(int)LaraWeaponType::Pistol].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::Pistol].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountRocketsAmmo = player.Weapons[(int)LaraWeaponType::RocketLauncher].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::RocketLauncher].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountHarpoonAmmo = player.Weapons[(int)LaraWeaponType::HarpoonGun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite()? -1 : player.Weapons[(int)LaraWeaponType::HarpoonGun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountGrenadeAmmo1 = player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo1].GetCount(); + Ammo.AmountGrenadeAmmo2 = player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo2].GetCount(); + Ammo.AmountGrenadeAmmo3 = player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo3].HasInfinite() ? -1 : player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Ammo[(int)WeaponAmmoType::Ammo3].GetCount(); ConstructObjectList(item); if (EnterInventory == NO_VALUE) @@ -2243,7 +2243,7 @@ namespace TEN::Gui void GuiController::DoInventory(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); auto& invRing = Rings[(int)RingTypes::Inventory]; auto& ammoRing = Rings[(int)RingTypes::Ammo]; @@ -2546,7 +2546,7 @@ namespace TEN::Gui case MenuType::Diary: SetInventoryMode(InventoryMode::Diary); - lara->Inventory.Diary.CurrentPage = 1; + player.Inventory.Diary.CurrentPage = 1; break; } } @@ -2574,51 +2574,51 @@ namespace TEN::Gui // Update the selected ammo of weapons that require it, and only these. void GuiController::UpdateWeaponStatus(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - if (lara->Weapons[(int)LaraWeaponType::Shotgun].Present) + if (player.Weapons[(int)LaraWeaponType::Shotgun].Present) { if (Ammo.CurrentShotGunAmmoType) - lara->Weapons[(int)LaraWeaponType::Shotgun].SelectedAmmo = WeaponAmmoType::Ammo2; + player.Weapons[(int)LaraWeaponType::Shotgun].SelectedAmmo = WeaponAmmoType::Ammo2; else - lara->Weapons[(int)LaraWeaponType::Shotgun].SelectedAmmo = WeaponAmmoType::Ammo1; + player.Weapons[(int)LaraWeaponType::Shotgun].SelectedAmmo = WeaponAmmoType::Ammo1; } - if (lara->Weapons[(int)LaraWeaponType::Crossbow].Present) + if (player.Weapons[(int)LaraWeaponType::Crossbow].Present) { - lara->Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo = WeaponAmmoType::Ammo1; + player.Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo = WeaponAmmoType::Ammo1; if (Ammo.CurrentCrossBowAmmoType == 1) - lara->Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo = WeaponAmmoType::Ammo2; + player.Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo = WeaponAmmoType::Ammo2; else if (Ammo.CurrentCrossBowAmmoType == 2) - lara->Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo = WeaponAmmoType::Ammo3; + player.Weapons[(int)LaraWeaponType::Crossbow].SelectedAmmo = WeaponAmmoType::Ammo3; } - if (lara->Weapons[(int)LaraWeaponType::HK].Present) + if (player.Weapons[(int)LaraWeaponType::HK].Present) { - lara->Weapons[(int)LaraWeaponType::HK].WeaponMode = LaraWeaponTypeCarried::WTYPE_AMMO_1; - lara->Weapons[(int)LaraWeaponType::HK].SelectedAmmo = WeaponAmmoType::Ammo1; + player.Weapons[(int)LaraWeaponType::HK].WeaponMode = LaraWeaponTypeCarried::WTYPE_AMMO_1; + player.Weapons[(int)LaraWeaponType::HK].SelectedAmmo = WeaponAmmoType::Ammo1; if (Ammo.CurrentHKAmmoType == 1) { - lara->Weapons[(int)LaraWeaponType::HK].WeaponMode = LaraWeaponTypeCarried::WTYPE_AMMO_2; - lara->Weapons[(int)LaraWeaponType::HK].SelectedAmmo = WeaponAmmoType::Ammo1; + player.Weapons[(int)LaraWeaponType::HK].WeaponMode = LaraWeaponTypeCarried::WTYPE_AMMO_2; + player.Weapons[(int)LaraWeaponType::HK].SelectedAmmo = WeaponAmmoType::Ammo1; } else if (Ammo.CurrentHKAmmoType == 2) { - lara->Weapons[(int)LaraWeaponType::HK].WeaponMode = LaraWeaponTypeCarried::WTYPE_AMMO_3; - lara->Weapons[(int)LaraWeaponType::HK].SelectedAmmo = WeaponAmmoType::Ammo1; + player.Weapons[(int)LaraWeaponType::HK].WeaponMode = LaraWeaponTypeCarried::WTYPE_AMMO_3; + player.Weapons[(int)LaraWeaponType::HK].SelectedAmmo = WeaponAmmoType::Ammo1; } } - if (lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].Present) + if (player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Present) { - lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo = WeaponAmmoType::Ammo1; + player.Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo = WeaponAmmoType::Ammo1; if (Ammo.CurrentGrenadeGunAmmoType == 1) - lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo = WeaponAmmoType::Ammo2; + player.Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo = WeaponAmmoType::Ammo2; else if (Ammo.CurrentGrenadeGunAmmoType == 2) - lara->Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo = WeaponAmmoType::Ammo3; + player.Weapons[(int)LaraWeaponType::GrenadeLauncher].SelectedAmmo = WeaponAmmoType::Ammo3; } } @@ -3182,11 +3182,11 @@ namespace TEN::Gui bool GuiController::CallInventory(ItemInfo* item, bool resetMode) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); bool doLoad = false; - lara->Inventory.OldBusy = lara->Inventory.IsBusy; + player.Inventory.OldBusy = player.Inventory.IsBusy; g_Renderer.DumpGameScene(); PauseAllSounds(SoundPauseMode::Inventory); @@ -3286,7 +3286,7 @@ namespace TEN::Gui AlterFOV(LastFOV); ResumeAllSounds(SoundPauseMode::Inventory); - lara->Inventory.IsBusy = lara->Inventory.OldBusy; + player.Inventory.IsBusy = player.Inventory.OldBusy; SetInventoryMode(InventoryMode::None); return doLoad; @@ -3341,21 +3341,21 @@ namespace TEN::Gui void GuiController::DoDiary(ItemInfo* item) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); SetInventoryMode(InventoryMode::Diary); if (GuiIsPulsed(In::Right) && - lara->Inventory.Diary.CurrentPage < lara->Inventory.Diary.NumPages) + player.Inventory.Diary.CurrentPage < player.Inventory.Diary.NumPages) { - lara->Inventory.Diary.CurrentPage++; + player.Inventory.Diary.CurrentPage++; SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); } if (GuiIsPulsed(In::Left) && - lara->Inventory.Diary.CurrentPage > 1) + player.Inventory.Diary.CurrentPage > 1) { - lara->Inventory.Diary.CurrentPage--; + player.Inventory.Diary.CurrentPage--; SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); } @@ -3454,10 +3454,10 @@ namespace TEN::Gui bool GuiController::PerformWaterskinCombine(ItemInfo* item, bool flag) { - auto* lara = GetLaraInfo(item); + auto& player = GetLaraInfo(*item); - int smallLiters = lara->Inventory.SmallWaterskin - 1; // How many liters in the small one? - int bigLiters = lara->Inventory.BigWaterskin - 1; // How many liters in the big one? + int smallLiters = player.Inventory.SmallWaterskin - 1; // How many liters in the small one? + int bigLiters = player.Inventory.BigWaterskin - 1; // How many liters in the big one? int smallCapacity = 3 - smallLiters; // How many more liters can fit in the small one? int bigCapacity = 5 - bigLiters; // How many more liters can fit in the big one? @@ -3465,7 +3465,7 @@ namespace TEN::Gui if (flag) { // Big one isn't empty and the small one isn't full. - if (lara->Inventory.BigWaterskin != 1 && smallCapacity) + if (player.Inventory.BigWaterskin != 1 && smallCapacity) { i = bigLiters; @@ -3481,8 +3481,8 @@ namespace TEN::Gui i--; } while (i); - lara->Inventory.SmallWaterskin = smallLiters + 1; - lara->Inventory.BigWaterskin = bigLiters + 1; + player.Inventory.SmallWaterskin = smallLiters + 1; + player.Inventory.BigWaterskin = bigLiters + 1; CombineObject1 = (smallLiters + 1) + (INV_OBJECT_SMALL_WATERSKIN_EMPTY - 1); return true; } @@ -3490,9 +3490,9 @@ namespace TEN::Gui else { // Small one isn't empty and the big one isn't full. - if (lara->Inventory.SmallWaterskin != 1 && bigCapacity) + if (player.Inventory.SmallWaterskin != 1 && bigCapacity) { - i = lara->Inventory.SmallWaterskin - 1; + i = player.Inventory.SmallWaterskin - 1; do { @@ -3506,8 +3506,8 @@ namespace TEN::Gui i--; } while (i); - lara->Inventory.SmallWaterskin = smallLiters + 1; - lara->Inventory.BigWaterskin = bigLiters + 1; + player.Inventory.SmallWaterskin = smallLiters + 1; + player.Inventory.BigWaterskin = bigLiters + 1; CombineObject1 = (bigLiters + 1) + (INV_OBJECT_BIG_WATERSKIN_EMPTY - 1); return true; } From fcf32b1ad026c7c93356a6286e061f4ab3fd9fc0 Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:55:23 +0200 Subject: [PATCH 262/410] Fix young hair drawing. --- TombEngine/Game/effects/hair.cpp | 16 ++++++---------- TombEngine/Game/effects/hair.h | 1 + TombEngine/Renderer/RendererLara.cpp | 11 +---------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 70e3278c7..5567ded88 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -41,8 +41,8 @@ namespace TEN::Effects::Hair auto baseOrient = Geometry::ConvertDirectionToQuat(-Geometry::ConvertQuatToDirection(GetBoneOrientation(item, LM_HEAD))); // Set position of base segment. - auto basePos = worldMatrix.Translation(); - Segments[0].Position = basePos; + Segments[0].Position = worldMatrix.Translation(); + Segments[0].WorldMatrix = worldMatrix; if (!IsInitialized) { @@ -83,7 +83,7 @@ namespace TEN::Effects::Hair // TR3 UPV uses a hack which forces player water status to dry. // Therefore, cannot directly use water status value to determine enrironment. bool isOnLand = (player.Control.WaterStatus == WaterStatus::Dry && - (player.Context.Vehicle == -1 || g_Level.Items[player.Context.Vehicle].ObjectNumber != ID_UPV)); + (player.Context.Vehicle == NO_VALUE || g_Level.Items[player.Context.Vehicle].ObjectNumber != ID_UPV)); // Handle segment room collision. CollideSegmentWithRoom(segment, waterHeight, roomNumber, isOnLand); @@ -97,6 +97,7 @@ namespace TEN::Effects::Hair // Calculate world matrix. worldMatrix = Matrix::CreateTranslation(prevSegment.Position); worldMatrix = Matrix::CreateFromQuaternion(prevSegment.Orientation) * worldMatrix; + segment.WorldMatrix = worldMatrix; auto jointOffset = (i == (Segments.size() - 1)) ? GetJointOffset(ID_HAIR, (i - 1) - 1) : @@ -118,12 +119,12 @@ namespace TEN::Effects::Hair { // Left pigtail offset. case 0: - relOffset = Vector3(-52.0f, -48.0f, -50.0f); + relOffset = Vector3(-48.0f, -48.0f, -50.0f); break; // Right pigtail offset. case 1: - relOffset = Vector3(44.0f, -48.0f, -50.0f); + relOffset = Vector3(48.0f, -48.0f, -50.0f); break; } } @@ -346,11 +347,6 @@ namespace TEN::Effects::Hair void HairEffectController::Update(ItemInfo& item, bool isYoung) { for (int i = 0; i < Units.size(); i++) - { Units[i].Update(item, i); - - if (isYoung && i == 1) - Units[i].Update(item, i); - } } } diff --git a/TombEngine/Game/effects/hair.h b/TombEngine/Game/effects/hair.h index 8e0a842b6..814e3c1fc 100644 --- a/TombEngine/Game/effects/hair.h +++ b/TombEngine/Game/effects/hair.h @@ -15,6 +15,7 @@ namespace TEN::Effects::Hair Vector3 Position = Vector3::Zero; Vector3 Velocity = Vector3::Zero; Quaternion Orientation = Quaternion::Identity; + Matrix WorldMatrix = Matrix::Identity; }; public: diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index bccc49e04..80bddf428 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -333,10 +333,6 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render const auto& hairObject = *_moveableObjects[ID_HAIR]; - // TODO - bool isYoung = (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); - - bool isHead = true; for (const auto& unit : HairEffect.Units) { if (!unit.IsEnabled) @@ -349,10 +345,7 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render for (int i = 0; i < unit.Segments.size(); i++) { - const auto& segment = unit.Segments[i]; - auto worldMatrix = Matrix::CreateFromQuaternion(segment.Orientation) * Matrix::CreateTranslation(segment.Position); - - _stItem.BonesMatrices[i + 1] = worldMatrix; + _stItem.BonesMatrices[i + 1] = unit.Segments[i].WorldMatrix; _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; } @@ -363,8 +356,6 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render auto& rMesh = *hairObject.ObjectMeshes[i]; DrawMoveableMesh(itemToDraw, &rMesh, room, i, view, rendererPass); } - - isHead = false; } } From 6b18d46096c7bf27619800243b60cb7c27831d3f Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:08:47 +0200 Subject: [PATCH 263/410] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 674b3fdee..85a365f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed teeth spikes not triggering the player impale animation. * Fixed TR4 mine crash with OCB 1 when triggered. * Fixed cases where Atlantean mutant's bombs cause the game to crash. +* Fixed young hair drawing. ### Features/Amendments * Changed Rome Hammer to not hurt player whilst deactivated. From cce384d3de7f5f058dcdc906813dfaa1656c6421 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 15 Aug 2024 22:40:08 +1000 Subject: [PATCH 264/410] Remove unused parameter --- TombEngine/Game/Lara/lara.cpp | 2 +- TombEngine/Game/effects/hair.cpp | 10 ++++------ TombEngine/Game/effects/hair.h | 11 +++++++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 053a5ce44..b8c65783b 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -640,7 +640,7 @@ void UpdateLara(ItemInfo* item, bool isTitle) g_Renderer.UpdateLaraAnimations(true); // Update player effects. - HairEffect.Update(*item, g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); + HairEffect.Update(*item); HandlePlayerWetnessDrips(*item); HandlePlayerDiveBubbles(*item); ProcessEffects(item); diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 5567ded88..e0f0cd7da 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -85,10 +85,8 @@ namespace TEN::Effects::Hair bool isOnLand = (player.Control.WaterStatus == WaterStatus::Dry && (player.Context.Vehicle == NO_VALUE || g_Level.Items[player.Context.Vehicle].ObjectNumber != ID_UPV)); - // Handle segment room collision. + // Handle segment collision. CollideSegmentWithRoom(segment, waterHeight, roomNumber, isOnLand); - - // Handle segment sphere collision. CollideSegmentWithSpheres(segment, spheres); // Calculate orientation. @@ -318,7 +316,7 @@ namespace TEN::Effects::Hair void HairEffectController::Initialize() { - constexpr auto ORIENT_DEFAULT = EulerAngles(ANGLE(-90.0f), 0, 0); + constexpr auto DEFAULT_ORIENT = EulerAngles(ANGLE(-90.0f), 0, 0); bool isYoung = (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); @@ -337,14 +335,14 @@ namespace TEN::Effects::Hair { segment.Position = GetJointOffset(ID_HAIR, 0); segment.Velocity = Vector3::Zero; - segment.Orientation = ORIENT_DEFAULT.ToQuaternion(); + segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); } isHead = false; } } - void HairEffectController::Update(ItemInfo& item, bool isYoung) + void HairEffectController::Update(ItemInfo& item) { for (int i = 0; i < Units.size(); i++) Units[i].Update(item, i); diff --git a/TombEngine/Game/effects/hair.h b/TombEngine/Game/effects/hair.h index 814e3c1fc..be4baa049 100644 --- a/TombEngine/Game/effects/hair.h +++ b/TombEngine/Game/effects/hair.h @@ -8,6 +8,7 @@ namespace TEN::Effects::Hair { private: // Constants + static constexpr auto HAIR_GRAVITY = 10.0f; struct HairSegment @@ -15,20 +16,23 @@ namespace TEN::Effects::Hair Vector3 Position = Vector3::Zero; Vector3 Velocity = Vector3::Zero; Quaternion Orientation = Quaternion::Identity; - Matrix WorldMatrix = Matrix::Identity; + Matrix WorldMatrix = Matrix::Identity; }; public: // Members + bool IsEnabled = false; bool IsInitialized = false; std::vector Segments = {}; // Utilities + void Update(const ItemInfo& item, int hairUnitIndex); private: // Helpers + Vector3 GetRelBaseOffset(int hairUnitIndex, bool isYoung); Vector3 GetWaterProbeOffset(const ItemInfo& item); Quaternion GetSegmentOrientation(const Vector3& origin, const Vector3& target, const Quaternion& baseOrient); @@ -42,15 +46,18 @@ namespace TEN::Effects::Hair { private: // Constants + static constexpr auto UNIT_COUNT_MAX = 2; public: // Members + std::array Units = {}; // Utilities + void Initialize(); - void Update(ItemInfo& item, bool isYoung); + void Update(ItemInfo& item); }; extern HairEffectController HairEffect; From bea28104087c08296e4d1d02d4be843bc02ea6ba Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 15 Aug 2024 22:44:35 +1000 Subject: [PATCH 265/410] Remove Ptr suffix; use const --- TombEngine/Game/effects/hair.cpp | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index e0f0cd7da..d3d214dc4 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -197,21 +197,21 @@ namespace TEN::Effects::Hair spheres.reserve(SPHERE_COUNT); // Hips sphere. - auto* meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_HIPS]]; - auto pos = GetJointPosition(item, LM_HIPS, Vector3i(meshPtr->sphere.Center)).ToVector3(); - spheres.push_back(BoundingSphere(pos, meshPtr->sphere.Radius)); + const auto* mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_HIPS]]; + auto pos = GetJointPosition(item, LM_HIPS, Vector3i(mesh->sphere.Center)).ToVector3(); + spheres.push_back(BoundingSphere(pos, mesh->sphere.Radius)); // Torso sphere. - meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_TORSO]]; - pos = GetJointPosition(item, LM_TORSO, Vector3i(meshPtr->sphere.Center) + TORSO_SPHERE_OFFSET).ToVector3(); - spheres.push_back(BoundingSphere(pos, meshPtr->sphere.Radius)); + mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_TORSO]]; + pos = GetJointPosition(item, LM_TORSO, Vector3i(mesh->sphere.Center) + TORSO_SPHERE_OFFSET).ToVector3(); + spheres.push_back(BoundingSphere(pos, mesh->sphere.Radius)); if (isYoung) spheres.back().Radius = spheres.back().Radius - ((spheres.back().Radius / 4) + (spheres.back().Radius / 8)); // Head sphere. - meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_HEAD]]; - pos = GetJointPosition(item, LM_HEAD, Vector3i(meshPtr->sphere.Center) + HEAD_SPHERE_OFFSET).ToVector3(); - spheres.push_back(BoundingSphere(pos, meshPtr->sphere.Radius)); + mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_HEAD]]; + pos = GetJointPosition(item, LM_HEAD, Vector3i(mesh->sphere.Center) + HEAD_SPHERE_OFFSET).ToVector3(); + spheres.push_back(BoundingSphere(pos, mesh->sphere.Radius)); // Neck sphere. spheres.push_back(BoundingSphere( @@ -219,30 +219,30 @@ namespace TEN::Effects::Hair isYoung ? 0.0f : (spheres[2].Radius * 0.75f))); // Left arm sphere. - meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_LINARM]]; - pos = GetJointPosition(item, LM_LINARM, Vector3i(meshPtr->sphere.Center)).ToVector3(); - spheres.push_back(BoundingSphere(pos, (meshPtr->sphere.Radius / 3) * 4)); + mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_LINARM]]; + pos = GetJointPosition(item, LM_LINARM, Vector3i(mesh->sphere.Center)).ToVector3(); + spheres.push_back(BoundingSphere(pos, (mesh->sphere.Radius / 3) * 4)); // Right arm sphere. - meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_RINARM]]; - pos = GetJointPosition(item, LM_RINARM, Vector3i(meshPtr->sphere.Center)).ToVector3(); - spheres.push_back(BoundingSphere(pos, (meshPtr->sphere.Radius / 3) * 4)); + mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_RINARM]]; + pos = GetJointPosition(item, LM_RINARM, Vector3i(mesh->sphere.Center)).ToVector3(); + spheres.push_back(BoundingSphere(pos, (mesh->sphere.Radius / 3) * 4)); // Left holster sphere. - meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_LTHIGH]]; - pos = GetJointPosition(item, LM_LTHIGH, Vector3i(meshPtr->sphere.Center)).ToVector3(); + mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_LTHIGH]]; + pos = GetJointPosition(item, LM_LTHIGH, Vector3i(mesh->sphere.Center)).ToVector3(); spheres.push_back( BoundingSphere( pos + ((spheres[0].Center - pos) / 2), - meshPtr->sphere.Radius)); + mesh->sphere.Radius)); // Right holster sphere. - meshPtr = &g_Level.Meshes[item.Model.MeshIndex[LM_RTHIGH]]; - pos = GetJointPosition(item, LM_RTHIGH, Vector3i(meshPtr->sphere.Center)).ToVector3(); + mesh = &g_Level.Meshes[item.Model.MeshIndex[LM_RTHIGH]]; + pos = GetJointPosition(item, LM_RTHIGH, Vector3i(mesh->sphere.Center)).ToVector3(); spheres.push_back( BoundingSphere( pos + ((spheres[0].Center - pos) / 2), - meshPtr->sphere.Radius)); + mesh->sphere.Radius)); if (isYoung) spheres[1].Center = (spheres[1].Center + spheres[2].Center) / 2; From 2439e7cd46f25fc521dd9f4075125494f5bb7d83 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 15 Aug 2024 22:46:08 +1000 Subject: [PATCH 266/410] Minor cleanup --- TombEngine/Game/effects/hair.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index d3d214dc4..5ca0c4c0e 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -174,13 +174,13 @@ namespace TEN::Effects::Hair Quaternion HairUnit::GetSegmentOrientation(const Vector3& origin, const Vector3& target, const Quaternion& baseOrient) { // Calculate absolute orientation. - auto absDirection = target - origin; - absDirection.Normalize(); - auto absOrient = Geometry::ConvertDirectionToQuat(absDirection); + auto absDir = target - origin; + absDir.Normalize(); + auto absOrient = Geometry::ConvertDirectionToQuat(absDir); // Calculate relative twist rotation. // TODO: Find accurate twist angle based on relation between absOrient and baseOrient. - auto twistAxisAngle = AxisAngle(absDirection, EulerAngles(baseOrient).y); + auto twistAxisAngle = AxisAngle(absDir, EulerAngles(baseOrient).y); auto twistRot = twistAxisAngle.ToQuaternion(); // Return ideal orientation. @@ -252,13 +252,12 @@ namespace TEN::Effects::Hair void HairUnit::CollideSegmentWithRoom(HairSegment& segment, int waterHeight, int roomNumber, bool isOnLand) { - constexpr auto VELOCITY_COEFF = 0.75f; + constexpr auto VEL_COEFF = 0.75f; auto pointColl = GetPointCollision(segment.Position, roomNumber); - int floorHeight = pointColl.GetFloorHeight(); Segments[0].Velocity = segment.Position; - segment.Position += segment.Velocity * VELOCITY_COEFF; + segment.Position += segment.Velocity * VEL_COEFF; // Land collision. if (isOnLand) @@ -276,7 +275,7 @@ namespace TEN::Effects::Hair segment.Position.y = waterHeight; } // Avoid clipping through floor. - else if (floorHeight > Segments[0].Position.y && segment.Position.y > floorHeight) + else if (pointColl.GetFloorHeight() > Segments[0].Position.y && segment.Position.y > pointColl.GetFloorHeight()) { segment.Position = Segments[0].Velocity; } @@ -288,9 +287,9 @@ namespace TEN::Effects::Hair { segment.Position.y = waterHeight; } - else if (segment.Position.y > floorHeight) + else if (segment.Position.y > pointColl.GetFloorHeight()) { - segment.Position.y = floorHeight; + segment.Position.y = pointColl.GetFloorHeight(); } } } @@ -299,17 +298,17 @@ namespace TEN::Effects::Hair { for (const auto& sphere : spheres) { - auto direction = segment.Position - sphere.Center; + auto dir = segment.Position - sphere.Center; - float distance = Vector3::Distance(segment.Position, sphere.Center); - if (distance < sphere.Radius) + float dist = Vector3::Distance(segment.Position, sphere.Center); + if (dist < sphere.Radius) { // Avoid division by zero. - if (distance == 0.0f) - distance = 1.0f; + if (dist == 0.0f) + dist = 1.0f; // Push segment away from sphere. - segment.Position = sphere.Center + (direction * (sphere.Radius / distance)); + segment.Position = sphere.Center + (dir * (sphere.Radius / dist)); } } } From e3c1ccf5c294b2b9236afd0255e62317fccd35b4 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 16 Aug 2024 02:12:41 +1000 Subject: [PATCH 267/410] Integrate GetWaterSurface(), GetWaterDepth() and GetWaterHeight() into PointCollisionData --- Documentation/doc/1 modules/Flow.html | 15 +- TombEngine/Game/Lara/lara_collide.cpp | 4 +- TombEngine/Game/Lara/lara_swim.cpp | 4 +- TombEngine/Game/Lara/lara_tests.cpp | 6 +- TombEngine/Game/collision/Point.cpp | 206 ++++++++++++++- TombEngine/Game/collision/collide_room.cpp | 242 +----------------- TombEngine/Game/collision/collide_room.h | 9 +- TombEngine/Game/control/box.cpp | 6 +- TombEngine/Game/effects/drip.cpp | 3 +- TombEngine/Game/effects/effects.cpp | 4 +- TombEngine/Game/effects/hair.cpp | 2 +- TombEngine/Game/effects/tomb4fx.cpp | 6 +- TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp | 7 +- TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 10 +- TombEngine/Objects/TR3/Entity/FishSwarm.cpp | 5 +- .../Objects/TR3/Entity/tr3_scuba_diver.cpp | 32 ++- TombEngine/Objects/TR3/Object/corpse.cpp | 12 +- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 10 +- .../Objects/TR3/Vehicles/rubber_boat.cpp | 8 +- TombEngine/Objects/TR3/Vehicles/upv.cpp | 12 +- .../Objects/TR4/Entity/tr4_crocodile.cpp | 4 +- .../Objects/TR5/Object/tr5_bodypart.cpp | 2 +- .../Objects/TR5/Object/tr5_rollingball.cpp | 13 +- TombEngine/Objects/Utils/VehicleHelpers.cpp | 11 +- 24 files changed, 287 insertions(+), 346 deletions(-) diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index 9f3a108d4..81fc6b1b0 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -141,7 +141,7 @@ scripts too.

    LensFlare(Rotation., Color.)LensFlare(Pitch, Yaw, Color.) Create a LensFlare object.
    Get the lens flare's enabled status.
    LensFlare:GetObjectID()LensFlare:GetSunSpriteID() Get the sun's sprite ID.
    LensFlare:GetRotation()Get the lens flare's euler rotation.LensFlare:GetPitch()Get the lens flare's pitch angle in degrees.
    LensFlare:GetYaw()Get the lens flare's yaw angle in degrees.
    LensFlare:SetColor() Get the lens flare's color.
    LensFlare:SetSunbjectID(New)LensFlare:SetSunSpriteID(New) Set the lens flare's sun sprite ID.
    LensFlare:SetRotation(New)Set the lens flare's euler rotation.LensFlare:SetPitch(New)Set the lens flare's pitch angle.
    LensFlare:SetYaw(New)Set the lens flare's yaw angle.
    LensFlare:SetColor(New)
    Starfield:SetStarCount(New)Set the starfield's number of stars.Set the starfield's number of stars (6000 max).
    Starfield:SetMeteorCount(New)Set the starfield's number of meteors.Set the starfield's number of meteors (100 max).
    Starfield:SetMeteorSpawnDensity(New) Clear an action key.
    KeyClearAll()Clear all action keys.
    GetMouseDisplayPosition() Get the display position of the cursor in percent.
    Enable or disable level selection in title flyby.
    EnableHomeLevel(enabled)Enable or disable Home Level entry in the main menu.
    EnableLoadSave(enabled) Enable or disable saving and loading of savegames.
    - + @@ -371,7 +371,7 @@ Must be true or false EnableHomeLevel(enabled)
    - Enable or disable Home Level entry in the main menu. + Enable or disable Home Level entry in the main menu. () @@ -379,7 +379,7 @@ Must be true or false
    • enabled bool - true or false. + True or false.
    @@ -393,7 +393,7 @@ Must be true or false EnableLoadSave(enabled)
    - Enable or disable saving and loading of savegames. + Enable or disable saving and loading of savegames. () @@ -401,7 +401,7 @@ Must be true or false
    • enabled bool - true or false. + True or false.
    @@ -419,8 +419,7 @@ Must be true or false EnableFlyCheat(enabled)
    - Enable or disable DOZY mode (fly cheat). -Must be true or false + Enable or disable the fly cheat. () @@ -428,7 +427,7 @@ Must be true or false
    • enabled bool - true or false + True or false.
    diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index 2370e2339..377d0ee7b 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -497,13 +497,11 @@ void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll) } auto pointColl = GetPointCollision(*item); - int waterHeight = GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); - if ((pointColl.GetFloorHeight() - item->Pose.Position.y) < SWIM_WATER_DEPTH) { TestPlayerWaterStepOut(item, coll); } - else if ((waterHeight - item->Pose.Position.y) <= -LARA_HEADROOM) + else if ((pointColl.GetWaterTopHeight() - item->Pose.Position.y) <= -LARA_HEADROOM) { SetLaraSwimDiveAnimation(item); } diff --git a/TombEngine/Game/Lara/lara_swim.cpp b/TombEngine/Game/Lara/lara_swim.cpp index 713a56e2a..c814159aa 100644 --- a/TombEngine/Game/Lara/lara_swim.cpp +++ b/TombEngine/Game/Lara/lara_swim.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/camera.h" +#include "Game/collision/Point.h" #include "Game/control/control.h" #include "Game/items.h" #include "Game/Lara/lara_collide.h" @@ -14,6 +15,7 @@ #include "Specific/level.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::Point; using namespace TEN::Input; // ----------------------------- @@ -187,7 +189,7 @@ void lara_col_underwater_death(ItemInfo* item, CollisionInfo* coll) item->HitPoints = -1; lara->Control.HandStatus = HandStatus::Busy; - int waterHeight = GetWaterHeight(item); + int waterHeight = GetPointCollision(*item).GetWaterTopHeight(); if (waterHeight < (item->Pose.Position.y - (CLICK(0.4f) - 2)) && waterHeight != NO_HEIGHT) { diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index a208daf54..cf6bafdcf 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -1087,15 +1087,13 @@ void TestLaraWaterDepth(ItemInfo* item, CollisionInfo* coll) auto& player = GetLaraInfo(*item); auto pointColl = GetPointCollision(*item); - int waterDepth = GetWaterDepth(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, pointColl.GetRoomNumber()); - if (waterDepth == NO_HEIGHT) + if (pointColl.GetWaterBottomHeight() == NO_HEIGHT) { item->Animation.Velocity.y = 0.0f; item->Pose.Position = coll->Setup.PrevPosition; } - - else if (waterDepth <= (LARA_HEIGHT - (LARA_HEADROOM / 2))) + else if (pointColl.GetWaterBottomHeight() <= (LARA_HEIGHT - (LARA_HEADROOM / 2))) { SetAnimation(item, LA_UNDERWATER_TO_STAND); ResetPlayerLean(item); diff --git a/TombEngine/Game/collision/Point.cpp b/TombEngine/Game/collision/Point.cpp index b7e49bdd2..652421c8c 100644 --- a/TombEngine/Game/collision/Point.cpp +++ b/TombEngine/Game/collision/Point.cpp @@ -177,9 +177,24 @@ namespace TEN::Collision::Point if (_waterSurfaceHeight.has_value()) return *_waterSurfaceHeight; - // Set water surface height. TODO: Calculate here. - _waterSurfaceHeight = GetWaterSurface(_position.x, _position.y, _position.z, _roomNumber); + auto* room = &g_Level.Rooms[_roomNumber]; + const auto* sector = Room::GetSector(room, _position.x - room->Position.x, _position.z - room->Position.z); + // Set water surface height. + bool isBelow = !TestEnvironment(ENV_FLAG_WATER, room); + while (sector->GetNextRoomNumber(_position, isBelow).has_value()) + { + room = &g_Level.Rooms[sector->GetNextRoomNumber(_position, isBelow).value_or(sector->RoomNumber)]; + if (isBelow == TestEnvironment(ENV_FLAG_WATER, room)) + { + _waterSurfaceHeight = sector->GetSurfaceHeight(_position.x, _position.z, isBelow); + return *_waterSurfaceHeight; + } + + sector = Room::GetSector(room, _position.x - room->Position.x, _position.z - room->Position.z); + } + + _waterSurfaceHeight = NO_HEIGHT; return *_waterSurfaceHeight; } @@ -188,10 +203,100 @@ namespace TEN::Collision::Point if (_waterBottomHeight.has_value()) return *_waterBottomHeight; - // Set water bottom height. TODO: Calculate here. - _waterBottomHeight = GetWaterDepth(_position.x, _position.y, _position.z, _roomNumber); + FloorInfo* sector = nullptr; + auto* room = &g_Level.Rooms[_roomNumber]; + short roomNumber = _roomNumber; - return *_waterBottomHeight; + int adjoiningRoomNumber = NO_VALUE; + do + { + int x = (_position.x - room->Position.x) / BLOCK(1); + int z = (_position.z - room->Position.z) / BLOCK(1); + + if (z <= 0) + { + z = 0; + if (x < 1) + { + x = 1; + } + else if (x > (room->XSize - 2)) + { + x = room->XSize - 2; + } + } + else if (z >= (room->ZSize - 1)) + { + z = room->ZSize - 1; + if (x < 1) + { + x = 1; + } + else if (x > (room->XSize - 2)) + { + x = room->XSize - 2; + } + } + else if (x < 0) + { + x = 0; + } + else if (x >= room->XSize) + { + x = room->XSize - 1; + } + + sector = &room->Sectors[z + (x * room->ZSize)]; + adjoiningRoomNumber = sector->SidePortalRoomNumber; + if (adjoiningRoomNumber != NO_VALUE) + { + roomNumber = adjoiningRoomNumber; + room = &g_Level.Rooms[adjoiningRoomNumber]; + } + } + while (adjoiningRoomNumber != NO_VALUE); + + // Set water bottom height. + if (TestEnvironment(ENV_FLAG_WATER, room) || TestEnvironment(ENV_FLAG_SWAMP, room)) + { + while (sector->GetNextRoomNumber(_position, false).value_or(NO_VALUE) != NO_VALUE) + { + room = &g_Level.Rooms[sector->GetNextRoomNumber(_position, false).value_or(sector->RoomNumber)]; + if (!TestEnvironment(ENV_FLAG_WATER, room) && !TestEnvironment(ENV_FLAG_SWAMP, room)) + { + int waterHeight = sector->GetSurfaceHeight(_position.x, _position.z, false); + int floorHeight = GetPointCollision(_position, sector->RoomNumber).GetBottomSector().GetSurfaceHeight(_position.x, _position.z, true); + + _waterBottomHeight = floorHeight - waterHeight; + return *_waterBottomHeight; + } + + sector = Room::GetSector(room, _position.x - room->Position.x, _position.z - room->Position.z); + } + + _waterBottomHeight = DEEP_WATER; + return *_waterBottomHeight; + } + else + { + while (sector->GetNextRoomNumber(_position, true).value_or(NO_VALUE) != NO_VALUE) + { + room = &g_Level.Rooms[sector->GetNextRoomNumber(_position, true).value_or(sector->RoomNumber)]; + if (TestEnvironment(ENV_FLAG_WATER, room) || TestEnvironment(ENV_FLAG_SWAMP, room)) + { + int waterHeight = sector->GetSurfaceHeight(_position.x, _position.z, true); + sector = GetFloor(_position.x, _position.y, _position.z, &roomNumber); + + _waterBottomHeight = GetPointCollision(_position, sector->RoomNumber).GetFloorHeight() - waterHeight; + return *_waterBottomHeight; + } + + sector = Room::GetSector(room, _position.x - room->Position.x, _position.z - room->Position.z); + } + + _waterBottomHeight = NO_HEIGHT; + return *_waterBottomHeight; + } } int PointCollisionData::GetWaterTopHeight() @@ -199,9 +304,96 @@ namespace TEN::Collision::Point if (_waterTopHeight.has_value()) return *_waterTopHeight; - // Set water top height. TODO: Calculate here. - _waterTopHeight = GetWaterHeight(_position.x, _position.y, _position.z, _roomNumber); + FloorInfo* sector = nullptr; + auto* room = &g_Level.Rooms[_roomNumber]; + int roomNumber = _roomNumber; + int adjoiningRoomNumber = NO_VALUE; + do + { + int x = (_position.x - room->Position.x) / BLOCK(1); + int z = (_position.z - room->Position.z) / BLOCK(1); + + if (z <= 0) + { + z = 0; + if (x < 1) + { + x = 1; + } + else if (x > (room->XSize - 2)) + { + x = room->XSize - 2; + } + } + else if (z >= (room->ZSize - 1)) + { + z = room->ZSize - 1; + if (x < 1) + { + x = 1; + } + else if (x > (room->XSize - 2)) + { + x = room->XSize - 2; + } + } + else if (x < 0) + { + x = 0; + } + else if (x >= room->XSize) + { + x = room->XSize - 1; + } + + sector = &room->Sectors[z + (x * room->ZSize)]; + adjoiningRoomNumber = sector->SidePortalRoomNumber; + + if (adjoiningRoomNumber != NO_VALUE) + { + roomNumber = adjoiningRoomNumber; + room = &g_Level.Rooms[adjoiningRoomNumber]; + } + } + while (adjoiningRoomNumber != NO_VALUE); + + if (sector->IsWall(_position.x, _position.z)) + { + _waterTopHeight = NO_HEIGHT; + return *_waterTopHeight; + } + + if (TestEnvironment(ENV_FLAG_WATER, room) || TestEnvironment(ENV_FLAG_SWAMP, room)) + { + while (sector->GetNextRoomNumber(_position, false).has_value()) + { + room = &g_Level.Rooms[sector->GetNextRoomNumber(_position, false).value_or(sector->RoomNumber)]; + if (!TestEnvironment(ENV_FLAG_WATER, room) && !TestEnvironment(ENV_FLAG_SWAMP, room)) + break; + + sector = Room::GetSector(room, _position.x - room->Position.x, _position.z - room->Position.z); + } + + _waterTopHeight = sector->GetSurfaceHeight(_position, false); + return *_waterTopHeight; + } + else if (sector->GetNextRoomNumber(_position, true).has_value()) + { + while (sector->GetNextRoomNumber(_position, true).has_value()) + { + room = &g_Level.Rooms[sector->GetNextRoomNumber(_position, true).value_or(sector->RoomNumber)]; + if (TestEnvironment(ENV_FLAG_WATER, room) || TestEnvironment(ENV_FLAG_SWAMP, room)) + break; + + sector = Room::GetSector(room, _position.x - room->Position.x, _position.z - room->Position.z); + } + + _waterTopHeight = sector->GetSurfaceHeight(_position, true); + return *_waterTopHeight; + } + + _waterTopHeight = NO_HEIGHT; return *_waterTopHeight; } diff --git a/TombEngine/Game/collision/collide_room.cpp b/TombEngine/Game/collision/collide_room.cpp index d453e172e..a083624d0 100644 --- a/TombEngine/Game/collision/collide_room.cpp +++ b/TombEngine/Game/collision/collide_room.cpp @@ -1081,246 +1081,6 @@ int GetDistanceToFloor(int itemNumber, bool precise) return (minHeight + item.Pose.Position.y - height); } -int GetWaterSurface(int x, int y, int z, short roomNumber) -{ - auto* room = &g_Level.Rooms[roomNumber]; - auto* sector = GetSector(room, x - room->Position.x, z - room->Position.z); - - if (TestEnvironment(ENV_FLAG_WATER, room)) - { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).has_value()) - { - room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; - if (!TestEnvironment(ENV_FLAG_WATER, room)) - return (sector->GetSurfaceHeight(x, z, false)); - - sector = GetSector(room, x - room->Position.x, z - room->Position.z); - } - - return NO_HEIGHT; - } - else - { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).has_value()) - { - room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; - if (TestEnvironment(ENV_FLAG_WATER, room)) - return (sector->GetSurfaceHeight(x, z, true)); - - sector = GetSector(room, x - room->Position.x, z - room->Position.z); - } - } - - return NO_HEIGHT; -} - -int GetWaterSurface(ItemInfo* item) -{ - return GetWaterSurface(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); -} - -int GetWaterDepth(int x, int y, int z, short roomNumber) -{ - FloorInfo* sector = nullptr; - auto* room = &g_Level.Rooms[roomNumber]; - - int adjoiningRoomNumber = NO_VALUE; - do - { - int xFloor = (x - room->Position.x) / BLOCK(1); - int zFloor = (z - room->Position.z) / BLOCK(1); - - if (zFloor <= 0) - { - zFloor = 0; - if (xFloor < 1) - { - xFloor = 1; - } - else if (xFloor > (room->XSize - 2)) - { - xFloor = room->XSize - 2; - } - } - else if (zFloor >= (room->ZSize - 1)) - { - zFloor = room->ZSize - 1; - if (xFloor < 1) - { - xFloor = 1; - } - else if (xFloor > (room->XSize - 2)) - { - xFloor = room->XSize - 2; - } - } - else if (xFloor < 0) - { - xFloor = 0; - } - else if (xFloor >= room->XSize) - { - xFloor = room->XSize - 1; - } - - sector = &room->Sectors[zFloor + (xFloor * room->ZSize)]; - adjoiningRoomNumber = sector->SidePortalRoomNumber; - if (adjoiningRoomNumber != NO_VALUE) - { - roomNumber = adjoiningRoomNumber; - room = &g_Level.Rooms[adjoiningRoomNumber]; - } - } - while (adjoiningRoomNumber != NO_VALUE); - - if (TestEnvironment(ENV_FLAG_WATER, room) || - TestEnvironment(ENV_FLAG_SWAMP, room)) - { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(NO_VALUE) != NO_VALUE) - { - room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; - - if (!TestEnvironment(ENV_FLAG_WATER, room) && - !TestEnvironment(ENV_FLAG_SWAMP, room)) - { - int waterHeight = sector->GetSurfaceHeight(x, z, false); - int floorHeight = GetPointCollision(Vector3i(x, y, z), sector->RoomNumber).GetBottomSector().GetSurfaceHeight(x, z, true); - return (floorHeight - waterHeight); - } - - sector = GetSector(room, x - room->Position.x, z - room->Position.z); - } - - return DEEP_WATER; - } - else - { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(NO_VALUE) != NO_VALUE) - { - room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; - - if (TestEnvironment(ENV_FLAG_WATER, room) || - TestEnvironment(ENV_FLAG_SWAMP, room)) - { - int waterHeight = sector->GetSurfaceHeight(x, z, true); - sector = GetFloor(x, y, z, &roomNumber); - return (GetFloorHeight(sector, x, y, z) - waterHeight); - } - - sector = GetSector(room, x - room->Position.x, z - room->Position.z); - } - - return NO_HEIGHT; - } -} - -int GetWaterDepth(ItemInfo* item) -{ - return GetWaterDepth(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); -} - -int GetWaterHeight(int x, int y, int z, short roomNumber) -{ - FloorInfo* sector = nullptr; - auto* room = &g_Level.Rooms[roomNumber]; - - int adjoiningRoomNumber = NO_VALUE; - do - { - int xBlock = (x - room->Position.x) / BLOCK(1); - int zBlock = (z - room->Position.z) / BLOCK(1); - - if (zBlock <= 0) - { - zBlock = 0; - if (xBlock < 1) - { - xBlock = 1; - } - else if (xBlock > (room->XSize - 2)) - { - xBlock = room->XSize - 2; - } - } - else if (zBlock >= (room->ZSize - 1)) - { - zBlock = room->ZSize - 1; - if (xBlock < 1) - { - xBlock = 1; - } - else if (xBlock > (room->XSize - 2)) - { - xBlock = room->XSize - 2; - } - } - else if (xBlock < 0) - { - xBlock = 0; - } - else if (xBlock >= room->XSize) - { - xBlock = room->XSize - 1; - } - - sector = &room->Sectors[zBlock + (xBlock * room->ZSize)]; - adjoiningRoomNumber = sector->SidePortalRoomNumber; - - if (adjoiningRoomNumber != NO_VALUE) - { - roomNumber = adjoiningRoomNumber; - room = &g_Level.Rooms[adjoiningRoomNumber]; - } - } - while (adjoiningRoomNumber != NO_VALUE); - - if (sector->IsWall(x, z)) - return NO_HEIGHT; - - if (TestEnvironment(ENV_FLAG_WATER, room) || - TestEnvironment(ENV_FLAG_SWAMP, room)) - { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), false).has_value()) - { - auto* room = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), false).value_or(sector->RoomNumber)]; - - if (!TestEnvironment(ENV_FLAG_WATER, room) && - !TestEnvironment(ENV_FLAG_SWAMP, room)) - { - break; - } - - sector = GetSector(room, x - room->Position.x, z - room->Position.z); - } - - return sector->GetSurfaceHeight(Vector3i(x, y, z), false); - } - else if (sector->GetNextRoomNumber(Vector3i(x, y, z), true).has_value()) - { - while (sector->GetNextRoomNumber(Vector3i(x, y, z), true).has_value()) - { - auto* room2 = &g_Level.Rooms[sector->GetNextRoomNumber(Vector3i(x, y, z), true).value_or(sector->RoomNumber)]; - - if (TestEnvironment(ENV_FLAG_WATER, room2) || - TestEnvironment(ENV_FLAG_SWAMP, room2)) - { - break; - } - - sector = GetSector(room2, x - room2->Position.x, z - room2->Position.z); - } - - return sector->GetSurfaceHeight(Vector3i(x, y, z), true); - } - - return NO_HEIGHT; -} - -int GetWaterHeight(ItemInfo* item) -{ - return GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); -} - bool TestEnvironment(RoomEnvFlags environmentType, int x, int y, int z, int roomNumber) { return TestEnvironment(environmentType, GetPointCollision(Vector3i(x, y, z), roomNumber).GetRoomNumber()); @@ -1341,7 +1101,7 @@ bool TestEnvironment(RoomEnvFlags environmentType, int roomNumber) return TestEnvironment(environmentType, &g_Level.Rooms[roomNumber]); } -bool TestEnvironment(RoomEnvFlags environmentType, ROOM_INFO* room) +bool TestEnvironment(RoomEnvFlags environmentType, const ROOM_INFO* room) { return TestEnvironmentFlags(environmentType, room->flags); } diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 1dc1c5ef2..41af7775f 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -137,13 +137,6 @@ int GetFloorHeight(FloorInfo* floor, int x, int y, int z); int GetCeiling(FloorInfo* floor, int x, int y, int z); int GetDistanceToFloor(int itemNumber, bool precise = true); -int GetWaterSurface(int x, int y, int z, short roomNumber); -int GetWaterSurface(ItemInfo* item); -int GetWaterDepth(int x, int y, int z, short roomNumber); -int GetWaterDepth(ItemInfo* item); -int GetWaterHeight(int x, int y, int z, short roomNumber); -int GetWaterHeight(ItemInfo* item); - int FindGridShift(int x, int z); void ShiftItem(ItemInfo* item, CollisionInfo* coll); void SnapItemToLedge(ItemInfo* item, CollisionInfo* coll, float offsetMultiplier = 0.0f, bool snapToAngle = true); @@ -157,5 +150,5 @@ bool TestEnvironment(RoomEnvFlags environmentType, int x, int y, int z, int room bool TestEnvironment(RoomEnvFlags environmentType, const Vector3i& pos, int roomNumber); bool TestEnvironment(RoomEnvFlags environmentType, const ItemInfo* item); bool TestEnvironment(RoomEnvFlags environmentType, int roomNumber); -bool TestEnvironment(RoomEnvFlags environmentType, ROOM_INFO* room); +bool TestEnvironment(RoomEnvFlags environmentType, const ROOM_INFO* room); bool TestEnvironmentFlags(RoomEnvFlags environmentType, int flags); diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 6b765938f..20640dd0f 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -613,7 +613,7 @@ void CreatureUnderwater(ItemInfo* item, int depth) } else { - waterHeight = GetWaterHeight(item); + waterHeight = GetPointCollision(*item).GetWaterTopHeight(); } int y = waterHeight + waterLevel; @@ -647,7 +647,7 @@ void CreatureFloat(short itemNumber) item->Pose.Orientation.x = 0; int y = item->Pose.Position.y; - int waterLevel = GetWaterHeight(item); + int waterLevel = GetPointCollision(*item).GetWaterTopHeight(); if (waterLevel == NO_HEIGHT) return; @@ -794,7 +794,7 @@ void CreatureHealth(ItemInfo* item) TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, &g_Level.Rooms[item->RoomNumber])) { auto bounds = GameBoundingBox(item); - auto height = item->Pose.Position.y - GetWaterHeight(item); + auto height = item->Pose.Position.y - GetPointCollision(*item).GetWaterTopHeight(); if (abs(bounds.Y1 + bounds.Y2) < height) DoDamage(item, INT_MAX); diff --git a/TombEngine/Game/effects/drip.cpp b/TombEngine/Game/effects/drip.cpp index 08336ecfc..69e5370ab 100644 --- a/TombEngine/Game/effects/drip.cpp +++ b/TombEngine/Game/effects/drip.cpp @@ -130,9 +130,8 @@ namespace TEN::Effects::Drip // Spawn ripple on surface only. if (!TestEnvironment(ENV_FLAG_WATER, prevRoomNumber)) { - float waterHeight = GetWaterHeight(drip.Position.x, drip.Position.y, drip.Position.z, drip.RoomNumber); SpawnRipple( - Vector3(drip.Position.x, waterHeight - RIPPLE_HEIGHT_OFFSET, drip.Position.z), + Vector3(drip.Position.x, pointColl.GetWaterTopHeight() - RIPPLE_HEIGHT_OFFSET, drip.Position.z), pointColl.GetRoomNumber(), Random::GenerateFloat(RIPPLE_SIZE_WATER_MIN, RIPPLE_SIZE_WATER_MAX), (int)RippleFlags::SlowFade | (int)RippleFlags::LowOpacity); diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 128c65022..a2b52a526 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -1308,7 +1308,7 @@ void Splash(ItemInfo* item) if (!TestEnvironment(ENV_FLAG_WATER, probedRoomNumber)) return; - int waterHeight = GetWaterHeight(item); + int waterHeight = GetPointCollision(*item).GetWaterTopHeight(); SplashSetup.x = item->Pose.Position.x; SplashSetup.y = waterHeight - 1; @@ -1940,7 +1940,7 @@ void ProcessEffects(ItemInfo* item) if (item->Effect.Type != EffectType::Sparks && item->Effect.Type != EffectType::Smoke) { const auto& bounds = GameBoundingBox(item); - int waterHeight = GetWaterHeight(item); + int waterHeight = GetPointCollision(*item).GetWaterTopHeight(); int itemLevel = item->Pose.Position.y + bounds.Y2 - (bounds.GetHeight() / 3); if (waterHeight != NO_HEIGHT && itemLevel > waterHeight) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 5ca0c4c0e..86262876f 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -69,7 +69,7 @@ namespace TEN::Effects::Hair // Get water height. auto pos = item.Pose.Position + Vector3i(GetWaterProbeOffset(item)); int roomNumber = item.RoomNumber; - int waterHeight = GetWaterHeight(pos.x, pos.y, pos.z, roomNumber); + int waterHeight = GetPointCollision(pos, roomNumber).GetWaterTopHeight(); // Get collision spheres. auto spheres = GetSpheres(item, isYoung); diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index f5bf359da..2e77628d8 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -5,6 +5,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" +#include "Game/collision/Point.h" #include "Game/effects/effects.h" #include "Game/effects/Bubble.h" #include "Game/effects/debris.h" @@ -27,6 +28,7 @@ using namespace TEN::Effects::Environment; using namespace TEN::Effects::Ripple; using namespace TEN::Effects::Smoke; using namespace TEN::Collision::Floordata; +using namespace TEN::Collision::Point; using namespace TEN::Math; using TEN::Renderer::g_Renderer; @@ -1117,7 +1119,7 @@ void TriggerUnderwaterExplosion(ItemInfo* item, int flag) TriggerExplosionBubbles(x, y, z, item->RoomNumber); TriggerExplosionSparks(x, y, z, 2, -1, 1, item->RoomNumber); - int waterHeight = GetWaterHeight(x, y, z, item->RoomNumber); + int waterHeight = GetPointCollision(Vector3i(x, y, z), item->RoomNumber).GetWaterTopHeight(); if (waterHeight != NO_HEIGHT) SomeSparkEffect(x, waterHeight, z, 8); } @@ -1129,7 +1131,7 @@ void TriggerUnderwaterExplosion(ItemInfo* item, int flag) for (int i = 0; i < 3; i++) TriggerExplosionSparks(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 2, -1, 1, item->RoomNumber); - int waterHeight = GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); + int waterHeight = GetPointCollision(*item).GetWaterTopHeight(); if (waterHeight != NO_HEIGHT) { int dy = item->Pose.Position.y - waterHeight; diff --git a/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp b/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp index cfd63dc11..97f53fb50 100644 --- a/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp +++ b/TombEngine/Objects/TR1/Entity/tr1_big_rat.cpp @@ -2,6 +2,7 @@ #include "Objects/TR1/Entity/tr1_big_rat.h" #include "Game/collision/collide_room.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -13,6 +14,7 @@ #include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::Creatures::TR1 @@ -83,8 +85,7 @@ namespace TEN::Entities::Creatures::TR1 bool RatOnWater(ItemInfo* item) { - int waterDepth = GetWaterSurface(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); - + int waterDepth = GetPointCollision(*item).GetWaterSurfaceHeight(); if (item->IsCreature()) { auto& creature = *GetCreatureInfo(item); @@ -240,7 +241,7 @@ namespace TEN::Entities::Creatures::TR1 if (RatOnWater(item)) { CreatureUnderwater(item, 0); - item->Pose.Position.y = GetWaterHeight(item) - BIG_RAT_WATER_SURFACE_OFFSET; + item->Pose.Position.y = GetPointCollision(*item).GetWaterTopHeight() - BIG_RAT_WATER_SURFACE_OFFSET; } else { diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index f0914c1b7..e9807e149 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -549,11 +549,11 @@ namespace TEN::Entities::Vehicles SpeedboatDoShift(speedboatItem, &f, &frontOld); } - auto probe = GetPointCollision(*speedboatItem); - auto height = GetWaterHeight(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z, probe.GetRoomNumber()); + auto pointColl = GetPointCollision(*speedboatItem); + auto height = GetPointCollision(Vector3i(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z), pointColl.GetRoomNumber()).GetWaterTopHeight(); if (height == NO_HEIGHT) - height = GetFloorHeight(&probe.GetSector(), speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z); + height = GetFloorHeight(&pointColl.GetSector(), speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y - 5, speedboatItem->Pose.Position.z); if (height < (speedboatItem->Pose.Position.y - CLICK(0.5f))) SpeedboatDoShift(speedboatItem, (Vector3i*)&speedboatItem->Pose, &old); @@ -825,7 +825,7 @@ namespace TEN::Entities::Vehicles TestTriggers(speedboatItem, false); } - auto water = GetWaterHeight(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y, speedboatItem->Pose.Position.z, probe.GetRoomNumber()); + auto water = GetPointCollision(Vector3i(speedboatItem->Pose.Position.x, speedboatItem->Pose.Position.y, speedboatItem->Pose.Position.z), probe.GetRoomNumber()).GetWaterTopHeight(); speedboat->Water = water; bool noTurn = true; @@ -968,7 +968,7 @@ namespace TEN::Entities::Vehicles TEN::Effects::TriggerSpeedboatFoam(speedboatItem, Vector3(0.0f, 0.0f, SPEEDBOAT_BACK)); } - int waterHeight = GetWaterHeight(speedboatItem); + int waterHeight = GetPointCollision(*speedboatItem).GetWaterTopHeight(); SpawnVehicleWake(*speedboatItem, SPEEDBOAT_WAKE_OFFSET, waterHeight); } } diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp index e9d5fedd5..bcab64a3b 100644 --- a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp @@ -221,7 +221,6 @@ namespace TEN::Entities::Creatures::TR3 // Get point collision. auto pointColl = GetPointCollision(pos, item.RoomNumber); - int waterHeight = GetWaterHeight(pointColl.GetPosition().x, pointColl.GetPosition().y, pointColl.GetPosition().z, pointColl.GetRoomNumber()); // 1) Test for water room. if (!TestEnvironment(ENV_FLAG_WATER, pointColl.GetRoomNumber())) @@ -229,7 +228,7 @@ namespace TEN::Entities::Creatures::TR3 // 2) Assess point collision. if (pos.y >= (pointColl.GetFloorHeight() - BUFFER) || - pos.y <= (waterHeight + BUFFER) || + pos.y <= (pointColl.GetWaterTopHeight() + BUFFER) || pointColl.GetSector().IsWall(item.Pose.Position.x + BUFFER, item.Pose.Position.z + BUFFER) || pointColl.GetSector().IsWall(item.Pose.Position.x - BUFFER, item.Pose.Position.z - BUFFER)) { @@ -380,7 +379,7 @@ namespace TEN::Entities::Creatures::TR3 } // Clamp position to slightly below water surface. - int waterHeight = GetWaterHeight(fish.Position.x, fish.Position.y, fish.Position.z, fish.RoomNumber); + int waterHeight = pointColl.GetWaterTopHeight(); if (fish.Position.y < (waterHeight + WATER_SURFACE_OFFSET)) fish.Position.y = waterHeight + WATER_SURFACE_OFFSET; diff --git a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp index 92b5c5a95..9f4baad45 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_scuba_diver.cpp @@ -130,11 +130,11 @@ namespace TEN::Entities::Creatures::TR3 } else { - AI_INFO AI; - CreatureAIInfo(item, &AI); + AI_INFO ai; + CreatureAIInfo(item, &ai); - GetCreatureMood(item, &AI, false); - CreatureMood(item, &AI, false); + GetCreatureMood(item, &ai, false); + CreatureMood(item, &ai, false); bool shoot = false; if (Lara.Control.WaterStatus == WaterStatus::Dry) @@ -143,23 +143,21 @@ namespace TEN::Entities::Creatures::TR3 item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z, - item->RoomNumber - ); + item->RoomNumber); auto target = GameVector( LaraItem->Pose.Position.x, LaraItem->Pose.Position.y - (LARA_HEIGHT - 150), - LaraItem->Pose.Position.z - ); + LaraItem->Pose.Position.z); shoot = LOS(&origin, &target); if (shoot) creature->Target = LaraItem->Pose.Position; - if (AI.angle < -ANGLE(45.0f) || AI.angle > ANGLE(45.0f)) + if (ai.angle < -ANGLE(45.0f) || ai.angle > ANGLE(45.0f)) shoot = false; } - else if (AI.angle > -ANGLE(45.0f) && AI.angle < ANGLE(45.0f)) + else if (ai.angle > -ANGLE(45.0f) && ai.angle < ANGLE(45.0f)) { auto origin = GameVector(item->Pose.Position, item->RoomNumber); auto target = GameVector(LaraItem->Pose.Position); @@ -168,7 +166,7 @@ namespace TEN::Entities::Creatures::TR3 } angle = CreatureTurn(item, creature->MaxTurn); - waterHeight = GetWaterSurface(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber) + BLOCK(0.5f); + waterHeight = GetPointCollision(*item).GetWaterSurfaceHeight() + BLOCK(0.5f); switch (item->Animation.ActiveState) { @@ -176,7 +174,7 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = SCUBA_DIVER_SWIM_TURN_RATE_MAX; if (shoot) - neck = -AI.angle; + neck = -ai.angle; if (creature->Target.y < waterHeight && item->Pose.Position.y < (waterHeight + creature->LOT.Fly)) @@ -194,7 +192,7 @@ namespace TEN::Entities::Creatures::TR3 creature->Flags = 0; if (shoot) - neck = -AI.angle; + neck = -ai.angle; if (!shoot || creature->Mood == MoodType::Escape || (creature->Target.y < waterHeight && @@ -209,7 +207,7 @@ namespace TEN::Entities::Creatures::TR3 case SDIVER_STATE_SWIM_SHOOT: if (shoot) - neck = -AI.angle; + neck = -ai.angle; if (!creature->Flags) { @@ -224,7 +222,7 @@ namespace TEN::Entities::Creatures::TR3 creature->MaxTurn = SCUBA_DIVER_SWIM_TURN_RATE_MAX; if (shoot) - head = AI.angle; + head = ai.angle; if (creature->Target.y > waterHeight) item->Animation.TargetState = SDIVER_STATE_SWIM; @@ -239,7 +237,7 @@ namespace TEN::Entities::Creatures::TR3 creature->Flags = 0; if (shoot) - head = AI.angle; + head = ai.angle; if (!shoot || creature->Mood == MoodType::Escape || creature->Target.y > waterHeight) item->Animation.TargetState = SDIVER_STATE_TREAD_WATER_IDLE; @@ -250,7 +248,7 @@ namespace TEN::Entities::Creatures::TR3 case SDIVER_STATE_TREAD_WATER_SHOOT: if (shoot) - head = AI.angle; + head = ai.angle; if (!creature->Flags) { diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp index c646f49f4..295792a8a 100644 --- a/TombEngine/Objects/TR3/Object/corpse.cpp +++ b/TombEngine/Objects/TR3/Object/corpse.cpp @@ -74,24 +74,24 @@ namespace TEN::Entities::TR3 bool isWater = TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber); float verticalVelCoeff = isWater ? 81.0f : 1.0f; - int roomNumber = GetPointCollision(item).GetRoomNumber(); - if (item.RoomNumber != roomNumber) + auto pointColl = GetPointCollision(item); + if (item.RoomNumber != pointColl.GetRoomNumber()) { - if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, roomNumber) && + if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointColl.GetRoomNumber()) && !TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber)) { - int waterHeight = GetWaterHeight(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, roomNumber); + int waterHeight = pointColl.GetWaterTopHeight(); SplashSetup.y = waterHeight - 1; SplashSetup.x = item.Pose.Position.x; SplashSetup.z = item.Pose.Position.z; SplashSetup.splashPower = item.Animation.Velocity.y * 4; SplashSetup.innerRadius = 160.0f; - SetupSplash(&SplashSetup, roomNumber); + SetupSplash(&SplashSetup, pointColl.GetRoomNumber()); item.Animation.Velocity.y = 0.0f; } - ItemNewRoom(itemNumber, roomNumber); + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); } auto pointColl = GetPointCollision(item); diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index 242998432..69d165de6 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -215,7 +215,7 @@ namespace TEN::Entities::Vehicles int z = kayakItem->Pose.Position.z + (zOffset * cosY) - (xOffset * sinY); int probedRoomNumber = GetPointCollision(Vector3i(x, kayakItem->Pose.Position.y, z), kayakItem->RoomNumber).GetRoomNumber(); - int waterHeight = GetWaterHeight(x, kayakItem->Pose.Position.y, z, probedRoomNumber); + int waterHeight = GetPointCollision(Vector3i(x, kayakItem->Pose.Position.y, z), probedRoomNumber).GetWaterTopHeight(); //if (waterHeight != NO_HEIGHT) // SetupRipple(x, kayakItem->Pose.Position.y, z, -2 - (GetRandomControl() & 1), 0, Objects[ID_KAYAK_PADDLE_TRAIL_SPRITE].meshIndex,TO_RAD(kayakItem->Pose.Orientation.y)); @@ -538,7 +538,7 @@ namespace TEN::Entities::Vehicles auto probe = GetPointCollision(*kayakItem); int probedRoomNum = probe.GetRoomNumber(); - height2 = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probedRoomNum); + height2 = GetPointCollision(kayakItem->Pose.Position, probedRoomNum).GetWaterTopHeight(); if (height2 == NO_HEIGHT) height2 = probe.GetFloorHeight(); @@ -548,7 +548,7 @@ namespace TEN::Entities::Vehicles probe = GetPointCollision(*kayakItem); probedRoomNum = probe.GetRoomNumber(); - height2 = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probedRoomNum); + height2 = GetPointCollision(kayakItem->Pose.Position, probedRoomNum).GetWaterTopHeight(); if (height2 == NO_HEIGHT) height2 = probe.GetFloorHeight(); @@ -1084,7 +1084,7 @@ namespace TEN::Entities::Vehicles TestTriggers(kayakItem, false); auto probe = GetPointCollision(*kayakItem); - int water = GetWaterHeight(kayakItem->Pose.Position.x, kayakItem->Pose.Position.y, kayakItem->Pose.Position.z, probe.GetRoomNumber()); + int water = GetPointCollision(kayakItem->Pose.Position, probe.GetRoomNumber()).GetWaterTopHeight(); kayak->WaterHeight = water; if (kayak->WaterHeight == NO_HEIGHT) @@ -1131,7 +1131,7 @@ namespace TEN::Entities::Vehicles if (kayak->TrueWater && (kayakItem->Animation.Velocity.z != 0.0f || lara->Context.WaterCurrentPull != Vector3i::Zero)) { - int waterHeight = GetWaterHeight(kayakItem); + int waterHeight = GetPointCollision(*kayakItem).GetWaterTopHeight(); SpawnVehicleWake(*kayakItem, KAYAK_WAKE_OFFSET, waterHeight); } diff --git a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp index ef36e34c7..4d63e4247 100644 --- a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp +++ b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp @@ -423,7 +423,7 @@ namespace TEN::Entities::Vehicles short roomNumber = rBoatItem->RoomNumber; auto floor = GetFloor(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y, rBoatItem->Pose.Position.z, &roomNumber); - int height = GetWaterHeight(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y, rBoatItem->Pose.Position.z, roomNumber); + int height = GetPointCollision(rBoatItem->Pose.Position, roomNumber).GetWaterTopHeight(); if (height == NO_HEIGHT) height = GetFloorHeight(floor, rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y, rBoatItem->Pose.Position.z); @@ -827,7 +827,7 @@ namespace TEN::Entities::Vehicles } auto probe = GetPointCollision(*rBoatItem); - int water = GetWaterHeight(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y, rBoatItem->Pose.Position.z, probe.GetRoomNumber()); + int water = GetPointCollision(rBoatItem->Pose.Position, probe.GetRoomNumber()).GetWaterTopHeight(); rBoat->Water = water; if (lara->Context.Vehicle == itemNumber && laraItem->HitPoints > 0) @@ -936,7 +936,7 @@ namespace TEN::Entities::Vehicles DoRubberBoatDismount(rBoatItem, laraItem); short probedRoomNumber = GetPointCollision(Vector3i(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y + 128, rBoatItem->Pose.Position.z), rBoatItem->RoomNumber).GetRoomNumber(); - height = GetWaterHeight(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y + 128, rBoatItem->Pose.Position.z, probedRoomNumber); + height = GetPointCollision(Vector3i(rBoatItem->Pose.Position.x, rBoatItem->Pose.Position.y + 128, rBoatItem->Pose.Position.z), probedRoomNumber).GetWaterTopHeight(); if (height > rBoatItem->Pose.Position.y + 32 || height == NO_HEIGHT) height = 0; else @@ -951,7 +951,7 @@ namespace TEN::Entities::Vehicles { TriggerRubberBoatMist(prop.x, prop.y, prop.z, abs(rBoatItem->Animation.Velocity.z), rBoatItem->Pose.Orientation.y + ANGLE(180.0f), 0); - int waterHeight = GetWaterHeight(rBoatItem); + int waterHeight = GetPointCollision(*rBoatItem).GetWaterTopHeight(); SpawnVehicleWake(*rBoatItem, RBOAT_WAKE_OFFSET, waterHeight); if ((GetRandomControl() & 1) == 0) diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index 2a5928033..dceac3961 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -731,8 +731,9 @@ namespace TEN::Entities::Vehicles UPV->Flags &= ~UPV_FLAG_CONTROL; int waterDepth, waterHeight, heightFromWater; - waterDepth = GetWaterSurface(laraItem); - waterHeight = GetWaterHeight(laraItem); + auto pointColl = GetPointCollision(*laraItem); + waterDepth = pointColl.GetWaterSurfaceHeight(); + waterHeight = pointColl.GetWaterTopHeight(); if (waterHeight != NO_HEIGHT) heightFromWater = laraItem->Pose.Position.y - waterHeight; @@ -871,8 +872,9 @@ namespace TEN::Entities::Vehicles TranslateItem(UPVItem, UPVItem->Pose.Orientation, UPVItem->Animation.Velocity.z); } - int newHeight = GetPointCollision(*UPVItem).GetFloorHeight(); - int waterHeight = GetWaterHeight(UPVItem); + auto pointColl = GetPointCollision(*UPVItem); + int newHeight = pointColl.GetFloorHeight(); + int waterHeight = pointColl.GetWaterTopHeight(); if ((newHeight - waterHeight) < UPV_HEIGHT || (newHeight < UPVItem->Pose.Position.y - UPV_HEIGHT / 2) || (newHeight == NO_HEIGHT) || (waterHeight == NO_HEIGHT)) @@ -943,7 +945,7 @@ namespace TEN::Entities::Vehicles if (UPV->Velocity || IsDirectionalActionHeld()) { - waterHeight = GetWaterHeight(UPVItem); + waterHeight = GetPointCollision(*UPVItem).GetWaterTopHeight(); SpawnVehicleWake(*UPVItem, UPV_WAKE_OFFSET, waterHeight, true); } diff --git a/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp b/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp index 22b35629a..8f3013e92 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_crocodile.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/effects/effects.h" @@ -15,6 +16,7 @@ #include "Math/Math.h" #include "Specific/level.h" +using namespace TEN::Collision::Point; using namespace TEN::Math; namespace TEN::Entities::TR4 @@ -90,7 +92,7 @@ namespace TEN::Entities::TR4 { auto* creature = GetCreatureInfo(item); - int waterDepth = GetWaterSurface(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber); + int waterDepth = GetPointCollision(*item).GetWaterSurfaceHeight(); if (waterDepth != NO_HEIGHT) { creature->LOT.Step = BLOCK(20); diff --git a/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp b/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp index dcb5e844d..e95d695c4 100644 --- a/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_bodypart.cpp @@ -209,7 +209,7 @@ void ControlBodyPart(short fxNumber) if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointColl.GetRoomNumber()) && !TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, fx->roomNumber)) { - int waterHeight = GetWaterHeight(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, pointColl.GetRoomNumber()); + int waterHeight = GetPointCollision(fx->pos.Position, pointColl.GetRoomNumber()).GetWaterTopHeight(); SplashSetup.y = waterHeight - 1; SplashSetup.x = fx->pos.Position.x; diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index 5b46ad3b0..f7e3b7211 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -259,23 +259,22 @@ void RollingBallControl(short itemNumber) } } - auto roomNumber = GetPointCollision(*item).GetRoomNumber(); - - if (item->RoomNumber != roomNumber) + auto pointColl = GetPointCollision(*item); + if (item->RoomNumber != pointColl.GetRoomNumber()) { - if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, roomNumber) && + if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, pointColl.GetRoomNumber()) && !TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item->RoomNumber)) { - int waterHeight = GetWaterHeight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, roomNumber); + int waterHeight = pointColl.GetWaterTopHeight(); SplashSetup.y = waterHeight - 1; SplashSetup.x = item->Pose.Position.x; SplashSetup.z = item->Pose.Position.z; SplashSetup.splashPower = item->Animation.Velocity.y * 4; SplashSetup.innerRadius = 160; - SetupSplash(&SplashSetup, roomNumber); + SetupSplash(&SplashSetup, pointColl.GetRoomNumber()); } - ItemNewRoom(itemNumber, roomNumber); + ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); } if (item->ItemFlags[0] > ROLLING_BALL_MAX_VELOCITY) diff --git a/TombEngine/Objects/Utils/VehicleHelpers.cpp b/TombEngine/Objects/Utils/VehicleHelpers.cpp index ae9a5b137..d2a121bb7 100644 --- a/TombEngine/Objects/Utils/VehicleHelpers.cpp +++ b/TombEngine/Objects/Utils/VehicleHelpers.cpp @@ -178,7 +178,7 @@ namespace TEN::Entities::Vehicles *pos = Vector3i(point); auto pointColl = GetPointCollision(*pos, vehicleItem->RoomNumber); - int height = GetWaterHeight(pos->x, pos->y, pos->z, pointColl.GetRoomNumber()); + int height = GetPointCollision(Vector3i(pos->x, pos->y, pos->z), pointColl.GetRoomNumber()).GetWaterTopHeight(); if (height == NO_HEIGHT) { @@ -218,7 +218,7 @@ namespace TEN::Entities::Vehicles if (TestEnvironment(ENV_FLAG_WATER, vehicleItem) || TestEnvironment(ENV_FLAG_SWAMP, vehicleItem)) { - auto waterDepth = (float)GetWaterDepth(vehicleItem); + int waterDepth = GetPointCollision(*vehicleItem).GetWaterBottomHeight(); // HACK: Sometimes quadbike test position may end up under non-portal ceiling block. // GetWaterDepth returns DEEP_WATER constant in that case, which is too large for our needs. @@ -239,11 +239,8 @@ namespace TEN::Entities::Vehicles if (isWater) { - int waterHeight = GetWaterHeight(vehicleItem); + int waterHeight = GetPointCollision(*vehicleItem).GetWaterTopHeight(); SpawnVehicleWake(*vehicleItem, wakeOffset, waterHeight); - - //SpawnStreamer(vehicleItem, -wakeOffset.x, waterHeight / 2, wakeOffset.z, 1, true, 5.0f, 50, 9.0f); - //SpawnStreamer(vehicleItem, wakeOffset.x, waterHeight / 2, wakeOffset.z, 2, true, 5.0f, 50, 9.0f); } } @@ -255,7 +252,7 @@ namespace TEN::Entities::Vehicles } else { - int waterHeight = vehicleItem->Pose.Position.y - GetWaterHeight(vehicleItem); + int waterHeight = vehicleItem->Pose.Position.y - GetPointCollision(*vehicleItem).GetWaterTopHeight(); if (waterDepth > VEHICLE_WATER_HEIGHT_MAX && waterHeight > VEHICLE_WATER_HEIGHT_MAX) { From 349d7e5cdd2e4ede8830f76c05135956f2c5858d Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:15:46 +0200 Subject: [PATCH 268/410] Fixed hair again (for good this time) --- TombEngine/Game/effects/hair.cpp | 52 +++++----- TombEngine/Game/effects/hair.h | 2 +- TombEngine/Objects/TR3/Object/corpse.cpp | 2 +- TombEngine/Objects/game_object_ids.h | 1 + TombEngine/Renderer/RendererCompatibility.cpp | 94 ++++++++++++++++--- TombEngine/Renderer/RendererLara.cpp | 38 ++++++-- .../Internal/TEN/Objects/ObjectIDs.h | 1 + 7 files changed, 148 insertions(+), 42 deletions(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 86262876f..77f9d60dc 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -23,7 +23,7 @@ namespace TEN::Effects::Hair { HairEffectController HairEffect = {}; - void HairUnit::Update(const ItemInfo& item, int hairUnitIndex) + void HairUnit::Update(const ItemInfo& item, GAME_OBJECT_ID objectNumber, int hairUnitIndex) { const auto& player = GetLaraInfo(item); @@ -53,7 +53,7 @@ namespace TEN::Effects::Hair auto& nextSegment = Segments[i + 1]; // NOTE: Joint offset determines segment length. - auto jointOffset = GetJointOffset(ID_HAIR, i); + auto jointOffset = GetJointOffset(objectNumber, i); worldMatrix = Matrix::CreateTranslation(segment.Position); worldMatrix = Matrix::CreateFromQuaternion(segment.Orientation) * worldMatrix; @@ -98,8 +98,8 @@ namespace TEN::Effects::Hair segment.WorldMatrix = worldMatrix; auto jointOffset = (i == (Segments.size() - 1)) ? - GetJointOffset(ID_HAIR, (i - 1) - 1) : - GetJointOffset(ID_HAIR, (i - 1)); + GetJointOffset(objectNumber, (i - 1) - 1) : + GetJointOffset(objectNumber, (i - 1)); worldMatrix = Matrix::CreateTranslation(jointOffset) * worldMatrix; segment.Position = worldMatrix.Translation(); @@ -320,30 +320,38 @@ namespace TEN::Effects::Hair bool isYoung = (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); // Initialize hair units. - bool isHead = true; - for (auto& unit : Units) + auto& unit0 = Units[0]; + unit0.IsEnabled = Objects[ID_HAIR].loaded; + unit0.IsInitialized = false; + unit0.Segments.resize(Objects[ID_HAIR].nmeshes + 1); + // Initialize segments. + for (auto& segment : unit0.Segments) { - unit.IsEnabled = (!isHead || isYoung); - unit.IsInitialized = false; - - unsigned int segmentCount = Objects[ID_HAIR].nmeshes + 1; - unit.Segments.resize(segmentCount); + segment.Position = GetJointOffset(ID_HAIR, 0); + segment.Velocity = Vector3::Zero; + segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); + } - // Initialize segments. - for (auto& segment : unit.Segments) - { - segment.Position = GetJointOffset(ID_HAIR, 0); - segment.Velocity = Vector3::Zero; - segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); - } - - isHead = false; + auto& unit1 = Units[1]; + unit1.IsEnabled = Objects[ID_HAIR_2].loaded && isYoung; + unit1.IsInitialized = false; + unit1.Segments.resize(Objects[ID_HAIR_2].nmeshes + 1); + // Initialize segments. + for (auto& segment : unit1.Segments) + { + segment.Position = GetJointOffset(ID_HAIR_2, 0); + segment.Velocity = Vector3::Zero; + segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); } } void HairEffectController::Update(ItemInfo& item) { - for (int i = 0; i < Units.size(); i++) - Units[i].Update(item, i); + auto& unit0 = Units[0]; + if (unit0.IsEnabled) + unit0.Update(item, ID_HAIR, 0); + auto& unit1 = Units[1]; + if (unit1.IsEnabled) + unit1.Update(item, ID_HAIR_2, 1); } } diff --git a/TombEngine/Game/effects/hair.h b/TombEngine/Game/effects/hair.h index be4baa049..6ae1bc9e7 100644 --- a/TombEngine/Game/effects/hair.h +++ b/TombEngine/Game/effects/hair.h @@ -28,7 +28,7 @@ namespace TEN::Effects::Hair // Utilities - void Update(const ItemInfo& item, int hairUnitIndex); + void Update(const ItemInfo& item, GAME_OBJECT_ID objectNumber, int hairUnitIndex); private: // Helpers diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp index 295792a8a..d27b409ec 100644 --- a/TombEngine/Objects/TR3/Object/corpse.cpp +++ b/TombEngine/Objects/TR3/Object/corpse.cpp @@ -94,7 +94,7 @@ namespace TEN::Entities::TR3 ItemNewRoom(itemNumber, pointColl.GetRoomNumber()); } - auto pointColl = GetPointCollision(item); + pointColl = GetPointCollision(item); item.Animation.IsAirborne = true; if (pointColl.GetFloorHeight() < item.Pose.Position.y) diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index 21132980f..19aa5bd8f 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -41,6 +41,7 @@ enum GAME_OBJECT_ID : short ID_LARA_CROWBAR_ANIM, ID_LARA_TORCH_ANIM, ID_HAIR, + ID_HAIR_2, ID_SNOWMOBILE_LARA_ANIMS = 50, ID_SNOWMOBILE, diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp index 9a0b17e5e..a4cca9f9c 100644 --- a/TombEngine/Renderer/RendererCompatibility.cpp +++ b/TombEngine/Renderer/RendererCompatibility.cpp @@ -516,7 +516,7 @@ namespace TEN::Renderer &moveable, &g_Level.Meshes[obj->meshIndex + j], j, MoveablesIds[i] == ID_LARA_SKIN_JOINTS, - MoveablesIds[i] == ID_HAIR, &lastVertex, &lastIndex); + MoveablesIds[i] == ID_HAIR || MoveablesIds[i] == ID_HAIR_2, &lastVertex, &lastIndex); moveable.ObjectMeshes.push_back(mesh); _meshes.push_back(mesh); @@ -709,7 +709,6 @@ namespace TEN::Renderer // HACK: Hardcoded hair base parent vertices. int parentVertices0[] = { 37, 39, 40, 38 }; // Single braid. int parentVertices1[] = { 79, 78, 76, 77 }; // Left pigtail. - int parentVertices2[] = { 68, 69, 70, 71 }; // Right pigtail. auto& skinObj = GetRendererObject(GAME_OBJECT_ID::ID_LARA_SKIN); auto* parentMesh = skinObj.ObjectMeshes[LM_HEAD]; @@ -724,8 +723,6 @@ namespace TEN::Renderer for (int v2 = 0; v2 < parentBucket->NumVertices; v2++) { auto* parentVertex = &_moveablesVertices[parentBucket->StartVertex + v2]; - - // TODO if (isYoung) { if (parentVertex->OriginalIndex == parentVertices1[currentVertex->OriginalIndex]) @@ -735,14 +732,11 @@ namespace TEN::Renderer currentVertex->Normal = parentVertex->Normal; } } - else + else if (parentVertex->OriginalIndex == parentVertices0[currentVertex->OriginalIndex]) { - if (parentVertex->OriginalIndex == parentVertices0[currentVertex->OriginalIndex]) - { - currentVertex->Bone = 0; - currentVertex->Position = parentVertex->Position; - currentVertex->Normal = parentVertex->Normal; - } + currentVertex->Bone = 0; + currentVertex->Position = parentVertex->Position; + currentVertex->Normal = parentVertex->Normal; } } } @@ -754,6 +748,84 @@ namespace TEN::Renderer auto* parentMesh = moveable.ObjectMeshes[j - 1]; auto* parentBone = moveable.LinearizedBones[j - 1]; + for (int b2 = 0; b2 < parentMesh->Buckets.size(); b2++) + { + auto* parentBucket = &parentMesh->Buckets[b2]; + for (int v2 = 0; v2 < parentBucket->NumVertices; v2++) + { + auto* parentVertex = &_moveablesVertices[parentBucket->StartVertex + v2]; + + int x1 = _moveablesVertices[currentBucket.StartVertex + v1].Position.x + currentBone->GlobalTranslation.x; + int y1 = _moveablesVertices[currentBucket.StartVertex + v1].Position.y + currentBone->GlobalTranslation.y; + int z1 = _moveablesVertices[currentBucket.StartVertex + v1].Position.z + currentBone->GlobalTranslation.z; + + int x2 = _moveablesVertices[parentBucket->StartVertex + v2].Position.x + parentBone->GlobalTranslation.x; + int y2 = _moveablesVertices[parentBucket->StartVertex + v2].Position.y + parentBone->GlobalTranslation.y; + int z2 = _moveablesVertices[parentBucket->StartVertex + v2].Position.z + parentBone->GlobalTranslation.z; + + if (abs(x1 - x2) < 2 && abs(y1 - y2) < 2 && abs(z1 - z2) < 2) + { + currentVertex->Bone = j; + currentVertex->Position = parentVertex->Position; + currentVertex->Normal = parentVertex->Normal; + currentVertex->AnimationFrameOffset = parentVertex->AnimationFrameOffset; + currentVertex->Tangent = parentVertex->Tangent; + break; + } + } + } + } + } + } + } + } + else if (MoveablesIds[i] == ID_HAIR_2 && isSkinPresent) + { + for (int j = 0; j < obj->nmeshes; j++) + { + auto* currentMesh = moveable.ObjectMeshes[j]; + auto* currentBone = moveable.LinearizedBones[j]; + + for (const auto& currentBucket : currentMesh->Buckets) + { + for (int v1 = 0; v1 < currentBucket.NumVertices; v1++) + { + auto* currentVertex = &_moveablesVertices[currentBucket.StartVertex + v1]; + currentVertex->Bone = j + 1; + + // Link mesh 0 to head. + if (j == 0) + { + bool isYoung = (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); + + // HACK: Hardcoded hair base parent vertices. + int parentVertices2[] = { 68, 69, 70, 71 }; // Right pigtail. + + auto& skinObj = GetRendererObject(GAME_OBJECT_ID::ID_LARA_SKIN); + auto* parentMesh = skinObj.ObjectMeshes[LM_HEAD]; + auto* parentBone = skinObj.LinearizedBones[LM_HEAD]; + + for (int b2 = 0; b2 < parentMesh->Buckets.size(); b2++) + { + auto* parentBucket = &parentMesh->Buckets[b2]; + for (int v2 = 0; v2 < parentBucket->NumVertices; v2++) + { + auto* parentVertex = &_moveablesVertices[parentBucket->StartVertex + v2]; + if (isYoung && parentVertex->OriginalIndex == parentVertices2[currentVertex->OriginalIndex]) + { + currentVertex->Bone = 0; + currentVertex->Position = parentVertex->Position; + currentVertex->Normal = parentVertex->Normal; + } + } + } + } + // Link meshes > 0 to parent meshes. + else + { + auto* parentMesh = moveable.ObjectMeshes[j - 1]; + auto* parentBone = moveable.LinearizedBones[j - 1]; + for (int b2 = 0; b2 < parentMesh->Buckets.size(); b2++) { auto* parentBucket = &parentMesh->Buckets[b2]; diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index 80bddf428..d02e3dcce 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -332,20 +332,17 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render return; const auto& hairObject = *_moveableObjects[ID_HAIR]; - - for (const auto& unit : HairEffect.Units) + const auto& unit = HairEffect.Units[0]; + if (unit.IsEnabled) { - if (!unit.IsEnabled) - continue; - // First matrix is Lara's head matrix, then all hair unit segment matrices. // Bones are adjusted at load time to account for this. _stItem.World = Matrix::Identity; _stItem.BonesMatrices[0] = itemToDraw->AnimationTransforms[LM_HEAD] * _laraWorldMatrix; - for (int i = 0; i < unit.Segments.size(); i++) + for (int i = 1; i < unit.Segments.size(); i++) { - _stItem.BonesMatrices[i + 1] = unit.Segments[i].WorldMatrix; + _stItem.BonesMatrices[i] = unit.Segments[i].WorldMatrix; _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; } @@ -357,6 +354,33 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render DrawMoveableMesh(itemToDraw, &rMesh, room, i, view, rendererPass); } } + + if (!Objects[ID_HAIR_2].loaded) + return; + + const auto& hair2Object = *_moveableObjects[ID_HAIR_2]; + const auto& unit2 = HairEffect.Units[1]; + if (unit2.IsEnabled) + { + // First matrix is Lara's head matrix, then all hair unit segment matrices. + // Bones are adjusted at load time to account for this. + _stItem.World = Matrix::Identity; + _stItem.BonesMatrices[0] = itemToDraw->AnimationTransforms[LM_HEAD] * _laraWorldMatrix; + + for (int i = 1; i < unit2.Segments.size(); i++) + { + _stItem.BonesMatrices[i] = unit2.Segments[i].WorldMatrix; + _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; + } + + _cbItem.UpdateData(_stItem, _context.Get()); + + for (int i = 0; i < hair2Object.ObjectMeshes.size(); i++) + { + auto& rMesh = *hair2Object.ObjectMeshes[i]; + DrawMoveableMesh(itemToDraw, &rMesh, room, i, view, rendererPass); + } + } } void Renderer::DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass) diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index 6a9209f5d..46c526051 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -1231,6 +1231,7 @@ static const std::unordered_map kObjIDs { { "LARA_CROWBAR_ANIM", ID_LARA_CROWBAR_ANIM }, { "LARA_TORCH_ANIM", ID_LARA_TORCH_ANIM }, { "HAIR", ID_HAIR }, + { "HAIR_2", ID_HAIR_2 }, { "SNOWMOBILE_LARA_ANIMS", ID_SNOWMOBILE_LARA_ANIMS }, { "SNOWMOBILE", ID_SNOWMOBILE }, { "QUAD_LARA_ANIMS", ID_QUAD_LARA_ANIMS }, From e4b3124a68c95d05f1d2c65e6cef277612f048a6 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Fri, 16 Aug 2024 00:09:13 +0100 Subject: [PATCH 269/410] Rename hair objects to distinguish between the two ID_HAIR -> SINGLE_BRAID_HAIR ID_HAIR2 -> DUAL_PIGTAIL_HAIR --- Documentation/doc/4 enums/Objects.ObjID.html | 3 ++- TombEngine/Game/effects/hair.cpp | 16 ++++++++-------- TombEngine/Objects/game_object_ids.h | 4 ++-- TombEngine/Renderer/RendererCompatibility.cpp | 6 +++--- TombEngine/Renderer/RendererLara.cpp | 8 ++++---- .../Scripting/Internal/TEN/Objects/ObjectIDs.h | 7 ++++--- 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 9068ee709..4328065c5 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -171,7 +171,8 @@ LARA_PETROL_MESH LARA_DIRT_MESH LARA_CROWBAR_ANIM LARA_TORCH_ANIM -HAIR +SINGLE_BRAID_HAIR +DUAL_PIGTAIL_HAIR SNOWMOBILE_LARA_ANIMS SNOWMOBILE QUAD_LARA_ANIMS diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 77f9d60dc..7751c4a03 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -321,25 +321,25 @@ namespace TEN::Effects::Hair // Initialize hair units. auto& unit0 = Units[0]; - unit0.IsEnabled = Objects[ID_HAIR].loaded; + unit0.IsEnabled = Objects[ID_SINGLE_BRAID_HAIR].loaded; unit0.IsInitialized = false; - unit0.Segments.resize(Objects[ID_HAIR].nmeshes + 1); + unit0.Segments.resize(Objects[ID_SINGLE_BRAID_HAIR].nmeshes + 1); // Initialize segments. for (auto& segment : unit0.Segments) { - segment.Position = GetJointOffset(ID_HAIR, 0); + segment.Position = GetJointOffset(ID_SINGLE_BRAID_HAIR, 0); segment.Velocity = Vector3::Zero; segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); } auto& unit1 = Units[1]; - unit1.IsEnabled = Objects[ID_HAIR_2].loaded && isYoung; + unit1.IsEnabled = Objects[ID_DUAL_PIGTAIL_HAIR].loaded && isYoung; unit1.IsInitialized = false; - unit1.Segments.resize(Objects[ID_HAIR_2].nmeshes + 1); + unit1.Segments.resize(Objects[ID_DUAL_PIGTAIL_HAIR].nmeshes + 1); // Initialize segments. for (auto& segment : unit1.Segments) { - segment.Position = GetJointOffset(ID_HAIR_2, 0); + segment.Position = GetJointOffset(ID_DUAL_PIGTAIL_HAIR, 0); segment.Velocity = Vector3::Zero; segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); } @@ -349,9 +349,9 @@ namespace TEN::Effects::Hair { auto& unit0 = Units[0]; if (unit0.IsEnabled) - unit0.Update(item, ID_HAIR, 0); + unit0.Update(item, ID_SINGLE_BRAID_HAIR, 0); auto& unit1 = Units[1]; if (unit1.IsEnabled) - unit1.Update(item, ID_HAIR_2, 1); + unit1.Update(item, ID_DUAL_PIGTAIL_HAIR, 1); } } diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index 19aa5bd8f..f1574ccfa 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -40,8 +40,8 @@ enum GAME_OBJECT_ID : short ID_LARA_DIRT_MESH, ID_LARA_CROWBAR_ANIM, ID_LARA_TORCH_ANIM, - ID_HAIR, - ID_HAIR_2, + ID_SINGLE_BRAID_HAIR, + ID_DUAL_PIGTAIL_HAIR, ID_SNOWMOBILE_LARA_ANIMS = 50, ID_SNOWMOBILE, diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp index a4cca9f9c..292251d69 100644 --- a/TombEngine/Renderer/RendererCompatibility.cpp +++ b/TombEngine/Renderer/RendererCompatibility.cpp @@ -516,7 +516,7 @@ namespace TEN::Renderer &moveable, &g_Level.Meshes[obj->meshIndex + j], j, MoveablesIds[i] == ID_LARA_SKIN_JOINTS, - MoveablesIds[i] == ID_HAIR || MoveablesIds[i] == ID_HAIR_2, &lastVertex, &lastIndex); + MoveablesIds[i] == ID_SINGLE_BRAID_HAIR || MoveablesIds[i] == ID_DUAL_PIGTAIL_HAIR, &lastVertex, &lastIndex); moveable.ObjectMeshes.push_back(mesh); _meshes.push_back(mesh); @@ -687,7 +687,7 @@ namespace TEN::Renderer } } } - else if (MoveablesIds[i] == ID_HAIR && isSkinPresent) + else if (MoveablesIds[i] == ID_SINGLE_BRAID_HAIR && isSkinPresent) { for (int j = 0; j < obj->nmeshes; j++) { @@ -779,7 +779,7 @@ namespace TEN::Renderer } } } - else if (MoveablesIds[i] == ID_HAIR_2 && isSkinPresent) + else if (MoveablesIds[i] == ID_DUAL_PIGTAIL_HAIR && isSkinPresent) { for (int j = 0; j < obj->nmeshes; j++) { diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index d02e3dcce..fca823525 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -328,10 +328,10 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass) { - if (!Objects[ID_HAIR].loaded) + if (!Objects[ID_SINGLE_BRAID_HAIR].loaded) return; - const auto& hairObject = *_moveableObjects[ID_HAIR]; + const auto& hairObject = *_moveableObjects[ID_SINGLE_BRAID_HAIR]; const auto& unit = HairEffect.Units[0]; if (unit.IsEnabled) { @@ -355,10 +355,10 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render } } - if (!Objects[ID_HAIR_2].loaded) + if (!Objects[ID_DUAL_PIGTAIL_HAIR].loaded) return; - const auto& hair2Object = *_moveableObjects[ID_HAIR_2]; + const auto& hair2Object = *_moveableObjects[ID_DUAL_PIGTAIL_HAIR]; const auto& unit2 = HairEffect.Units[1]; if (unit2.IsEnabled) { diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index 46c526051..a9fd40d03 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -53,7 +53,8 @@ The following constants are inside ObjID. LARA_DIRT_MESH LARA_CROWBAR_ANIM LARA_TORCH_ANIM - HAIR + SINGLE_BRAID_HAIR + DUAL_PIGTAIL_HAIR SNOWMOBILE_LARA_ANIMS SNOWMOBILE QUAD_LARA_ANIMS @@ -1230,8 +1231,8 @@ static const std::unordered_map kObjIDs { { "LARA_DIRT_MESH", ID_LARA_DIRT_MESH }, { "LARA_CROWBAR_ANIM", ID_LARA_CROWBAR_ANIM }, { "LARA_TORCH_ANIM", ID_LARA_TORCH_ANIM }, - { "HAIR", ID_HAIR }, - { "HAIR_2", ID_HAIR_2 }, + { "SINGLE_BRAID_HAIR", ID_SINGLE_BRAID_HAIR }, + { "DUAL_PIGTAIL_HAIR", ID_DUAL_PIGTAIL_HAIR }, { "SNOWMOBILE_LARA_ANIMS", ID_SNOWMOBILE_LARA_ANIMS }, { "SNOWMOBILE", ID_SNOWMOBILE }, { "QUAD_LARA_ANIMS", ID_QUAD_LARA_ANIMS }, From 08d74d660891cb85eca208e6b6081bf4b89e8762 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 16 Aug 2024 15:48:36 +1000 Subject: [PATCH 270/410] Fix formatting --- TombEngine/Game/effects/hair.cpp | 69 +++++++++++++--------------- TombEngine/Game/effects/hair.h | 9 ++-- TombEngine/Renderer/RendererLara.cpp | 59 ++++++++---------------- 3 files changed, 58 insertions(+), 79 deletions(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 7751c4a03..d1137b60b 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -23,7 +23,7 @@ namespace TEN::Effects::Hair { HairEffectController HairEffect = {}; - void HairUnit::Update(const ItemInfo& item, GAME_OBJECT_ID objectNumber, int hairUnitIndex) + void HairUnit::Update(const ItemInfo& item, int hairUnitID) { const auto& player = GetLaraInfo(item); @@ -34,15 +34,14 @@ namespace TEN::Effects::Hair g_Renderer.GetBoneMatrix(item.Index, LM_HEAD, &worldMatrix); // Apply base offset to world matrix. - auto relOffset = GetRelBaseOffset(hairUnitIndex, isYoung); + auto relOffset = GetRelBaseOffset(hairUnitID, isYoung); worldMatrix = Matrix::CreateTranslation(relOffset) * worldMatrix; - + // Use player's head bone orientation as base. auto baseOrient = Geometry::ConvertDirectionToQuat(-Geometry::ConvertQuatToDirection(GetBoneOrientation(item, LM_HEAD))); // Set position of base segment. Segments[0].Position = worldMatrix.Translation(); - Segments[0].WorldMatrix = worldMatrix; if (!IsInitialized) { @@ -53,7 +52,7 @@ namespace TEN::Effects::Hair auto& nextSegment = Segments[i + 1]; // NOTE: Joint offset determines segment length. - auto jointOffset = GetJointOffset(objectNumber, i); + auto jointOffset = GetJointOffset(ObjectID, i); worldMatrix = Matrix::CreateTranslation(segment.Position); worldMatrix = Matrix::CreateFromQuaternion(segment.Orientation) * worldMatrix; @@ -95,11 +94,10 @@ namespace TEN::Effects::Hair // Calculate world matrix. worldMatrix = Matrix::CreateTranslation(prevSegment.Position); worldMatrix = Matrix::CreateFromQuaternion(prevSegment.Orientation) * worldMatrix; - segment.WorldMatrix = worldMatrix; auto jointOffset = (i == (Segments.size() - 1)) ? - GetJointOffset(objectNumber, (i - 1) - 1) : - GetJointOffset(objectNumber, (i - 1)); + GetJointOffset(ObjectID, (i - 1) - 1) : + GetJointOffset(ObjectID, (i - 1)); worldMatrix = Matrix::CreateTranslation(jointOffset) * worldMatrix; segment.Position = worldMatrix.Translation(); @@ -108,12 +106,12 @@ namespace TEN::Effects::Hair } } - Vector3 HairUnit::GetRelBaseOffset(int hairUnitIndex, bool isYoung) + Vector3 HairUnit::GetRelBaseOffset(int hairUnitID, bool isYoung) { auto relOffset = Vector3::Zero; if (isYoung) { - switch (hairUnitIndex) + switch (hairUnitID) { // Left pigtail offset. case 0: @@ -320,38 +318,37 @@ namespace TEN::Effects::Hair bool isYoung = (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() == LaraType::Young); // Initialize hair units. - auto& unit0 = Units[0]; - unit0.IsEnabled = Objects[ID_SINGLE_BRAID_HAIR].loaded; - unit0.IsInitialized = false; - unit0.Segments.resize(Objects[ID_SINGLE_BRAID_HAIR].nmeshes + 1); - // Initialize segments. - for (auto& segment : unit0.Segments) + for (int i = 0; i < Units.size(); i++) { - segment.Position = GetJointOffset(ID_SINGLE_BRAID_HAIR, 0); - segment.Velocity = Vector3::Zero; - segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); - } + auto& unit = Units[i]; - auto& unit1 = Units[1]; - unit1.IsEnabled = Objects[ID_DUAL_PIGTAIL_HAIR].loaded && isYoung; - unit1.IsInitialized = false; - unit1.Segments.resize(Objects[ID_DUAL_PIGTAIL_HAIR].nmeshes + 1); - // Initialize segments. - for (auto& segment : unit1.Segments) - { - segment.Position = GetJointOffset(ID_DUAL_PIGTAIL_HAIR, 0); - segment.Velocity = Vector3::Zero; - segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); + auto objectID = (i == 0) ? ID_SINGLE_BRAID_HAIR : ID_DUAL_PIGTAIL_HAIR; + const auto& object = Objects[objectID]; + + unit.IsEnabled = (object.loaded && (i == 0 || (i == 1 && isYoung))); + unit.IsInitialized = false; + unit.ObjectID = objectID; + unit.Segments.resize(object.nmeshes + 1); + + // Initialize segments. + for (auto& segment : unit.Segments) + { + segment.Position = GetJointOffset(objectID, 0); + segment.Velocity = Vector3::Zero; + segment.Orientation = DEFAULT_ORIENT.ToQuaternion(); + } } } void HairEffectController::Update(ItemInfo& item) { - auto& unit0 = Units[0]; - if (unit0.IsEnabled) - unit0.Update(item, ID_SINGLE_BRAID_HAIR, 0); - auto& unit1 = Units[1]; - if (unit1.IsEnabled) - unit1.Update(item, ID_DUAL_PIGTAIL_HAIR, 1); + for (int i = 0; i < Units.size(); i++) + { + auto& unit = Units[i]; + if (!unit.IsEnabled) + continue; + + unit.Update(item, i); + } } } diff --git a/TombEngine/Game/effects/hair.h b/TombEngine/Game/effects/hair.h index 6ae1bc9e7..c0a9a8b4b 100644 --- a/TombEngine/Game/effects/hair.h +++ b/TombEngine/Game/effects/hair.h @@ -1,5 +1,7 @@ #pragma once +#include "Objects/game_object_ids.h" + struct ItemInfo; namespace TEN::Effects::Hair @@ -16,7 +18,6 @@ namespace TEN::Effects::Hair Vector3 Position = Vector3::Zero; Vector3 Velocity = Vector3::Zero; Quaternion Orientation = Quaternion::Identity; - Matrix WorldMatrix = Matrix::Identity; }; public: @@ -24,16 +25,18 @@ namespace TEN::Effects::Hair bool IsEnabled = false; bool IsInitialized = false; + + GAME_OBJECT_ID ObjectID = GAME_OBJECT_ID::ID_NO_OBJECT; std::vector Segments = {}; // Utilities - void Update(const ItemInfo& item, GAME_OBJECT_ID objectNumber, int hairUnitIndex); + void Update(const ItemInfo& item, int hairUnitID); private: // Helpers - Vector3 GetRelBaseOffset(int hairUnitIndex, bool isYoung); + Vector3 GetRelBaseOffset(int hairUnitID, bool isYoung); Vector3 GetWaterProbeOffset(const ItemInfo& item); Quaternion GetSegmentOrientation(const Vector3& origin, const Vector3& target, const Quaternion& baseOrient); std::vector GetSpheres(const ItemInfo& item, bool isYoung); diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index fca823525..5a09c030e 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -328,57 +328,36 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass) { - if (!Objects[ID_SINGLE_BRAID_HAIR].loaded) - return; - - const auto& hairObject = *_moveableObjects[ID_SINGLE_BRAID_HAIR]; - const auto& unit = HairEffect.Units[0]; - if (unit.IsEnabled) + for (int i = 0; i < HairEffect.Units.size(); i++) { - // First matrix is Lara's head matrix, then all hair unit segment matrices. - // Bones are adjusted at load time to account for this. + const auto& unit = HairEffect.Units[i]; + if (!unit.IsEnabled) + continue; + + const auto& object = Objects[unit.ObjectID]; + if (!object.loaded) + continue; + + const auto& rendererObject = *_moveableObjects[unit.ObjectID]; + _stItem.World = Matrix::Identity; _stItem.BonesMatrices[0] = itemToDraw->AnimationTransforms[LM_HEAD] * _laraWorldMatrix; - for (int i = 1; i < unit.Segments.size(); i++) + for (int i = 0; i < unit.Segments.size(); i++) { - _stItem.BonesMatrices[i] = unit.Segments[i].WorldMatrix; + const auto& segment = unit.Segments[i]; + auto worldMatrix = Matrix::CreateFromQuaternion(segment.Orientation) * Matrix::CreateTranslation(segment.Position); + + _stItem.BonesMatrices[i + 1] = worldMatrix; _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; } _cbItem.UpdateData(_stItem, _context.Get()); - for (int i = 0; i < hairObject.ObjectMeshes.size(); i++) + for (int i = 0; i < rendererObject.ObjectMeshes.size(); i++) { - auto& rMesh = *hairObject.ObjectMeshes[i]; - DrawMoveableMesh(itemToDraw, &rMesh, room, i, view, rendererPass); - } - } - - if (!Objects[ID_DUAL_PIGTAIL_HAIR].loaded) - return; - - const auto& hair2Object = *_moveableObjects[ID_DUAL_PIGTAIL_HAIR]; - const auto& unit2 = HairEffect.Units[1]; - if (unit2.IsEnabled) - { - // First matrix is Lara's head matrix, then all hair unit segment matrices. - // Bones are adjusted at load time to account for this. - _stItem.World = Matrix::Identity; - _stItem.BonesMatrices[0] = itemToDraw->AnimationTransforms[LM_HEAD] * _laraWorldMatrix; - - for (int i = 1; i < unit2.Segments.size(); i++) - { - _stItem.BonesMatrices[i] = unit2.Segments[i].WorldMatrix; - _stItem.BoneLightModes[i] = (int)LightMode::Dynamic; - } - - _cbItem.UpdateData(_stItem, _context.Get()); - - for (int i = 0; i < hair2Object.ObjectMeshes.size(); i++) - { - auto& rMesh = *hair2Object.ObjectMeshes[i]; - DrawMoveableMesh(itemToDraw, &rMesh, room, i, view, rendererPass); + auto& rendererMesh = *rendererObject.ObjectMeshes[i]; + DrawMoveableMesh(itemToDraw, &rendererMesh, room, i, view, rendererPass); } } } From d8aced8ab4f1cc000f95416eeee0e71e2c0fb362 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Fri, 16 Aug 2024 10:05:01 +0200 Subject: [PATCH 271/410] Fixed exploding body parts --- TombEngine/Game/control/control.cpp | 2 ++ TombEngine/Renderer/RendererFrame.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 329b8f6be..e8b158e41 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -669,7 +669,9 @@ void EndGameLoop(int levelIndex, GameStatus reason) void SetupInterpolation() { for (int i = 0; i < g_Level.Items.size(); i++) + { g_Level.Items[i].DisableInterpolation = false; + } } void HandleControls(bool isTitle) diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 8014cb3e2..d4ad5c1b6 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -927,6 +927,15 @@ namespace TEN::Renderer for (int j = 0; j < MAX_BONES; j++) _items[i].OldAnimationTransforms[j] = _items[i].AnimationTransforms[j]; } + + for (int i = 0; i < ITEM_COUNT_MAX; i++) + { + _effects[i].OldPosition = _effects[i].Position; + _effects[i].OldWorld = _effects[i].World; + _effects[i].OldTranslation = _effects[i].Translation; + _effects[i].OldRotation = _effects[i].Rotation; + _effects[i].OldScale = _effects[i].Scale; + } } } // namespace TEN::Renderer From 7bc21f7d3a94c865bc7752c746f6e1cbaf8fe1c6 Mon Sep 17 00:00:00 2001 From: Sezz Date: Fri, 16 Aug 2024 19:05:52 +1000 Subject: [PATCH 272/410] Fix formatting --- TombEngine/Game/control/control.cpp | 2 - TombEngine/Game/effects/effects.h | 64 +++-- TombEngine/Renderer/RendererDraw.cpp | 28 +- TombEngine/Renderer/RendererDrawEffect.cpp | 20 +- TombEngine/Renderer/RendererFrame.cpp | 245 +++++++----------- TombEngine/Renderer/RendererHelper.cpp | 12 +- TombEngine/Renderer/RendererLara.cpp | 8 +- .../Renderer/Structures/RendererEffect.h | 50 ++-- TombEngine/Renderer/Structures/RendererItem.h | 63 +++-- 9 files changed, 216 insertions(+), 276 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index c29255508..83be16663 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -671,9 +671,7 @@ void EndGameLoop(int levelIndex, GameStatus reason) void SetupInterpolation() { for (int i = 0; i < g_Level.Items.size(); i++) - { g_Level.Items[i].DisableInterpolation = false; - } } void HandleControls(bool isTitle) diff --git a/TombEngine/Game/effects/effects.h b/TombEngine/Game/effects/effects.h index 5bd7ee50f..717b08c14 100644 --- a/TombEngine/Game/effects/effects.h +++ b/TombEngine/Game/effects/effects.h @@ -152,25 +152,25 @@ struct Particle int roomNumber; unsigned char nodeNumber; // ParticleNodeOffsetIDs enum. - int oldX; - int oldY; - int oldZ; - short oldRotAng; - byte oldR; - byte oldG; - byte oldB; - byte oldScalar; + int PrevX; + int PrevY; + int PrevZ; + short PrevRotAng; + byte PrevR; + byte PrevG; + byte PrevB; + byte PrevScalar; void StoreInterpolationData() { - oldX = x; - oldY = y; - oldZ = z; - oldRotAng = rotAng; - oldR = r; - oldG = g; - oldB = b; - oldScalar = scalar; + PrevX = x; + PrevY = y; + PrevZ = z; + PrevRotAng = rotAng; + PrevR = r; + PrevG = g; + PrevB = b; + PrevScalar = scalar; } }; @@ -194,27 +194,23 @@ struct SPLASH_STRUCT bool isRipple; bool isActive; - float oldX; - float oldY; - float oldZ; - float oldInnerRad; - float oldOuterRad; - float oldHeight; - unsigned short oldLife; - float oldHeightSpeed; - float oldAnimationPhase; + Vector3 PrevPosition = Vector3::Zero; + float PrevInnerRad = 0.0f; + float PrevOuterRad = 0.0f; + float PrevHeight = 0.0f; + float PrevHeightSpeed = 0.0f; + float PrevAnimPhase = 0.0f; + unsigned short PrevLife = 0; void StoreInterpolationData() { - oldX = x; - oldY = y; - oldZ = z; - oldInnerRad = innerRad; - oldOuterRad = outerRad; - oldHeight = height; - oldLife = life; - oldHeightSpeed = heightSpeed; - oldAnimationPhase = animationPhase; + PrevPosition = Vector3(x, y, z); + PrevInnerRad = innerRad; + PrevOuterRad = outerRad; + PrevHeight = height; + PrevHeightSpeed = heightSpeed; + PrevAnimPhase = animationPhase; + PrevLife = life; } }; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 3ff2b7d28..1c27cca62 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -130,11 +130,11 @@ namespace TEN::Renderer void Renderer::RenderShadowMap(RendererItem* item, RenderView& renderView) { // Doesn't cast shadow - if (_moveableObjects[item->ObjectNumber].value().ShadowType == ShadowMode::None) + if (_moveableObjects[item->ObjectID].value().ShadowType == ShadowMode::None) return; // Only render for Lara if such setting is active - if (g_Configuration.ShadowType == ShadowMode::Lara && _moveableObjects[item->ObjectNumber].value().ShadowType != ShadowMode::Lara) + if (g_Configuration.ShadowType == ShadowMode::Lara && _moveableObjects[item->ObjectID].value().ShadowType != ShadowMode::Lara) return; // No shadow light found @@ -210,12 +210,12 @@ namespace TEN::Renderer SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD); - RendererObject& obj = GetRendererObject((GAME_OBJECT_ID)item->ObjectNumber); + RendererObject& obj = GetRendererObject((GAME_OBJECT_ID)item->ObjectID); _stItem.World = item->InterpolatedWorld; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; - memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); + memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, sizeof(Matrix) * MAX_BONES); for (int k = 0; k < MAX_BONES; k++) _stItem.BoneLightModes[k] = (int)LightMode::Static; @@ -225,7 +225,7 @@ namespace TEN::Renderer for (int k = 0; k < obj.ObjectMeshes.size(); k++) { - auto* mesh = GetMesh(item->MeshIndex[k]); + auto* mesh = GetMesh(item->MeshIds[k]); for (auto& bucket : mesh->Buckets) { @@ -242,7 +242,7 @@ namespace TEN::Renderer } } - if (item->ObjectNumber == ID_LARA) + if (item->ObjectID == ID_LARA) { RendererRoom& room = _rooms[item->RoomNumber]; @@ -2200,7 +2200,7 @@ namespace TEN::Renderer { for (auto itemToDraw : room->ItemsToDraw) { - switch (itemToDraw->ObjectNumber) + switch (itemToDraw->ObjectID) { case ID_LARA: DrawLara(view, rendererPass); @@ -2242,7 +2242,7 @@ namespace TEN::Renderer // Extremely hacky function to get first rendered face of a waterfall object mesh, calculate // its texture height and scroll all the textures according to that height. - RendererObject& moveableObj = *_moveableObjects[item->ObjectNumber]; + RendererObject& moveableObj = *_moveableObjects[item->ObjectID]; // No mesh or bucket, abort if (!moveableObj.ObjectMeshes.size() || !moveableObj.ObjectMeshes[0]->Buckets.size()) @@ -2284,13 +2284,13 @@ namespace TEN::Renderer { ItemInfo* nativeItem = &g_Level.Items[item->ItemNumber]; RendererRoom* room = &_rooms[item->RoomNumber]; - RendererObject& moveableObj = *_moveableObjects[item->ObjectNumber]; + RendererObject& moveableObj = *_moveableObjects[item->ObjectID]; // Bind item main properties _stItem.World = item->InterpolatedWorld; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; - memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); + memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, sizeof(Matrix) * MAX_BONES); for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) _stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode; @@ -2303,7 +2303,7 @@ namespace TEN::Renderer if (!(nativeItem->MeshBits & (1 << k))) continue; - DrawMoveableMesh(item, GetMesh(item->MeshIndex[k]), room, k, view, rendererPass); + DrawMoveableMesh(item, GetMesh(item->MeshIds[k]), room, k, view, rendererPass); } } @@ -3079,7 +3079,7 @@ namespace TEN::Renderer for (int p = 0; p < bucket.Polygons.size(); p++) { auto centre = Vector3::Transform( - bucket.Polygons[p].Centre, itemToDraw->InterpolatedAnimationTransforms[boneIndex] * itemToDraw->InterpolatedWorld); + bucket.Polygons[p].Centre, itemToDraw->InterpolatedAnimTransforms[boneIndex] * itemToDraw->InterpolatedWorld); int distance = (centre - cameraPos).Length(); RendererSortableObject object; @@ -3521,9 +3521,9 @@ namespace TEN::Renderer _stItem.World = objectInfo->Item->InterpolatedWorld; _stItem.Color = objectInfo->Item->Color; _stItem.AmbientLight = objectInfo->Item->AmbientLight; - memcpy(_stItem.BonesMatrices, objectInfo->Item->InterpolatedAnimationTransforms, sizeof(Matrix) * MAX_BONES); + memcpy(_stItem.BonesMatrices, objectInfo->Item->InterpolatedAnimTransforms, sizeof(Matrix) * MAX_BONES); - const auto& moveableObj = *_moveableObjects[objectInfo->Item->ObjectNumber]; + const auto& moveableObj = *_moveableObjects[objectInfo->Item->ObjectID]; for (int k = 0; k < moveableObj.ObjectMeshes.size(); k++) _stItem.BoneLightModes[k] = (int)moveableObj.ObjectMeshes[k]->LightMode; diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 0afce3e3e..d717597ba 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -535,13 +535,13 @@ namespace TEN::Renderer } } - byte prevColor = (splash.oldLife >= 32 ? 128 : (byte)((splash.oldLife / 32.0f) * 128)); + byte prevColor = (splash.PrevLife >= 32 ? 128 : (byte)((splash.PrevLife / 32.0f) * 128)); if (!splash.isRipple) { - if (splash.oldHeightSpeed < 0 && splash.oldHeight < 1024) + if (splash.PrevHeightSpeed < 0 && splash.PrevHeight < 1024) { - float multiplier = splash.oldHeight / 1024.0f; + float multiplier = splash.PrevHeight / 1024.0f; prevColor = (float)prevColor * multiplier; } } @@ -559,8 +559,8 @@ namespace TEN::Renderer float yInner = splash.y; float yOuter = splash.y - splash.height; - float innerRadius = Lerp(splash.oldInnerRad, splash.innerRad, _interpolationFactor); - float outerRadius = Lerp(splash.oldOuterRad, splash.outerRad, _interpolationFactor); + float innerRadius = Lerp(splash.PrevInnerRad, splash.innerRad, _interpolationFactor); + float outerRadius = Lerp(splash.PrevOuterRad, splash.outerRad, _interpolationFactor); for (int i = 0; i < NUM_POINTS; i++) { @@ -1081,7 +1081,7 @@ namespace TEN::Renderer auto worldMatrix = Matrix::Identity; if (Lara.LeftArm.GunFlash) { - worldMatrix = itemPtr->AnimationTransforms[LM_LHAND] * itemPtr->World; + worldMatrix = itemPtr->AnimTransforms[LM_LHAND] * itemPtr->World; worldMatrix = tMatrix * worldMatrix; worldMatrix = rotMatrix * worldMatrix; @@ -1095,7 +1095,7 @@ namespace TEN::Renderer if (Lara.RightArm.GunFlash) { - worldMatrix = itemPtr->AnimationTransforms[LM_RHAND] * itemPtr->World; + worldMatrix = itemPtr->AnimTransforms[LM_RHAND] * itemPtr->World; worldMatrix = tMatrix * worldMatrix; worldMatrix = rotMatrix * worldMatrix; @@ -1166,7 +1166,7 @@ namespace TEN::Renderer auto rotMatrixX = Matrix::CreateRotationX(TO_RAD(ANGLE(270.0f))); auto rotMatrixZ = Matrix::CreateRotationZ(TO_RAD(2 * GetRandomControl())); - auto worldMatrix = rItemPtr->AnimationTransforms[creature.MuzzleFlash[0].Bite.BoneID] * rItemPtr->World; + auto worldMatrix = rItemPtr->AnimTransforms[creature.MuzzleFlash[0].Bite.BoneID] * rItemPtr->World; worldMatrix = tMatrix * worldMatrix; if (creature.MuzzleFlash[0].ApplyXRotation) @@ -1206,7 +1206,7 @@ namespace TEN::Renderer auto rotMatrixX = Matrix::CreateRotationX(TO_RAD(ANGLE(270.0f))); auto rotMatrixZ = Matrix::CreateRotationZ(TO_RAD(2 * GetRandomControl())); - auto worldMatrix = rItemPtr->AnimationTransforms[creature.MuzzleFlash[1].Bite.BoneID] * rItemPtr->World; + auto worldMatrix = rItemPtr->AnimTransforms[creature.MuzzleFlash[1].Bite.BoneID] * rItemPtr->World; worldMatrix = tMatrix * worldMatrix; if (creature.MuzzleFlash[1].ApplyXRotation) @@ -1339,7 +1339,7 @@ namespace TEN::Renderer for (auto* effectPtr : roomPtr->EffectsToDraw) { const auto& room = _rooms[effectPtr->RoomNumber]; - const auto& object = Objects[effectPtr->ObjectNumber]; + const auto& object = Objects[effectPtr->ObjectID]; if (object.drawRoutine && object.loaded) DrawEffect(view, effectPtr, rendererPass); diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index d4ad5c1b6..bd48fa1d5 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -193,16 +193,14 @@ namespace TEN::Renderer door->Visited = true; if (zClip == 4) - { return false; - } if (zClip > 0) { for (int i = 0; i < 4; i++) { - Vector4 a = p[i]; - Vector4 b = p[(i + 1) % 4]; + auto a = p[i]; + auto b = p[(i + 1) % 4]; if ((a.w > 0.0f) ^ (b.w > 0.0f)) { @@ -244,7 +242,10 @@ namespace TEN::Renderer } } - if (clipPort->x > viewPort.z || clipPort->y > viewPort.w || clipPort->z < viewPort.x || clipPort->w < viewPort.y) + if (clipPort->x > viewPort.z || + clipPort->y > viewPort.w || + clipPort->z < viewPort.x || + clipPort->w < viewPort.y) { return false; } @@ -270,7 +271,7 @@ namespace TEN::Renderer { if (_visitedRoomsStack[i] == to) { - TENLog("Circle detected! Room " + std::to_string(to), LogLevel::Warning, LogConfig::Debug); + TENLog("Circle detected in room " + std::to_string(to), LogLevel::Warning, LogConfig::Debug); return; } } @@ -278,8 +279,9 @@ namespace TEN::Renderer static constexpr int MAX_SEARCH_DEPTH = 64; if (_rooms[to].Visited && count > MAX_SEARCH_DEPTH) { - TENLog("Maximum room collection depth of " + std::to_string(MAX_SEARCH_DEPTH) + - " was reached with room " + std::to_string(to), LogLevel::Warning, LogConfig::Debug); + TENLog( + "Maximum room collection depth of " + std::to_string(MAX_SEARCH_DEPTH) + " was reached with room " + std::to_string(to), + LogLevel::Warning, LogConfig::Debug); return; } @@ -287,7 +289,7 @@ namespace TEN::Renderer _numGetVisibleRoomsCalls++; - RendererRoom* room = &_rooms[to]; + auto* room = &_rooms[to]; if (!room->Visited) { @@ -313,12 +315,10 @@ namespace TEN::Renderer Vector4 clipPort; for (int i = 0; i < room->Doors.size(); i++) { - RendererDoor* door = &room->Doors[i]; + auto* door = &room->Doors[i]; if (door->InvisibleFromCamera) - { continue; - } if (!door->Visited) { @@ -357,49 +357,35 @@ namespace TEN::Renderer void Renderer::CollectItems(short roomNumber, RenderView& renderView) { if (_rooms.size() < roomNumber) - { return; - } - RendererRoom& room = _rooms[roomNumber]; - ROOM_INFO* r = &g_Level.Rooms[room.RoomNumber]; + auto& room = _rooms[roomNumber]; + auto* r = &g_Level.Rooms[room.RoomNumber]; short itemNum = NO_VALUE; for (itemNum = r->itemNumber; itemNum != NO_VALUE; itemNum = g_Level.Items[itemNum].NextItem) { - ItemInfo* item = &g_Level.Items[itemNum]; + auto* item = &g_Level.Items[itemNum]; if (item->ObjectNumber == ID_LARA && itemNum == g_Level.Items[itemNum].NextItem) - { break; - } if (item->Status == ITEM_INVISIBLE) - { continue; - } if (item->ObjectNumber == ID_LARA && (Lara.Control.Look.OpticRange || SpotcamOverlay || SpotcamDontDrawLara)) - { continue; - } if (item->ObjectNumber == ID_LARA && CurrentLevel == 0 && !g_GameFlow->IsLaraInTitleEnabled()) - { continue; - } if (!_moveableObjects[item->ObjectNumber].has_value()) - { continue; - } auto& obj = _moveableObjects[item->ObjectNumber].value(); if (obj.DoNotDraw) - { continue; - } // Clip object by frustum only if it doesn't cast shadows. Otherwise we may see // disappearing shadows if object gets out of frustum. @@ -423,7 +409,7 @@ namespace TEN::Renderer auto newItem = &_items[itemNum]; newItem->ItemNumber = itemNum; - newItem->ObjectNumber = item->ObjectNumber; + newItem->ObjectID = item->ObjectNumber; newItem->Color = item->Model.Color; newItem->Position = item->Pose.Position.ToVector3(); newItem->Translation = Matrix::CreateTranslation(newItem->Position.x, newItem->Position.y, newItem->Position.z); @@ -433,21 +419,23 @@ namespace TEN::Renderer if (item->DisableInterpolation) { - // In this way the interpolation will return always the same result - newItem->OldPosition = newItem->Position; - newItem->OldTranslation = newItem->Translation; - newItem->OldRotation = newItem->Rotation; - newItem->OldWorld = newItem->World; + // NOTE: Interpolation alwasy returns same result. + newItem->PrevPosition = newItem->Position; + newItem->PrevTranslation = newItem->Translation; + newItem->PrevRotation = newItem->Rotation; + newItem->PrevWorld = newItem->World; + for (int j = 0; j < MAX_BONES; j++) - newItem->OldAnimationTransforms[j] = newItem->AnimationTransforms[j]; + newItem->PrevAnimTransforms[j] = newItem->AnimTransforms[j]; } - newItem->InterpolatedPosition = Vector3::Lerp(newItem->OldPosition, newItem->Position, _interpolationFactor); - newItem->InterpolatedTranslation = Matrix::Lerp(newItem->OldTranslation, newItem->Translation, _interpolationFactor); + newItem->InterpolatedPosition = Vector3::Lerp(newItem->PrevPosition, newItem->Position, _interpolationFactor); + newItem->InterpolatedTranslation = Matrix::Lerp(newItem->PrevTranslation, newItem->Translation, _interpolationFactor); newItem->InterpolatedRotation = Matrix::Lerp(newItem->InterpolatedRotation, newItem->Rotation, _interpolationFactor); - newItem->InterpolatedWorld = Matrix::Lerp(newItem->OldWorld, newItem->World, _interpolationFactor); + newItem->InterpolatedWorld = Matrix::Lerp(newItem->PrevWorld, newItem->World, _interpolationFactor); + for (int j = 0; j < MAX_BONES; j++) - newItem->InterpolatedAnimationTransforms[j] = Matrix::Lerp(newItem->OldAnimationTransforms[j], newItem->AnimationTransforms[j], _interpolationFactor); + newItem->InterpolatedAnimTransforms[j] = Matrix::Lerp(newItem->PrevAnimTransforms[j], newItem->AnimTransforms[j], _interpolationFactor); CalculateLightFades(newItem); CollectLightsForItem(newItem); @@ -459,22 +447,18 @@ namespace TEN::Renderer void Renderer::CollectStatics(short roomNumber, RenderView& renderView) { if (_rooms.size() < roomNumber) - { return; - } - RendererRoom& room = _rooms[roomNumber]; - ROOM_INFO* r = &g_Level.Rooms[room.RoomNumber]; + auto& room = _rooms[roomNumber]; + auto* r = &g_Level.Rooms[room.RoomNumber]; if (r->mesh.empty()) - { return; - } for (int i = 0; i < room.Statics.size(); i++) { auto* mesh = &room.Statics[i]; - MESH_INFO* nativeMesh = &r->mesh[i]; + auto* nativeMesh = &r->mesh[i]; if (nativeMesh->Dirty || _invalidateCache) { @@ -489,26 +473,18 @@ namespace TEN::Renderer } if (!(nativeMesh->flags & StaticMeshFlags::SM_VISIBLE)) - { continue; - } if (!_staticObjects[mesh->ObjectNumber].has_value()) - { continue; - } auto& obj = *_staticObjects[mesh->ObjectNumber]; if (obj.ObjectMeshes.empty()) - { continue; - } if (!renderView.Camera.Frustum.SphereInFrustum(mesh->VisibilityBox.Center, mesh->VisibilitySphereRadius)) - { continue; - } // Collect the lights std::vector lights; @@ -545,15 +521,13 @@ namespace TEN::Renderer void Renderer::CollectLights(Vector3 position, float radius, int roomNumber, int prevRoomNumber, bool prioritizeShadowLight, bool useCachedRoomLights, std::vector* roomsLights, std::vector* outputLights) { if (_rooms.size() < roomNumber) - { return; - } // Now collect lights from dynamic list and from rooms std::vector tempLights; tempLights.reserve(MAX_LIGHTS_DRAW); - RendererRoom& room = _rooms[roomNumber]; + auto& room = _rooms[roomNumber]; RendererLight* brightestLight = nullptr; float brightest = 0.0f; @@ -561,24 +535,20 @@ namespace TEN::Renderer // Dynamic lights have the priority for (auto& light : _dynamicLights) { - float distanceSquared = + float distSqr = SQUARE(position.x - light.Position.x) + SQUARE(position.y - light.Position.y) + SQUARE(position.z - light.Position.z); // Collect only lights nearer than 20 sectors - if (distanceSquared >= SQUARE(BLOCK(20))) - { + if (distSqr >= SQUARE(BLOCK(20))) continue; - } // Check the out radius - if (distanceSquared > SQUARE(light.Out + radius)) - { + if (distSqr > SQUARE(light.Out + radius)) continue; - } - float distance = sqrt(distanceSquared); + float distance = sqrt(distSqr); float attenuation = 1.0f - distance / light.Out; float intensity = attenuation * light.Intensity * light.Luma; @@ -588,55 +558,49 @@ namespace TEN::Renderer if (!useCachedRoomLights) { - // Check current room and also neighbour rooms + // Check current room and neighbor rooms. for (int roomToCheck : room.Neighbors) { - RendererRoom& currentRoom = _rooms[roomToCheck]; - int numLights = (int)currentRoom.Lights.size(); + auto& currentRoom = _rooms[roomToCheck]; + int lightCount = (int)currentRoom.Lights.size(); - for (int j = 0; j < numLights; j++) + for (int j = 0; j < lightCount; j++) { - RendererLight* light = ¤tRoom.Lights[j]; + auto* light = ¤tRoom.Lights[j]; float intensity = 0; - float distance = 0; + float dist = 0; - // Check only lights different from sun + // Check only lights different from sun. if (light->Type == LightType::Sun) { - // Suns from non-adjacent rooms are not added! + // Suns from non-adjacent rooms not added. if (roomToCheck != roomNumber && (prevRoomNumber != roomToCheck || prevRoomNumber == NO_VALUE)) - { continue; - } - // Sun is added without distance checks + // Sun is added without distance checks. intensity = light->Intensity * Luma(light->Color); } else if (light->Type == LightType::Point || light->Type == LightType::Shadow) { - float distanceSquared = + float distSqr = SQUARE(position.x - light->Position.x) + SQUARE(position.y - light->Position.y) + SQUARE(position.z - light->Position.z); - // Collect only lights nearer than 20 sectors - if (distanceSquared >= SQUARE(BLOCK(20))) - { + // Collect only lights nearer than 20 blocks. + if (distSqr >= SQUARE(BLOCK(20))) continue; - } - // Check the out radius - if (distanceSquared > SQUARE(light->Out + radius)) - { + // Check out radius. + if (distSqr > SQUARE(light->Out + radius)) continue; - } - distance = sqrt(distanceSquared); - float attenuation = 1.0f - distance / light->Out; + dist = sqrt(distSqr); + float attenuation = 1.0f - dist / light->Out; intensity = attenuation * light->Intensity * Luma(light->Color); - // If collecting shadows, try to collect shadow casting light + // If collecting shadows, try collecting shadow-casting light. if (light->CastShadows && prioritizeShadowLight && light->Type == LightType::Point) { if (intensity >= brightest) @@ -648,28 +612,24 @@ namespace TEN::Renderer } else if (light->Type == LightType::Spot) { - float distanceSquared = + float distSqr = SQUARE(position.x - light->Position.x) + SQUARE(position.y - light->Position.y) + SQUARE(position.z - light->Position.z); - // Collect only lights nearer than 20 sectors - if (distanceSquared >= SQUARE(BLOCK(20))) - { + // Collect only lights nearer than 20 blocks. + if (distSqr >= SQUARE(BLOCK(20))) continue; - } - // Check the range - if (distanceSquared > SQUARE(light->Out + radius)) - { + // Check range. + if (distSqr > SQUARE(light->Out + radius)) continue; - } - distance = sqrt(distanceSquared); - float attenuation = 1.0f - distance / light->Out; + dist = sqrt(distSqr); + float attenuation = 1.0f - dist / light->Out; intensity = attenuation * light->Intensity * light->Luma; - // If shadow pointer provided, try to collect shadow casting light + // If shadow pointer provided, try collecting shadow-casting light. if (light->CastShadows && prioritizeShadowLight) { if (intensity >= brightest) @@ -681,16 +641,14 @@ namespace TEN::Renderer } else { - // Invalid light type + // Invalid light type. continue; } - RendererLightNode node = { light, intensity, distance, 0 }; + RendererLightNode node = { light, intensity, dist, 0 }; if (roomsLights != nullptr) - { roomsLights->push_back(node); - } tempLights.push_back(node); } @@ -699,12 +657,10 @@ namespace TEN::Renderer else { for (int i = 0; i < roomsLights->size(); i++) - { tempLights.push_back(roomsLights->at(i)); - } } - // Sort lights + // Sort lights. if (tempLights.size() > MAX_LIGHTS_PER_ITEM) { std::sort( @@ -713,36 +669,33 @@ namespace TEN::Renderer [](RendererLightNode a, RendererLightNode b) { if (a.Dynamic == b.Dynamic) - return a.LocalIntensity > b.LocalIntensity; + { + return (a.LocalIntensity > b.LocalIntensity); + } else - return a.Dynamic > b.Dynamic; - } - ); + { + return (a.Dynamic > b.Dynamic); + } + }); } - // Now put actual lights to provided vector + // Put actual lights in provided vector. outputLights->clear(); - // Always add brightest light, if collecting shadow light is specified, even if it's far in range + // Add brightest ligh, if collecting shadow light is specified, even if it's far in range. if (prioritizeShadowLight && brightestLight) - { outputLights->push_back(brightestLight); - } - // Add max 8 lights per item, including the shadow light for Lara eventually + // Add max 8 lights per item, including shadow light for player eventually. for (auto l : tempLights) { if (prioritizeShadowLight && brightestLight == l.Light) - { continue; - } outputLights->push_back(l.Light); if (outputLights->size() == MAX_LIGHTS_PER_ITEM) - { break; - } } } @@ -877,7 +830,7 @@ namespace TEN::Renderer newEffect->Rotation = fx->pos.Orientation.ToRotationMatrix(); newEffect->Scale = Matrix::CreateScale(1.0f); newEffect->World = newEffect->Rotation * newEffect->Translation; - newEffect->ObjectNumber = fx->objectNumber; + newEffect->ObjectID = fx->objectNumber; newEffect->RoomNumber = fx->roomNumber; newEffect->Position = fx->pos.Position.ToVector3(); newEffect->AmbientLight = room.AmbientLight; @@ -887,18 +840,18 @@ namespace TEN::Renderer if (fx->DisableInterpolation) { // In this way the interpolation will return always the same result - newEffect->OldPosition = newEffect->Position; - newEffect->OldTranslation = newEffect->Translation; - newEffect->OldRotation = newEffect->Rotation; - newEffect->OldWorld = newEffect->World; - newEffect->OldScale = newEffect->Scale; + newEffect->PrevPosition = newEffect->Position; + newEffect->PrevTranslation = newEffect->Translation; + newEffect->PrevRotation = newEffect->Rotation; + newEffect->PrevWorld = newEffect->World; + newEffect->PrevScale = newEffect->Scale; } - newEffect->InterpolatedPosition = Vector3::Lerp(newEffect->OldPosition, newEffect->Position, _interpolationFactor); - newEffect->InterpolatedTranslation = Matrix::Lerp(newEffect->OldTranslation, newEffect->Translation, _interpolationFactor); + newEffect->InterpolatedPosition = Vector3::Lerp(newEffect->PrevPosition, newEffect->Position, _interpolationFactor); + newEffect->InterpolatedTranslation = Matrix::Lerp(newEffect->PrevTranslation, newEffect->Translation, _interpolationFactor); newEffect->InterpolatedRotation = Matrix::Lerp(newEffect->InterpolatedRotation, newEffect->Rotation, _interpolationFactor); - newEffect->InterpolatedWorld = Matrix::Lerp(newEffect->OldWorld, newEffect->World, _interpolationFactor); - newEffect->InterpolatedScale = Matrix::Lerp(newEffect->OldScale, newEffect->Scale, _interpolationFactor); + newEffect->InterpolatedWorld = Matrix::Lerp(newEffect->PrevWorld, newEffect->World, _interpolationFactor); + newEffect->InterpolatedScale = Matrix::Lerp(newEffect->PrevScale, newEffect->Scale, _interpolationFactor); CollectLightsForEffect(fx->roomNumber, newEffect); @@ -909,34 +862,30 @@ namespace TEN::Renderer void Renderer::ResetItems() { for (int i = 0; i < ITEM_COUNT_MAX; i++) - { _items[i].DoneAnimations = false; - } } - void Renderer::SaveOldState() { for (int i = 0; i < g_Level.Items.size(); i++) { - _items[i].OldPosition = _items[i].Position; - _items[i].OldWorld = _items[i].World; - _items[i].OldTranslation = _items[i].Translation; - _items[i].OldRotation = _items[i].Rotation; - _items[i].OldScale = _items[i].Scale; + _items[i].PrevPosition = _items[i].Position; + _items[i].PrevWorld = _items[i].World; + _items[i].PrevTranslation = _items[i].Translation; + _items[i].PrevRotation = _items[i].Rotation; + _items[i].PrevScale = _items[i].Scale; + for (int j = 0; j < MAX_BONES; j++) - _items[i].OldAnimationTransforms[j] = _items[i].AnimationTransforms[j]; + _items[i].PrevAnimTransforms[j] = _items[i].AnimTransforms[j]; } for (int i = 0; i < ITEM_COUNT_MAX; i++) { - _effects[i].OldPosition = _effects[i].Position; - _effects[i].OldWorld = _effects[i].World; - _effects[i].OldTranslation = _effects[i].Translation; - _effects[i].OldRotation = _effects[i].Rotation; - _effects[i].OldScale = _effects[i].Scale; + _effects[i].PrevPosition = _effects[i].Position; + _effects[i].PrevWorld = _effects[i].World; + _effects[i].PrevTranslation = _effects[i].Translation; + _effects[i].PrevRotation = _effects[i].Rotation; + _effects[i].PrevScale = _effects[i].Scale; } } - -} // namespace TEN::Renderer - +} diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 8dd9814bb..ae57caabe 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -49,7 +49,7 @@ namespace TEN::Renderer RendererBone* bones[MAX_BONES] = {}; int nextBone = 0; - auto* transforms = ((rItem == nullptr) ? rObject.AnimationTransforms.data() : &rItem->AnimationTransforms[0]); + auto* transforms = ((rItem == nullptr) ? rObject.AnimationTransforms.data() : &rItem->AnimTransforms[0]); // Push. bones[nextBone++] = rObject.Skeleton; @@ -67,7 +67,7 @@ namespace TEN::Renderer (frameData.Alpha != 0.0f && frameData.FramePtr0->BoneOrientations.size() <= bonePtr->Index)) { TENLog( - "Attempted to animate object with ID " + GetObjectName((GAME_OBJECT_ID)rItem->ObjectNumber) + + "Attempted to animate object with ID " + GetObjectName((GAME_OBJECT_ID)rItem->ObjectID) + " using incorrect animation data. Bad animations set for slot?", LogLevel::Error); @@ -174,7 +174,7 @@ namespace TEN::Renderer auto& moveableObj = *_moveableObjects[nativeItem->ObjectNumber]; // Copy meshswaps - itemToDraw->MeshIndex = nativeItem->Model.MeshIndex; + itemToDraw->MeshIds = nativeItem->Model.MeshIndex; if (obj->animIndex == -1) return; @@ -310,7 +310,7 @@ namespace TEN::Renderer UpdateAnimation(itemToDraw, moveableObj, frameData, UINT_MAX); for (int m = 0; m < obj->nmeshes; m++) - itemToDraw->AnimationTransforms[m] = itemToDraw->AnimationTransforms[m]; + itemToDraw->AnimTransforms[m] = itemToDraw->AnimTransforms[m]; } void Renderer::UpdateItemAnimations(RenderView& view) @@ -452,7 +452,7 @@ namespace TEN::Renderer if (worldSpace & SPHERES_SPACE_BONE_ORIGIN) pos += moveable.LinearizedBones[i]->Translation; - spheres[i].Center = Vector3::Transform(pos, (itemToDraw->AnimationTransforms[i] * world)); + spheres[i].Center = Vector3::Transform(pos, (itemToDraw->AnimTransforms[i] * world)); spheres[i].Radius = mesh->Sphere.Radius; // Spheres debug @@ -591,7 +591,7 @@ namespace TEN::Renderer if (jointIndex >= MAX_BONES) jointIndex = 0; - auto world = rendererItem->AnimationTransforms[jointIndex] * rendererItem->World; + auto world = rendererItem->AnimTransforms[jointIndex] * rendererItem->World; return Vector3::Transform(relOffset, world); } diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index 173cb08ff..05db2e62c 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -268,10 +268,10 @@ void Renderer::UpdateLaraAnimations(bool force) // Copy matrices in player object. for (int m = 0; m < NUM_LARA_MESHES; m++) - playerObject.AnimationTransforms[m] = rItem.AnimationTransforms[m]; + playerObject.AnimationTransforms[m] = rItem.AnimTransforms[m]; // Copy meshswap indices. - rItem.MeshIndex = LaraItem->Model.MeshIndex; + rItem.MeshIds = LaraItem->Model.MeshIndex; rItem.DoneAnimations = true; } @@ -305,7 +305,7 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa _stItem.World = item->InterpolatedWorld; // _laraWorldMatrix; _stItem.Color = item->Color; _stItem.AmbientLight = item->AmbientLight; - memcpy(_stItem.BonesMatrices, item->InterpolatedAnimationTransforms, laraObj.AnimationTransforms.size() * sizeof(Matrix)); + memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, laraObj.AnimationTransforms.size() * sizeof(Matrix)); for (int k = 0; k < laraSkin.ObjectMeshes.size(); k++) { _stItem.BoneLightModes[k] = (int)GetMesh(nativeItem->Model.MeshIndex[k])->LightMode; @@ -341,7 +341,7 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render const auto& rendererObject = *_moveableObjects[unit.ObjectID]; _stItem.World = Matrix::Identity; - _stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimationTransforms[LM_HEAD] * itemToDraw->InterpolatedWorld; + _stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimTransforms[LM_HEAD] * itemToDraw->InterpolatedWorld; for (int i = 0; i < unit.Segments.size(); i++) { diff --git a/TombEngine/Renderer/Structures/RendererEffect.h b/TombEngine/Renderer/Structures/RendererEffect.h index 492df404d..1473c784c 100644 --- a/TombEngine/Renderer/Structures/RendererEffect.h +++ b/TombEngine/Renderer/Structures/RendererEffect.h @@ -1,36 +1,36 @@ #pragma once -#include -#include "Renderer/Structures/RendererMesh.h" + #include "Renderer/Structures/RendererLight.h" +#include "Renderer/Structures/RendererMesh.h" namespace TEN::Renderer::Structures { - using namespace DirectX::SimpleMath; - struct RendererEffect { - int ObjectNumber; - int RoomNumber; - Vector3 Position; - Matrix World; - Matrix Translation; - Matrix Rotation; - Matrix Scale; - Vector4 Color; - Vector4 AmbientLight; - RendererMesh* Mesh; - std::vector LightsToDraw; + int ObjectID = 0; + int RoomNumber = 0; - Vector3 OldPosition; - Matrix OldWorld; - Matrix OldTranslation; - Matrix OldRotation; - Matrix OldScale; + Vector3 Position = Vector3::Zero; + Matrix World = Matrix::Identity; + Matrix Translation = Matrix::Identity; + Matrix Rotation = Matrix::Identity; + Matrix Scale = Matrix::Identity; + Vector4 Color = Vector4::Zero; + Vector4 AmbientLight = Vector4::Zero; - Vector3 InterpolatedPosition; - Matrix InterpolatedWorld; - Matrix InterpolatedTranslation; - Matrix InterpolatedRotation; - Matrix InterpolatedScale; + RendererMesh* Mesh = nullptr; + std::vector LightsToDraw = {}; + + Vector3 InterpolatedPosition = Vector3::Zero; + Matrix InterpolatedWorld = Matrix::Identity; + Matrix InterpolatedTranslation = Matrix::Identity; + Matrix InterpolatedRotation = Matrix::Identity; + Matrix InterpolatedScale = Matrix::Identity; + + Vector3 PrevPosition = Vector3::Zero; + Matrix PrevWorld = Matrix::Identity; + Matrix PrevTranslation = Matrix::Identity; + Matrix PrevRotation = Matrix::Identity; + Matrix PrevScale = Matrix::Identity; }; } diff --git a/TombEngine/Renderer/Structures/RendererItem.h b/TombEngine/Renderer/Structures/RendererItem.h index 31f2a4204..0dee42a2a 100644 --- a/TombEngine/Renderer/Structures/RendererItem.h +++ b/TombEngine/Renderer/Structures/RendererItem.h @@ -1,49 +1,46 @@ #pragma once -#include + +#include "Game/room.h" #include "Renderer/RendererEnums.h" #include "Renderer/Structures/RendererLight.h" -#include "Game/room.h" namespace TEN::Renderer::Structures { - using namespace DirectX::SimpleMath; - struct RendererItem { - int ItemNumber; - int ObjectNumber; + int ItemNumber = 0; + int ObjectID = 0; - Vector3 Position; - Matrix World; - Matrix Translation; - Matrix Rotation; - Matrix Scale; - Matrix AnimationTransforms[MAX_BONES]; + Vector3 Position = Vector3::Zero; + int RoomNumber = NO_VALUE; + Matrix World = Matrix::Identity; + Matrix Translation = Matrix::Identity; + Matrix Rotation = Matrix::Identity; + Matrix Scale = Matrix::Identity; + Matrix AnimTransforms[MAX_BONES] = {}; - Vector3 OldPosition; - Matrix OldWorld; - Matrix OldTranslation; - Matrix OldRotation; - Matrix OldScale; - Matrix OldAnimationTransforms[MAX_BONES]; + Vector4 Color = Vector4::Zero; + Vector4 AmbientLight = Vector4::Zero; - Vector3 InterpolatedPosition; - Matrix InterpolatedWorld; - Matrix InterpolatedTranslation; - Matrix InterpolatedRotation; - Matrix InterpolatedScale; - Matrix InterpolatedAnimationTransforms[MAX_BONES]; + std::vector MeshIds = {}; + std::vector LightsToDraw = {}; + float LightFade = 0.0f; - int RoomNumber = NO_VALUE; - int PrevRoomNumber = NO_VALUE; + bool DoneAnimations = false; - Vector4 Color; - Vector4 AmbientLight; - std::vector LightsToDraw; - float LightFade; + Vector3 InterpolatedPosition = Vector3::Zero; + Matrix InterpolatedWorld = Matrix::Identity; + Matrix InterpolatedTranslation = Matrix::Identity; + Matrix InterpolatedRotation = Matrix::Identity; + Matrix InterpolatedScale = Matrix::Identity; + Matrix InterpolatedAnimTransforms[MAX_BONES]; - std::vector MeshIndex; - - bool DoneAnimations; + Vector3 PrevPosition = Vector3::Zero; + int PrevRoomNumber = NO_VALUE; + Matrix PrevWorld = Matrix::Identity; + Matrix PrevTranslation = Matrix::Identity; + Matrix PrevRotation = Matrix::Identity; + Matrix PrevScale = Matrix::Identity; + Matrix PrevAnimTransforms[MAX_BONES]; }; } From 5c834a09068bdf9e8481860839ae19feb9b04276 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 17 Aug 2024 22:11:36 +1000 Subject: [PATCH 273/410] Use `BoundingSphere` natively (#1339) * Use BoundingSphere natively; remove CreatureSpheres and LaraSpheres globals * Remove parameter from GetSpheres() * Remove useless includes; rename file; add namespace * Tabs * Change pointer argument to reference * Fix weapon crash * Rename function and return bool * Pass reference arguments * Rename parameter * Fix errors * Use Intersects() method * Define local constant * Rename function; use generic variable names * Update RendererHelper.cpp * Fix merge errors * Fix and further simplify item spheres * Fix weapon firing * Add GetSpheres() ItemInfo method * Fix GenericSphereBoxCollision() --- TombEngine/Game/Lara/lara_climb.cpp | 1 - TombEngine/Game/Lara/lara_fire.cpp | 51 ++++---- TombEngine/Game/collision/collide_item.cpp | 116 ++++++++---------- TombEngine/Game/collision/collide_item.h | 2 +- TombEngine/Game/collision/sphere.cpp | 101 ++++++--------- TombEngine/Game/collision/sphere.h | 31 +---- TombEngine/Game/control/box.cpp | 1 - TombEngine/Game/control/control.cpp | 1 - TombEngine/Game/control/los.cpp | 47 ++++--- TombEngine/Game/effects/debris.cpp | 23 ++-- TombEngine/Game/effects/debris.h | 9 +- TombEngine/Game/effects/hair.cpp | 1 - TombEngine/Game/items.cpp | 7 ++ TombEngine/Game/items.h | 8 ++ TombEngine/Game/people.cpp | 1 - TombEngine/Objects/Effects/enemy_missile.cpp | 4 +- TombEngine/Objects/Effects/flame_emitters.cpp | 1 - TombEngine/Objects/Effects/tr4_locusts.cpp | 1 - .../Objects/Effects/tr5_electricity.cpp | 1 - .../Objects/Generic/Doors/double_doors.cpp | 1 - .../Objects/Generic/Doors/generic_doors.cpp | 5 +- .../Generic/Doors/pushpull_kick_door.cpp | 1 - .../Objects/Generic/Doors/sequence_door.cpp | 1 - .../Objects/Generic/Doors/steel_door.cpp | 6 +- .../Objects/Generic/Doors/underwater_door.cpp | 1 - TombEngine/Objects/Generic/Object/objects.cpp | 1 - .../Objects/Generic/Object/polerope.cpp | 5 +- TombEngine/Objects/Generic/Object/rope.cpp | 1 - .../Objects/Generic/Switches/switch.cpp | 1 - .../Objects/Generic/Traps/falling_block.cpp | 7 +- TombEngine/Objects/TR2/Entity/Dragon.cpp | 1 - TombEngine/Objects/TR2/Entity/tr2_skidman.cpp | 5 +- TombEngine/Objects/TR2/Vehicles/skidoo.cpp | 1 - TombEngine/Objects/TR2/Vehicles/speedboat.cpp | 1 - TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp | 1 - .../Objects/TR3/Entity/tr3_tribesman.cpp | 1 - TombEngine/Objects/TR3/Object/corpse.cpp | 1 - TombEngine/Objects/TR3/Trap/train.cpp | 7 +- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 3 +- .../Objects/TR3/Vehicles/rubber_boat.cpp | 1 - TombEngine/Objects/TR3/Vehicles/upv.cpp | 5 +- TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp | 22 ++-- .../Objects/TR4/Entity/tr4_horseman.cpp | 3 +- TombEngine/Objects/TR4/Entity/tr4_mutant.cpp | 1 - .../Objects/TR4/Object/tr4_element_puzzle.cpp | 6 +- TombEngine/Objects/TR4/Object/tr4_mapper.cpp | 3 +- TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp | 6 +- TombEngine/Objects/TR4/Trap/SpikyWall.cpp | 5 +- TombEngine/Objects/TR4/Trap/SquishyBlock.cpp | 7 +- TombEngine/Objects/TR4/Trap/tr4_chain.cpp | 6 +- TombEngine/Objects/TR4/Trap/tr4_hammer.cpp | 1 - TombEngine/Objects/TR4/Trap/tr4_mine.cpp | 28 ++--- .../Objects/TR4/Trap/tr4_moving_blade.cpp | 1 - TombEngine/Objects/TR4/Trap/tr4_stargate.cpp | 9 +- TombEngine/Objects/TR5/Entity/AutoGun.cpp | 3 +- TombEngine/Objects/TR5/Object/tr5_missile.cpp | 5 +- .../Objects/TR5/Object/tr5_rollingball.cpp | 8 +- .../Objects/TR5/Trap/tr5_wreckingball.cpp | 1 - TombEngine/Objects/Utils/VehicleHelpers.cpp | 5 +- TombEngine/Renderer/Renderer.h | 3 +- TombEngine/Renderer/RendererFrame.cpp | 8 +- TombEngine/Renderer/RendererHelper.cpp | 66 ++++------ TombEngine/Renderer/RendererLara.cpp | 2 +- TombEngine/TombEngine.vcxproj | 4 +- 64 files changed, 295 insertions(+), 372 deletions(-) diff --git a/TombEngine/Game/Lara/lara_climb.cpp b/TombEngine/Game/Lara/lara_climb.cpp index 68917f419..44aaa2360 100644 --- a/TombEngine/Game/Lara/lara_climb.cpp +++ b/TombEngine/Game/Lara/lara_climb.cpp @@ -4,7 +4,6 @@ #include "Game/animation.h" #include "Game/camera.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/items.h" #include "Game/Lara/lara.h" diff --git a/TombEngine/Game/Lara/lara_fire.cpp b/TombEngine/Game/Lara/lara_fire.cpp index 5bac95a04..08a97f190 100644 --- a/TombEngine/Game/Lara/lara_fire.cpp +++ b/TombEngine/Game/Lara/lara_fire.cpp @@ -4,7 +4,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/los.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" @@ -31,6 +31,7 @@ #include "Specific/level.h" #include "Specific/trutils.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Entities::Generic; using namespace TEN::Input; using namespace TEN::Math; @@ -842,32 +843,38 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, Ite auto target = origin + (directionNorm * weapon.TargetDist); auto ray = Ray(origin, directionNorm); - int num = GetSpheres(&targetEntity, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - int bestJointIndex = NO_VALUE; - float bestDistance = INFINITY; - for (int i = 0; i < num; i++) - { - auto sphere = BoundingSphere(Vector3(CreatureSpheres[i].x, CreatureSpheres[i].y, CreatureSpheres[i].z), CreatureSpheres[i].r); - float distance = 0.0f; - if (ray.Intersects(sphere, distance)) - { - if (distance < bestDistance) - { - bestDistance = distance; - bestJointIndex = i; - } - } - } - player.Control.Weapon.HasFired = true; player.Control.Weapon.Fired = true; - + auto vOrigin = GameVector(pos); short roomNumber = laraItem.RoomNumber; GetFloor(pos.x, pos.y, pos.z, &roomNumber); vOrigin.RoomNumber = roomNumber; - if (bestJointIndex < 0) + if (&targetEntity == nullptr) + { + auto vTarget = GameVector(target); + GetTargetOnLOS(&vOrigin, &vTarget, false, true); + return FireWeaponType::Miss; + } + + auto spheres = targetEntity.GetSpheres(); + int closestJointIndex = NO_VALUE; + float closestDist = INFINITY; + for (int i = 0; i < spheres.size(); i++) + { + float dist = 0.0f; + if (ray.Intersects(spheres[i], dist)) + { + if (dist < closestDist) + { + closestDist = dist; + closestJointIndex = i; + } + } + } + + if (closestJointIndex < 0) { auto vTarget = GameVector(target); GetTargetOnLOS(&vOrigin, &vTarget, false, true); @@ -876,13 +883,13 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, Ite else { SaveGame::Statistics.Game.AmmoHits++; - target = origin + (directionNorm * bestDistance); + target = origin + (directionNorm * closestDist); auto vTarget = GameVector(target); // NOTE: It seems that entities hit by the player in the normal way must have GetTargetOnLOS return false. // It's strange, but this replicates original behaviour until we fully understand what is happening. if (!GetTargetOnLOS(&vOrigin, &vTarget, false, true)) - HitTarget(&laraItem, &targetEntity, &vTarget, weapon.Damage, false, bestJointIndex); + HitTarget(&laraItem, &targetEntity, &vTarget, weapon.Damage, false, closestJointIndex); return FireWeaponType::PossibleHit; } diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index bcefa102c..502d36654 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -6,7 +6,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/floordata.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" @@ -23,81 +23,73 @@ using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; using namespace TEN::Math; constexpr auto ANIMATED_ALIGNMENT_FRAME_COUNT_THRESHOLD = 6; // Globals + GameBoundingBox GlobalCollisionBounds; -void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) +void GenericSphereBoxCollision(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; + if (item.Status == ITEM_INVISIBLE) + return; - if (item->Status != ITEM_INVISIBLE) + if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) + return; + + HandleItemSphereCollision(item, *playerItem); + if (!item.TouchBits.TestAny()) + return; + + short prevYOrient = item.Pose.Orientation.y; + item.Pose.Orientation.y = 0; + auto spheres = item.GetSpheres(); + item.Pose.Orientation.y = prevYOrient; + + int harmBits = *(int*)&item.ItemFlags[0]; // NOTE: Value spread across ItemFlags[0] and ItemFlags[1]. + + auto collidedBits = item.TouchBits; + if (item.ItemFlags[2] != 0) + collidedBits.Clear(0); + + coll->Setup.EnableObjectPush = (item.ItemFlags[4] == 0); + + // Handle push and damage. + for (int i = 0; i < spheres.size(); i++) { - if (TestBoundsCollide(item, laraItem, coll->Setup.Radius)) + if (collidedBits.Test(i)) { - int collidedBits = TestCollision(item, laraItem); - if (collidedBits) + const auto& sphere = spheres[i]; + + GlobalCollisionBounds.X1 = sphere.Center.x - sphere.Radius - item.Pose.Position.x; + GlobalCollisionBounds.X2 = sphere.Center.x + sphere.Radius - item.Pose.Position.x; + GlobalCollisionBounds.Y1 = sphere.Center.y - sphere.Radius - item.Pose.Position.y; + GlobalCollisionBounds.Y2 = sphere.Center.y + sphere.Radius - item.Pose.Position.y; + GlobalCollisionBounds.Z1 = sphere.Center.z - sphere.Radius - item.Pose.Position.z; + GlobalCollisionBounds.Z2 = sphere.Center.z + sphere.Radius - item.Pose.Position.z; + + auto pos = playerItem->Pose.Position; + if (ItemPushItem(&item, playerItem, coll, harmBits & 1, 3) && (harmBits & 1)) { - short prevYOrient = item->Pose.Orientation.y; + DoDamage(playerItem, item.ItemFlags[3]); - item->Pose.Orientation.y = 0; - GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - item->Pose.Orientation.y = prevYOrient; - - int deadlyBits = *((int*)&item->ItemFlags[0]); - auto* sphere = &CreatureSpheres[0]; - - if (item->ItemFlags[2] != 0) - collidedBits &= ~1; - coll->Setup.EnableObjectPush = item->ItemFlags[4] == 0; - - while (collidedBits) + auto deltaPos = pos - playerItem->Pose.Position; + if (deltaPos != Vector3i::Zero) { - if (collidedBits & 1) - { - GlobalCollisionBounds.X1 = sphere->x - sphere->r - item->Pose.Position.x; - GlobalCollisionBounds.X2 = sphere->x + sphere->r - item->Pose.Position.x; - GlobalCollisionBounds.Y1 = sphere->y - sphere->r - item->Pose.Position.y; - GlobalCollisionBounds.Y2 = sphere->y + sphere->r - item->Pose.Position.y; - GlobalCollisionBounds.Z1 = sphere->z - sphere->r - item->Pose.Position.z; - GlobalCollisionBounds.Z2 = sphere->z + sphere->r - item->Pose.Position.z; - - int x = laraItem->Pose.Position.x; - int y = laraItem->Pose.Position.y; - int z = laraItem->Pose.Position.z; - - if (ItemPushItem(item, laraItem, coll, deadlyBits & 1, 3) && (deadlyBits & 1)) - { - DoDamage(laraItem, item->ItemFlags[3]); - - int dx = x - laraItem->Pose.Position.x; - int dy = y - laraItem->Pose.Position.y; - int dz = z - laraItem->Pose.Position.z; - - if (dx || dy || dz) - { - if (TriggerActive(item)) - TriggerLaraBlood(); - } - - if (!coll->Setup.EnableObjectPush) - { - laraItem->Pose.Position.x += dx; - laraItem->Pose.Position.y += dy; - laraItem->Pose.Position.z += dz; - } - } - } - - collidedBits >>= 1; - deadlyBits >>= 1; - sphere++; + if (TriggerActive(&item)) + TriggerLaraBlood(); } + + if (!coll->Setup.EnableObjectPush) + playerItem->Pose.Position += deltaPos; } } + + harmBits >>= 1; } } @@ -1958,7 +1950,7 @@ void ObjectCollision(const short itemNumber, ItemInfo* laraItem, CollisionInfo* if (TestBoundsCollide(item, laraItem, coll->Setup.Radius)) { - if (TestCollision(item, laraItem)) + if (HandleItemSphereCollision(*item, *laraItem)) { if (coll->Setup.EnableObjectPush) ItemPushItem(item, laraItem, coll, false, 1); @@ -1973,7 +1965,7 @@ void CreatureCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll if (!TestBoundsCollide(item, laraItem, coll->Setup.Radius)) return; - if (!TestCollision(item, laraItem)) + if (!HandleItemSphereCollision(*item, *laraItem)) return; bool doPlayerCollision = laraItem->IsLara(); @@ -2008,7 +2000,7 @@ void TrapCollision(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll) if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) return; - TestCollision(&item, playerItem); + HandleItemSphereCollision(item, *playerItem); } else if (item.Status != ITEM_INVISIBLE) { diff --git a/TombEngine/Game/collision/collide_item.h b/TombEngine/Game/collision/collide_item.h index 6c39f9abb..5c0a4f908 100644 --- a/TombEngine/Game/collision/collide_item.h +++ b/TombEngine/Game/collision/collide_item.h @@ -36,7 +36,7 @@ struct CollidedObjectData bool IsEmpty() const { return (Items.empty() && Statics.empty()); }; }; -void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); +void GenericSphereBoxCollision(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll); CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, bool ignorePlayer, float customRadius = 0.0f, ObjectCollectionMode mode = ObjectCollectionMode::All); bool TestWithGlobalCollisionBounds(ItemInfo* item, ItemInfo* laraItem, CollisionInfo* coll); void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll); diff --git a/TombEngine/Game/collision/sphere.cpp b/TombEngine/Game/collision/sphere.cpp index 22ca14f86..fd20d15f8 100644 --- a/TombEngine/Game/collision/sphere.cpp +++ b/TombEngine/Game/collision/sphere.cpp @@ -1,5 +1,5 @@ #include "framework.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/Lara/lara.h" #include "Game/items.h" @@ -8,85 +8,54 @@ #include "Math/Math.h" #include "Renderer/Renderer.h" +using namespace TEN::Math; using namespace TEN::Renderer; -SPHERE LaraSpheres[MAX_SPHERES]; -SPHERE CreatureSpheres[MAX_SPHERES]; - -int GetSpheres(ItemInfo* item, SPHERE* ptr, int worldSpace, Matrix local) +namespace TEN::Collision::Sphere { - if (item == nullptr) - return 0; - - BoundingSphere spheres[MAX_SPHERES]; - int num = g_Renderer.GetSpheres(item->Index, spheres, worldSpace, local); - - for (int i = 0; i < MAX_SPHERES; i++) + bool HandleItemSphereCollision(ItemInfo& item0, ItemInfo& item1) { - ptr[i].x = spheres[i].Center.x; - ptr[i].y = spheres[i].Center.y; - ptr[i].z = spheres[i].Center.z; - ptr[i].r = spheres[i].Radius; - } + auto spheres0 = item0.GetSpheres(); + auto spheres1 = item1.GetSpheres(); - return num; -} + item1.TouchBits.ClearAll(); -int TestCollision(ItemInfo* item, ItemInfo* laraItem) -{ - int flags = 0; - - int creatureSphereCount = GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - int laraSphereCount = GetSpheres(laraItem, LaraSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - - laraItem->TouchBits = NO_JOINT_BITS; - - if (creatureSphereCount <= 0) - { - item->TouchBits = NO_JOINT_BITS; - return 0; - } - else - { - for (int i = 0; i < creatureSphereCount; i++) + if (spheres0.empty()) { - auto* ptr1 = &CreatureSpheres[i]; - - int x1 = item->Pose.Position.x + ptr1->x; - int y1 = item->Pose.Position.y + ptr1->y; - int z1 = item->Pose.Position.z + ptr1->z; - int r1 = ptr1->r; + item0.TouchBits.ClearAll(); + return false; + } - if (r1 > 0) + // Run through item 0 spheres. + bool isCollided = false; + for (int i = 0; i < spheres0.size(); i++) + { + // Get sphere 0. + const auto& sphere0 = spheres0[i]; + if (sphere0.Radius <= 0.0f) + continue; + + // Run through item 1 spheres. + for (int j = 0; j < spheres1.size(); j++) { - for (int j = 0; j < laraSphereCount; j++) - { - auto* ptr2 = &LaraSpheres[j]; + // Get sphere 1. + const auto& sphere1 = spheres1[j]; + if (sphere1.Radius <= 0.0f) + continue; - int x2 = item->Pose.Position.x + ptr2->x; - int y2 = item->Pose.Position.y + ptr2->y; - int z2 = item->Pose.Position.z + ptr2->z; - int r2 = ptr2->r; + // Test sphere collision. + if (!sphere0.Intersects(sphere1)) + continue; - if (r2 > 0) - { - int dx = x1 - x2; - int dy = y1 - y2; - int dz = z1 - z2; - int r = r1 + r2; + // Set touch bits. + item0.TouchBits.Set(i); + item1.TouchBits.Set(j); - if ((SQUARE(dx) + SQUARE(dy) + SQUARE(dz)) < SQUARE(r)) - { - item->TouchBits.Set(i); - laraItem->TouchBits.Set(j); - flags |= 1 << i; - break; - } - } - } + isCollided = true; + break; } } - return flags; + return isCollided; } } diff --git a/TombEngine/Game/collision/sphere.h b/TombEngine/Game/collision/sphere.h index d02c36198..30883d9be 100644 --- a/TombEngine/Game/collision/sphere.h +++ b/TombEngine/Game/collision/sphere.h @@ -1,31 +1,8 @@ #pragma once -#include "Game/items.h" -#define SPHERES_SPACE_LOCAL 0 -#define SPHERES_SPACE_WORLD 1 -#define SPHERES_SPACE_BONE_ORIGIN 2 -#define MAX_SPHERES 34 +struct ItemInfo; -struct SPHERE +namespace TEN::Collision::Sphere { - int x = 0; - int y = 0; - int z = 0; - int r = 0; - - SPHERE() {}; - - SPHERE(const Vector3& pos, float radius) - { - this->x = (int)round(pos.x); - this->y = (int)round(pos.y); - this->z = (int)round(pos.z); - this->r = (int)round(radius); - } -}; - -extern SPHERE LaraSpheres[MAX_SPHERES]; -extern SPHERE CreatureSpheres[MAX_SPHERES]; - -int TestCollision(ItemInfo* item, ItemInfo* laraItem); -int GetSpheres(ItemInfo* item, SPHERE* ptr, int worldSpace, Matrix local); + bool HandleItemSphereCollision(ItemInfo& item0, ItemInfo& item1); +} diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 20640dd0f..a2b12fdc8 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" #include "Game/control/control.h" diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 5509c4383..75e8648d2 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -6,7 +6,6 @@ #include "Game/camera.h" #include "Game/collision/collide_room.h" -#include "Game/collision/sphere.h" #include "Game/control/flipeffect.h" #include "Game/control/lot.h" #include "Game/control/volume.h" diff --git a/TombEngine/Game/control/los.cpp b/TombEngine/Game/control/los.cpp index d527584ce..61fc6a5e6 100644 --- a/TombEngine/Game/control/los.cpp +++ b/TombEngine/Game/control/los.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" +#include "Game/collision/Sphere.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/debris.h" #include "Game/items.h" @@ -18,6 +19,7 @@ #include "Sound/sound.h" #include "Specific/Input/Input.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Math; using TEN::Renderer::g_Renderer; @@ -308,7 +310,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo { item->MeshBits &= ~ShatterItem.bit; ShatterImpactData.impactDirection = dir; - ShatterImpactData.impactLocation = Vector3(ShatterItem.sphere.x, ShatterItem.sphere.y, ShatterItem.sphere.z); + ShatterImpactData.impactLocation = ShatterItem.sphere.Center; ShatterObject(&ShatterItem, 0, 128, target2.RoomNumber, 0); TriggerRicochetSpark(target2, LaraItem->Pose.Orientation.y, 3, 0); } @@ -323,20 +325,19 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo { const auto& weapon = Weapons[(int)Lara.Control.Weapon.GunType]; - int num = GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); + auto spheres = item->GetSpheres(); auto ray = Ray(origin->ToVector3(), dir); float bestDistance = INFINITY; int bestJointIndex = NO_VALUE; - for (int i = 0; i < num; i++) + for (int i = 0; i < spheres.size(); i++) { - auto sphere = BoundingSphere(Vector3(CreatureSpheres[i].x, CreatureSpheres[i].y, CreatureSpheres[i].z), CreatureSpheres[i].r); - float distance = 0.0f; - if (ray.Intersects(sphere, distance)) + float dist = 0.0f; + if (ray.Intersects(spheres[i], dist)) { - if (distance < bestDistance) + if (dist < bestDistance) { - bestDistance = distance; + bestDistance = dist; bestJointIndex = i; } } @@ -500,27 +501,23 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G auto* item = &g_Level.Items[closestItemNumber]; auto* object = &Objects[item->ObjectNumber]; - // Get transformed mesh sphere. - GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); - SPHERE spheres[34]; - memcpy(spheres, CreatureSpheres, sizeof(SPHERE) * 34); - if (object->nmeshes <= 0) return false; meshIndex = object->meshIndex; + auto spheres = item->GetSpheres(); for (int i = 0; i < object->nmeshes; i++) { // If mesh is visible. if (item->MeshBits & (1 << i)) { - auto* sphere = &CreatureSpheres[i]; + const auto& sphere = spheres[i]; + // NOTE: Not worth doing what's commented below. *Rewrite completely.* // TODO: this approach is the correct one but, again, Core's math is a mystery and this test was meant // to fail deliberately in some way. I've so added again Core's legacy test for allowing the current game logic // but after more testing we should trash it in the future and restore the new way. - #if 0 // Create the bounding sphere and test it against the ray BoundingSphere sph = BoundingSphere(Vector3(sphere->x, sphere->y, sphere->z), sphere->r); @@ -551,9 +548,9 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G p[2].x = target.x; p[2].y = target.y; p[2].z = target.z; - p[3].x = sphere->x; - p[3].y = sphere->y; - p[3].z = sphere->z; + p[3].x = sphere.Center.x; + p[3].y = sphere.Center.y; + p[3].z = sphere.Center.z; int r0 = (p[3].x - p[1].x) * (p[2].x - p[1].x) + (p[3].y - p[1].y) * (p[2].y - p[1].y) + @@ -583,11 +580,11 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G int distance = dx + dy + dz; - if (distance < SQUARE(sphere->r)) + if (distance < SQUARE(sphere.Radius)) { - dx = SQUARE(sphere->x - origin.x); - dy = SQUARE(sphere->y - origin.y); - dz = SQUARE(sphere->z - origin.z); + dx = SQUARE(sphere.Center.x - origin.x); + dy = SQUARE(sphere.Center.y - origin.y); + dz = SQUARE(sphere.Center.z - origin.z); distance = dx + dy + dz; @@ -622,14 +619,12 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G { auto* item = &g_Level.Items[closestItemNumber]; - GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity); + auto spheres = item->GetSpheres(); ShatterItem.yRot = item->Pose.Orientation.y; ShatterItem.meshIndex = meshIndex; ShatterItem.color = item->Model.Color; - ShatterItem.sphere.x = CreatureSpheres[sp].x; - ShatterItem.sphere.y = CreatureSpheres[sp].y; - ShatterItem.sphere.z = CreatureSpheres[sp].z; + ShatterItem.sphere.Center = spheres[sp].Center; ShatterItem.bit = bit; ShatterItem.flags = 0; } diff --git a/TombEngine/Game/effects/debris.cpp b/TombEngine/Game/effects/debris.cpp index 9d98a0ada..eae73d0cb 100644 --- a/TombEngine/Game/effects/debris.cpp +++ b/TombEngine/Game/effects/debris.cpp @@ -2,14 +2,15 @@ #include "Game/effects/debris.h" #include "Game/collision/collide_room.h" +#include "Game/collision/Sphere.h" #include "Game/effects/tomb4fx.h" #include "Game/Setup.h" #include "Specific/level.h" -#include "Math/Random.h" #include "Math/Math.h" +using namespace TEN::Collision::Sphere; +using namespace TEN::Math; using namespace TEN::Renderer; -using namespace TEN::Math::Random; ShatterImpactInfo ShatterImpactData; SHATTER_ITEM ShatterItem; @@ -26,17 +27,15 @@ bool ExplodeItemNode(ItemInfo* item, int node, int noXZVel, int bits) if (number == BODY_DO_EXPLOSION) number = -64; - GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity); + auto spheres = item->GetSpheres(); ShatterItem.yRot = item->Pose.Orientation.y; ShatterItem.bit = 1 << node; ShatterItem.meshIndex = Objects[item->ObjectNumber].meshIndex + node; - ShatterItem.sphere.x = CreatureSpheres[node].x; - ShatterItem.sphere.y = CreatureSpheres[node].y; - ShatterItem.sphere.z = CreatureSpheres[node].z; + ShatterItem.sphere.Center = spheres[node].Center; ShatterItem.color = item->Model.Color; ShatterItem.flags = item->ObjectNumber == ID_CROSSBOW_BOLT ? 0x400 : 0; ShatterImpactData.impactDirection = Vector3(0, -1, 0); - ShatterImpactData.impactLocation = { (float)ShatterItem.sphere.x, (float)ShatterItem.sphere.y, (float)ShatterItem.sphere.z }; + ShatterImpactData.impactLocation = ShatterItem.sphere.Center; ShatterObject(&ShatterItem, NULL, number, item->RoomNumber, noXZVel); item->MeshBits &= ~ShatterItem.bit; @@ -88,7 +87,7 @@ void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num, short roomNumbe isStatic = false; meshIndex = item->meshIndex; yRot = item->yRot; - pos = Vector3(item->sphere.x, item->sphere.y, item->sphere.z); + pos = item->sphere.Center; scale = 1.0f; } @@ -177,8 +176,8 @@ void ShatterObject(SHATTER_ITEM* item, MESH_INFO* mesh, int num, short roomNumbe fragment->restitution = 0.6f; fragment->friction = 0.6f; fragment->linearDrag = .99f; - fragment->angularVelocity = Vector3(GenerateFloat(-1, 1) * 0.39, GenerateFloat(-1, 1) * 0.39, GenerateFloat(-1, 1) * 0.39); - fragment->angularDrag = GenerateFloat(0.9f, 0.999f); + fragment->angularVelocity = Vector3(Random::GenerateFloat(-1, 1) * 0.39, Random::GenerateFloat(-1, 1) * 0.39, Random::GenerateFloat(-1, 1) * 0.39); + fragment->angularDrag = Random::GenerateFloat(0.9f, 0.999f); fragment->velocity = CalculateFragmentImpactVelocity(fragment->worldPosition, ShatterImpactData.impactDirection, ShatterImpactData.impactLocation); fragment->roomNumber = roomNumber; fragment->numBounces = 0; @@ -196,10 +195,10 @@ Vector3 CalculateFragmentImpactVelocity(const Vector3& fragmentWorldPosition, co radiusNormVec.Normalize(); float radiusStrenght = 1-((fragmentWorldPosition - impactLocation).Length() / 1024); radiusStrenght = fmax(radiusStrenght, 0); - Vector3 radiusRandomVector = Vector3(GenerateFloat(-0.2f, 0.2f), GenerateFloat(-0.2f, 0.2f), GenerateFloat(-0.2f, 0.2f)) + radiusNormVec; + Vector3 radiusRandomVector = Vector3(Random::GenerateFloat(-0.2f, 0.2f), Random::GenerateFloat(-0.2f, 0.2f), Random::GenerateFloat(-0.2f, 0.2f)) + radiusNormVec; radiusRandomVector.Normalize(); Vector3 radiusVelocity = radiusRandomVector * radiusStrenght*40; - Vector3 impactDirectionVelocity = (impactDirection + Vector3(GenerateFloat(-0.2f, 0.2f), GenerateFloat(-0.2f, 0.2f), GenerateFloat(-0.2f, 0.2f))) * 80 ; + Vector3 impactDirectionVelocity = (impactDirection + Vector3(Random::GenerateFloat(-0.2f, 0.2f), Random::GenerateFloat(-0.2f, 0.2f), Random::GenerateFloat(-0.2f, 0.2f))) * 80 ; return radiusVelocity + impactDirectionVelocity; } diff --git a/TombEngine/Game/effects/debris.h b/TombEngine/Game/effects/debris.h index 1c2df5372..bd9faf9cf 100644 --- a/TombEngine/Game/effects/debris.h +++ b/TombEngine/Game/effects/debris.h @@ -1,9 +1,8 @@ #pragma once -#include "Game/collision/sphere.h" -#include "Specific/newtypes.h" -#include "Specific/level.h" -#include "Renderer/Renderer.h" #include "Renderer/Graphics/Vertices/Vertex.h" +#include "Renderer/Renderer.h" +#include "Specific/level.h" +#include "Specific/newtypes.h" constexpr int MAX_DEBRIS = 2048; @@ -26,7 +25,7 @@ struct ITEM_LIGHT struct SHATTER_ITEM { - SPHERE sphere; + BoundingSphere sphere; ITEM_LIGHT* il; int meshIndex; Vector4 color; diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index d1137b60b..abe1bc940 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -4,7 +4,6 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/weather.h" #include "Game/items.h" diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 2c9ffd758..120d63343 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -17,6 +17,7 @@ #include "Objects/Generic/Object/BridgeObject.h" #include "Objects/Generic/Object/Pushable/PushableInfo.h" #include "Objects/Generic/Object/Pushable/PushableObject.h" +#include "Renderer/Renderer.h" #include "Scripting/Include/Objects/ScriptInterfaceObjectsHandler.h" #include "Scripting/Include/ScriptInterfaceGame.h" #include "Scripting/Internal/TEN/Objects/ObjectIDs.h" @@ -35,6 +36,7 @@ using namespace TEN::Entities::Generic; using namespace TEN::Input; using namespace TEN::Math; using namespace TEN::Utils; +using TEN::Renderer::g_Renderer; constexpr auto ITEM_DEATH_TIMEOUT = 4 * FPS; @@ -182,6 +184,11 @@ bool ItemInfo::IsBridge() const return Contains(BRIDGE_OBJECT_IDS, ObjectNumber); } +std::vector ItemInfo::GetSpheres() const +{ + return g_Renderer.GetSpheres(Index); +} + bool TestState(int refState, const std::vector& stateList) { for (const auto& state : stateList) diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index cda9aafee..d375bffad 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -150,11 +150,13 @@ struct ItemInfo short CarriedItem = 0; // OCB utilities + bool TestOcb(short ocbFlags) const; void RemoveOcb(short ocbFlags); void ClearAllOcb(); // ItemFlags utilities + bool TestFlags(int id, short flags) const; // ItemFlags[id] & flags bool TestFlagField(int id, short flags) const; // ItemFlags[id] == flags short GetFlagField(int id) const; // ItemFlags[id] @@ -162,6 +164,7 @@ struct ItemInfo void ClearFlags(int id, short flags); // ItemFlags[id] &= ~flags // Model utilities + bool TestMeshSwapFlags(unsigned int flags); bool TestMeshSwapFlags(const std::vector& flags); void SetMeshSwapFlags(unsigned int flags, bool clear = false); @@ -169,9 +172,14 @@ struct ItemInfo void ResetModelToDefault(); // Inquirers + bool IsLara() const; bool IsCreature() const; bool IsBridge() const; + + // Getters + + std::vector GetSpheres() const; }; bool TestState(int refState, const std::vector& stateList); diff --git a/TombEngine/Game/people.cpp b/TombEngine/Game/people.cpp index ff9c24d7e..5b9b1e943 100644 --- a/TombEngine/Game/people.cpp +++ b/TombEngine/Game/people.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/control/los.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/debris.h" #include "Game/itemdata/creature_info.h" diff --git a/TombEngine/Objects/Effects/enemy_missile.cpp b/TombEngine/Objects/Effects/enemy_missile.cpp index 286b3b43b..2ab48ec11 100644 --- a/TombEngine/Objects/Effects/enemy_missile.cpp +++ b/TombEngine/Objects/Effects/enemy_missile.cpp @@ -121,9 +121,7 @@ namespace TEN::Entities::Effects ShatterItem.yRot = fx->pos.Orientation.y; ShatterItem.meshIndex = fx->frameNumber; ShatterItem.color = Vector4::One; - ShatterItem.sphere.x = fx->pos.Position.x; - ShatterItem.sphere.y = fx->pos.Position.y; - ShatterItem.sphere.z = fx->pos.Position.z; + ShatterItem.sphere.Center = fx->pos.Position.ToVector3(); ShatterItem.bit = 0; ShatterItem.flags = fx->flag2 & 0x400; ShatterObject(&ShatterItem, 0, param2, fx->roomNumber, param1); diff --git a/TombEngine/Objects/Effects/flame_emitters.cpp b/TombEngine/Objects/Effects/flame_emitters.cpp index d0040a6f7..725afb751 100644 --- a/TombEngine/Objects/Effects/flame_emitters.cpp +++ b/TombEngine/Objects/Effects/flame_emitters.cpp @@ -5,7 +5,6 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/Electricity.h" #include "Game/effects/item_fx.h" diff --git a/TombEngine/Objects/Effects/tr4_locusts.cpp b/TombEngine/Objects/Effects/tr4_locusts.cpp index e828ce78b..1ca7f581b 100644 --- a/TombEngine/Objects/Effects/tr4_locusts.cpp +++ b/TombEngine/Objects/Effects/tr4_locusts.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" #include "Game/effects/tomb4fx.h" #include "Game/items.h" #include "Game/Lara/lara.h" diff --git a/TombEngine/Objects/Effects/tr5_electricity.cpp b/TombEngine/Objects/Effects/tr5_electricity.cpp index 1e79cb09f..b93bd1a34 100644 --- a/TombEngine/Objects/Effects/tr5_electricity.cpp +++ b/TombEngine/Objects/Effects/tr5_electricity.cpp @@ -5,7 +5,6 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/effects/item_fx.h" diff --git a/TombEngine/Objects/Generic/Doors/double_doors.cpp b/TombEngine/Objects/Generic/Doors/double_doors.cpp index 9e605f320..8a20011c6 100644 --- a/TombEngine/Objects/Generic/Doors/double_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/double_doors.cpp @@ -10,7 +10,6 @@ #include "Game/pickup/pickup.h" #include "Sound/sound.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" #include "Game/Lara/lara_struct.h" diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index cc1016f63..ebb460372 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -10,7 +10,7 @@ #include "Game/pickup/pickup.h" #include "Sound/sound.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Objects/Generic/Switches/cog_switch.h" #include "Objects/objectslist.h" #include "Game/Lara/lara.h" @@ -24,6 +24,7 @@ #include "Game/itemdata/itemdata.h" using namespace TEN::Collision::Room; +using namespace TEN::Collision::Sphere; using namespace TEN::Gui; using namespace TEN::Input; @@ -247,7 +248,7 @@ namespace TEN::Entities::Doors if (TestBoundsCollide(doorItem, laraItem, coll->Setup.Radius)) { - if (TestCollision(doorItem, laraItem)) + if (HandleItemSphereCollision(*doorItem, *laraItem)) { if (coll->Setup.EnableObjectPush) { diff --git a/TombEngine/Objects/Generic/Doors/pushpull_kick_door.cpp b/TombEngine/Objects/Generic/Doors/pushpull_kick_door.cpp index be3992325..5f13849ab 100644 --- a/TombEngine/Objects/Generic/Doors/pushpull_kick_door.cpp +++ b/TombEngine/Objects/Generic/Doors/pushpull_kick_door.cpp @@ -10,7 +10,6 @@ #include "Game/pickup/pickup.h" #include "Sound/sound.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" #include "Game/Lara/lara_helpers.h" #include "Game/Lara/lara_struct.h" #include "Game/Lara/lara.h" diff --git a/TombEngine/Objects/Generic/Doors/sequence_door.cpp b/TombEngine/Objects/Generic/Doors/sequence_door.cpp index a83a24eb9..27133e958 100644 --- a/TombEngine/Objects/Generic/Doors/sequence_door.cpp +++ b/TombEngine/Objects/Generic/Doors/sequence_door.cpp @@ -10,7 +10,6 @@ #include "Game/pickup/pickup.h" #include "Sound/sound.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" #include "Game/Lara/lara_struct.h" #include "Game/Lara/lara.h" #include "Math/Math.h" diff --git a/TombEngine/Objects/Generic/Doors/steel_door.cpp b/TombEngine/Objects/Generic/Doors/steel_door.cpp index 42077147b..e0024d854 100644 --- a/TombEngine/Objects/Generic/Doors/steel_door.cpp +++ b/TombEngine/Objects/Generic/Doors/steel_door.cpp @@ -10,7 +10,7 @@ #include "Game/pickup/pickup.h" #include "Sound/sound.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/Lara/lara_struct.h" #include "Game/Lara/lara.h" #include "Math/Math.h" @@ -19,6 +19,8 @@ #include "Game/collision/collide_room.h" #include "Game/collision/collide_item.h" +using namespace TEN::Collision::Sphere; + namespace TEN::Entities::Doors { void InitializeSteelDoor(short itemNumber) @@ -37,7 +39,7 @@ namespace TEN::Entities::Doors { if (TestBoundsCollide(doorItem, laraItem, coll->Setup.Radius)) { - if (TestCollision(doorItem, laraItem)) + if (HandleItemSphereCollision(*doorItem, *laraItem)) { if (coll->Setup.EnableObjectPush) ItemPushItem(doorItem, laraItem, coll, 0, 1); diff --git a/TombEngine/Objects/Generic/Doors/underwater_door.cpp b/TombEngine/Objects/Generic/Doors/underwater_door.cpp index e93b308bd..c6a7aac4f 100644 --- a/TombEngine/Objects/Generic/Doors/underwater_door.cpp +++ b/TombEngine/Objects/Generic/Doors/underwater_door.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/lot.h" diff --git a/TombEngine/Objects/Generic/Object/objects.cpp b/TombEngine/Objects/Generic/Object/objects.cpp index 5207da4f0..3a109f9b0 100644 --- a/TombEngine/Objects/Generic/Object/objects.cpp +++ b/TombEngine/Objects/Generic/Object/objects.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" diff --git a/TombEngine/Objects/Generic/Object/polerope.cpp b/TombEngine/Objects/Generic/Object/polerope.cpp index e8f5faf11..ff5826d1b 100644 --- a/TombEngine/Objects/Generic/Object/polerope.cpp +++ b/TombEngine/Objects/Generic/Object/polerope.cpp @@ -2,7 +2,7 @@ #include "Objects/Generic/Object/polerope.h" #include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/lot.h" @@ -15,6 +15,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Input; using namespace TEN::Math; @@ -119,7 +120,7 @@ namespace TEN::Entities::Generic // Test bounds collision. if (TestBoundsCollide(&poleItem, laraItem, LARA_RADIUS + (int)round(abs(laraItem->Animation.Velocity.z)))) { - if (TestCollision(&poleItem, laraItem)) + if (HandleItemSphereCollision(poleItem, *laraItem)) { // Temporarily reorient pole. short yOrient = poleItem.Pose.Orientation.y; diff --git a/TombEngine/Objects/Generic/Object/rope.cpp b/TombEngine/Objects/Generic/Object/rope.cpp index ce4b64671..4f1c4fd8e 100644 --- a/TombEngine/Objects/Generic/Object/rope.cpp +++ b/TombEngine/Objects/Generic/Object/rope.cpp @@ -10,7 +10,6 @@ #include "Game/Lara/lara.h" #include "Math/Math.h" #include "Game/collision/collide_room.h" -#include "Game/collision/sphere.h" #include "Objects/Generic/Object/rope.h" #include "Sound/sound.h" #include "Game/camera.h" diff --git a/TombEngine/Objects/Generic/Switches/switch.cpp b/TombEngine/Objects/Generic/Switches/switch.cpp index 19b2dc1c1..4a2ca8962 100644 --- a/TombEngine/Objects/Generic/Switches/switch.cpp +++ b/TombEngine/Objects/Generic/Switches/switch.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" #include "Game/control/lot.h" #include "Game/effects/debris.h" #include "Game/items.h" diff --git a/TombEngine/Objects/Generic/Traps/falling_block.cpp b/TombEngine/Objects/Generic/Traps/falling_block.cpp index ce6994747..61ed241e1 100644 --- a/TombEngine/Objects/Generic/Traps/falling_block.cpp +++ b/TombEngine/Objects/Generic/Traps/falling_block.cpp @@ -152,12 +152,11 @@ namespace TEN::Entities::Generic ShatterItem.yRot = item->Pose.Orientation.y; ShatterItem.meshIndex = Objects[item->ObjectNumber].meshIndex; ShatterItem.color = item->Model.Color; - ShatterItem.sphere.x = item->Pose.Position.x; - ShatterItem.sphere.y = item->Pose.Position.y - CLICK(1); // So debris won't spawn below floor - ShatterItem.sphere.z = item->Pose.Position.z; + ShatterItem.sphere.Center = item->Pose.Position.ToVector3(); + ShatterItem.sphere.Center.y -= CLICK(1); // Prevent debris from spawning below floor. ShatterItem.bit = 0; ShatterImpactData.impactDirection = Vector3(0, -(float)item->ItemFlags[1] / (float)FALLINGBLOCK_MAX_SPEED, 0); - ShatterImpactData.impactLocation = { (float)ShatterItem.sphere.x, (float)ShatterItem.sphere.y, (float)ShatterItem.sphere.z }; + ShatterImpactData.impactLocation = ShatterItem.sphere.Center; ShatterObject(&ShatterItem, nullptr, 0, item->RoomNumber, false); SoundEffect(SFX_TR4_ROCK_FALL_LAND, &item->Pose); diff --git a/TombEngine/Objects/TR2/Entity/Dragon.cpp b/TombEngine/Objects/TR2/Entity/Dragon.cpp index e4dc52f49..90e90a51c 100644 --- a/TombEngine/Objects/TR2/Entity/Dragon.cpp +++ b/TombEngine/Objects/TR2/Entity/Dragon.cpp @@ -4,7 +4,6 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/control/lot.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" diff --git a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp index 17c95d586..bb34b1716 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/items.h" #include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/box.h" #include "Game/control/lot.h" #include "Game/effects/smoke.h" @@ -19,6 +19,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Effects::Smoke; namespace TEN::Entities::Creatures::TR2 @@ -96,7 +97,7 @@ namespace TEN::Entities::Creatures::TR2 if (!TestBoundsCollide(&item, laraItem, coll->Setup.Radius)) return; - if (!TestCollision(&item, laraItem)) + if (!HandleItemSphereCollision(item, *laraItem)) return; if (coll->Setup.EnableObjectPush) diff --git a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp index 0032ae11b..d13a21f71 100644 --- a/TombEngine/Objects/TR2/Vehicles/skidoo.cpp +++ b/TombEngine/Objects/TR2/Vehicles/skidoo.cpp @@ -5,7 +5,6 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" #include "Game/effects/tomb4fx.h" diff --git a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp index e9807e149..7b7310172 100644 --- a/TombEngine/Objects/TR2/Vehicles/speedboat.cpp +++ b/TombEngine/Objects/TR2/Vehicles/speedboat.cpp @@ -5,7 +5,6 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/simple_particle.h" #include "Game/items.h" diff --git a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp index 31c011d34..00e6e74e5 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_mp_gun.cpp @@ -6,7 +6,6 @@ #include "Game/collision/Point.h" #include "Game/control/box.h" #include "Game/control/lot.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/itemdata/creature_info.h" #include "Game/items.h" diff --git a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp index f32925ff2..06bf326d6 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_tribesman.cpp @@ -2,7 +2,6 @@ #include "Objects/TR3/Entity/tr3_tribesman.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" #include "Game/control/box.h" #include "Game/effects/effects.h" #include "Game/itemdata/creature_info.h" diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp index d27b409ec..cba3931ea 100644 --- a/TombEngine/Objects/TR3/Object/corpse.cpp +++ b/TombEngine/Objects/TR3/Object/corpse.cpp @@ -9,7 +9,6 @@ #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" #include "Game/collision/floordata.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/Ripple.h" #include "Game/items.h" diff --git a/TombEngine/Objects/TR3/Trap/train.cpp b/TombEngine/Objects/TR3/Trap/train.cpp index aee8a2e81..94d29c5ce 100644 --- a/TombEngine/Objects/TR3/Trap/train.cpp +++ b/TombEngine/Objects/TR3/Trap/train.cpp @@ -8,7 +8,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" #include "Game/collision/floordata.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/effects/effects.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -18,6 +18,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; namespace TEN::Entities::Traps { @@ -108,8 +109,8 @@ namespace TEN::Entities::Traps if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) return; - if (!TestCollision(&item, playerItem)) - return; + if (!HandleItemSphereCollision(item, *playerItem)) + return; SoundEffect(SFX_TR4_LARA_GENERAL_DEATH, &playerItem->Pose, SoundEnvironment::Always); SoundEffect(SFX_TR4_LARA_HIGH_FALL_DEATH, &playerItem->Pose, SoundEnvironment::Always); diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index 118374c04..c0d4e8e88 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -3,9 +3,9 @@ #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" +#include "Game/collision/Sphere.h" #include "Game/effects/effects.h" #include "Game/effects/spark.h" #include "Game/effects/tomb4fx.h" @@ -22,6 +22,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; using namespace TEN::Effects::Spark; using namespace TEN::Input; using namespace TEN::Math; diff --git a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp index 4d63e4247..1b52158e4 100644 --- a/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp +++ b/TombEngine/Objects/TR3/Vehicles/rubber_boat.cpp @@ -5,7 +5,6 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/effects/Bubble.h" #include "Game/effects/effects.h" #include "Game/items.h" diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index dceac3961..d80b3c98b 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -3,10 +3,10 @@ #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" +#include "Game/collision/Sphere.h" #include "Game/control/box.h" #include "Game/control/los.h" #include "Game/effects/Bubble.h" @@ -28,6 +28,7 @@ #include "Specific/Input/Input.h" using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Streamer; using namespace TEN::Input; @@ -185,7 +186,7 @@ namespace TEN::Entities::Vehicles if (mountType == VehicleMountType::None) { // HACK: Collision in water behaves differently? @Sezz 2022.06.28 - if (TestBoundsCollide(UPVItem, laraItem, coll->Setup.Radius) && TestCollision(UPVItem, laraItem)) + if (TestBoundsCollide(UPVItem, laraItem, coll->Setup.Radius) && HandleItemSphereCollision(*UPVItem, *laraItem)) ItemPushItem(UPVItem, laraItem, coll, false, 0); } else diff --git a/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp b/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp index a2754fb84..71284ef93 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_ahmet.cpp @@ -1,7 +1,7 @@ #include "framework.h" #include "Objects/TR4/Entity/tr4_ahmet.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/control/lot.h" @@ -17,6 +17,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Effects::Environment; using namespace TEN::Math; @@ -80,26 +81,21 @@ namespace TEN::Entities::TR4 static void TriggerAhmetDeathEffect(ItemInfo* item) { - // HACK: Using CreatureSpheres here in release mode results in total mess-up - // of LaraSpheres, which in-game appears as a ghostly Lara fire silhouette. - // Later, both CreatureSpheres and LaraSpheres globals should be eradicated. - - static SPHERE spheres[MAX_SPHERES] = {}; - if (!(Wibble & 7)) { - int meshCount = GetSpheres(item, spheres, SPHERES_SPACE_WORLD, Matrix::Identity); - auto sphere = &spheres[(Wibble / 8) & 1]; - for (int i = meshCount; i > 0; i--, sphere += 2) - TriggerFireFlame(sphere->x, sphere->y, sphere->z, FlameType::Medium); + auto spheres = item->GetSpheres(); + const auto* spherePtr = &spheres[(Wibble / 8) & 1]; + + // TODO + for (int i = (int)spheres.size(); i > 0; i--, spherePtr += 2) + TriggerFireFlame(spherePtr->Center.x, spherePtr->Center.y, spherePtr->Center.z, FlameType::Medium); } TriggerDynamicLight( item->Pose.Position.x, item->Pose.Position.y - CLICK(1), item->Pose.Position.z, - 13, (GetRandomControl() & 0x3F) - 64, (GetRandomControl() & 0x1F) + 96, 0 - ); + 13, (GetRandomControl() & 0x3F) - 64, (GetRandomControl() & 0x1F) + 96, 0); SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item->Pose); } diff --git a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp index c486535a6..b0815a528 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_horseman.cpp @@ -4,7 +4,6 @@ #include "Game/animation.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/control/box.h" #include "Game/control/control.h" #include "Game/effects/debris.h" @@ -354,7 +353,7 @@ namespace TEN::Entities::TR4 SoundEffect(SFX_TR4_HORSEMAN_TAKEHIT, &item->Pose); SoundEffect(SFX_TR4_HORSE_RICOCHET, &item->Pose); - auto pos = GetJointPosition(item, SPHERES_SPACE_WORLD, Vector3i(0, -128, 80)); + auto pos = GetJointPosition(item, 0, Vector3i(0, -128, 80)); HorsemanSparks(&pos, item->Pose.Orientation.y, 7); } else if (Random::TestProbability(1 / 8.0f)) diff --git a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp index 41cc2809d..3db6fd88a 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp @@ -2,7 +2,6 @@ #include "Objects/TR4/Entity/tr4_mutant.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/itemdata/creature_info.h" diff --git a/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp b/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp index 5bb0117ff..4ef807d66 100644 --- a/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_element_puzzle.cpp @@ -1,12 +1,13 @@ #include "framework.h" #include "tr4_element_puzzle.h" + #include "Specific/level.h" +#include "Game/Collision/Sphere.h" #include "Game/control/control.h" #include "Sound/sound.h" #include "Game/animation.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_helpers.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Specific/Input/Input.h" @@ -15,6 +16,7 @@ #include "Game/collision/collide_item.h" #include "Game/items.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Input; using namespace TEN::Entities::Switches; @@ -149,7 +151,7 @@ namespace TEN::Entities::TR4 if (TestBoundsCollide(item, laraItem, coll->Setup.Radius)) { - if (TestCollision(item, laraItem)) + if (HandleItemSphereCollision(*item, *laraItem)) { if (coll->Setup.EnableObjectPush) ItemPushItem(item, laraItem, coll, false, 0); diff --git a/TombEngine/Objects/TR4/Object/tr4_mapper.cpp b/TombEngine/Objects/TR4/Object/tr4_mapper.cpp index faf2fe1f0..27d8f26fa 100644 --- a/TombEngine/Objects/TR4/Object/tr4_mapper.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_mapper.cpp @@ -7,7 +7,6 @@ #include "Sound/sound.h" #include "Game/animation.h" #include "Game/Lara/lara.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/items.h" #include "Renderer/RendererEnums.h" @@ -34,7 +33,7 @@ namespace TEN::Entities::TR4 item->MeshBits |= 2; - auto pos = GetJointPosition(item, SPHERES_SPACE_WORLD); + auto pos = GetJointPosition(item, 0); byte color = (GetRandomControl() & 0x1F) + 192; TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 3) + 16, color, color, 0); diff --git a/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp b/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp index ac0bc9a2d..6db8d0843 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyCeiling.cpp @@ -5,7 +5,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -13,7 +13,7 @@ #include "Sound/sound.h" #include "Specific/level.h" -using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; namespace TEN::Entities::Traps { @@ -80,7 +80,7 @@ namespace TEN::Entities::Traps if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) return; - TestCollision(&item, playerItem); + HandleItemSphereCollision(item, *playerItem); } else if (item.Status != ITEM_INVISIBLE) { diff --git a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp index 7f707153f..225b5efe1 100644 --- a/TombEngine/Objects/TR4/Trap/SpikyWall.cpp +++ b/TombEngine/Objects/TR4/Trap/SpikyWall.cpp @@ -4,7 +4,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/control.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" @@ -16,6 +16,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; using namespace TEN::Math; // NOTES: @@ -131,7 +132,7 @@ namespace TEN::Entities::Traps if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) return; - TestCollision(&item, playerItem); + HandleItemSphereCollision(item, *playerItem); } else if (item.Status != ITEM_INVISIBLE) { diff --git a/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp b/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp index b46ff97a3..0a025cd1a 100644 --- a/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp +++ b/TombEngine/Objects/TR4/Trap/SquishyBlock.cpp @@ -6,7 +6,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -17,6 +17,7 @@ #include "Specific/level.h" using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; // NOTES: // item.ItemFlags[0]: use dynamic motion. @@ -175,7 +176,7 @@ namespace TEN::Entities::Traps if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) return; - if (!TestCollision(&item, playerItem)) + if (!HandleItemSphereCollision(item, *playerItem)) return; if (!ItemPushItem(&item, playerItem, coll, false, 1)) @@ -201,7 +202,7 @@ namespace TEN::Entities::Traps if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius)) return; - if (!TestCollision(&item, playerItem)) + if (!HandleItemSphereCollision(item, *playerItem)) return; if ((item.Animation.FrameNumber - GetAnimData(item).frameBase) <= FALLING_BLOCK_IMPACT_FRAME) diff --git a/TombEngine/Objects/TR4/Trap/tr4_chain.cpp b/TombEngine/Objects/TR4/Trap/tr4_chain.cpp index d6f650447..e58a2c0a3 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_chain.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_chain.cpp @@ -19,7 +19,7 @@ namespace TEN::Entities::Traps if (TriggerActive(&item)) { - *((int*)&item.ItemFlags[0]) = 0x787E; + *(int*)&item.ItemFlags[0] = 0x787E; AnimateItem(&item); return; } @@ -30,12 +30,12 @@ namespace TEN::Entities::Traps if (TriggerActive(&item)) { - *((int*)&item.ItemFlags[0]) = 0x780; + *(int*)&item.ItemFlags[0] = 0x780; AnimateItem(&item); return; } } - *((int*)&item.ItemFlags[0]) = 0; + *(int*)&item.ItemFlags[0] = 0; } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp b/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp index 773134cf9..526dfab17 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_hammer.cpp @@ -2,7 +2,6 @@ #include "Objects/TR4/Trap/tr4_hammer.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" #include "Game/control/control.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" diff --git a/TombEngine/Objects/TR4/Trap/tr4_mine.cpp b/TombEngine/Objects/TR4/Trap/tr4_mine.cpp index 5601c2c8e..63266999b 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_mine.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_mine.cpp @@ -2,7 +2,7 @@ #include "Objects/TR4/Trap/tr4_mine.h" #include "Game/collision/collide_item.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" @@ -12,6 +12,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Effects::Environment; namespace TEN::Entities::Traps @@ -28,30 +29,29 @@ namespace TEN::Entities::Traps { auto& item = g_Level.Items[itemNumber]; - int sphereCount = GetSpheres(&item, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity); + auto spheres = item.GetSpheres(); if (item.ItemFlags[0] >= 150) { SoundEffect(SFX_TR4_EXPLOSION1, &item.Pose); SoundEffect(SFX_TR4_EXPLOSION2, &item.Pose); SoundEffect(SFX_TR4_EXPLOSION1, &item.Pose, SoundEnvironment::Land, 0.7f, 0.5f); - if (sphereCount > 0) + if (!spheres.empty()) { - for (int i = 0; i < sphereCount; i++) + for (int i = 0; i < spheres.size(); i++) { + // TODO: Hardcoding. if (i >= 7 && i != 9) { - auto& sphere = CreatureSpheres[i]; + const auto& sphere = spheres[i]; - auto pose = Pose(Vector3i(sphere.x, sphere.y, sphere.z)); - - TriggerExplosionSparks(sphere.x, sphere.y, sphere.z, 3, -2, 0, -item.RoomNumber); - TriggerExplosionSparks(sphere.x, sphere.y, sphere.z, 3, -1, 0, -item.RoomNumber); - TriggerShockwave(&pose, 48, 304, (GetRandomControl() & 0x1F) + 112, 0, 96, 128, 32, EulerAngles(ANGLE(11.25f), 0, 0), 0, true, false, false, (int)ShockwaveStyle::Normal); + TriggerExplosionSparks(sphere.Center.x, sphere.Center.y, sphere.Center.z, 3, -2, 0, -item.RoomNumber); + TriggerExplosionSparks(sphere.Center.x, sphere.Center.y, sphere.Center.z, 3, -1, 0, -item.RoomNumber); + TriggerShockwave(&Pose(Vector3i(sphere.Center)), 48, 304, (GetRandomControl() & 0x1F) + 112, 0, 96, 128, 32, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); } } - for (int i = 0; i < sphereCount; i++) + for (int i = 0; i < spheres.size(); i++) ExplodeItemNode(&item, i, 0, -128); } @@ -80,12 +80,12 @@ namespace TEN::Entities::Traps if (fade > 255) fade = 0; - for (int i = 0; i < sphereCount; i++) + for (int i = 0; i < spheres.size(); i++) { if (i == 0 || i > 5) { - auto& sphere = CreatureSpheres[i]; - AddFire(sphere.x, sphere.y, sphere.z, item.RoomNumber, 0.25f, fade); + const auto& sphere = spheres[i]; + AddFire(sphere.Center.x, sphere.Center.y, sphere.Center.z, item.RoomNumber, 0.25f, fade); } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp b/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp index 48064341d..652f10943 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_moving_blade.cpp @@ -3,7 +3,6 @@ #include "Game/animation.h" #include "Game/control/control.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/items.h" #include "Game/Lara/lara.h" diff --git a/TombEngine/Objects/TR4/Trap/tr4_stargate.cpp b/TombEngine/Objects/TR4/Trap/tr4_stargate.cpp index 4e2956f2e..606015596 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_stargate.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_stargate.cpp @@ -4,7 +4,7 @@ #include "Game/animation.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -12,6 +12,8 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Sphere; + namespace TEN::Entities::Traps { constexpr auto STARGATE_HARM_DAMAGE = 100; @@ -61,12 +63,13 @@ namespace TEN::Entities::Traps if (!TestBoundsCollide(item, laraItem, coll->Setup.Radius)) return; - if (TestCollision(item, laraItem) && + if (HandleItemSphereCollision(*item, *laraItem) && TriggerActive(item) && item->Animation.FrameNumber > GetAnimData(item).frameBase + 20 && // Hardcoded frame range. item->Animation.FrameNumber < GetAnimData(item).frameBase + 60) { // Blades deal damage cumulatively. + auto spheres = item->GetSpheres(); for (int i = 0; i < StargateHarmJoints.size(); i++) { if (item->TouchBits.Test(StargateHarmJoints[i])) @@ -74,7 +77,7 @@ namespace TEN::Entities::Traps DoDamage(laraItem, STARGATE_HARM_DAMAGE); DoBloodSplat( (GetRandomControl() & 0x3F) + laraItem->Pose.Position.x - 32, - (GetRandomControl() & 0x1F) + CreatureSpheres[i].y - 16, + (GetRandomControl() & 0x1F) + spheres[i].Center.y - 16, (GetRandomControl() & 0x3F) + laraItem->Pose.Position.z - 32, (GetRandomControl() & 3) + 2, GetRandomControl() * 2, diff --git a/TombEngine/Objects/TR5/Entity/AutoGun.cpp b/TombEngine/Objects/TR5/Entity/AutoGun.cpp index 6ed1cb87c..03c1b9d3b 100644 --- a/TombEngine/Objects/TR5/Entity/AutoGun.cpp +++ b/TombEngine/Objects/TR5/Entity/AutoGun.cpp @@ -2,7 +2,7 @@ #include "Objects/TR5/Entity/AutoGun.h" #include "Game/animation.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/los.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" @@ -14,6 +14,7 @@ #include "Sound/sound.h" #include "Specific/level.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Math; // NOTES: diff --git a/TombEngine/Objects/TR5/Object/tr5_missile.cpp b/TombEngine/Objects/TR5/Object/tr5_missile.cpp index 838dd04fd..8bcffe8d7 100644 --- a/TombEngine/Objects/TR5/Object/tr5_missile.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_missile.cpp @@ -3,7 +3,6 @@ #include "Game/items.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/effects.h" #include "Specific/level.h" @@ -210,9 +209,7 @@ void ExplodeFX(FX_INFO* fx, int noXZVel, int bits) ShatterItem.yRot = fx->pos.Orientation.y; ShatterItem.meshIndex = fx->frameNumber; ShatterItem.color = Vector4::One; - ShatterItem.sphere.x = fx->pos.Position.x; - ShatterItem.sphere.y = fx->pos.Position.y; - ShatterItem.sphere.z = fx->pos.Position.z; + ShatterItem.sphere.Center = fx->pos.Position.ToVector3(); ShatterItem.bit = 0; ShatterItem.flags = fx->flag2 & 0x1400; diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index f7e3b7211..82f200631 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -5,7 +5,7 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/control.h" #include "Game/effects/effects.h" #include "Game/items.h" @@ -18,6 +18,8 @@ using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; + constexpr auto ROLLING_BALL_MAX_VELOCITY = BLOCK(3); void RollingBallCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) @@ -25,7 +27,7 @@ void RollingBallCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* c auto* ballItem = &g_Level.Items[itemNumber]; if (!TestBoundsCollide(ballItem, laraItem, coll->Setup.Radius) || - !TestCollision(ballItem, laraItem)) + !HandleItemSphereCollision(*ballItem, *laraItem)) { return; } @@ -322,7 +324,7 @@ void ClassicRollingBallCollision(short itemNum, ItemInfo* lara, CollisionInfo* c if (!TestBoundsCollide(item, lara, coll->Setup.Radius)) return; - if (!TestCollision(item, lara)) + if (!HandleItemSphereCollision(*item, *lara)) return; if (lara->Animation.IsAirborne) diff --git a/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp b/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp index 6774daacc..55909c4ca 100644 --- a/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp +++ b/TombEngine/Objects/TR5/Trap/tr5_wreckingball.cpp @@ -5,7 +5,6 @@ #include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" -#include "Game/collision/sphere.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/weather.h" diff --git a/TombEngine/Objects/Utils/VehicleHelpers.cpp b/TombEngine/Objects/Utils/VehicleHelpers.cpp index d2a121bb7..3f0244684 100644 --- a/TombEngine/Objects/Utils/VehicleHelpers.cpp +++ b/TombEngine/Objects/Utils/VehicleHelpers.cpp @@ -3,7 +3,7 @@ #include "Game/collision/collide_item.h" #include "Game/collision/Point.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/effects/simple_particle.h" #include "Game/effects/Streamer.h" #include "Game/effects/tomb4fx.h" @@ -17,6 +17,7 @@ #include "Specific/Input/Input.h" using namespace TEN::Collision::Point; +using namespace TEN::Collision::Sphere; using namespace TEN::Effects::Streamer; using namespace TEN::Hud; using namespace TEN::Input; @@ -56,7 +57,7 @@ namespace TEN::Entities::Vehicles return VehicleMountType::None; // Assess object collision. - if (!TestBoundsCollide(vehicleItem, laraItem, coll->Setup.Radius) || !TestCollision(vehicleItem, laraItem)) + if (!TestBoundsCollide(vehicleItem, laraItem, coll->Setup.Radius) || !HandleItemSphereCollision(*vehicleItem, *laraItem)) return VehicleMountType::None; bool hasInputAction = IsHeld(In::Action); diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index db408b8a5..d93bc635a 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -68,6 +68,7 @@ #include "Graphics/Vertices/PostProcessVertex.h" enum GAME_OBJECT_ID : short; +enum class SphereSpaceType; class EulerAngles; struct AnimFrameInterpData; struct CAMERA_INFO; @@ -628,7 +629,7 @@ namespace TEN::Renderer void FlipRooms(short roomNumber1, short roomNumber2); void UpdateLaraAnimations(bool force); void UpdateItemAnimations(int itemNumber, bool force); - int GetSpheres(short itemNumber, BoundingSphere* ptr, char worldSpace, Matrix local); + std::vector GetSpheres(int itemNumber); void GetBoneMatrix(short itemNumber, int jointIndex, Matrix* outMatrix); void DrawObjectIn2DSpace(int objectNumber, Vector2 pos2D, EulerAngles orient, float scale1, float opacity = 1.0f, int meshBits = NO_JOINT_BITS); void SetLoadingScreen(std::wstring& fileName); diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 525a4631f..c746d528f 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -4,7 +4,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/effects/effects.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -14,6 +14,7 @@ #include "Specific/level.h" #include "Renderer/RenderView.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Math; namespace TEN::Renderer @@ -361,11 +362,10 @@ namespace TEN::Renderer if (obj.ShadowType == ShadowMode::None) { // Get all spheres and check if frustum intersects any of them. - static BoundingSphere spheres[MAX_BONES]; - int cnt = GetSpheres(itemNum, spheres, SPHERES_SPACE_WORLD, Matrix::Identity); + auto spheres = GetSpheres(itemNum); bool inFrustum = false; - for (int i = 0; !inFrustum, i < cnt; i++) + for (int i = 0; !inFrustum, i < spheres.size(); i++) // Blow up sphere radius by half for cases of too small calculated spheres. if (renderView.Camera.Frustum.SphereInFrustum(spheres[i].Center, spheres[i].Radius * 1.5f)) inFrustum = true; diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 490a0b48d..85d17338b 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -9,7 +9,7 @@ #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Game/animation.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/control/control.h" #include "Game/itemdata/creature_info.h" #include "Game/items.h" @@ -34,6 +34,7 @@ #include "Specific/level.h" #include "Specific/trutils.h" +using namespace TEN::Collision::Sphere; using namespace TEN::Math; extern GameConfiguration g_Configuration; @@ -408,17 +409,16 @@ namespace TEN::Renderer return _meshes[meshIndex]; } - int Renderer::GetSpheres(short itemNumber, BoundingSphere* spheres, char worldSpace, Matrix local) + std::vector Renderer::GetSpheres(int itemNumber) { - auto* itemToDraw = &_items[itemNumber]; - auto* nativeItem = &g_Level.Items[itemNumber]; + auto& itemToDraw = _items[itemNumber]; + itemToDraw.ItemNumber = itemNumber; - itemToDraw->ItemNumber = itemNumber; + const auto* nativeItem = &g_Level.Items[itemNumber]; + if (nativeItem == nullptr) + return {}; - if (!nativeItem) - return 0; - - if (!itemToDraw->DoneAnimations) + if (!itemToDraw.DoneAnimations) { if (itemNumber == LaraItem->Index) { @@ -430,38 +430,26 @@ namespace TEN::Renderer } } - auto world = Matrix::Identity; - if (worldSpace & SPHERES_SPACE_WORLD) + auto translationMatrix = Matrix::CreateTranslation(nativeItem->Pose.Position.ToVector3()); + auto rotMatrix = nativeItem->Pose.Orientation.ToRotationMatrix(); + auto worldMatrix = rotMatrix * translationMatrix; + + const auto& moveable = GetRendererObject(nativeItem->ObjectNumber); + + // Collect spheres. + auto spheres = std::vector{}; + for (int i = 0; i < moveable.ObjectMeshes.size(); i++) { - world = Matrix::CreateTranslation(nativeItem->Pose.Position.x, nativeItem->Pose.Position.y, nativeItem->Pose.Position.z) * local; + const auto& mesh = *moveable.ObjectMeshes[i]; + + const auto& translationMatrix = itemToDraw.AnimationTransforms[i]; + auto pos = Vector3::Transform(mesh.Sphere.Center, translationMatrix * worldMatrix); + + auto sphere = BoundingSphere(pos, mesh.Sphere.Radius); + spheres.push_back(sphere); } - else - { - world = Matrix::Identity * local; - } - - world = nativeItem->Pose.Orientation.ToRotationMatrix() * world; - - auto& moveable = GetRendererObject(nativeItem->ObjectNumber); - - for (int i = 0; i< moveable.ObjectMeshes.size();i++) - { - auto mesh = moveable.ObjectMeshes[i]; - - auto pos = (Vector3)mesh->Sphere.Center; - if (worldSpace & SPHERES_SPACE_BONE_ORIGIN) - pos += moveable.LinearizedBones[i]->Translation; - - spheres[i].Center = Vector3::Transform(pos, (itemToDraw->AnimationTransforms[i] * world)); - spheres[i].Radius = mesh->Sphere.Radius; - - // Spheres debug - // auto v1 = Vector3(spheres[i].Center.x - spheres[i].Radius, spheres[i].Center.y, spheres[i].Center.z); - // auto v2 = Vector3(spheres[i].Center.x + spheres[i].Radius, spheres[i].Center.y, spheres[i].Center.z); - // AddDebugLine(v1, v2, Vector4::One); - } - - return (int)moveable.ObjectMeshes.size(); + + return spheres; } void Renderer::GetBoneMatrix(short itemNumber, int jointIndex, Matrix* outMatrix) diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index 5a09c030e..e72079083 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -9,7 +9,7 @@ #include "Game/control/control.h" #include "Game/spotcam.h" #include "Game/camera.h" -#include "Game/collision/sphere.h" +#include "Game/collision/Sphere.h" #include "Game/Setup.h" #include "Math/Math.h" #include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index aa6f981f4..cbe3d8e1b 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -340,6 +340,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + @@ -377,7 +378,6 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - @@ -862,7 +862,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" - + From f85769f3ca22bb89c562603db86aefd70b22a7b7 Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Sat, 17 Aug 2024 19:10:04 +0200 Subject: [PATCH 274/410] Update RendererCompatibility.cpp --- TombEngine/Renderer/RendererCompatibility.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp index 292251d69..79e93a3f6 100644 --- a/TombEngine/Renderer/RendererCompatibility.cpp +++ b/TombEngine/Renderer/RendererCompatibility.cpp @@ -723,14 +723,11 @@ namespace TEN::Renderer for (int v2 = 0; v2 < parentBucket->NumVertices; v2++) { auto* parentVertex = &_moveablesVertices[parentBucket->StartVertex + v2]; - if (isYoung) + if (isYoung && parentVertex->OriginalIndex == parentVertices1[currentVertex->OriginalIndex]) { - if (parentVertex->OriginalIndex == parentVertices1[currentVertex->OriginalIndex]) - { - currentVertex->Bone = 0; - currentVertex->Position = parentVertex->Position; - currentVertex->Normal = parentVertex->Normal; - } + currentVertex->Bone = 0; + currentVertex->Position = parentVertex->Position; + currentVertex->Normal = parentVertex->Normal; } else if (parentVertex->OriginalIndex == parentVertices0[currentVertex->OriginalIndex]) { @@ -805,17 +802,20 @@ namespace TEN::Renderer auto* parentMesh = skinObj.ObjectMeshes[LM_HEAD]; auto* parentBone = skinObj.LinearizedBones[LM_HEAD]; - for (int b2 = 0; b2 < parentMesh->Buckets.size(); b2++) + if (currentVertex->OriginalIndex < 4) { - auto* parentBucket = &parentMesh->Buckets[b2]; - for (int v2 = 0; v2 < parentBucket->NumVertices; v2++) + for (int b2 = 0; b2 < parentMesh->Buckets.size(); b2++) { - auto* parentVertex = &_moveablesVertices[parentBucket->StartVertex + v2]; - if (isYoung && parentVertex->OriginalIndex == parentVertices2[currentVertex->OriginalIndex]) + auto* parentBucket = &parentMesh->Buckets[b2]; + for (int v2 = 0; v2 < parentBucket->NumVertices; v2++) { - currentVertex->Bone = 0; - currentVertex->Position = parentVertex->Position; - currentVertex->Normal = parentVertex->Normal; + auto* parentVertex = &_moveablesVertices[parentBucket->StartVertex + v2]; + if (isYoung && parentVertex->OriginalIndex == parentVertices2[currentVertex->OriginalIndex]) + { + currentVertex->Bone = 0; + currentVertex->Position = parentVertex->Position; + currentVertex->Normal = parentVertex->Normal; + } } } } From 806c052ff560353a979af84f865f2e2ac3e922bc Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 18 Aug 2024 22:58:50 +1000 Subject: [PATCH 275/410] Fix GetBoneOrientation() --- TombEngine/Game/animation.cpp | 13 ++----- TombEngine/Game/effects/hair.cpp | 2 +- TombEngine/Renderer/Renderer.h | 6 ++- TombEngine/Renderer/RendererHelper.cpp | 38 +++++++++++++------ TombEngine/Renderer/Structures/RendererItem.h | 8 ++-- 5 files changed, 38 insertions(+), 29 deletions(-) diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 0db8e490f..f4fb1869a 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -711,7 +711,7 @@ void ClampRotation(Pose& outPose, short angle, short rotation) Vector3i GetJointPosition(const ItemInfo& item, int jointIndex, const Vector3i& relOffset) { // Use matrices done in renderer to transform relative offset. - return Vector3i(g_Renderer.GetAbsEntityBonePosition(item.Index, jointIndex, relOffset.ToVector3())); + return Vector3i(g_Renderer.GetMoveableBonePosition(item.Index, jointIndex, relOffset.ToVector3())); } Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOffset) @@ -737,16 +737,9 @@ Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex) return Vector3(*(bonePtr + 1), *(bonePtr + 2), *(bonePtr + 3)); } -Quaternion GetBoneOrientation(const ItemInfo& item, int boneIndex) +Quaternion GetBoneOrientation(const ItemInfo& item, int boneID) { - static const auto REF_DIRECTION = Vector3::UnitZ; - - auto origin = g_Renderer.GetAbsEntityBonePosition(item.Index, boneIndex); - auto target = g_Renderer.GetAbsEntityBonePosition(item.Index, boneIndex, REF_DIRECTION); - - auto direction = target - origin; - direction.Normalize(); - return Geometry::ConvertDirectionToQuat(direction); + return g_Renderer.GetMoveableBoneOrientation(item.Index, boneID); } // NOTE: Will not work for bones at ends of hierarchies. diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index abe1bc940..33cf2dd46 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -37,7 +37,7 @@ namespace TEN::Effects::Hair worldMatrix = Matrix::CreateTranslation(relOffset) * worldMatrix; // Use player's head bone orientation as base. - auto baseOrient = Geometry::ConvertDirectionToQuat(-Geometry::ConvertQuatToDirection(GetBoneOrientation(item, LM_HEAD))); + auto baseOrient = Geometry::ConvertDirectionToQuat(-Geometry::ConvertQuatToDirection(GetBoneOrientation(item, LM_HEAD))) * item.Pose.Orientation.ToQuaternion(); // Set position of base segment. Segments[0].Position = worldMatrix.Translation(); diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index d93bc635a..c4ecdcdb4 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -638,9 +638,11 @@ namespace TEN::Renderer Vector2i GetScreenResolution() const; std::optional Get2DPosition(const Vector3& pos) const; - Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero); std::pair GetRay(const Vector2& pos) const; - + + Vector3 GetMoveableBonePosition(int itemNumber, int boneID, const Vector3& relOffset = Vector3::Zero); + Quaternion GetMoveableBoneOrientation(int itemNumber, int boneID); + void AddDisplaySprite(const RendererSprite& sprite, const Vector2& pos2D, short orient, const Vector2& size, const Vector4& color, int priority, BlendMode blendMode, const Vector2& aspectCorrection, RenderView& renderView); void CollectDisplaySprites(RenderView& renderView); diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 85d17338b..c34040661 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -95,6 +95,10 @@ namespace TEN::Renderer rotMatrix = Matrix::CreateFromQuaternion(quat3); } + // Store bone orientation on current frame. + if (rItem != nullptr) + rItem->BoneOrientations[bonePtr->Index] = Quaternion::CreateFromRotationMatrix(rotMatrix); + auto tMatrix = (bonePtr == rObject.Skeleton) ? Matrix::CreateTranslation(offset0) : Matrix::Identity; auto extraRotMatrix = Matrix::CreateFromQuaternion(bonePtr->ExtraRotation); @@ -549,30 +553,40 @@ namespace TEN::Renderer return std::pair(nearPoint, farPoint); } - Vector3 Renderer::GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset) + Vector3 Renderer::GetMoveableBonePosition(int itemNumber, int boneID, const Vector3& relOffset) { auto* rendererItem = &_items[itemNumber]; - rendererItem->ItemNumber = itemNumber; - if (!rendererItem) + if (rendererItem == nullptr) return Vector3::Zero; if (!rendererItem->DoneAnimations) - { - if (itemNumber == LaraItem->Index) - UpdateLaraAnimations(false); - else - UpdateItemAnimations(itemNumber, false); - } + (itemNumber == LaraItem->Index) ? UpdateLaraAnimations(false) : UpdateItemAnimations(itemNumber, false); - if (jointIndex >= MAX_BONES) - jointIndex = 0; + if (boneID >= MAX_BONES) + boneID = 0; - auto world = rendererItem->AnimationTransforms[jointIndex] * rendererItem->World; + auto world = rendererItem->AnimationTransforms[boneID] * rendererItem->World; return Vector3::Transform(relOffset, world); } + Quaternion Renderer::GetMoveableBoneOrientation(int itemNumber, int boneID) + { + const auto* rendererItem = &_items[itemNumber]; + + if (rendererItem == nullptr) + return Quaternion::Identity; + + if (!rendererItem->DoneAnimations) + (itemNumber == LaraItem->Index) ? UpdateLaraAnimations(false) : UpdateItemAnimations(itemNumber, false); + + if (boneID >= MAX_BONES) + boneID = 0; + + return rendererItem->BoneOrientations[boneID]; + } + void Renderer::SaveScreenshot() { char buffer[64]; diff --git a/TombEngine/Renderer/Structures/RendererItem.h b/TombEngine/Renderer/Structures/RendererItem.h index 48780aa27..b4c974e22 100644 --- a/TombEngine/Renderer/Structures/RendererItem.h +++ b/TombEngine/Renderer/Structures/RendererItem.h @@ -1,13 +1,11 @@ #pragma once -#include + +#include "Game/room.h" #include "Renderer/RendererEnums.h" #include "Renderer/Structures/RendererLight.h" -#include "Game/room.h" namespace TEN::Renderer::Structures { - using namespace DirectX::SimpleMath; - struct RendererItem { int ItemNumber; @@ -20,6 +18,8 @@ namespace TEN::Renderer::Structures Matrix Scale; Matrix AnimationTransforms[MAX_BONES]; + Quaternion BoneOrientations[MAX_BONES]; + int RoomNumber = NO_VALUE; int PrevRoomNumber = NO_VALUE; Vector4 Color; From b46641a2cff2fd689b82bfc21beaaa173737c2f9 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 21 Aug 2024 06:03:30 +0200 Subject: [PATCH 276/410] Fixed flickering frame on camera transition --- TombEngine/Game/camera.cpp | 15 +++++++++++- TombEngine/Game/camera.h | 2 ++ TombEngine/Renderer/RendererDraw.cpp | 36 ++++++++++++++++++++-------- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index eea1c889f..9fcc0a9a3 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -254,6 +254,7 @@ void InitializeCamera() Camera.bounce = 0; Camera.number = -1; Camera.fixedCamera = false; + Camera.disableInterpolation = true; AlterFOV(ANGLE(DEFAULT_FOV)); @@ -1085,7 +1086,9 @@ void CalculateCamera(const CollisionInfo& coll) { Camera.type = CameraType::Fixed; if (Camera.oldType != CameraType::Fixed) + { Camera.speed = 1; + } } // Camera is in a water room, play water sound effect. @@ -1167,7 +1170,6 @@ void CalculateCamera(const CollisionInfo& coll) Lara.ExtraTorsoRot.x = Lara.ExtraHeadRot.x; Lara.Control.Look.Orientation = lookOrient; - Camera.type = CameraType::Look; Camera.item->LookedAt = true; } @@ -1291,6 +1293,17 @@ void CalculateCamera(const CollisionInfo& coll) Camera.fixedCamera = isFixedCamera; Camera.last = Camera.number; + if (Camera.lastType != Camera.type) + { + Camera.disableInterpolation = true; + } + else + { + Camera.disableInterpolation = false; + } + + Camera.lastType = Camera.type; + if ((Camera.type != CameraType::Heavy || Camera.timer == -1) && LaraItem->HitPoints > 0) { diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 969dec236..7424dac5b 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -24,6 +24,7 @@ struct CAMERA_INFO GameVector target; CameraType type; CameraType oldType; + CameraType lastType; int shift; int flags; bool fixedCamera; @@ -45,6 +46,7 @@ struct CAMERA_INFO ItemInfo* lastItem; int mikeAtLara; Vector3i mikePos; + bool disableInterpolation; }; struct ObjectCameraInfo diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 3ff2b7d28..f109018fe 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3041,21 +3041,37 @@ namespace TEN::Renderer { //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); + _interpolationFactor = interpFactor; + // Interpolate camera. - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); - _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; - _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; - _gameCamera.Camera.Frustum=_currentGameCamera.Camera.Frustum; + if (!Camera.disableInterpolation) + { + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = Lerp(_oldGameCamera.Camera.FOV, _currentGameCamera.Camera.FOV,interpFactor); + _gameCamera.Camera.Frustum.Update(_gameCamera.Camera.View, _gameCamera.Camera.Projection); + } + else + { + _gameCamera.Camera.WorldPosition = _currentGameCamera.Camera.WorldPosition; + _gameCamera.Camera.WorldDirection = _currentGameCamera.Camera.WorldDirection; + _gameCamera.Camera.View = _currentGameCamera.Camera.View; + _gameCamera.Camera.Projection = _currentGameCamera.Camera.Projection; + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; + _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; + + Camera.disableInterpolation = false; + } + _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - - _interpolationFactor = interpFactor; - + RenderScene(&_backBuffer, true, _gameCamera); _context->ClearState(); From 39a52d26a4e3f5d8637c1ad04c8eb16972d2f406 Mon Sep 17 00:00:00 2001 From: Sezz Date: Wed, 21 Aug 2024 17:38:24 +1000 Subject: [PATCH 277/410] Formatting --- TombEngine/Game/camera.cpp | 15 ++------------- TombEngine/Game/camera.h | 3 ++- TombEngine/Renderer/RendererDraw.cpp | 6 ++---- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 9fcc0a9a3..a0c19fdf1 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -254,7 +254,7 @@ void InitializeCamera() Camera.bounce = 0; Camera.number = -1; Camera.fixedCamera = false; - Camera.disableInterpolation = true; + Camera.DisableInterpolation = true; AlterFOV(ANGLE(DEFAULT_FOV)); @@ -1086,9 +1086,7 @@ void CalculateCamera(const CollisionInfo& coll) { Camera.type = CameraType::Fixed; if (Camera.oldType != CameraType::Fixed) - { Camera.speed = 1; - } } // Camera is in a water room, play water sound effect. @@ -1292,16 +1290,7 @@ void CalculateCamera(const CollisionInfo& coll) Camera.fixedCamera = isFixedCamera; Camera.last = Camera.number; - - if (Camera.lastType != Camera.type) - { - Camera.disableInterpolation = true; - } - else - { - Camera.disableInterpolation = false; - } - + Camera.DisableInterpolation = (Camera.lastType != Camera.type); Camera.lastType = Camera.type; if ((Camera.type != CameraType::Heavy || Camera.timer == -1) && diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 7424dac5b..9c65b8177 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -46,7 +46,8 @@ struct CAMERA_INFO ItemInfo* lastItem; int mikeAtLara; Vector3i mikePos; - bool disableInterpolation; + + bool DisableInterpolation = false; }; struct ObjectCameraInfo diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 0315bb05d..01af676d9 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3039,12 +3039,10 @@ namespace TEN::Renderer void Renderer::Render(float interpFactor) { - //RenderToCubemap(reflectionCubemap, Vector3(LaraItem->pos.xPos, LaraItem->pos.yPos - 1024, LaraItem->pos.zPos), LaraItem->roomNumber); - _interpolationFactor = interpFactor; // Interpolate camera. - if (!Camera.disableInterpolation) + if (!Camera.DisableInterpolation) { _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); @@ -3064,7 +3062,7 @@ namespace TEN::Renderer _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; - Camera.disableInterpolation = false; + Camera.DisableInterpolation = false; } _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; From dd2d8e88999c708f7773237f2e6f4ae08409f022 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 21 Aug 2024 16:58:06 +0200 Subject: [PATCH 278/410] Fixed turn switch flickering frame --- TombEngine/Game/camera.cpp | 2 +- TombEngine/Objects/Generic/Switches/turn_switch.cpp | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index a0c19fdf1..be0a4f653 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1290,7 +1290,7 @@ void CalculateCamera(const CollisionInfo& coll) Camera.fixedCamera = isFixedCamera; Camera.last = Camera.number; - Camera.DisableInterpolation = (Camera.lastType != Camera.type); + Camera.DisableInterpolation = (Camera.DisableInterpolation || Camera.lastType != Camera.type); Camera.lastType = Camera.type; if ((Camera.type != CameraType::Heavy || Camera.timer == -1) && diff --git a/TombEngine/Objects/Generic/Switches/turn_switch.cpp b/TombEngine/Objects/Generic/Switches/turn_switch.cpp index 662058a76..050168886 100644 --- a/TombEngine/Objects/Generic/Switches/turn_switch.cpp +++ b/TombEngine/Objects/Generic/Switches/turn_switch.cpp @@ -128,6 +128,7 @@ namespace TEN::Entities::Switches UseForcedFixedCamera = true; ForcedFixedCamera.y = switchItem->Pose.Position.y - 2048; ForcedFixedCamera.RoomNumber = switchItem->RoomNumber; + Camera.DisableInterpolation = true; AddActiveItem(itemNumber); @@ -176,6 +177,8 @@ namespace TEN::Entities::Switches if (switchItem->Animation.AnimNumber == Objects[switchItem->ObjectNumber].animIndex + 2) { switchItem->Pose.Orientation.y += ANGLE(90.0f); + switchItem->DisableInterpolation = true; + if (IsHeld(In::Action)) { laraItem->Animation.AnimNumber = LA_TURNSWITCH_PUSH_CLOCKWISE_START; @@ -187,9 +190,12 @@ namespace TEN::Entities::Switches } if (laraItem->Animation.AnimNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_END && - laraItem->Animation.FrameNumber == GetAnimData(laraItem).frameEnd && + laraItem->Animation.FrameNumber == GetAnimData(laraItem).frameEnd && !switchItem->ItemFlags[1]) + { switchItem->ItemFlags[1] = 1; + switchItem->DisableInterpolation = true; + } if ((laraItem->Animation.FrameNumber >= GetAnimData(*laraItem, LA_TURNSWITCH_PUSH_CLOCKWISE_START).frameBase && laraItem->Animation.FrameNumber <= GetAnimData(*laraItem, LA_TURNSWITCH_PUSH_CLOCKWISE_START).frameBase + 43) || @@ -204,6 +210,8 @@ namespace TEN::Entities::Switches if (switchItem->Animation.AnimNumber == Objects[ID_TURN_SWITCH].animIndex + 6) { switchItem->Pose.Orientation.y -= ANGLE(90.0f); + switchItem->DisableInterpolation = true; + if (IsHeld(In::Action)) { SetAnimation(*laraItem, LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START); @@ -216,6 +224,7 @@ namespace TEN::Entities::Switches !switchItem->ItemFlags[1]) { switchItem->ItemFlags[1] = 1; + switchItem->DisableInterpolation = true; } if ((laraItem->Animation.FrameNumber >= GetAnimData(*laraItem, LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_START).frameBase && @@ -242,6 +251,7 @@ namespace TEN::Entities::Switches Lara.Control.HandStatus = HandStatus::Free; UseForcedFixedCamera = 0; + Camera.DisableInterpolation = true; switchItem->ItemFlags[1] = 2; } } From 08f43e146d626b4cf7a9be913ffd0fbf8f3e6cc0 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 22 Aug 2024 15:15:59 +0200 Subject: [PATCH 279/410] Fixed strings flickering in title menu --- TombEngine/Renderer/RendererDrawMenu.cpp | 46 +++++++++++++++++------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 2fb246dc8..cc243c5a5 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -572,6 +572,8 @@ namespace TEN::Renderer RenderOptionsMenu(menu, MenuVerticalOptionsTitle); break; } + + DrawAllStrings(); } void Renderer::RenderPauseMenu(Menu menu) @@ -1151,30 +1153,50 @@ namespace TEN::Renderer void Renderer::RenderTitle(float interpFactor) { - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); - _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; - _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; - _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; + _interpolationFactor = interpFactor; + + // Interpolate camera. + if (!Camera.disableInterpolation) + { + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = Lerp(_oldGameCamera.Camera.FOV, _currentGameCamera.Camera.FOV, interpFactor); + _gameCamera.Camera.Frustum.Update(_gameCamera.Camera.View, _gameCamera.Camera.Projection); + } + else + { + _gameCamera.Camera.WorldPosition = _currentGameCamera.Camera.WorldPosition; + _gameCamera.Camera.WorldDirection = _currentGameCamera.Camera.WorldDirection; + _gameCamera.Camera.View = _currentGameCamera.Camera.View; + _gameCamera.Camera.Projection = _currentGameCamera.Camera.Projection; + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; + _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; + + Camera.disableInterpolation = false; + } + _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - _interpolationFactor = interpFactor; + _stringsToDraw.clear(); + _isLocked = false; - RenderScene(&_dumpScreenRenderTarget, false, _gameCamera); + DumpGameScene(); _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 1.0f); - DrawAllStrings(); - - _context->ClearState(); + _swapChain->Present(1, 0); + + _isLocked = true; } void Renderer::DrawDebugInfo(RenderView& view) From d23d68e1bab6e266053332426aea0d9d5fa3d325 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Thu, 22 Aug 2024 15:40:12 +0200 Subject: [PATCH 280/410] Fixed wrong GIT merge --- TombEngine/Renderer/RendererDrawMenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index cc243c5a5..200df9dbb 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1156,7 +1156,7 @@ namespace TEN::Renderer _interpolationFactor = interpFactor; // Interpolate camera. - if (!Camera.disableInterpolation) + if (!Camera.DisableInterpolation) { _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); @@ -1176,7 +1176,7 @@ namespace TEN::Renderer _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; - Camera.disableInterpolation = false; + Camera.DisableInterpolation = false; } _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; From 5fa6b81ff31e42354da55ca11f44387ea0ed1ca3 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 26 Aug 2024 05:12:57 +0200 Subject: [PATCH 281/410] Fixed ghost frame in spotcams --- TombEngine/Game/spotcam.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index 3b006c2d0..e9234f1c7 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -138,6 +138,7 @@ void InitializeSpotCam(short Sequence) SpotcamPaused = false; SpotcamLoopCnt = 0; Lara.Control.IsLocked = false; + Camera.DisableInterpolation = true; LaraAir = Lara.Status.Air; @@ -573,6 +574,7 @@ void CalculateSpotCameras() { cn = FirstCamera + SpotCam[CurrentSplineCamera].timer; + Camera.DisableInterpolation = true; CameraXposition[1] = SpotCam[cn].x; CameraYposition[1] = SpotCam[cn].y; CameraZposition[1] = SpotCam[cn].z; @@ -642,6 +644,8 @@ void CalculateSpotCameras() } else if (s->flags & SCF_CUT_TO_LARA_CAM || SplineToCamera) { + Camera.DisableInterpolation = true; + if (CheckTrigger) { CameraType oldType = Camera.type; From 60b9055d0adf90b02bc0c57ebfded36f7d70dcba Mon Sep 17 00:00:00 2001 From: Sezz Date: Tue, 27 Aug 2024 19:17:57 +1000 Subject: [PATCH 282/410] Add F12 as alternative to PrtSc for screenshots --- CHANGELOG.md | 1 + TombEngine/Specific/Input/Input.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85a365f08..4917c3c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added option to enable or disable menu option looping. * Menu scrolling using held inputs will stop at the last option until a new input is made. * Added the ability to display "Lara's Home" entry in the main menu. +* Added F12 as alternative to PrtSc for screenshots. ### Lua API changes * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. diff --git a/TombEngine/Specific/Input/Input.cpp b/TombEngine/Specific/Input/Input.cpp index 80b8cd0b6..1365e4fc7 100644 --- a/TombEngine/Specific/Input/Input.cpp +++ b/TombEngine/Specific/Input/Input.cpp @@ -632,9 +632,9 @@ namespace TEN::Input { // Save screenshot. static bool dbScreenshot = true; - if (KeyMap[KC_SYSRQ] && dbScreenshot) + if ((KeyMap[KC_SYSRQ] || KeyMap[KC_F12]) && dbScreenshot) g_Renderer.SaveScreenshot(); - dbScreenshot = !KeyMap[KC_SYSRQ]; + dbScreenshot = !(KeyMap[KC_SYSRQ] || KeyMap[KC_F12]); // Toggle fullscreen. static bool dbFullscreen = true; From 398e3364fa7ea36782983d819257c65aadf40c04 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 28 Aug 2024 11:48:02 +0200 Subject: [PATCH 283/410] Fixed rope interpolation --- TombEngine/Objects/Generic/Object/rope.cpp | 2 ++ TombEngine/Objects/Generic/Object/rope.h | 6 ++++++ TombEngine/Renderer/RendererDraw.cpp | 17 +++++++++++++---- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/rope.cpp b/TombEngine/Objects/Generic/Object/rope.cpp index 4f1c4fd8e..9ca11766a 100644 --- a/TombEngine/Objects/Generic/Object/rope.cpp +++ b/TombEngine/Objects/Generic/Object/rope.cpp @@ -154,6 +154,8 @@ namespace TEN::Entities::Generic if (TriggerActive(item)) { rope->active = 1; + rope->StoreInterpolationData(); + RopeDynamics(rope); } else diff --git a/TombEngine/Objects/Generic/Object/rope.h b/TombEngine/Objects/Generic/Object/rope.h index cc6865516..57fe39a30 100644 --- a/TombEngine/Objects/Generic/Object/rope.h +++ b/TombEngine/Objects/Generic/Object/rope.h @@ -26,10 +26,16 @@ namespace TEN::Entities::Generic Vector3i normalisedSegment[ROPE_SEGMENTS]; Vector3i meshSegment[ROPE_SEGMENTS]; Vector3i coords[ROPE_SEGMENTS]; + Vector3i oldMeshSegments[ROPE_SEGMENTS]; int segmentLength; short active; short coiled; + + void StoreInterpolationData() + { + memcpy(oldMeshSegments, meshSegment, sizeof(Vector3i) * ROPE_SEGMENTS); + } }; struct PENDULUM diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 01af676d9..cb45eaf0c 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -348,17 +348,26 @@ namespace TEN::Renderer for (int n = 0; n < ROPE_SEGMENTS; n++) { - auto* s = &rope.meshSegment[n]; + auto* s = &rope.oldMeshSegments[n]; Vector3 t; - Vector3 output; + Vector3 oldOutput; t.x = s->x >> FP_SHIFT; t.y = s->y >> FP_SHIFT; t.z = s->z >> FP_SHIFT; - output = Vector3::Transform(t, world); + oldOutput = Vector3::Transform(t, world); - auto absolutePosition = output; + s = &rope.meshSegment[n]; + Vector3 currentOutput; + + t.x = s->x >> FP_SHIFT; + t.y = s->y >> FP_SHIFT; + t.z = s->z >> FP_SHIFT; + + currentOutput = Vector3::Transform(t, world); + + auto absolutePosition = Vector3::Lerp(oldOutput, currentOutput, _interpolationFactor); absolute[n] = absolutePosition; } From 768e5a559de3dbbf16dee4369eef2680099431fc Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 29 Aug 2024 16:11:55 +1000 Subject: [PATCH 284/410] Use std::array to avoid memcpy(); minor cleanup --- TombEngine/Objects/Generic/Object/rope.cpp | 6 +- TombEngine/Objects/Generic/Object/rope.h | 15 +-- TombEngine/Renderer/RendererDraw.cpp | 118 ++++++++------------- 3 files changed, 57 insertions(+), 82 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/rope.cpp b/TombEngine/Objects/Generic/Object/rope.cpp index 9ca11766a..63cd732b6 100644 --- a/TombEngine/Objects/Generic/Object/rope.cpp +++ b/TombEngine/Objects/Generic/Object/rope.cpp @@ -278,9 +278,9 @@ namespace TEN::Entities::Generic for (int i = pendulumPointer->node; i >= 0; --i) { - rope->segment[i].x = rope->meshSegment[i - 1].x + ((int64_t)rope->segmentLength * vec.x >> FP_SHIFT); - rope->segment[i].y = rope->meshSegment[i - 1].y + ((int64_t)rope->segmentLength * vec.y >> FP_SHIFT); - rope->segment[i].z = rope->meshSegment[i - 1].z + ((int64_t)rope->segmentLength * vec.z >> FP_SHIFT); + rope->segment[i].x = rope->meshSegment[std::clamp(i - 1, 0, ROPE_SEGMENTS)].x + ((int64_t)rope->segmentLength * vec.x >> FP_SHIFT); + rope->segment[i].y = rope->meshSegment[std::clamp(i - 1, 0, ROPE_SEGMENTS)].y + ((int64_t)rope->segmentLength * vec.y >> FP_SHIFT); + rope->segment[i].z = rope->meshSegment[std::clamp(i - 1, 0, ROPE_SEGMENTS)].z + ((int64_t)rope->segmentLength * vec.z >> FP_SHIFT); rope->velocity[i].x = 0; rope->velocity[i].y = 0; diff --git a/TombEngine/Objects/Generic/Object/rope.h b/TombEngine/Objects/Generic/Object/rope.h index 57fe39a30..18333a59b 100644 --- a/TombEngine/Objects/Generic/Object/rope.h +++ b/TombEngine/Objects/Generic/Object/rope.h @@ -21,20 +21,21 @@ namespace TEN::Entities::Generic int room; Vector3i position; - Vector3i segment[ROPE_SEGMENTS]; - Vector3i velocity[ROPE_SEGMENTS]; - Vector3i normalisedSegment[ROPE_SEGMENTS]; - Vector3i meshSegment[ROPE_SEGMENTS]; - Vector3i coords[ROPE_SEGMENTS]; - Vector3i oldMeshSegments[ROPE_SEGMENTS]; + std::array segment = {}; + std::array velocity = {}; + std::array normalisedSegment = {}; + std::array meshSegment = {}; + std::array coords = {}; int segmentLength; short active; short coiled; + std::array PrevMeshSegments = {}; + void StoreInterpolationData() { - memcpy(oldMeshSegments, meshSegment, sizeof(Vector3i) * ROPE_SEGMENTS); + PrevMeshSegments = meshSegment; } }; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index cb45eaf0c..f6c0b7a5e 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -258,56 +258,49 @@ namespace TEN::Renderer auto& room = _rooms[LaraItem->RoomNumber]; auto* item = &_items[LaraItem->Index]; - int gunShellsCount = 0; - short objectNumber = 0; + int gunShellCount = 0; + int objectID = 0; for (int i = 0; i < MAX_GUNSHELL; i++) { auto* gunshell = &Gunshells[i]; if (gunshell->counter <= 0) - { continue; - } - objectNumber = gunshell->objectNumber; + objectID = gunshell->objectNumber; - Matrix translation = Matrix::CreateTranslation( - gunshell->pos.Position.x, - gunshell->pos.Position.y, - gunshell->pos.Position.z - ); - Matrix rotation = gunshell->pos.Orientation.ToRotationMatrix(); - Matrix world = rotation * translation; + auto translation = Matrix::CreateTranslation(gunshell->pos.Position.ToVector3()); + auto rotMatrix = gunshell->pos.Orientation.ToRotationMatrix(); + auto worldMatrix = rotMatrix * translation; - Matrix oldTranslation = Matrix::CreateTranslation( + auto prevTranslation = Matrix::CreateTranslation( gunshell->oldPos.Position.x, gunshell->oldPos.Position.y, - gunshell->oldPos.Position.z - ); - Matrix oldRotation = gunshell->oldPos.Orientation.ToRotationMatrix(); - Matrix oldWorld = oldRotation * oldTranslation; + gunshell->oldPos.Position.z); + auto prevRotMatrix = gunshell->oldPos.Orientation.ToRotationMatrix(); + auto prevWorldMatrix = prevRotMatrix * prevTranslation; - world = Matrix::Lerp(oldWorld, world, _interpolationFactor); + worldMatrix = Matrix::Lerp(prevWorldMatrix, worldMatrix, _interpolationFactor); - _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].World = world; - _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].Ambient = room.AmbientLight; - _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].Color = room.AmbientLight; - _stInstancedStaticMeshBuffer.StaticMeshes[gunShellsCount].LightMode = (int)LightMode::Dynamic; - BindInstancedStaticLights(item->LightsToDraw, gunShellsCount); + _stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].World = worldMatrix; + _stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Ambient = room.AmbientLight; + _stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Color = room.AmbientLight; + _stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].LightMode = (int)LightMode::Dynamic; + BindInstancedStaticLights(item->LightsToDraw, gunShellCount); - gunShellsCount++; + gunShellCount++; } - if (gunShellsCount > 0) + if (gunShellCount > 0) { - auto& moveableObject = *_moveableObjects[objectNumber]; + auto& moveableObject = *_moveableObjects[objectID]; _context->VSSetShader(_vsInstancedStaticMeshes.Get(), nullptr, 0); _context->PSSetShader(_psInstancedStaticMeshes.Get(), nullptr, 0); - UINT stride = sizeof(Vertex); - UINT offset = 0; + unsigned int stride = sizeof(Vertex); + unsigned int offset = 0; _context->IASetVertexBuffers(0, 1, _moveablesVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _context->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0); @@ -316,19 +309,16 @@ namespace TEN::Renderer _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get()); - auto* mesh = moveableObject.ObjectMeshes[0]; - - for (auto& bucket : mesh->Buckets) + const auto& mesh = *moveableObject.ObjectMeshes[0]; + for (const auto& bucket : mesh.Buckets) { if (bucket.NumVertices == 0) - { continue; - } BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); BindTexture(TextureRegister::NormalMap, &std::get<1>(_moveablesTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp); - DrawIndexedInstancedTriangles(bucket.NumIndices, gunShellsCount, bucket.StartIndex, 0); + DrawIndexedInstancedTriangles(bucket.NumIndices, gunShellCount, bucket.StartIndex, 0); _numInstancedStaticsDrawCalls++; } @@ -337,59 +327,43 @@ namespace TEN::Renderer void Renderer::PrepareRopes(RenderView& view) { - for (auto& rope : Ropes) + for (const auto& rope : Ropes) { if (!rope.active) continue; - auto world = Matrix::CreateTranslation(rope.position.x, rope.position.y, rope.position.z); + auto translationMatrix = Matrix::CreateTranslation(rope.position.ToVector3()); + auto absolutePoints = std::array{}; - Vector3 absolute[24]; - - for (int n = 0; n < ROPE_SEGMENTS; n++) + for (int i = 0; i < rope.segment.size(); i++) { - auto* s = &rope.oldMeshSegments[n]; - Vector3 t; - Vector3 oldOutput; + const auto* segment = &rope.PrevMeshSegments[i]; - t.x = s->x >> FP_SHIFT; - t.y = s->y >> FP_SHIFT; - t.z = s->z >> FP_SHIFT; + auto relPos = Vector3(segment->x >> FP_SHIFT, segment->y >> FP_SHIFT, segment->z >> FP_SHIFT); + auto prevOutput = Vector3::Transform(relPos, translationMatrix); - oldOutput = Vector3::Transform(t, world); + segment = &rope.meshSegment[i]; - s = &rope.meshSegment[n]; - Vector3 currentOutput; + relPos = Vector3(segment->x >> FP_SHIFT, segment->y >> FP_SHIFT, segment->z >> FP_SHIFT); + auto currentOutput = Vector3::Transform(relPos, translationMatrix); - t.x = s->x >> FP_SHIFT; - t.y = s->y >> FP_SHIFT; - t.z = s->z >> FP_SHIFT; - - currentOutput = Vector3::Transform(t, world); - - auto absolutePosition = Vector3::Lerp(oldOutput, currentOutput, _interpolationFactor); - absolute[n] = absolutePosition; + auto absolutePos = Vector3::Lerp(prevOutput, currentOutput, _interpolationFactor); + absolutePoints[i] = absolutePos; } - for (int n = 0; n < ROPE_SEGMENTS - 1; n++) + for (int i = 0; i < (rope.segment.size() - 1); i++) { - auto pos1 = absolute[n]; - auto pos2 = absolute[n + 1]; + const auto& pos0 = absolutePoints[i]; + const auto& pos1 = absolutePoints[i + 1]; + auto pos = (pos0 + pos1) / 2; - auto d = pos2 - pos1; - d.Normalize(); + auto dir = pos1 - pos0; + dir.Normalize(); - auto c = (pos1 + pos2) / 2.0f; - - AddSpriteBillboardConstrained(&_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_EMPTY1], - c, - _rooms[rope.room].AmbientLight, - (PI / 2), - 1.0f, - { 32, - Vector3::Distance(pos1, pos2) }, - BlendMode::AlphaBlend, - d, false, view); + AddSpriteBillboardConstrained( + &_sprites[Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_EMPTY1], + pos, _rooms[rope.room].AmbientLight, + PI_DIV_2, 1.0f, Vector2(32.0f, Vector3::Distance(pos0, pos1)), BlendMode::AlphaBlend, dir, false, view); } } } From cccd0d9bfb76e514368a301d064148f26e264087 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sat, 31 Aug 2024 15:23:01 +0100 Subject: [PATCH 285/410] level.rumble sound effect parameters exposed to user Formally: this was hardcoded in TR5 to the klaxon from the Sinking Submarine level. I have moved this to a new sound enum in the default soundmap and removed the pitch shift as this can be set in the XML by the user. This change has also been documented on the TombEngine website. --- CHANGELOG.md | 1 + TombEngine/Game/camera.cpp | 3 ++- TombEngine/Sound/sound_effects.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4917c3c69..7cd6f74af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Features/Amendments * Changed Rome Hammer to not hurt player whilst deactivated. * Changed Statue with blade damage, from 20 to 200. +* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed. * Enhanced Rolling Spindle detection to avoid them going down through pits. * Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) * Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index b6fe8b185..aaa81edcb 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1545,7 +1545,8 @@ void UpdateMikePos(const ItemInfo& item) void RumbleScreen() { if (!(GlobalCounter & 0x1FF)) - SoundEffect(SFX_TR5_KLAXON, nullptr, SoundEnvironment::Land, 0.25f); + // SFX Enum Changed from TR5 and pitch shift removed. User can set this in their sound XML. Stranger1992 31st August 2024 + SoundEffect(SFX_TR4_ENVIORONMENT_RUMBLE, nullptr, SoundEnvironment::Land); if (RumbleTimer >= 0) RumbleTimer++; diff --git a/TombEngine/Sound/sound_effects.h b/TombEngine/Sound/sound_effects.h index f0643e6c8..eb21f8e53 100644 --- a/TombEngine/Sound/sound_effects.h +++ b/TombEngine/Sound/sound_effects.h @@ -361,7 +361,7 @@ enum SOUND_EFFECTS SFX_TR4_LIGHT_BEAM_LOOP = 356, SFX_TR4_GUIDE_FIRE_LIGHT = 357, SFX_TR4_AUTOGUNS = 358, - SFX_TR4_EMPTY8 = 359, + SFX_TR4_ENVIORONMENT_RUMBLE = 359, SFX_TR4_STEAM = 360, SFX_TR4_GARAGE_DOOR = 361, SFX_TR4_WIND = 362, From a9516cd7f712075d747d9127eae24eae0cad313b Mon Sep 17 00:00:00 2001 From: davidmarr <116632612+davidmarr@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:13:20 +0200 Subject: [PATCH 286/410] Add Room:GetRoomNumber() method (#1401) * add RoomGetRoomNumber() method * Update CHANGELOG.md * fix GetReverbType() method * Update MoveableObject.cpp Modified Moveable() function description for consistency --- CHANGELOG.md | 1 + TombEngine/Scripting/Internal/ReservedScriptNames.h | 1 + .../Internal/TEN/Objects/Moveable/MoveableObject.cpp | 2 +- .../Internal/TEN/Objects/Room/RoomObject.cpp | 12 +++++++++++- .../Scripting/Internal/TEN/Objects/Room/RoomObject.h | 1 + 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cd6f74af..1ce6d1cc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() * Added Flow.EnableHomeLevel() +* Added Room:GetRoomNumber() * Removed anims.monkeyAutoJump. It is now a player menu configuration. * Fixed Volume:GetActive() method diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index eafb807cf..a881cf082 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -199,6 +199,7 @@ static constexpr char ScriptReserved_GetFlag[] = "GetFlag"; static constexpr char ScriptReserved_SetFlag[] = "SetFlag"; static constexpr char ScriptReserved_IsTagPresent[] = "IsTagPresent"; static constexpr char ScriptReserved_SetReverbType[] = "SetReverbType"; +static constexpr char ScriptReserved_GetReverbType[] = "GetReverbType"; // Flow Functions static constexpr char ScriptReserved_AddLevel[] = "AddLevel"; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 76610d3f1..e6e7224c5 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -79,7 +79,7 @@ most can just be ignored (see usage). @tparam string name Lua name of the item @tparam Vec3 position position in level @tparam Rotation rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) - @tparam int roomID room ID item is in (default: calculated automatically) + @tparam int roomNumber room number item is in (default: calculated automatically) @tparam int animNumber animation number @tparam int frameNumber frame number @tparam int hp HP of item diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp index a215f8563..d07f621be 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp @@ -38,6 +38,11 @@ void Room::Register(sol::table& parent) // @treturn bool true if the room is active ScriptReserved_GetActive, &Room::GetActive, + /// Get the room ID + // @function Room:GetRoomNumber + // @treturn int the room ID + ScriptReserved_GetRoomNumber, & Room::GetRoomNumber, + /// Get the room's ambient light color. // @function Room:GetColor // @treturn Color ambient light color of the room @@ -46,7 +51,7 @@ void Room::Register(sol::table& parent) /// Get the room's reverb type. // @function Room:GetReverbType // @treturn Objects.RoomReverb room's reverb type - ScriptReserved_GetPosition, &Room::GetReverbType, + ScriptReserved_GetReverbType, &Room::GetReverbType, /// Set the room's reverb type. // @function Room:SetReverbType @@ -87,6 +92,11 @@ bool Room::GetActive() const return m_room.Active(); } +int Room::GetRoomNumber() const +{ + return m_room.RoomNumber; +} + ScriptColor Room::GetColor() const { return ScriptColor{ m_room.ambient }; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h index 8569a1e5c..6d8701662 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h @@ -20,6 +20,7 @@ public: static void Register(sol::table& parent); [[nodiscard]] bool GetActive() const; + [[nodiscard]] int GetRoomNumber() const; [[nodiscard]] ScriptColor GetColor() const; [[nodiscard]] std::string GetName() const; From b318179bb9f12f2bde16b96e084fcb61328825c2 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 1 Sep 2024 22:25:40 +1000 Subject: [PATCH 287/410] Organise Lua room class --- .../Scripting/Internal/ReservedScriptNames.h | 41 ++- .../TEN/Objects/Moveable/MoveableObject.cpp | 2 +- .../TEN/Objects/Moveable/MoveableObject.h | 1 + .../Internal/TEN/Objects/Room/RoomObject.cpp | 269 +++++++++--------- .../Internal/TEN/Objects/Room/RoomObject.h | 62 ++-- TombEngine/Scripting/Internal/TEN/Vec2/Vec2.h | 5 + TombEngine/Scripting/Internal/TEN/Vec3/Vec3.h | 8 +- 7 files changed, 214 insertions(+), 174 deletions(-) diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index a881cf082..7aa0f4afa 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -22,10 +22,8 @@ static constexpr char ScriptReserved_Sink[] = "Sink"; static constexpr char ScriptReserved_SoundSource[] = "SoundSource"; static constexpr char ScriptReserved_AIObject[] = "AIObject"; static constexpr char ScriptReserved_Volume[] = "Volume"; -static constexpr char ScriptReserved_Room[] = "Room"; static constexpr char ScriptReserved_Color[] = "Color"; static constexpr char ScriptReserved_DisplayString[] = "DisplayString"; -static constexpr char ScriptReserved_Vec2[] = "Vec2"; static constexpr char ScriptReserved_Rotation[] = "Rotation"; static constexpr char ScriptReserved_LevelFunc[] = "LevelFunc"; @@ -198,8 +196,6 @@ static constexpr char ScriptReserved_IsMoveableInside[] = "IsMoveableInside"; static constexpr char ScriptReserved_GetFlag[] = "GetFlag"; static constexpr char ScriptReserved_SetFlag[] = "SetFlag"; static constexpr char ScriptReserved_IsTagPresent[] = "IsTagPresent"; -static constexpr char ScriptReserved_SetReverbType[] = "SetReverbType"; -static constexpr char ScriptReserved_GetReverbType[] = "GetReverbType"; // Flow Functions static constexpr char ScriptReserved_AddLevel[] = "AddLevel"; @@ -372,22 +368,39 @@ static constexpr char ScriptReserved_LogLevelError[] = "ERROR"; // Internal static constexpr char ScriptReserved_LaraObject[] = "LaraObject"; +// Room + +constexpr char ScriptReserved_Room[] = "Room"; +constexpr char ScriptReserved_RoomGetActive[] = "GetActive"; +constexpr char ScriptReserved_RoomGetColor[] = "GetColor"; +constexpr char ScriptReserved_RoomGetFlag[] = "GetFlag"; +constexpr char ScriptReserved_RoomGetName[] = "GetName"; +constexpr char ScriptReserved_RoomGetReverbType[] = "GetReverbType"; +constexpr char ScriptReserved_RoomGetRoomNumber[] = "GetRoomNumber"; +constexpr char ScriptReserved_RoomIsTagPresent[] = "IsTagPresent"; +constexpr char ScriptReserved_RoomSetFlag[] = "SetFlag"; +constexpr char ScriptReserved_RoomSetName[] = "SetName"; +constexpr char ScriptReserved_RoomSetReverbType[] = "SetReverbType"; + // Vec2 + +constexpr char ScriptReserved_Vec2[] = "Vec2"; +constexpr char ScriptReserved_Vec2Cross[] = "Cross"; +constexpr char ScriptReserved_Vec2Distance[] = "Distance"; +constexpr char ScriptReserved_Vec2Dot[] = "Dot"; +constexpr char ScriptReserved_Vec2Length[] = "Length"; +constexpr char ScriptReserved_Vec2Lerp[] = "Lerp"; constexpr char ScriptReserved_Vec2SetLength[] = "ToLength"; constexpr char ScriptReserved_Vec2Normalize[] = "Normalize"; constexpr char ScriptReserved_Vec2Rotate[] = "Rotate"; -constexpr char ScriptReserved_Vec2Lerp[] = "Lerp"; -constexpr char ScriptReserved_Vec2Cross[] = "Cross"; -constexpr char ScriptReserved_Vec2Dot[] = "Dot"; -constexpr char ScriptReserved_Vec2Distance[] = "Distance"; -constexpr char ScriptReserved_Vec2Length[] = "Length"; // Vec3 + constexpr char ScriptReserved_Vec3[] = "Vec3"; +constexpr char ScriptReserved_Vec3Cross[] = "Cross"; +constexpr char ScriptReserved_Vec3Distance[] = "Distance"; +constexpr char ScriptReserved_Vec3Dot[] = "Dot"; +constexpr char ScriptReserved_Vec3Length[] = "Length"; +constexpr char ScriptReserved_Vec3Lerp[] = "Lerp"; constexpr char ScriptReserved_Vec3Normalize[] = "Normalize"; constexpr char ScriptReserved_Vec3Rotate[] = "Rotate"; -constexpr char ScriptReserved_Vec3Lerp[] = "Lerp"; -constexpr char ScriptReserved_Vec3Cross[] = "Cross"; -constexpr char ScriptReserved_Vec3Dot[] = "Dot"; -constexpr char ScriptReserved_Vec3Distance[] = "Distance"; -constexpr char ScriptReserved_Vec3Length[] = "Length"; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index e6e7224c5..e808c33f4 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -79,7 +79,7 @@ most can just be ignored (see usage). @tparam string name Lua name of the item @tparam Vec3 position position in level @tparam Rotation rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) - @tparam int roomNumber room number item is in (default: calculated automatically) + @tparam int roomNumber the room number the moveable is in (default: calculated automatically). @tparam int animNumber animation number @tparam int frameNumber frame number @tparam int hp HP of item diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h index 931cfbdbc..63854ee27 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h @@ -1,4 +1,5 @@ #pragma once + #include "Scripting/Internal/ScriptUtil.h" #include "Scripting/Internal/TEN/Objects/NamedBase.h" #include "Scripting/Internal/TEN/Objects/Room/RoomObject.h" diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp index d07f621be..3cac49f14 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.cpp @@ -13,151 +13,148 @@ #include "Specific/level.h" #include "Specific/trutils.h" -/*** -Rooms +/// Room object. +// @tenclass Objects.Room +// @pragma nostrip -@tenclass Objects.Room -@pragma nostrip -*/ +//namespace TEN::Scripting +//{ + static auto IndexError = index_error_maker(Room, ScriptReserved_Volume); + static auto NewIndexError = newindex_error_maker(Room, ScriptReserved_Volume); -static auto IndexError = index_error_maker(Room, ScriptReserved_Volume); -static auto NewIndexError = newindex_error_maker(Room, ScriptReserved_Volume); - -Room::Room(ROOM_INFO& room) : m_room{ room } -{}; - -void Room::Register(sol::table& parent) -{ - parent.new_usertype(ScriptReserved_Room, - sol::no_constructor, - sol::meta_function::index, IndexError, - sol::meta_function::new_index, NewIndexError, - - /// Determine whether the room is active or not - // @function Room:GetActive - // @treturn bool true if the room is active - ScriptReserved_GetActive, &Room::GetActive, - - /// Get the room ID - // @function Room:GetRoomNumber - // @treturn int the room ID - ScriptReserved_GetRoomNumber, & Room::GetRoomNumber, - - /// Get the room's ambient light color. - // @function Room:GetColor - // @treturn Color ambient light color of the room - ScriptReserved_GetColor, & Room::GetColor, - - /// Get the room's reverb type. - // @function Room:GetReverbType - // @treturn Objects.RoomReverb room's reverb type - ScriptReserved_GetReverbType, &Room::GetReverbType, - - /// Set the room's reverb type. - // @function Room:SetReverbType - // @tparam Objects.RoomReverb new reverb type of the room - ScriptReserved_SetReverbType, &Room::SetReverbType, - - /// Get the room's unique string identifier. - // @function Room:GetName - // @treturn string the room's name - ScriptReserved_GetName, &Room::GetName, - - /// Set the room's name (its unique string identifier). - // @function Room:SetName - // @tparam string name The room's new name - ScriptReserved_SetName, &Room::SetName, - - /// Get the room's specified flag value (true or false). - // @function Room:GetFlag - // @tparam Objects.RoomFlagID flagID The room's flag ID - // @treturn bool the room's specified flag value - ScriptReserved_GetFlag, &Room::GetFlag, - - /// Set the room's specified flag value. - // @function Room:SetFlag - // @tparam Objects.RoomFlagID flagID The room's flag ID - // @tparam bool the room's new flag value - ScriptReserved_SetFlag, &Room::SetFlag, - - /// Checks if specified tag is set for this room. - // @function Room:IsTagPresent - // @tparam string tag A text tag to check (case sensitive) - // @treturn bool true if tag is present, false if not - ScriptReserved_IsTagPresent, &Room::IsTagPresent); -} - -bool Room::GetActive() const -{ - return m_room.Active(); -} - -int Room::GetRoomNumber() const -{ - return m_room.RoomNumber; -} - -ScriptColor Room::GetColor() const -{ - return ScriptColor{ m_room.ambient }; -} - -ReverbType Room::GetReverbType() const -{ - return m_room.reverbType; -} - -void Room::SetReverbType(ReverbType reverb) -{ - m_room.reverbType = reverb; -} - -std::string Room::GetName() const -{ - return m_room.Name; -} - -void Room::SetName(const std::string& name) -{ - if (!ScriptAssert(!name.empty(), "Unable to set name. Name cannot be blank.")) - return; - - // Remove old name if it already exists. - if (s_callbackSetName(name, m_room)) + Room::Room(ROOM_INFO& room) : + _room(room) { - s_callbackRemoveName(m_room.Name); - m_room.Name = name; - } - else + }; + + void Room::Register(sol::table& parent) { - ScriptAssertF(false, "Could not add name {} - does an object with this name already exist?", name); - TENLog("Name will not be set", LogLevel::Warning, LogConfig::All); + // Register type. + parent.new_usertype( + ScriptReserved_Room, + sol::no_constructor, + sol::meta_function::index, IndexError, + sol::meta_function::new_index, NewIndexError, + + ScriptReserved_RoomGetRoomNumber, &Room::GetRoomNumber, + ScriptReserved_RoomGetName, &Room::GetName, + ScriptReserved_RoomGetColor, &Room::GetColor, + ScriptReserved_RoomGetReverbType, &Room::GetReverbType, + ScriptReserved_RoomSetName, &Room::SetName, + ScriptReserved_RoomSetReverbType, &Room::SetReverbType, + ScriptReserved_RoomSetFlag, &Room::SetFlag, + ScriptReserved_RoomIsTagPresent, &Room::IsTagPresent, + ScriptReserved_RoomGetActive, &Room::GetActive, + ScriptReserved_RoomGetFlag, &Room::GetFlag); } -} -bool Room::GetFlag(RoomEnvFlags flag) const -{ - return ((m_room.flags & flag) == flag); -} - -void Room::SetFlag(RoomEnvFlags flag, bool value) -{ - if (value) + /// Get the room's number. + // @function Room:GetRoomNumber() + // @treturn int Room number. + int Room::GetRoomNumber() const { - m_room.flags |= flag; + return _room.RoomNumber; } - else + + /// Get the room's unique string identifier. + // @function Room:GetName() + // @treturn string Room name. + std::string Room::GetName() const { - m_room.flags &= ~flag; + return _room.Name; } -} -bool Room::IsTagPresent(const std::string& tag) const -{ - if (m_room.Tags.empty()) - return false; + /// Get the room's ambient light color. + // @function Room:GetColor() + // @treturn Color Ambient light color. + ScriptColor Room::GetColor() const + { + return ScriptColor(_room.ambient); + } - return std::any_of( - m_room.Tags.begin(), m_room.Tags.end(), - [&tag](const std::string& value) { return (value == tag); }); -} + /// Get the room's reverb type. + // @function Room:GetReverbType() + // @treturn Objects.RoomReverb Reverb type. + ReverbType Room::GetReverbType() const + { + return _room.reverbType; + } + + /// Set the room's unique string identifier. + // @function Room:SetName() + // @tparam string name New name. + void Room::SetName(const std::string& name) + { + if (!ScriptAssert(!name.empty(), "Unable to set name. Name cannot be blank.")) + return; + + // Remove previous name if it already exists. + if (s_callbackSetName(name, _room)) + { + s_callbackRemoveName(_room.Name); + _room.Name = name; + } + else + { + ScriptAssertF(false, "Could not add name {} - does an object with this name already exist?", name); + TENLog("Name will not be set", LogLevel::Warning, LogConfig::All); + } + } + + /// Set the room's reverb type. + // @function Room:SetReverbType() + // @tparam Objects.RoomReverb Reverb type. + void Room::SetReverbType(ReverbType reverb) + { + _room.reverbType = reverb; + } + + /// Set the room's specified flag. + // @function Room:SetFlag() + // @tparam Objects.RoomFlagID flagID Room flag ID. + // @tparam bool Boolean to set the flag to. + void Room::SetFlag(RoomEnvFlags flag, bool value) + { + if (value) + { + _room.flags |= flag; + } + else + { + _room.flags &= ~flag; + } + } + + /// Get the room's specified flag value (true or false). + // @function Room:GetFlag() + // @tparam Objects.RoomFlagID flagID Room flag ID. + bool Room::IsTagPresent(const std::string& tag) const + { + if (_room.Tags.empty()) + return false; + + return std::any_of( + _room.Tags.begin(), _room.Tags.end(), + [&tag](const std::string& value) + { + return (value == tag); + }); + } + + /// Check if the specified tag is set for the room. + // @function Room:IsTagPresent() + // @tparam string tag Text tag to check (case sensitive). + // @treturn bool Boolean of the tag's presence. + bool Room::GetActive() const + { + return _room.Active(); + } + + /// Check if the room is active. + // @function Room:GetActive() + // @treturn bool Boolean of the room's active status. + bool Room::GetFlag(RoomEnvFlags flag) const + { + return ((_room.flags & flag) == flag); + } +//} diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h index 6d8701662..3672b5b24 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/Room/RoomObject.h @@ -1,4 +1,5 @@ #pragma once + #include "Game/room.h" #include "Scripting/Internal/TEN/Objects/NamedBase.h" @@ -7,33 +8,50 @@ enum class ReverbType; class ScriptColor; class Vec3; -class Room : public NamedBase -{ -public: - using IdentifierType = std::reference_wrapper; - Room(ROOM_INFO& room); - ~Room() = default; +//namespace TEN::Scripting +//{ + class Room : public NamedBase + { + private: + // Members - Room& operator =(const Room& other) = delete; - Room(const Room& other) = delete; + ROOM_INFO& _room; - static void Register(sol::table& parent); + public: + using IdentifierType = std::reference_wrapper; - [[nodiscard]] bool GetActive() const; - [[nodiscard]] int GetRoomNumber() const; - [[nodiscard]] ScriptColor GetColor() const; + static void Register(sol::table& parent); - [[nodiscard]] std::string GetName() const; - void SetName(const std::string& name); + // Constructors - [[nodiscard]] bool GetFlag(RoomEnvFlags flag) const; - void SetFlag(RoomEnvFlags flag, bool value); + Room(ROOM_INFO& room); + Room(const Room& room) = delete; - [[nodiscard]] ReverbType GetReverbType() const; - void SetReverbType(ReverbType reverbType); + // Destructors - [[nodiscard]] bool IsTagPresent(const std::string& tag) const; + ~Room() = default; -private: - ROOM_INFO& m_room; -}; + // Getters + + int GetRoomNumber() const; + std::string GetName() const; + ScriptColor GetColor() const; + ReverbType GetReverbType() const; + + // Setters + + void SetName(const std::string& name); + void SetReverbType(ReverbType reverbType); + void SetFlag(RoomEnvFlags flag, bool value); + + // Inquirers + + bool IsTagPresent(const std::string& tag) const; + bool GetActive() const; // TODO: Rename to IsActive(). + bool GetFlag(RoomEnvFlags flag) const; // TODO: Rename to HasFlag(). + + // Operators + + Room& operator =(const Room& room) = delete; + }; +//} diff --git a/TombEngine/Scripting/Internal/TEN/Vec2/Vec2.h b/TombEngine/Scripting/Internal/TEN/Vec2/Vec2.h index 0bae39e3b..072e0dfa9 100644 --- a/TombEngine/Scripting/Internal/TEN/Vec2/Vec2.h +++ b/TombEngine/Scripting/Internal/TEN/Vec2/Vec2.h @@ -9,10 +9,12 @@ public: static void Register(sol::table& parent); // Members + float x = 0; float y = 0; // Constructors + Vec2(float x, float y); Vec2(float value); Vec2(const Vector2& vector); @@ -28,6 +30,7 @@ public: float Length() const; // Meta functions + std::string ToString() const; static Vec2 Add(const Vec2& vector0, const Vec2& vector1); static Vec2 Subtract(const Vec2& vector0, const Vec2& vector1); @@ -38,9 +41,11 @@ public: static bool IsEqualTo(const Vec2& vector0, const Vec2& vector1); // Converters + Vector2 ToVector2() const; //Vector2i ToVector2i() const; // Operators + operator Vector2() const; }; diff --git a/TombEngine/Scripting/Internal/TEN/Vec3/Vec3.h b/TombEngine/Scripting/Internal/TEN/Vec3/Vec3.h index 1087ed117..de2d95365 100644 --- a/TombEngine/Scripting/Internal/TEN/Vec3/Vec3.h +++ b/TombEngine/Scripting/Internal/TEN/Vec3/Vec3.h @@ -1,10 +1,10 @@ #pragma once +namespace sol { class state; } class GameVector; class Pose; class Rotation; class Vector3i; -namespace sol { class state; } class Vec3 { @@ -12,11 +12,13 @@ public: static void Register(sol::table& parent); // Members + float x = 0; float y = 0; float z = 0; // Constructors + Vec3() {}; Vec3(float x, float y, float z); Vec3(float value); @@ -24,6 +26,7 @@ public: Vec3(const Vector3i& vector); // Utilities + Vec3 Normalize() const; Vec3 Rotate(const Rotation& rot) const; Vec3 Lerp(const Vec3& vector, float alpha) const; @@ -33,6 +36,7 @@ public: float Length() const; // Meta functions + std::string ToString() const; static Vec3 Add(const Vec3& vector0, const Vec3& vector1); static Vec3 Subtract(const Vec3& vector0, const Vec3& vector1); @@ -43,10 +47,12 @@ public: static bool IsEqualTo(const Vec3& vector0, const Vec3& vector1); // Converters + Vector3 ToVector3() const; Vector3i ToVector3i() const; GameVector ToGameVector() const; // Operators + operator Vector3() const; }; From feee7c8285d58cf216c320f0781f249a68dcbf15 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 5 Sep 2024 23:02:24 +1000 Subject: [PATCH 288/410] Update InputAction class --- TombEngine/Specific/Input/InputAction.cpp | 75 +++++++++++------------ TombEngine/Specific/Input/InputAction.h | 12 ++-- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/TombEngine/Specific/Input/InputAction.cpp b/TombEngine/Specific/Input/InputAction.cpp index b832bcac0..48b28f6c2 100644 --- a/TombEngine/Specific/Input/InputAction.cpp +++ b/TombEngine/Specific/Input/InputAction.cpp @@ -3,43 +3,42 @@ #include "Specific/clock.h" - namespace TEN::Input { InputAction::InputAction(ActionID actionID) { - ID = actionID; + _id = actionID; } ActionID InputAction::GetID() const { - return ID; + return _id; } float InputAction::GetValue() const { - return Value; + return _value; } float InputAction::GetTimeActive() const { - return TimeActive; + return _timeActive; } float InputAction::GetTimeInactive() const { - return TimeInactive; + return _timeInactive; } bool InputAction::IsClicked() const { - return ((Value != 0.0f) && (PrevValue == 0.0f)); + return ((_value != 0.0f) && (_prevValue == 0.0f)); } bool InputAction::IsHeld(float delayInSec) const { float delayInFrameTime = (delayInSec == 0.0f) ? 0.0f : round(delayInSec / DELTA_TIME); - return ((Value != 0.0f) && (TimeActive >= delayInFrameTime)); + return ((_value != 0.0f) && (_timeActive >= delayInFrameTime)); } // NOTE: To avoid stutter on second pulse, ensure initialDelayInSec is multiple of delayInSec. @@ -48,12 +47,12 @@ namespace TEN::Input if (IsClicked()) return true; - if (!IsHeld() || PrevTimeActive == 0.0f || TimeActive == PrevTimeActive) + if (!IsHeld() || _prevTimeActive == 0.0f || _timeActive == _prevTimeActive) return false; - float activeDelayInFrameTime = (TimeActive > round(initialDelayInSec / DELTA_TIME)) ? round(delayInSec / DELTA_TIME) : round(initialDelayInSec / DELTA_TIME); - float delayInFrameTime = std::floor(TimeActive / activeDelayInFrameTime) * activeDelayInFrameTime; - if (delayInFrameTime > (std::floor(PrevTimeActive / activeDelayInFrameTime) * activeDelayInFrameTime)) + float activeDelayInFrameTime = (_timeActive > round(initialDelayInSec / DELTA_TIME)) ? round(delayInSec / DELTA_TIME) : round(initialDelayInSec / DELTA_TIME); + float delayInFrameTime = std::floor(_timeActive / activeDelayInFrameTime) * activeDelayInFrameTime; + if (delayInFrameTime > (std::floor(_prevTimeActive / activeDelayInFrameTime) * activeDelayInFrameTime)) return true; // Keeping version counting real time for future reference. -- Sezz 2022.10.01 @@ -70,7 +69,7 @@ namespace TEN::Input bool InputAction::IsReleased(float maxDelayInSec) const { float maxDelayInFrameTime = (maxDelayInSec == INFINITY) ? INFINITY : round(maxDelayInSec / DELTA_TIME); - return ((Value == 0.0f) && (PrevValue != 0.0f) && (TimeActive <= maxDelayInFrameTime)); + return ((_value == 0.0f) && (_prevValue != 0.0f) && (_timeActive <= maxDelayInFrameTime)); } void InputAction::Update(bool value) @@ -89,57 +88,57 @@ namespace TEN::Input if (IsClicked()) { - PrevTimeActive = 0.0f; - TimeActive = 0.0f; - TimeInactive += FRAME_TIME;// DELTA_TIME; + _prevTimeActive = 0.0f; + _timeActive = 0.0f; + _timeInactive += FRAME_TIME;// DELTA_TIME; } else if (IsReleased()) { - PrevTimeActive = TimeActive; - TimeActive += FRAME_TIME;// DELTA_TIME; - TimeInactive = 0.0f; + _prevTimeActive = _timeActive; + _timeActive += FRAME_TIME;// DELTA_TIME; + _timeInactive = 0.0f; } else if (IsHeld()) { - PrevTimeActive = TimeActive; - TimeActive += FRAME_TIME;// DELTA_TIME; - TimeInactive = 0.0f; + _prevTimeActive = _timeActive; + _timeActive += FRAME_TIME;// DELTA_TIME; + _timeInactive = 0.0f; } else { - PrevTimeActive = 0.0f; - TimeActive = 0.0f; - TimeInactive += FRAME_TIME;// DELTA_TIME; + _prevTimeActive = 0.0f; + _timeActive = 0.0f; + _timeInactive += FRAME_TIME;// DELTA_TIME; } } void InputAction::Clear() { - Value = 0.0f; - PrevValue = 0.0f; - TimeActive = 0.0f; - PrevTimeActive = 0.0f; - TimeInactive = 0.0f; + _value = 0.0f; + _prevValue = 0.0f; + _timeActive = 0.0f; + _prevTimeActive = 0.0f; + _timeInactive = 0.0f; } void InputAction::DrawDebug() const { - PrintDebugMessage("ID: %d", (int)ID); + PrintDebugMessage("ID: %d", (int)_id); PrintDebugMessage("IsClicked: %d", IsClicked()); PrintDebugMessage("IsHeld: %d", IsHeld()); PrintDebugMessage("IsPulsed (.2s, .6s): %d", IsPulsed(0.2f, 0.6f)); PrintDebugMessage("IsReleased: %d", IsReleased()); PrintDebugMessage(""); - PrintDebugMessage("Value: %.3f", Value); - PrintDebugMessage("PrevValue: %.3f", PrevValue); - PrintDebugMessage("TimeActive: %.3f", TimeActive); - PrintDebugMessage("PrevTimeActive: %.3f", PrevTimeActive); - PrintDebugMessage("TimeInactive: %.3f", TimeInactive); + PrintDebugMessage("Value: %.3f", _value); + PrintDebugMessage("PrevValue: %.3f", _prevValue); + PrintDebugMessage("TimeActive: %.3f", _timeActive); + PrintDebugMessage("PrevTimeActive: %.3f", _prevTimeActive); + PrintDebugMessage("TimeInactive: %.3f", _timeInactive); } void InputAction::UpdateValue(float value) { - PrevValue = Value; - Value = value; + _prevValue = _value; + _value = value; } } diff --git a/TombEngine/Specific/Input/InputAction.h b/TombEngine/Specific/Input/InputAction.h index adeb7eda6..3287b85c7 100644 --- a/TombEngine/Specific/Input/InputAction.h +++ b/TombEngine/Specific/Input/InputAction.h @@ -65,12 +65,12 @@ namespace TEN::Input private: // Members - ActionID ID = In::Forward; - float Value = 0.0f; - float PrevValue = 0.0f; - float TimeActive = 0.0f; - float PrevTimeActive = 0.0f; - float TimeInactive = 0.0f; + ActionID _id = In::Forward; + float _value = 0.0f; + float _prevValue = 0.0f; + float _timeActive = 0.0f; + float _prevTimeActive = 0.0f; + float _timeInactive = 0.0f; public: // Constructors From 1695caa602f8fff58c3e5c322137df2bcf3e8c65 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Fri, 6 Sep 2024 06:07:12 +0200 Subject: [PATCH 289/410] Interpolation disable by default on CreateItem(); Interpolation enabled in renderer always after the first frame; --- .../doc/2 classes/Objects.Moveable.html | 8 +- Documentation/doc/2 classes/Objects.Room.html | 229 ++++++++++-------- Documentation/doc/index.html | 2 +- TombEngine/Game/items.cpp | 2 + TombEngine/Renderer/RendererFrame.cpp | 4 + 5 files changed, 135 insertions(+), 110 deletions(-) diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index b0ecc0d54..f4ba70179 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -110,7 +110,7 @@ pickups, and Lara herself (see also Functions
    EnableFlyCheat(enabled)Enable or disable DOZY mode (fly cheat).Enable or disable the fly cheat.
    EnablePointFilter(enabled)
    - + @@ -392,7 +392,7 @@ pickups, and Lara herself (see also
    - Moveable(object, name, position, rotation, roomID, animNumber, frameNumber, hp, OCB, AIBits) + Moveable(object, name, position, rotation, roomNumber, animNumber, frameNumber, hp, OCB, AIBits)
    Used to generate a new moveable dynamically at runtime.
    @@ -420,9 +420,9 @@ most can just be ignored (see usage). Rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) -
  • roomID +
  • roomNumber int - room ID item is in (default: calculated automatically) + the room number the moveable is in (default: calculated automatically).
  • animNumber int diff --git a/Documentation/doc/2 classes/Objects.Room.html b/Documentation/doc/2 classes/Objects.Room.html index c4e632774..306cb447b 100644 --- a/Documentation/doc/2 classes/Objects.Room.html +++ b/Documentation/doc/2 classes/Objects.Room.html @@ -102,7 +102,7 @@

    Class Objects.Room

    -

    Rooms

    +

    Room object.

    @@ -111,8 +111,12 @@

    Functions

  • Moveable(object, name, position, rotation, roomID, animNumber, frameNumber, hp, OCB, AIBits)Moveable(object, name, position, rotation, roomNumber, animNumber, frameNumber, hp, OCB, AIBits) Used to generate a new moveable dynamically at runtime.
    - - + + + + + + @@ -123,28 +127,28 @@ - + + + + + - - - - - - + + - - + + - - + +
    Room:GetActive()Determine whether the room is active or notRoom:GetRoomNumber()Get the room's number.
    Room:GetName()Get the room's unique string identifier.
    Room:GetColor()Get the room's reverb type.
    Room:SetReverbType(new)Room:SetName(name)Set the room's unique string identifier.
    Room:SetReverbType(Reverb) Set the room's reverb type.
    Room:GetName()Get the room's unique string identifier.
    Room:SetName(name)Set the room's name (its unique string identifier).Room:SetFlag(flagID, Boolean)Set the room's specified flag.
    Room:GetFlag(flagID) Get the room's specified flag value (true or false).
    Room:SetFlag(flagID, the)Set the room's specified flag value.Room:IsTagPresent(tag)Check if the specified tag is set for the room.
    Room:IsTagPresent(tag)Checks if specified tag is set for this room.Room:GetActive()Check if the room is active.
    @@ -156,11 +160,11 @@
    - - Room:GetActive() + + Room:GetRoomNumber()
    - Determine whether the room is active or not + Get the room's number. () @@ -168,8 +172,29 @@

    Returns:

      - bool - true if the room is active + int + Room number. +
    + + + + +
    +
    + + Room:GetName() +
    +
    + Get the room's unique string identifier. () + + + + +

    Returns:

    +
      + + string + Room name.
    @@ -181,7 +206,7 @@ Room:GetColor()
    - Get the room's ambient light color. + Get the room's ambient light color. () @@ -190,7 +215,7 @@
      Color - ambient light color of the room + Ambient light color.
    @@ -202,7 +227,7 @@ Room:GetReverbType()
    - Get the room's reverb type. + Get the room's reverb type. () @@ -211,50 +236,7 @@
      RoomReverb - room's reverb type -
    - - - - -
    -
    - - Room:SetReverbType(new) -
    -
    - Set the room's reverb type. - - - -

    Parameters:

    -
      -
    • new - RoomReverb - reverb type of the room -
    • -
    - - - - - -
    -
    - - Room:GetName() -
    -
    - Get the room's unique string identifier. - - - - -

    Returns:

    -
      - - string - the room's name + Reverb type.
    @@ -266,7 +248,7 @@ Room:SetName(name)
    - Set the room's name (its unique string identifier). + Set the room's unique string identifier. () @@ -274,7 +256,55 @@
    • name string - The room's new name + New name. +
    • +
    + + + + + +
    +
    + + Room:SetReverbType(Reverb) +
    +
    + Set the room's reverb type. () + + + +

    Parameters:

    + + + + + + +
    +
    + + Room:SetFlag(flagID, Boolean) +
    +
    + Set the room's specified flag. () + + + +

    Parameters:

    +
      +
    • flagID + RoomFlagID + Room flag ID. +
    • +
    • Boolean + bool + to set the flag to.
    @@ -288,7 +318,7 @@ Room:GetFlag(flagID)
    - Get the room's specified flag value (true or false). + Get the room's specified flag value (true or false). () @@ -296,39 +326,7 @@ - -

    Returns:

    -
      - - bool - the room's specified flag value -
    - - - - -
    -
    - - Room:SetFlag(flagID, the) -
    -
    - Set the room's specified flag value. - - - -

    Parameters:

    -
      -
    • flagID - RoomFlagID - The room's flag ID -
    • -
    • the - bool - room's new flag value + Room flag ID.
    @@ -342,7 +340,7 @@ Room:IsTagPresent(tag)
    - Checks if specified tag is set for this room. + Check if the specified tag is set for the room. () @@ -350,7 +348,7 @@
    • tag string - A text tag to check (case sensitive) + Text tag to check (case sensitive).
    @@ -358,7 +356,28 @@
      bool - true if tag is present, false if not + Boolean of the tag's presence. +
    + + + + +
    +
    + + Room:GetActive() +
    +
    + Check if the room is active. () + + + + +

    Returns:

    +
      + + bool + Boolean of the room's active status.
    diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index 4ced9efdc..4d237a75b 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -227,7 +227,7 @@ local door = GetMoveableByName("door_type4_14") Objects.Room - Rooms + Room object. Objects.Sink diff --git a/TombEngine/Game/items.cpp b/TombEngine/Game/items.cpp index 120d63343..5f30fac06 100644 --- a/TombEngine/Game/items.cpp +++ b/TombEngine/Game/items.cpp @@ -610,6 +610,8 @@ short CreateItem() g_Level.Items[NextItemFree].Flags = 0; NextItemFree = g_Level.Items[NextItemFree].NextItem; + g_Level.Items[itemNumber].DisableInterpolation = true; + return itemNumber; } diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index 9ff6fddbe..bf06ed3bf 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -424,6 +424,10 @@ namespace TEN::Renderer newItem->PrevTranslation = newItem->Translation; newItem->PrevRotation = newItem->Rotation; newItem->PrevWorld = newItem->World; + + // Otherwise all frames until the next ControlPhase will not + // be interpolated + item->DisableInterpolation = false; for (int j = 0; j < MAX_BONES; j++) newItem->PrevAnimTransforms[j] = newItem->AnimTransforms[j]; From 015adfb9c6cc6b29a576e260cebb8ad37fab2a95 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 11 Sep 2024 11:14:36 +0200 Subject: [PATCH 290/410] Improved disable interpolation flag for flyby cameras --- TombEngine/Game/spotcam.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index e9234f1c7..e986685e6 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -138,7 +138,6 @@ void InitializeSpotCam(short Sequence) SpotcamPaused = false; SpotcamLoopCnt = 0; Lara.Control.IsLocked = false; - Camera.DisableInterpolation = true; LaraAir = Lara.Status.Air; @@ -236,6 +235,8 @@ void InitializeSpotCam(short Sequence) CameraFOV[1] = SpotCam[CurrentSplineCamera].fov; CameraSpeed[1] = SpotCam[CurrentSplineCamera].speed; + Camera.DisableInterpolation = true; + SplineFromCamera = 0; int cn = CurrentSplineCamera; @@ -388,6 +389,7 @@ void CalculateSpotCameras() { SetScreenFadeIn(FADE_SCREEN_SPEED); CameraFade = CurrentSplineCamera; + Camera.DisableInterpolation = true; } if ((SpotCam[CurrentSplineCamera].flags & SCF_SCREEN_FADE_OUT) && @@ -395,6 +397,7 @@ void CalculateSpotCameras() { SetScreenFadeOut(FADE_SCREEN_SPEED); CameraFade = CurrentSplineCamera; + Camera.DisableInterpolation = true; } sp = 0; From 40b09be39b5516fe5c61fe0f173510505e3996ee Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Fri, 13 Sep 2024 06:37:24 +0200 Subject: [PATCH 291/410] Added Disable interpolation anim command --- TombEngine/Game/animation.cpp | 7 +++++++ TombEngine/Game/animation.h | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp index 1f8411bd7..f29ee8590 100644 --- a/TombEngine/Game/animation.cpp +++ b/TombEngine/Game/animation.cpp @@ -212,6 +212,13 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased) commandDataPtr += 2; break; + case AnimCommandType::DisableInterpolation: + if (isFrameBased && item.Animation.FrameNumber == commandDataPtr[0]) + item.DisableInterpolation = true; + + commandDataPtr += 1; + break; + default: break; } diff --git a/TombEngine/Game/animation.h b/TombEngine/Game/animation.h index 7cf2fc000..dc93532a0 100644 --- a/TombEngine/Game/animation.h +++ b/TombEngine/Game/animation.h @@ -24,7 +24,8 @@ enum class AnimCommandType AttackReady, Deactivate, SoundEffect, - Flipeffect + Flipeffect, + DisableInterpolation }; struct AnimFrame From a98ed141cc498088ec1a9f1c03b0247ff77baa5b Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sun, 15 Sep 2024 15:13:36 +0100 Subject: [PATCH 292/410] Update CHANGELOG.md Contains listings for branches to be merged for the next release. --- CHANGELOG.md | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ce6d1cc9..5b300ca41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,36 +26,42 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed teeth spikes not triggering the player impale animation. * Fixed TR4 mine crash with OCB 1 when triggered. * Fixed cases where Atlantean mutant's bombs cause the game to crash. -* Fixed young hair drawing. +* Fixed young hair drawing. https://tombengine.com/docs/level-settings/#young_lara ### Features/Amendments -* Changed Rome Hammer to not hurt player whilst deactivated. -* Changed Statue with blade damage, from 20 to 200. -* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed. -* Enhanced Rolling Spindle detection to avoid them going down through pits. -* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) -* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). -* Enhanced raptor behaviour and handling. - - OCB 0: Classic behaviour - - OCB 1: Can jump up/down up to 4 steps and jump across gaps up to 2 blocks wide. - - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2 -* Added TR3 seal mutant. - - OCB 0: Normal enemy behaviour. (TR3 RX-Tech mines level) - - OCB 1: Trap like behaviour. (TR3 Antarctica level) + +* Added variable framerate , that allows the engine to run at an unlocked framerate for a much smoother experience. Setting can be toggled on or off in the graphical settings menu. +* Added a customisable global lensflare effect. https://tombengine.com/docs/level-settings/#lensflare +* Added a customisable starry sky and meteor effect (based on TR5). https://tombengine.com/docs/level-settings/#stars +* Added the ability to display "Lara's Home" entry in the main menu. +* Added F12 as alternative to PrtSc for screenshots. +* Added option to enable or disable menu option looping. + - Menu scrolling using held inputs will stop at the last option until a new input is made. +* Added TR3 seal mutant. https://tombengine.com/docs/ocb-and-setup-instructions/#sealmutant - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Seal_Mutant.wad2 * Add new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. +* Added TR4 Enemy_Jeep https://tombengine.com/docs/ocb-and-setup-instructions/#enemy_jeep +* Changed Rome Hammer to not hurt player whilst deactivated. +* Changed Statue with blade damage, from 20 to 200. +* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed. * Changed Water sound condition to ShallowWater. -* Added option to enable or disable menu option looping. -* Menu scrolling using held inputs will stop at the last option until a new input is made. -* Added the ability to display "Lara's Home" entry in the main menu. -* Added F12 as alternative to PrtSc for screenshots. - +* Enhanced Rolling Spindle detection to avoid them going down through pits. +* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) +* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). +* Enhanced raptor behaviour and handling. https://tombengine.com/docs/ocb-and-setup-instructions/#raptor + - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2 +* Enhanced pushables. Pushables will now react to the texture sound of the floor below it. + - A soundpack for these new sounds has been created and can be found here: + ### Lua API changes + +* Added Flow.EnableHomeLevel() +* Added Flow.LensFlare() +* Added Flow.Starfield() * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() -* Added Flow.EnableHomeLevel() * Added Room:GetRoomNumber() * Removed anims.monkeyAutoJump. It is now a player menu configuration. * Fixed Volume:GetActive() method From 29c2363141c58ac11e3635574f9e6c03cb68e523 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sun, 15 Sep 2024 21:24:16 +0100 Subject: [PATCH 293/410] Update CHANGELOG.md --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b300ca41..67f1cf13a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,11 +49,9 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Changed Water sound condition to ShallowWater. * Enhanced Rolling Spindle detection to avoid them going down through pits. * Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) -* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing dar emitter ). +* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing-dart emitter ). * Enhanced raptor behaviour and handling. https://tombengine.com/docs/ocb-and-setup-instructions/#raptor - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2 -* Enhanced pushables. Pushables will now react to the texture sound of the floor below it. - - A soundpack for these new sounds has been created and can be found here: ### Lua API changes From d62ae232ee3cb6a02292e5fc6887d9ff41f0931f Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sun, 22 Sep 2024 09:48:22 +0100 Subject: [PATCH 294/410] Change player HAIR enumerations --- TombEngine/Game/effects/hair.cpp | 2 +- TombEngine/Objects/game_object_ids.h | 4 ++-- TombEngine/Renderer/RendererCompatibility.cpp | 6 +++--- TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/TombEngine/Game/effects/hair.cpp b/TombEngine/Game/effects/hair.cpp index 33cf2dd46..0f660f493 100644 --- a/TombEngine/Game/effects/hair.cpp +++ b/TombEngine/Game/effects/hair.cpp @@ -321,7 +321,7 @@ namespace TEN::Effects::Hair { auto& unit = Units[i]; - auto objectID = (i == 0) ? ID_SINGLE_BRAID_HAIR : ID_DUAL_PIGTAIL_HAIR; + auto objectID = (i == 0) ? ID_HAIR_PRIMARY : ID_HAIR_SECONDARY; const auto& object = Objects[objectID]; unit.IsEnabled = (object.loaded && (i == 0 || (i == 1 && isYoung))); diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index f1574ccfa..9307fa3bf 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -40,8 +40,8 @@ enum GAME_OBJECT_ID : short ID_LARA_DIRT_MESH, ID_LARA_CROWBAR_ANIM, ID_LARA_TORCH_ANIM, - ID_SINGLE_BRAID_HAIR, - ID_DUAL_PIGTAIL_HAIR, + ID_HAIR_PRIMARY, + ID_HAIR_SECONDARY, ID_SNOWMOBILE_LARA_ANIMS = 50, ID_SNOWMOBILE, diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp index 79e93a3f6..2bf5f89eb 100644 --- a/TombEngine/Renderer/RendererCompatibility.cpp +++ b/TombEngine/Renderer/RendererCompatibility.cpp @@ -516,7 +516,7 @@ namespace TEN::Renderer &moveable, &g_Level.Meshes[obj->meshIndex + j], j, MoveablesIds[i] == ID_LARA_SKIN_JOINTS, - MoveablesIds[i] == ID_SINGLE_BRAID_HAIR || MoveablesIds[i] == ID_DUAL_PIGTAIL_HAIR, &lastVertex, &lastIndex); + MoveablesIds[i] == ID_HAIR_PRIMARY || MoveablesIds[i] == ID_HAIR_SECONDARY, &lastVertex, &lastIndex); moveable.ObjectMeshes.push_back(mesh); _meshes.push_back(mesh); @@ -687,7 +687,7 @@ namespace TEN::Renderer } } } - else if (MoveablesIds[i] == ID_SINGLE_BRAID_HAIR && isSkinPresent) + else if (MoveablesIds[i] == ID_HAIR_PRIMARY && isSkinPresent) { for (int j = 0; j < obj->nmeshes; j++) { @@ -776,7 +776,7 @@ namespace TEN::Renderer } } } - else if (MoveablesIds[i] == ID_DUAL_PIGTAIL_HAIR && isSkinPresent) + else if (MoveablesIds[i] == ID_HAIR_SECONDARY && isSkinPresent) { for (int j = 0; j < obj->nmeshes; j++) { diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index a9fd40d03..6409f2f92 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -53,8 +53,8 @@ The following constants are inside ObjID. LARA_DIRT_MESH LARA_CROWBAR_ANIM LARA_TORCH_ANIM - SINGLE_BRAID_HAIR - DUAL_PIGTAIL_HAIR + HAIR_PRIMARY + HAIR_SECONDARY SNOWMOBILE_LARA_ANIMS SNOWMOBILE QUAD_LARA_ANIMS @@ -1231,8 +1231,8 @@ static const std::unordered_map kObjIDs { { "LARA_DIRT_MESH", ID_LARA_DIRT_MESH }, { "LARA_CROWBAR_ANIM", ID_LARA_CROWBAR_ANIM }, { "LARA_TORCH_ANIM", ID_LARA_TORCH_ANIM }, - { "SINGLE_BRAID_HAIR", ID_SINGLE_BRAID_HAIR }, - { "DUAL_PIGTAIL_HAIR", ID_DUAL_PIGTAIL_HAIR }, + { "HAIR_PRIMARY", ID_HAIR_PRIMARY }, + { "HAIR_SECONDARY", ID_HAIR_SECONDARY }, { "SNOWMOBILE_LARA_ANIMS", ID_SNOWMOBILE_LARA_ANIMS }, { "SNOWMOBILE", ID_SNOWMOBILE }, { "QUAD_LARA_ANIMS", ID_QUAD_LARA_ANIMS }, From f8f20a071c68ffcfabea13643c5df1dbff0b80ab Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 23 Sep 2024 00:23:49 +0200 Subject: [PATCH 295/410] Fixed leveljump vehicle transfer --- CHANGELOG.md | 3 ++- TombEngine/Game/Lara/lara_initialise.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67f1cf13a..15a1b5c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Bug fixes * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. +* Fixed vehicle transfer on leveljump. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. @@ -26,7 +27,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed teeth spikes not triggering the player impale animation. * Fixed TR4 mine crash with OCB 1 when triggered. * Fixed cases where Atlantean mutant's bombs cause the game to crash. -* Fixed young hair drawing. https://tombengine.com/docs/level-settings/#young_lara +* Fixed young Lara hair drawing. https://tombengine.com/docs/level-settings/#young_lara ### Features/Amendments diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 622d6c6c9..4d3e6004b 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -122,6 +122,9 @@ void InitializeLaraAnims(ItemInfo* item) player.LeftArm.Locked = false; player.RightArm.Locked = false; + if (PlayerVehicleObjectID != GAME_OBJECT_ID::ID_NO_OBJECT) + return; + if (TestEnvironment(ENV_FLAG_WATER, item)) { SetAnimation(item, LA_UNDERWATER_IDLE); From 1b95946db9492538d8d9039bec8088afbe7fff8a Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:04:19 +0200 Subject: [PATCH 296/410] Fix kayak and minecart meshswaps on leveljump --- TombEngine/Game/Lara/lara_initialise.cpp | 5 ++++ TombEngine/Objects/TR3/Vehicles/kayak.cpp | 32 ++++++++++++++--------- TombEngine/Objects/TR3/Vehicles/kayak.h | 10 ++++--- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 4d3e6004b..89e8451bc 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -200,6 +200,7 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) { case GAME_OBJECT_ID::ID_KAYAK: InitializeKayak(vehicle->Index); + KayakPaddleTake(&playerItem); break; case GAME_OBJECT_ID::ID_MOTORBIKE: @@ -218,6 +219,10 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) InitializeSkidoo(vehicle->Index); break; + case GAME_OBJECT_ID::ID_MINECART: + playerItem.Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; + break; + default: break; } diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index 69d165de6..f8f00d2aa 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -33,9 +33,9 @@ namespace TEN::Entities::Vehicles constexpr int KAYAK_VELOCITY_LR_ACCEL = 16 * VEHICLE_VELOCITY_SCALE; constexpr int KAYAK_VELOCITY_HOLD_TURN_DECEL = 0.5f * VEHICLE_VELOCITY_SCALE; constexpr int KAYAK_VELOCITY_FRICTION_DECEL = 0.5f * VEHICLE_VELOCITY_SCALE; - constexpr int KAYAK_VELOCITY_MAX = 56 * VEHICLE_VELOCITY_SCALE; + constexpr char KAYAK_FLAG_PADDLE_MESH = 0x80; constexpr auto KAYAK_WAKE_OFFSET = Vector3(BLOCK(0.1f), 0.0f, BLOCK(0.25f)); // TODO: Very confusing. @@ -221,6 +221,18 @@ namespace TEN::Entities::Vehicles // SetupRipple(x, kayakItem->Pose.Position.y, z, -2 - (GetRandomControl() & 1), 0, Objects[ID_KAYAK_PADDLE_TRAIL_SPRITE].meshIndex,TO_RAD(kayakItem->Pose.Orientation.y)); } + void KayakPaddleTake(ItemInfo* laraItem) + { + laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_KAYAK_LARA_ANIMS].meshIndex + LM_RHAND; + laraItem->MeshBits.Clear(KayakLaraLegJoints); + } + + void KayakPaddlePut(ItemInfo* laraItem) + { + laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; + laraItem->MeshBits.Set(KayakLaraLegJoints); + } + int KayakGetCollisionAnim(ItemInfo* kayakItem, int xDiff, int zDiff) { xDiff = kayakItem->Pose.Position.x - xDiff; @@ -897,25 +909,19 @@ namespace TEN::Entities::Vehicles break; case KAYAK_STATE_MOUNT_LEFT: - if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) && - frame == 24 && - !(kayak->Flags & 0x80)) + if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) && frame == 24 && !(kayak->Flags & KAYAK_FLAG_PADDLE_MESH)) { - kayak->Flags |= 0x80; - laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_KAYAK_LARA_ANIMS].meshIndex + LM_RHAND; - laraItem->MeshBits.Clear(KayakLaraLegJoints); + kayak->Flags |= KAYAK_FLAG_PADDLE_MESH; + KayakPaddleTake(laraItem); } break; case KAYAK_STATE_DISMOUNT: - if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) && - frame == 27 && - kayak->Flags & 0x80) + if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) && frame == 27 && kayak->Flags & KAYAK_FLAG_PADDLE_MESH) { - kayak->Flags &= ~0x80; - laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; - laraItem->MeshBits.Set(KayakLaraLegJoints); + kayak->Flags &= ~KAYAK_FLAG_PADDLE_MESH; + KayakPaddlePut(laraItem); } laraItem->Animation.TargetState = laraItem->Animation.RequiredState; diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.h b/TombEngine/Objects/TR3/Vehicles/kayak.h index 8eb409dea..2d00aa1c4 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.h +++ b/TombEngine/Objects/TR3/Vehicles/kayak.h @@ -11,19 +11,21 @@ namespace TEN::Entities::Vehicles void KayakPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void DoKayakMount(ItemInfo* kayakItem, ItemInfo* laraItem, VehicleMountType mountType); + void KayakPaddleTake(ItemInfo* laraItem); + void KayakPaddlePut(ItemInfo* laraItem); + void KayakDraw(ItemInfo* kayakItem); void KayakDoRipple(ItemInfo* kayakItem, int xOffset, int zOffset); - int KayakGetCollisionAnim(ItemInfo* kayakItem, int xDiff, int zDiff); - int KayakDoDynamics(int height, int verticalVelocity, int* y); + int KayakGetCollisionAnim(ItemInfo* kayakItem, int xDiff, int zDiff); + int KayakDoDynamics(int height, int verticalVelocity, int* y); void KayakDoCurrent(ItemInfo* kayakItem, ItemInfo* laraItem); bool KayakCanGetOut(ItemInfo* kayakItem, int dir); - int KayakDoShift(ItemInfo* kayakItem, Vector3i* pos, Vector3i* old); + int KayakDoShift(ItemInfo* kayakItem, Vector3i* pos, Vector3i* old); void KayakToBackground(ItemInfo* kayakItem, ItemInfo* laraItem); void KayakUserInput(ItemInfo* kayakItem, ItemInfo* laraItem); void KayakToItemCollision(ItemInfo* kayakItem, ItemInfo* laraItem); void KayakLaraRapidsDrown(ItemInfo* laraItem); - void PreDrawWakeFx(ItemInfo* kayakItem); bool KayakControl(ItemInfo* laraItem); } From 90effcdc588aafed1a380136a8cba9ef03805c0c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 23 Sep 2024 01:17:15 +0200 Subject: [PATCH 297/410] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a1b5c03..3c3edef1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Bug fixes * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. -* Fixed vehicle transfer on leveljump. +* Fixed leveljump vehicle transfer. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. From 3dafdf44e3bc174b312b111023abefa8285dae5f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:58:56 +0200 Subject: [PATCH 298/410] Update kayak.cpp --- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index f8f00d2aa..4fd265d16 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -35,7 +35,7 @@ namespace TEN::Entities::Vehicles constexpr int KAYAK_VELOCITY_FRICTION_DECEL = 0.5f * VEHICLE_VELOCITY_SCALE; constexpr int KAYAK_VELOCITY_MAX = 56 * VEHICLE_VELOCITY_SCALE; - constexpr char KAYAK_FLAG_PADDLE_MESH = 0x80; + constexpr auto KAYAK_FLAG_PADDLE_MESH = 0x80; constexpr auto KAYAK_WAKE_OFFSET = Vector3(BLOCK(0.1f), 0.0f, BLOCK(0.25f)); // TODO: Very confusing. From 5bc065c4118fd52a0dffea3092e76b6da4f15dc9 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Fri, 27 Sep 2024 07:23:40 +0200 Subject: [PATCH 299/410] Possibly fixed torch interpolation --- TombEngine/Renderer/RendererDrawEffect.cpp | 56 +++++++++++++++++----- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index d717597ba..0d0f6ca3b 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -400,7 +400,9 @@ namespace TEN::Renderer void Renderer::PrepareParticles(RenderView& view) { for (int i = 0; i < ParticleNodeOffsetIDs::NodeMax; i++) + { NodeOffsets[i].gotIt = false; + } for (auto& particle : Particles) { @@ -409,27 +411,49 @@ namespace TEN::Renderer if (particle.flags & SP_DEF) { - auto pos = Vector3(particle.x, particle.y, particle.z); + auto pos = Vector3::Lerp( + Vector3(particle.PrevX, particle.PrevY, particle.PrevZ), + Vector3(particle.x, particle.y, particle.z), + _interpolationFactor); if (particle.flags & SP_FX) { const auto& fx = EffectList[particle.fxObj]; - pos += fx.pos.Position.ToVector3(); + RendererEffect* newEffect = &_effects[particle.fxObj]; + + newEffect->Translation = Matrix::CreateTranslation(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z); + newEffect->Rotation = fx.pos.Orientation.ToRotationMatrix(); + newEffect->Scale = Matrix::CreateScale(1.0f); + newEffect->World = newEffect->Rotation * newEffect->Translation; + newEffect->ObjectID = fx.objectNumber; + newEffect->RoomNumber = fx.roomNumber; + newEffect->Position = fx.pos.Position.ToVector3(); + + newEffect->InterpolatedPosition = Vector3::Lerp(newEffect->PrevPosition, newEffect->Position, _interpolationFactor); + newEffect->InterpolatedTranslation = Matrix::Lerp(newEffect->PrevTranslation, newEffect->Translation, _interpolationFactor); + newEffect->InterpolatedRotation = Matrix::Lerp(newEffect->InterpolatedRotation, newEffect->Rotation, _interpolationFactor); + newEffect->InterpolatedWorld = Matrix::Lerp(newEffect->PrevWorld, newEffect->World, _interpolationFactor); + newEffect->InterpolatedScale = Matrix::Lerp(newEffect->PrevScale, newEffect->Scale, _interpolationFactor); + + pos += newEffect->InterpolatedPosition; if ((particle.sLife - particle.life) > Random::GenerateInt(8, 12)) { + // Particle becomes autonome particle.flags &= ~SP_FX; - particle.x = pos.x; - particle.y = pos.y; - particle.z = pos.z; + + particle.x = particle.PrevX = pos.x; + particle.y = particle.PrevY = pos.y; + particle.z = particle.PrevZ = pos.z; } } else if (!(particle.flags & SP_ITEM)) { - pos.x = particle.x; - pos.y = particle.y; - pos.z = particle.z; + // NOTE: pos already set before... + //pos.x = particle.x; + //pos.y = particle.y; + //pos.z = particle.z; } else { @@ -466,15 +490,17 @@ namespace TEN::Renderer if ((particle.sLife - particle.life) > Random::GenerateInt(4, 8)) { + // Particle becomes autonome particle.flags &= ~SP_ITEM; - particle.x = pos.x; - particle.y = pos.y; - particle.z = pos.z; + + particle.x = particle.PrevX = pos.x; + particle.y = particle.PrevY = pos.y; + particle.z = particle.PrevZ = pos.z; } } else { - pos += item->Pose.Position.ToVector3(); + pos += _items[particle.fxObj].InterpolatedPosition; } } @@ -494,7 +520,11 @@ namespace TEN::Renderer if (!CheckIfSlotExists(ID_SPARK_SPRITE, "Particle rendering")) continue; - auto pos = Vector3(particle.x, particle.y, particle.z); + auto pos = Vector3::Lerp( + Vector3(particle.PrevX, particle.PrevY, particle.PrevZ), + Vector3(particle.x, particle.y, particle.z), + _interpolationFactor); + auto axis = Vector3(particle.xVel, particle.yVel, particle.zVel); axis.Normalize(); From ef751cf236b98fdf4d890690f8150431c441ae08 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:29:27 +0200 Subject: [PATCH 300/410] Fixed #1405 --- CHANGELOG.md | 1 + TombEngine/Objects/TR4/Object/tr4_sarcophagus.cpp | 2 +- TombEngine/Specific/level.cpp | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c3edef1f..3c5063fc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Bug fixes * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. * Fixed leveljump vehicle transfer. +* Fixed sarcophagus pick-ups. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. diff --git a/TombEngine/Objects/TR4/Object/tr4_sarcophagus.cpp b/TombEngine/Objects/TR4/Object/tr4_sarcophagus.cpp index ba8071532..d9553cfe5 100644 --- a/TombEngine/Objects/TR4/Object/tr4_sarcophagus.cpp +++ b/TombEngine/Objects/TR4/Object/tr4_sarcophagus.cpp @@ -73,6 +73,6 @@ void SarcophagusCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* c } else { - CollectMultiplePickups(sarcItem->Index); + CollectCarriedItems(sarcItem); } } diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp index a48f820e2..2d7388c6e 100644 --- a/TombEngine/Specific/level.cpp +++ b/TombEngine/Specific/level.cpp @@ -1471,7 +1471,8 @@ void GetCarriedItems() const auto& object = Objects[item.ObjectNumber]; if (object.intelligent || - (item.ObjectNumber >= ID_SEARCH_OBJECT1 && item.ObjectNumber <= ID_SEARCH_OBJECT3)) + (item.ObjectNumber >= ID_SEARCH_OBJECT1 && item.ObjectNumber <= ID_SEARCH_OBJECT3) || + (item.ObjectNumber == ID_SARCOPHAGUS)) { for (short linkNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkNumber != NO_VALUE; linkNumber = g_Level.Items[linkNumber].NextItem) { From 3a0e703d1d9811d2f103691195f9a0fd5630f8e5 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:45:34 +0200 Subject: [PATCH 301/410] Fix Lara meshswaps after kayak dismount after leveljump --- TombEngine/Game/Lara/lara_initialise.cpp | 2 +- TombEngine/Objects/TR3/Vehicles/kayak.cpp | 20 +++++++------------- TombEngine/Objects/TR3/Vehicles/kayak.h | 5 +++-- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 89e8451bc..937b31fa4 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -200,7 +200,7 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) { case GAME_OBJECT_ID::ID_KAYAK: InitializeKayak(vehicle->Index); - KayakPaddleTake(&playerItem); + KayakPaddleTake(GetKayakInfo(&g_Level.Items[vehicle->Index]), &playerItem); break; case GAME_OBJECT_ID::ID_MOTORBIKE: diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.cpp b/TombEngine/Objects/TR3/Vehicles/kayak.cpp index 4fd265d16..e66e1c11d 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.cpp +++ b/TombEngine/Objects/TR3/Vehicles/kayak.cpp @@ -221,14 +221,16 @@ namespace TEN::Entities::Vehicles // SetupRipple(x, kayakItem->Pose.Position.y, z, -2 - (GetRandomControl() & 1), 0, Objects[ID_KAYAK_PADDLE_TRAIL_SPRITE].meshIndex,TO_RAD(kayakItem->Pose.Orientation.y)); } - void KayakPaddleTake(ItemInfo* laraItem) + void KayakPaddleTake(KayakInfo* kayak, ItemInfo* laraItem) { + kayak->Flags |= KAYAK_FLAG_PADDLE_MESH; laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_KAYAK_LARA_ANIMS].meshIndex + LM_RHAND; laraItem->MeshBits.Clear(KayakLaraLegJoints); } - void KayakPaddlePut(ItemInfo* laraItem) + void KayakPaddlePut(KayakInfo* kayak, ItemInfo* laraItem) { + kayak->Flags &= ~KAYAK_FLAG_PADDLE_MESH; laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; laraItem->MeshBits.Set(KayakLaraLegJoints); } @@ -910,21 +912,13 @@ namespace TEN::Entities::Vehicles case KAYAK_STATE_MOUNT_LEFT: if (TestAnimNumber(*laraItem, KAYAK_ANIM_GET_PADDLE) && frame == 24 && !(kayak->Flags & KAYAK_FLAG_PADDLE_MESH)) - { - kayak->Flags |= KAYAK_FLAG_PADDLE_MESH; - KayakPaddleTake(laraItem); - } - + KayakPaddleTake(kayak, laraItem); break; case KAYAK_STATE_DISMOUNT: - if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) && frame == 27 && kayak->Flags & KAYAK_FLAG_PADDLE_MESH) - { - kayak->Flags &= ~KAYAK_FLAG_PADDLE_MESH; - KayakPaddlePut(laraItem); - } - laraItem->Animation.TargetState = laraItem->Animation.RequiredState; + if (TestAnimNumber(*laraItem, KAYAK_ANIM_DISMOUNT_START) && frame == 27 && kayak->Flags & KAYAK_FLAG_PADDLE_MESH) + KayakPaddlePut(kayak, laraItem); break; case KAYAK_STATE_DISMOUNT_LEFT: diff --git a/TombEngine/Objects/TR3/Vehicles/kayak.h b/TombEngine/Objects/TR3/Vehicles/kayak.h index 2d00aa1c4..db7aec2b6 100644 --- a/TombEngine/Objects/TR3/Vehicles/kayak.h +++ b/TombEngine/Objects/TR3/Vehicles/kayak.h @@ -6,13 +6,14 @@ struct ItemInfo; namespace TEN::Entities::Vehicles { + KayakInfo* GetKayakInfo(ItemInfo* kayakItem); void InitializeKayak(short itemNumber); void KayakPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void DoKayakMount(ItemInfo* kayakItem, ItemInfo* laraItem, VehicleMountType mountType); - void KayakPaddleTake(ItemInfo* laraItem); - void KayakPaddlePut(ItemInfo* laraItem); + void KayakPaddleTake(KayakInfo* kayak, ItemInfo* laraItem); + void KayakPaddlePut(KayakInfo* kayak, ItemInfo* laraItem); void KayakDraw(ItemInfo* kayakItem); From ca87efa4fd14c8b4ff1f8292ee33de35034f372d Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 28 Sep 2024 18:59:09 +0200 Subject: [PATCH 302/410] Possibly fix minecart wrench --- TombEngine/Game/Lara/lara_initialise.cpp | 3 ++- TombEngine/Objects/TR3/Vehicles/minecart.cpp | 18 ++++++++++++++---- TombEngine/Objects/TR3/Vehicles/minecart.h | 4 ++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 937b31fa4..e2da15df7 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -14,6 +14,7 @@ #include "Game/Setup.h" #include "Objects/TR2/Vehicles/skidoo.h" #include "Objects/TR3/Vehicles/kayak.h" +#include "Objects/TR3/Vehicles/minecart.h" #include "Objects/TR3/Vehicles/quad_bike.h" #include "Objects/TR4/Vehicles/jeep.h" #include "Objects/TR4/Vehicles/motorbike.h" @@ -220,7 +221,7 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) break; case GAME_OBJECT_ID::ID_MINECART: - playerItem.Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; + MinecartWrenchTake(GetMinecartInfo(&g_Level.Items[vehicle->Index]), &playerItem); break; default: diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.cpp b/TombEngine/Objects/TR3/Vehicles/minecart.cpp index c0d4e8e88..5fc83591b 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.cpp +++ b/TombEngine/Objects/TR3/Vehicles/minecart.cpp @@ -241,6 +241,18 @@ namespace TEN::Entities::Vehicles } } + void MinecartWrenchTake(MinecartInfo* minecart, ItemInfo* laraItem) + { + laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; + minecart->Flags |= MINECART_FLAG_WRENCH_MESH; + } + + void MinecartWrenchPut(MinecartInfo* minecart, ItemInfo* laraItem) + { + laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; + minecart->Flags &= ~MINECART_FLAG_WRENCH_MESH; + } + static int GetMinecartCollision(ItemInfo* minecartItem, short angle, int distance) { auto probe = GetPointCollision(*minecartItem, angle, distance, -LARA_HEIGHT); @@ -755,8 +767,7 @@ namespace TEN::Entities::Vehicles if (laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME) && minecart->Flags & MINECART_FLAG_WRENCH_MESH) { - laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND; - minecart->Flags &= ~MINECART_FLAG_WRENCH_MESH; + MinecartWrenchPut(minecart, laraItem); } if (minecart->Flags & MINECART_FLAG_DISMOUNT_RIGHT) @@ -804,8 +815,7 @@ namespace TEN::Entities::Vehicles if (!(minecart->Flags & MINECART_FLAG_WRENCH_MESH) && laraItem->Animation.FrameNumber == GetFrameIndex(minecartItem, MINECART_WRENCH_MESH_TOGGLE_FRAME)) { - laraItem->Model.MeshIndex[LM_RHAND] = Objects[ID_MINECART_LARA_ANIMS].meshIndex + LM_RHAND; - minecart->Flags |= MINECART_FLAG_WRENCH_MESH; + MinecartWrenchTake(minecart, laraItem); } } diff --git a/TombEngine/Objects/TR3/Vehicles/minecart.h b/TombEngine/Objects/TR3/Vehicles/minecart.h index e5677b172..4fcfea6f6 100644 --- a/TombEngine/Objects/TR3/Vehicles/minecart.h +++ b/TombEngine/Objects/TR3/Vehicles/minecart.h @@ -7,9 +7,13 @@ struct ItemInfo; namespace TEN::Entities::Vehicles { void InitializeMinecart(short itemNumber); + MinecartInfo* GetMinecartInfo(ItemInfo* minecartItem); void MinecartPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void DoMinecartMount(ItemInfo* minecartItem, ItemInfo* laraItem, VehicleMountType mountType); bool MinecartControl(ItemInfo* laraItem); + + void MinecartWrenchTake(MinecartInfo* minecart, ItemInfo* laraItem); + void MinecartWrenchPut(MinecartInfo* minecart, ItemInfo* laraItem); } From 061d1522076345b267e75e0da9894885c231864c Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 29 Sep 2024 06:16:13 +0200 Subject: [PATCH 303/410] Fixed rolling ball interpolation --- Documentation/doc/4 enums/Objects.ObjID.html | 4 ++-- TombEngine/Objects/TR5/Object/tr5_rollingball.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index d47ca7bb4..5324243e9 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -173,8 +173,8 @@ LARA_PETROL_MESH LARA_DIRT_MESH LARA_CROWBAR_ANIM LARA_TORCH_ANIM -SINGLE_BRAID_HAIR -DUAL_PIGTAIL_HAIR +HAIR_PRIMARY +HAIR_SECONDARY SNOWMOBILE_LARA_ANIMS SNOWMOBILE QUAD_LARA_ANIMS diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index 82f200631..5c77a6512 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -99,7 +99,10 @@ void RollingBallControl(short itemNumber) item->Animation.Velocity.y = -(GetRandomControl() % int(round(item->Animation.Velocity.z) / 8.0f)); } else + { item->Animation.Velocity.y = -item->Animation.Velocity.y / 4.0f; + item->DisableInterpolation = true; + } } int frontX = item->Pose.Position.x; @@ -307,6 +310,8 @@ void RollingBallControl(short itemNumber) } else item->Pose.Orientation.y = angle; + + item->DisableInterpolation = true; } item->Pose.Orientation.x -= ((abs(item->ItemFlags[0]) + abs(item->ItemFlags[1])) / 2) / vDivider; From 5f7ac065d140886db5415549b0d479f9292a1e7f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:42:50 +0200 Subject: [PATCH 304/410] Show relative anim number in stats --- TombEngine/Renderer/RendererDrawMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 5cf475445..c84adc37b 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1260,7 +1260,7 @@ namespace TEN::Renderer case RendererDebugPage::PlayerStats: PrintDebugMessage("PLAYER STATS"); PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID); - PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber); + PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber - Objects[LaraItem->Animation.AnimObjectID].animIndex); PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber); PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState); PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState); From bc6bf2c5a4b0dfab70a75c22317367e6763ab6cd Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:44:09 +0200 Subject: [PATCH 305/410] Fix speedboat / rubber boat on leveljumps --- TombEngine/Game/Lara/lara_initialise.cpp | 22 ++++++++++++++++++++++ TombEngine/Renderer/RendererLara.cpp | 3 +++ 2 files changed, 25 insertions(+) diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index e2da15df7..2dc6cdc7d 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -13,9 +13,11 @@ #include "Game/Lara/PlayerStateMachine.h" #include "Game/Setup.h" #include "Objects/TR2/Vehicles/skidoo.h" +#include "Objects/TR2/Vehicles/speedboat.h" #include "Objects/TR3/Vehicles/kayak.h" #include "Objects/TR3/Vehicles/minecart.h" #include "Objects/TR3/Vehicles/quad_bike.h" +#include "Objects/TR3/Vehicles/rubber_boat.h" #include "Objects/TR4/Vehicles/jeep.h" #include "Objects/TR4/Vehicles/motorbike.h" #include "Specific/level.h" @@ -224,9 +226,29 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) MinecartWrenchTake(GetMinecartInfo(&g_Level.Items[vehicle->Index]), &playerItem); break; + case GAME_OBJECT_ID::ID_SPEEDBOAT: + InitializeSpeedboat(vehicle->Index); + DoSpeedboatMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart); + break; + + case GAME_OBJECT_ID::ID_RUBBER_BOAT: + InitializeRubberBoat(vehicle->Index); + DoRubberBoatMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart); + break; + default: break; } + + // HACK: Reset activity status because boats need to be on active item linked list. + + if (vehicle->ObjectNumber == GAME_OBJECT_ID::ID_RUBBER_BOAT || + vehicle->ObjectNumber == GAME_OBJECT_ID::ID_SPEEDBOAT) + { + g_Level.Items[vehicle->Index].Active = false; + AddActiveItem(vehicle->Index); + g_Level.Items[vehicle->Index].Status = ITEM_ACTIVE; + } } void InitializeLaraLevelJump(ItemInfo* item, LaraInfo* playerBackup) diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp index e72079083..33acdbcfa 100644 --- a/TombEngine/Renderer/RendererLara.cpp +++ b/TombEngine/Renderer/RendererLara.cpp @@ -85,6 +85,9 @@ void Renderer::UpdateLaraAnimations(bool force) if (!force && rItem.DoneAnimations) return; + if (_moveableObjects.empty()) + return; + auto& playerObject = *_moveableObjects[ID_LARA]; // Clear extra rotations. From 78485fd3ec4bb514ecf28b958257f80621b85d33 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:11:59 +0200 Subject: [PATCH 306/410] Fixed UPV transfer on leveljump --- TombEngine/Game/Lara/lara_initialise.cpp | 6 ++++++ TombEngine/Objects/TR3/Vehicles/upv.cpp | 10 +--------- TombEngine/Objects/TR3/Vehicles/upv.h | 11 ++++++++++- TombEngine/Objects/TR3/tr3_objects.cpp | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 2dc6cdc7d..736a07eec 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -18,6 +18,7 @@ #include "Objects/TR3/Vehicles/minecart.h" #include "Objects/TR3/Vehicles/quad_bike.h" #include "Objects/TR3/Vehicles/rubber_boat.h" +#include "Objects/TR3/Vehicles/upv.h" #include "Objects/TR4/Vehicles/jeep.h" #include "Objects/TR4/Vehicles/motorbike.h" #include "Specific/level.h" @@ -236,6 +237,11 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) DoRubberBoatMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart); break; + case GAME_OBJECT_ID::ID_UPV: + DoUPVMount(&g_Level.Items[vehicle->Index], &playerItem, VehicleMountType::LevelStart); + GetUPVInfo(&g_Level.Items[vehicle->Index])->Flags = UPVFlags::UPV_FLAG_CONTROL; + break; + default: break; } diff --git a/TombEngine/Objects/TR3/Vehicles/upv.cpp b/TombEngine/Objects/TR3/Vehicles/upv.cpp index d80b3c98b..60ea75f8a 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.cpp +++ b/TombEngine/Objects/TR3/Vehicles/upv.cpp @@ -151,21 +151,13 @@ namespace TEN::Entities::Vehicles UPV_BITE_RIGHT_RUDDER_RIGHT = 4, UPV_BITE_RIGHT_RUDDER_LEFT = 5 // Unused. }; - enum UPVFlags - { - UPV_FLAG_CONTROL = (1 << 0), - UPV_FLAG_SURFACE = (1 << 1), - UPV_FLAG_DIVE = (1 << 2), - UPV_FLAG_DEAD = (1 << 3) - }; - UPVInfo* GetUPVInfo(ItemInfo* UPVItem) { return (UPVInfo*)UPVItem->Data; } - void UPVInitialize(short itemNumber) + void InitializeUPV(short itemNumber) { auto* UPVItem = &g_Level.Items[itemNumber]; UPVItem->Data = UPVInfo(); diff --git a/TombEngine/Objects/TR3/Vehicles/upv.h b/TombEngine/Objects/TR3/Vehicles/upv.h index dec8f642a..897acd302 100644 --- a/TombEngine/Objects/TR3/Vehicles/upv.h +++ b/TombEngine/Objects/TR3/Vehicles/upv.h @@ -6,7 +6,16 @@ struct ItemInfo; namespace TEN::Entities::Vehicles { - void UPVInitialize(short itemNumber); + enum UPVFlags + { + UPV_FLAG_CONTROL = (1 << 0), + UPV_FLAG_SURFACE = (1 << 1), + UPV_FLAG_DIVE = (1 << 2), + UPV_FLAG_DEAD = (1 << 3) + }; + + void InitializeUPV(short itemNumber); + UPVInfo* GetUPVInfo(ItemInfo* UPVItem); void UPVPlayerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void DoUPVMount(ItemInfo* UPVItem, ItemInfo* laraItem, VehicleMountType mountType); diff --git a/TombEngine/Objects/TR3/tr3_objects.cpp b/TombEngine/Objects/TR3/tr3_objects.cpp index f5909af7d..950c4fb7d 100644 --- a/TombEngine/Objects/TR3/tr3_objects.cpp +++ b/TombEngine/Objects/TR3/tr3_objects.cpp @@ -583,7 +583,7 @@ static void StartVehicles(ObjectInfo* obj) obj = &Objects[ID_UPV]; if (obj->loaded) { - obj->Initialize = UPVInitialize; + obj->Initialize = InitializeUPV; obj->control = UPVEffects; obj->collision = UPVPlayerCollision; obj->shadowType = ShadowMode::Lara; From 1e6c2158eaabfd5f26c72883b2a2d3b13517f415 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 2 Oct 2024 00:16:26 +0200 Subject: [PATCH 307/410] Add IsStringPresent script function for further usage in nodes --- CHANGELOG.md | 14 +++++++------- .../Scripting/Internal/ReservedScriptNames.h | 1 + .../Scripting/Internal/TEN/Flow/FlowHandler.cpp | 11 +++++++++++ .../Scripting/Internal/TEN/Flow/FlowHandler.h | 1 + 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c5063fc0..dd12efb5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -Here you will find the full changelog of TEN's releases from Version 1.0 and up +Here you will find the full changelog of TEN's releases from Version 1.0 and up The dates are in European standard format where date is presented as **YYYY-MM-DD** @@ -57,14 +57,14 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Lua API changes -* Added Flow.EnableHomeLevel() -* Added Flow.LensFlare() -* Added Flow.Starfield() +* Added Flow.EnableHomeLevel() function. +* Added Flow.IsStringPresent() function. * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. -* Added Input.KeyClearAll() -* Added Room:GetRoomNumber() +* Added Flow.LensFlare() and Flow.Starfield() classes. +* Added Input.KeyClearAll() function. +* Added Room:GetRoomNumber() function. * Removed anims.monkeyAutoJump. It is now a player menu configuration. -* Fixed Volume:GetActive() method +* Fixed Volume:GetActive() method. ## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21 diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 7aa0f4afa..4ad0effd9 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -227,6 +227,7 @@ static constexpr char ScriptReserved_EnablePointFilter[] = "EnablePointFilter"; // Flow Functions static constexpr char ScriptReserved_SetStrings[] = "SetStrings"; static constexpr char ScriptReserved_GetString[] = "GetString"; +static constexpr char ScriptReserved_IsStringPresent[] = "IsStringPresent"; static constexpr char ScriptReserved_SetLanguageNames[] = "SetLanguageNames"; // Flow Tables diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp index 5aebe1328..1f1c439d2 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.cpp @@ -248,6 +248,12 @@ You will not need to call them manually. */ tableFlow.set_function(ScriptReserved_GetString, &FlowHandler::GetString, this); +/*** Check if translated string is present. +@function IsStringPresent +@tparam key string key for translated string +*/ + tableFlow.set_function(ScriptReserved_IsStringPresent, &FlowHandler::IsStringPresent, this); + /*** Set language names for translations. Specify which translations in the strings table correspond to which languages. @function SetLanguageNames @@ -371,6 +377,11 @@ char const * FlowHandler::GetString(const char* id) const } } +bool FlowHandler::IsStringPresent(const char* id) const +{ + return _translationMap.find(id) != _translationMap.end(); +} + Settings* FlowHandler::GetSettings() { return &_settings; diff --git a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h index d9bd1ac84..55092b97d 100644 --- a/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h +++ b/TombEngine/Scripting/Internal/TEN/Flow/FlowHandler.h @@ -51,6 +51,7 @@ public: void AddLevel(Level const& level); void LoadFlowScript(); char const* GetString(const char* id) const; + bool IsStringPresent(const char* id) const; void SetStrings(sol::nested>>&& src); void SetLanguageNames(sol::as_table_t>&& src); void SetAnimations(const Animations& src); From 9a6dfef47534697a88a1e42d08fa3fadd08fed25 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:14:06 +0200 Subject: [PATCH 308/410] Also show relative frame number in debug --- TombEngine/Renderer/RendererDrawMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index c84adc37b..5ca92cddb 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1261,7 +1261,7 @@ namespace TEN::Renderer PrintDebugMessage("PLAYER STATS"); PrintDebugMessage("AnimObjectID: %d", LaraItem->Animation.AnimObjectID); PrintDebugMessage("AnimNumber: %d", LaraItem->Animation.AnimNumber - Objects[LaraItem->Animation.AnimObjectID].animIndex); - PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber); + PrintDebugMessage("FrameNumber: %d", LaraItem->Animation.FrameNumber - GetAnimData(LaraItem).frameBase); PrintDebugMessage("ActiveState: %d", LaraItem->Animation.ActiveState); PrintDebugMessage("TargetState: %d", LaraItem->Animation.TargetState); PrintDebugMessage("Velocity: %.3f, %.3f, %.3f", LaraItem->Animation.Velocity.z, LaraItem->Animation.Velocity.y, LaraItem->Animation.Velocity.x); From a77d64b69bcf057936d2877a4fec6ae31065a82b Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:25:36 +0200 Subject: [PATCH 309/410] Fix binocular bugs --- CHANGELOG.md | 1 + TombEngine/Game/camera.cpp | 18 ++++++++++++++++++ TombEngine/Game/camera.h | 6 ++++-- TombEngine/Game/control/control.cpp | 18 ++---------------- TombEngine/Game/control/control.h | 4 ---- TombEngine/Game/effects/effects.cpp | 12 ++++++++++++ TombEngine/Game/effects/effects.h | 3 +++ .../Objects/TR4/Entity/tr4_beetle_swarm.cpp | 1 + 8 files changed, 41 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd12efb5d..87e0f8a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. * Fixed leveljump vehicle transfer. * Fixed sarcophagus pick-ups. +* Fixed several binocular bugs. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index aaa81edcb..1808a04dc 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -952,6 +952,7 @@ void BinocularCamera(ItemInfo* item) player.Inventory.IsBusy = false; Camera.type = BinocularOldCamera; + Camera.target = LastTarget; AlterFOV(LastFOV); return; } @@ -1025,6 +1026,8 @@ void BinocularCamera(ItemInfo* item) if (IsHeld(In::Action)) { + ClearAction(In::Action); + auto origin = Camera.pos.ToVector3i(); auto target = Camera.target.ToVector3i(); LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192); @@ -1518,6 +1521,21 @@ void ItemsCollideCamera() staticList.clear(); } +void UpdateCamera() +{ + if (UseSpotCam) + { + // Draw flyby cameras. + CalculateSpotCameras(); + } + else + { + // Do the standard camera. + TrackCameraInit = false; + CalculateCamera(LaraCollision); + } +} + void UpdateMikePos(const ItemInfo& item) { if (Camera.mikeAtLara) diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 504a59ed4..9a3c02af5 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -103,16 +103,18 @@ void RumbleScreen(); bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius); void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius); void ItemsCollideCamera(); +void RefreshFixedCamera(short camNumber); + void ObjCamera(ItemInfo* camSlotId, int camMeshID, ItemInfo* targetItem, int targetMeshID, bool cond); void MoveObjCamera(GameVector* ideal, ItemInfo* camSlotId, int camMeshID, ItemInfo* targetItem, int targetMeshID); -void RefreshFixedCamera(short camNumber); +void ClearObjCamera(); void SetScreenFadeOut(float speed, bool force = false); void SetScreenFadeIn(float speed, bool force = false); void SetCinematicBars(float height, float speed); void ClearCinematicBars(); +void UpdateCamera(); void UpdateFadeScreenAndCinematicBars(); void UpdateMikePos(const ItemInfo& item); -void ClearObjCamera(); float GetParticleDistanceFade(const Vector3i& pos); diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 75e8648d2..e5b63c261 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -89,7 +89,6 @@ using namespace TEN::Renderer; int GameTimer = 0; int GlobalCounter = 0; -int Wibble = 0; bool InitializeGame; bool DoTheGame; @@ -185,27 +184,13 @@ GameStatus ControlPhase(int numFrames) ApplyActionQueue(); ClearActionQueue(); + UpdateCamera(); UpdateAllItems(); UpdateAllEffects(); UpdateLara(LaraItem, isTitle); g_GameScriptEntities->TestCollidingObjects(); - if (UseSpotCam) - { - // Draw flyby cameras. - CalculateSpotCameras(); - } - else - { - // Do the standard camera. - TrackCameraInit = false; - CalculateCamera(LaraCollision); - } - - // Update oscillator seed. - Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX; - // Smash shatters and clear stopper flags under them. UpdateShatters(); @@ -213,6 +198,7 @@ GameStatus ControlPhase(int numFrames) Weather.Update(); // Update effects. + UpdateWibble(); StreamerEffect.Update(); UpdateSparks(); UpdateFireSparks(); diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index 168fd06d7..36778258b 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -50,15 +50,11 @@ enum FadeStatus constexpr int MAX_ROOMS = 1024; -constexpr int WIBBLE_SPEED = 4; -constexpr int WIBBLE_MAX = UCHAR_MAX - WIBBLE_SPEED + 1; - constexpr int LOOP_FRAME_COUNT = 2; extern int GameTimer; extern int RumbleTimer; extern int GlobalCounter; -extern int Wibble; extern bool InitializeGame; extern bool DoTheGame; diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index a2b52a526..b303fadb7 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -40,6 +40,9 @@ using namespace TEN::Math::Random; using TEN::Renderer::g_Renderer; +constexpr int WIBBLE_SPEED = 4; +constexpr int WIBBLE_MAX = UCHAR_MAX - WIBBLE_SPEED + 1; + // New particle class Particle Particles[MAX_PARTICLES]; ParticleDynamic ParticleDynamics[MAX_PARTICLE_DYNAMICS]; @@ -49,7 +52,9 @@ FX_INFO EffectList[NUM_EFFECTS]; GameBoundingBox DeadlyBounds; SPLASH_SETUP SplashSetup; SPLASH_STRUCT Splashes[MAX_SPLASHES]; + int SplashCount = 0; +int Wibble = 0; Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax]; NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] = @@ -180,6 +185,13 @@ void SetSpriteSequence(Particle& particle, GAME_OBJECT_ID objectID) particle.spriteIndex = Objects[objectID].meshIndex + (int)round(Lerp(0.0f, numSprites, normalizedAge)); } +void UpdateWibble() +{ + // Update oscillator seed. + Wibble = (Wibble + WIBBLE_SPEED) & WIBBLE_MAX; + +} + void UpdateSparks() { auto bounds = GameBoundingBox(LaraItem); diff --git a/TombEngine/Game/effects/effects.h b/TombEngine/Game/effects/effects.h index 0613feaf1..a4e19139e 100644 --- a/TombEngine/Game/effects/effects.h +++ b/TombEngine/Game/effects/effects.h @@ -18,6 +18,8 @@ constexpr auto NUM_EFFECTS = 256; constexpr auto MAX_PARTICLES = 1024; constexpr auto MAX_PARTICLE_DYNAMICS = 8; +extern int Wibble; + enum SpriteEnumFlag { SP_NONE = 0, @@ -279,5 +281,6 @@ void TriggerRocketFire(int x, int y, int z); void TriggerExplosionBubbles(int x, int y, int z, short roomNumber); void Ricochet(Pose& pos); void ProcessEffects(ItemInfo* item); +void UpdateWibble(); void TriggerDynamicLight(const Vector3& pos, const Color& color, float falloff); diff --git a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp index 2923a4f34..6bd700d00 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_beetle_swarm.cpp @@ -3,6 +3,7 @@ #include "Game/collision/collide_room.h" #include "Game/control/flipeffect.h" +#include "Game/effects/effects.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Game/Setup.h" From f51eed18006b7b01614aa5c67d7bdd6bdc34387b Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 5 Oct 2024 11:40:12 +0200 Subject: [PATCH 310/410] Fixed issues with death sectors and water climbouts with bridges --- CHANGELOG.md | 2 ++ TombEngine/Game/Lara/lara.cpp | 4 ++-- TombEngine/Game/Lara/lara_tests.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87e0f8a6e..12f2bfe14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed leveljump vehicle transfer. * Fixed sarcophagus pick-ups. * Fixed several binocular bugs. +* Fixed incorrect climbing out of water on bridge objects. +* Fixed faulty death sectors. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index b8c65783b..5f75e6aa3 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -362,8 +362,6 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll) coll->Setup.PrevFrameNumber = item->Animation.FrameNumber; coll->Setup.PrevState = item->Animation.ActiveState; - UpdateLaraRoom(item, -LARA_HEIGHT / 2); - // Handle look-around. if (((IsHeld(In::Look) && CanPlayerLookAround(*item)) || (player.Control.Look.IsUsingBinoculars || player.Control.Look.IsUsingLasersight)) && @@ -378,6 +376,8 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll) } player.Control.Look.Mode = LookMode::None; + UpdateLaraRoom(item, -LARA_HEIGHT / 2); + // Process vehicles. if (HandleLaraVehicle(item, coll)) return; diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index cf6bafdcf..fc5c8b384 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -935,11 +935,11 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) // Extra bridge check. if (coll->Front.Bridge != NO_VALUE) { - int bridgeBorder = GetBridgeBorder(g_Level.Items[coll->Front.Bridge], false) - item->Pose.Position.y; + frontFloor = GetBridgeBorder(g_Level.Items[coll->Front.Bridge], false) - item->Pose.Position.y; - frontFloor = bridgeBorder - CLICK(0.5f); - if (frontFloor <= -CLICK(2) || - frontFloor > CLICK(1.25f) - 4) + int bridgeBorder = frontFloor - CLICK(0.5f); + if (bridgeBorder <= -CLICK(2) || + bridgeBorder > CLICK(1.25f) - 4) { return false; } From deec54ff83971b3c242a6fc51085941a289dd7c9 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 6 Oct 2024 02:02:09 +0200 Subject: [PATCH 311/410] Fix lasersight action --- TombEngine/Game/camera.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 1808a04dc..bcf085d70 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -956,6 +956,15 @@ void BinocularCamera(ItemInfo* item) AlterFOV(LastFOV); return; } + + if (IsHeld(In::Action)) + { + ClearAction(In::Action); + + auto origin = Camera.pos.ToVector3i(); + auto target = Camera.target.ToVector3i(); + LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192); + } } AlterFOV(7 * (ANGLE(11.5f) - player.Control.Look.OpticRange), false); @@ -1023,15 +1032,6 @@ void BinocularCamera(ItemInfo* item) Camera.oldType = Camera.type; GetTargetOnLOS(&Camera.pos, &Camera.target, false, false); - - if (IsHeld(In::Action)) - { - ClearAction(In::Action); - - auto origin = Camera.pos.ToVector3i(); - auto target = Camera.target.ToVector3i(); - LaraTorch(&origin, &target, player.ExtraHeadRot.y, 192); - } } void ConfirmCameraTargetPos() From 0ac19594f22fc6e9e527f855f8bda05d99460c5e Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 8 Oct 2024 15:19:36 +0200 Subject: [PATCH 312/410] Camera is not inteprolated until next control phase if disable interpolation is true; Added more non-interpolation cases to spotcams; --- TombEngine/Game/camera.cpp | 11 ++--------- TombEngine/Game/camera.h | 2 ++ TombEngine/Game/control/control.cpp | 7 +++++++ TombEngine/Game/spotcam.cpp | 18 ++++++++++++++++-- TombEngine/Renderer/RendererDraw.cpp | 3 +-- TombEngine/Renderer/RendererDrawMenu.cpp | 2 -- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index e3570f294..1db7be864 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -194,15 +194,8 @@ void LookCamera(ItemInfo& item, const CollisionInfo& coll) void LookAt(CAMERA_INFO* cam, short roll) { - auto pos = cam->pos.ToVector3(); - auto target = cam->target.ToVector3(); - auto up = Vector3::Down; - float fov = TO_RAD(CurrentFOV / 1.333333f); - float r = TO_RAD(roll); - - float levelFarView = g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * float(BLOCK(1)); - - g_Renderer.UpdateCameraMatrices(cam, r, fov, levelFarView); + cam->currentFov = TO_RAD(CurrentFOV / 1.333333f); + cam->currentRoll = TO_RAD(roll); } void AlterFOV(short value, bool store) diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 9c65b8177..d9954f488 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -46,6 +46,8 @@ struct CAMERA_INFO ItemInfo* lastItem; int mikeAtLara; Vector3i mikePos; + float currentRoll; + float currentFov; bool DisableInterpolation = false; }; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index bb8811fed..81337c7cf 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -266,6 +266,13 @@ GameStatus ControlPhase() // Post-loop script and event handling. g_GameScript->OnLoop(DELTA_TIME, true); + // Update cameras matrices there, after having done all the possible camera logic + g_Renderer.UpdateCameraMatrices( + &Camera, + Camera.currentRoll, + Camera.currentFov, + g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * BLOCK(1)); + // Clear savegame loaded flag. JustLoaded = false; diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index e986685e6..d4bd804a2 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -490,11 +490,22 @@ void CalculateSpotCameras() auto outsideRoom = IsRoomOutside(cpx, cpy, cpz); if (outsideRoom == NO_VALUE) { + if (Camera.pos.RoomNumber != SpotCam[CurrentSplineCamera].roomNumber) + { + Camera.DisableInterpolation = true; + } Camera.pos.RoomNumber = SpotCam[CurrentSplineCamera].roomNumber; GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.RoomNumber); } else + { + if (Camera.pos.RoomNumber != outsideRoom) + { + Camera.DisableInterpolation = true; + } + Camera.pos.RoomNumber = outsideRoom; + } AlterFOV(cfov, false); @@ -578,6 +589,7 @@ void CalculateSpotCameras() cn = FirstCamera + SpotCam[CurrentSplineCamera].timer; Camera.DisableInterpolation = true; + CameraXposition[1] = SpotCam[cn].x; CameraYposition[1] = SpotCam[cn].y; CameraZposition[1] = SpotCam[cn].z; @@ -638,7 +650,10 @@ void CalculateSpotCameras() SpotcamPaused = 0; if (LastCamera >= CurrentSplineCamera) + { + Camera.DisableInterpolation = true; return; + } if (s->flags & SCF_LOOP_SEQUENCE) { @@ -647,8 +662,6 @@ void CalculateSpotCameras() } else if (s->flags & SCF_CUT_TO_LARA_CAM || SplineToCamera) { - Camera.DisableInterpolation = true; - if (CheckTrigger) { CameraType oldType = Camera.type; @@ -671,6 +684,7 @@ void CalculateSpotCameras() SetCinematicBars(0.0f, SPOTCAM_CINEMATIC_BARS_SPEED); + Camera.DisableInterpolation = true; UseSpotCam = false; Lara.Control.IsLocked = false; CheckTrigger = false; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index f6c0b7a5e..c6e7a945a 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -1592,6 +1592,7 @@ namespace TEN::Renderer _blinkTime -= PI_MUL_2; _oldGameCamera = _currentGameCamera; + Camera.DisableInterpolation = false; _isLocked = false; } @@ -3044,8 +3045,6 @@ namespace TEN::Renderer _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; - - Camera.DisableInterpolation = false; } _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 200df9dbb..45bf14e4c 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1175,8 +1175,6 @@ namespace TEN::Renderer _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; - - Camera.DisableInterpolation = false; } _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; From a3bc674c255f7cc57c0cbfd7dd0eb2403e307385 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:15:43 +0300 Subject: [PATCH 313/410] Fixed LOS and laserhead player teleportation/invisibility (#1416) --- CHANGELOG.md | 2 + TombEngine/Game/control/los.cpp | 84 ++----------------- .../Objects/TR5/Entity/tr5_laser_head.cpp | 10 ++- .../Objects/TR5/Entity/tr5_laserhead_info.h | 1 - 4 files changed, 15 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12f2bfe14..be12a6acd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Bug fixes * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. * Fixed leveljump vehicle transfer. +* Fixed weapons not properly hitting enemies. +* Fixed laserhead teleporting Lara and making her invisible on death. * Fixed sarcophagus pick-ups. * Fixed several binocular bugs. * Fixed incorrect climbing out of water on bridge objects. diff --git a/TombEngine/Game/control/los.cpp b/TombEngine/Game/control/los.cpp index 61fc6a5e6..7cd0b2c5f 100644 --- a/TombEngine/Game/control/los.cpp +++ b/TombEngine/Game/control/los.cpp @@ -312,7 +312,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo ShatterImpactData.impactDirection = dir; ShatterImpactData.impactLocation = ShatterItem.sphere.Center; ShatterObject(&ShatterItem, 0, 128, target2.RoomNumber, 0); - TriggerRicochetSpark(target2, LaraItem->Pose.Orientation.y, 3, 0); + TriggerRicochetSpark(target2, LaraItem->Pose.Orientation.y, 3, 0); } else { @@ -512,91 +512,21 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G // If mesh is visible. if (item->MeshBits & (1 << i)) { + float distance; const auto& sphere = spheres[i]; - // NOTE: Not worth doing what's commented below. *Rewrite completely.* - // TODO: this approach is the correct one but, again, Core's math is a mystery and this test was meant - // to fail deliberately in some way. I've so added again Core's legacy test for allowing the current game logic - // but after more testing we should trash it in the future and restore the new way. -#if 0 - // Create the bounding sphere and test it against the ray - BoundingSphere sph = BoundingSphere(Vector3(sphere->x, sphere->y, sphere->z), sphere->r); - float newDist; - if (sph.Intersects(rayStart, rayDirNormalized, newDist)) + if (sphere.Intersects(rayOrigin, rayDir, distance)) { - // HACK: Core seems to take in account for distance not the real hit point but the centre of the sphere. - // This can work well for example for GUARDIAN because the head sphere is so big that would always be hit - // and eyes would not be destroyed. - newDist = sqrt(SQUARE(sphere->x - start->x) + SQUARE(sphere->y - start->y) + SQUARE(sphere->z - start->z)); + // Test for minimum distance. - // Test for min distance - if (newDist < minDistance) + if (distance < minDist) { - minDistance = newDist; - meshPtr = &g_Level.Meshes[obj->meshIndex + i]; + minDist = distance; + meshIndex = object->meshIndex + i; bit = 1 << i; sp = i; } } -#endif - - Vector3i p[4]; - - p[1].x = origin.x; - p[1].y = origin.y; - p[1].z = origin.z; - p[2].x = target.x; - p[2].y = target.y; - p[2].z = target.z; - p[3].x = sphere.Center.x; - p[3].y = sphere.Center.y; - p[3].z = sphere.Center.z; - - int r0 = (p[3].x - p[1].x) * (p[2].x - p[1].x) + - (p[3].y - p[1].y) * (p[2].y - p[1].y) + - (p[3].z - p[1].z) * (p[2].z - p[1].z); - - int r1 = SQUARE(p[2].x - p[1].x) + - SQUARE(p[2].y - p[1].y) + - SQUARE(p[2].z - p[1].z); - - if (((r0 < 0 && r1 < 0) || - (r1 > 0 && r0 > 0)) && - (abs(r0) <= abs(r1))) - { - r1 >>= 16; - if (r1) - r0 /= r1; - else - r0 = 0; - - p[0].x = p[1].x + ((r0 * (p[2].x - p[1].x)) >> 16); - p[0].y = p[1].y + ((r0 * (p[2].y - p[1].y)) >> 16); - p[0].z = p[1].z + ((r0 * (p[2].z - p[1].z)) >> 16); - - int dx = SQUARE(p[0].x - p[3].x); - int dy = SQUARE(p[0].y - p[3].y); - int dz = SQUARE(p[0].z - p[3].z); - - int distance = dx + dy + dz; - - if (distance < SQUARE(sphere.Radius)) - { - dx = SQUARE(sphere.Center.x - origin.x); - dy = SQUARE(sphere.Center.y - origin.y); - dz = SQUARE(sphere.Center.z - origin.z); - - distance = dx + dy + dz; - - if (distance < minDist) - { - minDist = distance; - meshIndex = object->meshIndex + i; - bit = 1 << i; - sp = i; - } - } - } } } diff --git a/TombEngine/Objects/TR5/Entity/tr5_laser_head.cpp b/TombEngine/Objects/TR5/Entity/tr5_laser_head.cpp index 11ff82fb0..0be4cdc39 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_laser_head.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_laser_head.cpp @@ -591,9 +591,12 @@ namespace TEN::Entities::Creatures::TR5 void DoGuardianDeath(int itemNumber, ItemInfo& item) { const auto& guardian = GetGuardianInfo(item); - - ExplodeItemNode(&g_Level.Items[guardian.BaseItem], 0, 0, 128); - KillItem(guardian.BaseItem); + + if (g_Level.Items[guardian.BaseItem].ObjectNumber == ID_LASERHEAD_BASE) + { + ExplodeItemNode(&g_Level.Items[guardian.BaseItem], 0, 0, 128); + KillItem(guardian.BaseItem); + } ExplodeItemNode(&item, 0, 0, 128); @@ -605,7 +608,6 @@ namespace TEN::Entities::Creatures::TR5 TriggerShockwave(&item.Pose, 32, 160, 64, 0, 128, 64, 36, EulerAngles(0x3000, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); TriggerShockwave(&item.Pose, 32, 160, 64, 0, 128, 64, 36, EulerAngles(0x6000, 0.0f, 0.0f), 0, true, false, false, (int)ShockwaveStyle::Normal); - g_Level.Items[guardian.PuzzleItem].Pose.Position.y = item.Pose.Position.y; TestTriggers(&item, true); SoundEffect(SFX_TR5_GOD_HEAD_BLAST, &item.Pose, SoundEnvironment::Land, 0.5f); diff --git a/TombEngine/Objects/TR5/Entity/tr5_laserhead_info.h b/TombEngine/Objects/TR5/Entity/tr5_laserhead_info.h index b32f7ea90..393348eeb 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_laserhead_info.h +++ b/TombEngine/Objects/TR5/Entity/tr5_laserhead_info.h @@ -21,6 +21,5 @@ namespace TEN::Entities::Creatures::TR5 short yRot; int BaseItem; std::array Tentacles = {}; - int PuzzleItem; }; } From 4f3ea36bc1507e443584f5b6536de13bc5aaa70b Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Sun, 13 Oct 2024 05:52:52 +0200 Subject: [PATCH 314/410] Temporarly hack for solving invisible Lara in some cases with HUB system --- Documentation/doc/1 modules/Flow.html | 26 ++++++++++++++++++++++++++ TombEngine/Game/control/control.cpp | 11 +++++++++++ 2 files changed, 37 insertions(+) diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index a73a62661..1a38ee19a 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -236,6 +236,10 @@ scripts too.

    Get translated string. + IsStringPresent(string) + Check if translated string is present. + + SetLanguageNames(table) Set language names for translations. @@ -929,6 +933,28 @@ You will not need to call them manually. +
    +
    + + IsStringPresent(string) +
    +
    + Check if translated string is present. + + + +

    Parameters:

    +
      +
    • string + key + key for translated string +
    • +
    + + + + +
    diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 1c0ced827..e13eb6d01 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -522,6 +522,11 @@ void InitializeOrLoadGame(bool loadGame) { SaveGame::Load(g_GameFlow->SelectedSaveGame); + // TODO: hack for forcing Lara's room + ItemInfo* firstLaraItem = FindItem(ID_LARA); + int firstLaraItemNumber = FindItem(firstLaraItem); + ItemNewRoom(firstLaraItemNumber, firstLaraItem->RoomNumber); + Camera.pos.x = LaraItem->Pose.Position.x + 256; Camera.pos.y = LaraItem->Pose.Position.y + 256; Camera.pos.z = LaraItem->Pose.Position.z + 256; @@ -554,6 +559,12 @@ void InitializeOrLoadGame(bool loadGame) else { SaveGame::LoadHub(CurrentLevel); + + // TODO: hack for forcing Lara's room + ItemInfo* firstLaraItem = FindItem(ID_LARA); + int firstLaraItemNumber = FindItem(firstLaraItem); + ItemNewRoom(firstLaraItemNumber, firstLaraItem->RoomNumber); + TENLog("Starting new level.", LogLevel::Info); } From 9cf20770517b4448c0c17f3a303ae3545faeb03b Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Mon, 14 Oct 2024 05:56:34 +0200 Subject: [PATCH 315/410] Possibly fixed invisible Lara at HUB level switch --- TombEngine/Game/control/control.cpp | 11 ----------- TombEngine/Game/savegame.cpp | 5 +++++ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e13eb6d01..1c0ced827 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -522,11 +522,6 @@ void InitializeOrLoadGame(bool loadGame) { SaveGame::Load(g_GameFlow->SelectedSaveGame); - // TODO: hack for forcing Lara's room - ItemInfo* firstLaraItem = FindItem(ID_LARA); - int firstLaraItemNumber = FindItem(firstLaraItem); - ItemNewRoom(firstLaraItemNumber, firstLaraItem->RoomNumber); - Camera.pos.x = LaraItem->Pose.Position.x + 256; Camera.pos.y = LaraItem->Pose.Position.y + 256; Camera.pos.z = LaraItem->Pose.Position.z + 256; @@ -559,12 +554,6 @@ void InitializeOrLoadGame(bool loadGame) else { SaveGame::LoadHub(CurrentLevel); - - // TODO: hack for forcing Lara's room - ItemInfo* firstLaraItem = FindItem(ID_LARA); - int firstLaraItemNumber = FindItem(firstLaraItem); - ItemNewRoom(firstLaraItemNumber, firstLaraItem->RoomNumber); - TENLog("Starting new level.", LogLevel::Info); } diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 221d50862..9cefde261 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -2299,7 +2299,12 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) // Don't load player data in hub mode. if (item->ObjectNumber == ID_LARA && hubMode) + { + item->RoomNumber = savedItem->room_number(); + item->Floor = savedItem->floor(); + item->BoxNumber = savedItem->box_number(); continue; + } if (item->Index == Lara.Context.Vehicle && hubMode) continue; From 9ea62f711a3cac4bcf00fd20e92175e595d632af Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 15 Oct 2024 15:18:51 +0200 Subject: [PATCH 316/410] Fixed vehicle and Lara in HUB system level change --- Documentation/doc/1 modules/Flow.html | 26 ++ .../doc/2 classes/Objects.Moveable.html | 8 +- Documentation/doc/2 classes/Objects.Room.html | 229 ++++++++++-------- Documentation/doc/4 enums/Objects.ObjID.html | 4 +- Documentation/doc/index.html | 2 +- TombEngine/Game/Lara/lara_initialise.cpp | 8 +- TombEngine/Game/Lara/lara_initialise.h | 1 + TombEngine/Game/control/control.cpp | 5 + TombEngine/Game/savegame.cpp | 12 + 9 files changed, 177 insertions(+), 118 deletions(-) diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index 81fc6b1b0..481749867 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -234,6 +234,10 @@ scripts too.

    Get translated string. + IsStringPresent(string) + Check if translated string is present. + + SetLanguageNames(table) Set language names for translations. @@ -927,6 +931,28 @@ You will not need to call them manually. + +
    + + IsStringPresent(string) +
    +
    + Check if translated string is present. + + + +

    Parameters:

    +
      +
    • string + key + key for translated string +
    • +
    + + + + +
    diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index 00671976d..fe4d7c91a 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -108,7 +108,7 @@ pickups, and Lara herself (see also Functions - + @@ -390,7 +390,7 @@ pickups, and Lara herself (see also
    - Moveable(object, name, position, rotation, roomID, animNumber, frameNumber, hp, OCB, AIBits) + Moveable(object, name, position, rotation, roomNumber, animNumber, frameNumber, hp, OCB, AIBits)
    Used to generate a new moveable dynamically at runtime.
    @@ -418,9 +418,9 @@ most can just be ignored (see usage). Rotation rotation rotation about x, y, and z axes (default Rotation(0, 0, 0)) -
  • roomID +
  • roomNumber int - room ID item is in (default: calculated automatically) + the room number the moveable is in (default: calculated automatically).
  • animNumber int diff --git a/Documentation/doc/2 classes/Objects.Room.html b/Documentation/doc/2 classes/Objects.Room.html index d49f8c93b..d2efc7718 100644 --- a/Documentation/doc/2 classes/Objects.Room.html +++ b/Documentation/doc/2 classes/Objects.Room.html @@ -100,7 +100,7 @@

    Class Objects.Room

    -

    Rooms

    +

    Room object.

    @@ -109,8 +109,12 @@

    Functions

  • Moveable(object, name, position, rotation, roomID, animNumber, frameNumber, hp, OCB, AIBits)Moveable(object, name, position, rotation, roomNumber, animNumber, frameNumber, hp, OCB, AIBits) Used to generate a new moveable dynamically at runtime.
    - - + + + + + + @@ -121,28 +125,28 @@ - + + + + + - - - - - - + + - - + + - - + +
    Room:GetActive()Determine whether the room is active or notRoom:GetRoomNumber()Get the room's number.
    Room:GetName()Get the room's unique string identifier.
    Room:GetColor()Get the room's reverb type.
    Room:SetReverbType(new)Room:SetName(name)Set the room's unique string identifier.
    Room:SetReverbType(Reverb) Set the room's reverb type.
    Room:GetName()Get the room's unique string identifier.
    Room:SetName(name)Set the room's name (its unique string identifier).Room:SetFlag(flagID, Boolean)Set the room's specified flag.
    Room:GetFlag(flagID) Get the room's specified flag value (true or false).
    Room:SetFlag(flagID, the)Set the room's specified flag value.Room:IsTagPresent(tag)Check if the specified tag is set for the room.
    Room:IsTagPresent(tag)Checks if specified tag is set for this room.Room:GetActive()Check if the room is active.
    @@ -154,11 +158,11 @@
    - - Room:GetActive() + + Room:GetRoomNumber()
    - Determine whether the room is active or not + Get the room's number. () @@ -166,8 +170,29 @@

    Returns:

      - bool - true if the room is active + int + Room number. +
    + + + + +
    +
    + + Room:GetName() +
    +
    + Get the room's unique string identifier. () + + + + +

    Returns:

    +
      + + string + Room name.
    @@ -179,7 +204,7 @@ Room:GetColor()
    - Get the room's ambient light color. + Get the room's ambient light color. () @@ -188,7 +213,7 @@
      Color - ambient light color of the room + Ambient light color.
    @@ -200,7 +225,7 @@ Room:GetReverbType()
    - Get the room's reverb type. + Get the room's reverb type. () @@ -209,50 +234,7 @@
      RoomReverb - room's reverb type -
    - - - - -
    -
    - - Room:SetReverbType(new) -
    -
    - Set the room's reverb type. - - - -

    Parameters:

    -
      -
    • new - RoomReverb - reverb type of the room -
    • -
    - - - - - -
    -
    - - Room:GetName() -
    -
    - Get the room's unique string identifier. - - - - -

    Returns:

    -
      - - string - the room's name + Reverb type.
    @@ -264,7 +246,7 @@ Room:SetName(name)
    - Set the room's name (its unique string identifier). + Set the room's unique string identifier. () @@ -272,7 +254,55 @@
    • name string - The room's new name + New name. +
    • +
    + + + + + +
    +
    + + Room:SetReverbType(Reverb) +
    +
    + Set the room's reverb type. () + + + +

    Parameters:

    + + + + + + +
    +
    + + Room:SetFlag(flagID, Boolean) +
    +
    + Set the room's specified flag. () + + + +

    Parameters:

    +
      +
    • flagID + RoomFlagID + Room flag ID. +
    • +
    • Boolean + bool + to set the flag to.
    @@ -286,7 +316,7 @@ Room:GetFlag(flagID)
    - Get the room's specified flag value (true or false). + Get the room's specified flag value (true or false). () @@ -294,39 +324,7 @@ - -

    Returns:

    -
      - - bool - the room's specified flag value -
    - - - - -
    -
    - - Room:SetFlag(flagID, the) -
    -
    - Set the room's specified flag value. - - - -

    Parameters:

    -
      -
    • flagID - RoomFlagID - The room's flag ID -
    • -
    • the - bool - room's new flag value + Room flag ID.
    @@ -340,7 +338,7 @@ Room:IsTagPresent(tag)
    - Checks if specified tag is set for this room. + Check if the specified tag is set for the room. () @@ -348,7 +346,7 @@
    • tag string - A text tag to check (case sensitive) + Text tag to check (case sensitive).
    @@ -356,7 +354,28 @@
      bool - true if tag is present, false if not + Boolean of the tag's presence. +
    + + + + +
    +
    + + Room:GetActive() +
    +
    + Check if the room is active. () + + + + +

    Returns:

    +
      + + bool + Boolean of the room's active status.
    diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 4328065c5..099a2d745 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -171,8 +171,8 @@ LARA_PETROL_MESH LARA_DIRT_MESH LARA_CROWBAR_ANIM LARA_TORCH_ANIM -SINGLE_BRAID_HAIR -DUAL_PIGTAIL_HAIR +HAIR_PRIMARY +HAIR_SECONDARY SNOWMOBILE_LARA_ANIMS SNOWMOBILE QUAD_LARA_ANIMS diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index e481a6133..ef744a16b 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -217,7 +217,7 @@ local door = GetMoveableByName("door_type4_14") Objects.Room - Rooms + Room object. Objects.Sink diff --git a/TombEngine/Game/Lara/lara_initialise.cpp b/TombEngine/Game/Lara/lara_initialise.cpp index 736a07eec..507491f1e 100644 --- a/TombEngine/Game/Lara/lara_initialise.cpp +++ b/TombEngine/Game/Lara/lara_initialise.cpp @@ -182,7 +182,7 @@ void InitializeLaraStartPosition(ItemInfo& playerItem) playerItem.Location.Height = playerItem.Pose.Position.y; } -static void InitializePlayerVehicle(ItemInfo& playerItem) +void InitializePlayerVehicle(ItemInfo& playerItem) { if (PlayerVehicleObjectID == GAME_OBJECT_ID::ID_NO_OBJECT) return; @@ -194,7 +194,6 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) // Restore vehicle. TENLog("Transferring vehicle " + GetObjectName(PlayerVehicleObjectID) + " from the previous level."); vehicle->Pose = playerItem.Pose; - ItemNewRoom(vehicle->Index, playerItem.RoomNumber); SetLaraVehicle(&playerItem, vehicle); playerItem.Animation = PlayerAnim; @@ -251,7 +250,7 @@ static void InitializePlayerVehicle(ItemInfo& playerItem) if (vehicle->ObjectNumber == GAME_OBJECT_ID::ID_RUBBER_BOAT || vehicle->ObjectNumber == GAME_OBJECT_ID::ID_SPEEDBOAT) { - g_Level.Items[vehicle->Index].Active = false; + RemoveActiveItem(vehicle->Index, false); AddActiveItem(vehicle->Index); g_Level.Items[vehicle->Index].Status = ITEM_ACTIVE; } @@ -297,9 +296,6 @@ void InitializeLaraLevelJump(ItemInfo* item, LaraInfo* playerBackup) // Restore hit points. item->HitPoints = PlayerHitPoints; - - // Restore vehicle. - InitializePlayerVehicle(*item); } void InitializeLaraDefaultInventory(ItemInfo& item) diff --git a/TombEngine/Game/Lara/lara_initialise.h b/TombEngine/Game/Lara/lara_initialise.h index a218a7ccf..86ecd4829 100644 --- a/TombEngine/Game/Lara/lara_initialise.h +++ b/TombEngine/Game/Lara/lara_initialise.h @@ -9,3 +9,4 @@ void InitializeLaraAnims(ItemInfo* item); void InitializeLaraStartPosition(ItemInfo& playerItem); void InitializeLaraLevelJump(ItemInfo* item, LaraInfo* playerBackup); void InitializeLaraDefaultInventory(ItemInfo& item); +void InitializePlayerVehicle(ItemInfo& playerItem); \ No newline at end of file diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index e5b63c261..204324201 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -59,6 +59,7 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" #include "Specific/winmain.h" +#include "Game/Lara/lara_initialise.h" using namespace std::chrono; using namespace TEN::Effects; @@ -531,6 +532,10 @@ void InitializeOrLoadGame(bool loadGame) { SaveGame::LoadHub(CurrentLevel); TENLog("Starting new level.", LogLevel::Info); + + // Restore vehicle. + auto* item = FindItem(ID_LARA); + InitializePlayerVehicle(*item); } g_GameScript->OnStart(); diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 221d50862..a2a906d95 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -2299,10 +2299,22 @@ static void ParseLevel(const Save::SaveGame* s, bool hubMode) // Don't load player data in hub mode. if (item->ObjectNumber == ID_LARA && hubMode) + { + //item->Pose = ToPose(*savedItem->pose()); + item->RoomNumber = savedItem->room_number(); + item->Floor = savedItem->floor(); + item->BoxNumber = savedItem->box_number(); continue; + } if (item->Index == Lara.Context.Vehicle && hubMode) + { + //item->Pose = ToPose(*savedItem->pose()); + item->RoomNumber = savedItem->room_number(); + item->Floor = savedItem->floor(); + item->BoxNumber = savedItem->box_number(); continue; + } // Position item->Pose = ToPose(*savedItem->pose()); From b1bbd55328bce2c9a5e4bd3b30308fa69504bf17 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:11:51 +0200 Subject: [PATCH 317/410] Fixed issue with Lara not rotating together with bridges while picking up items --- CHANGELOG.md | 1 + TombEngine/Game/Lara/PlayerStateMachine.cpp | 4 ++-- TombEngine/Game/Lara/lara_basic.cpp | 12 +----------- TombEngine/Game/Lara/lara_collide.cpp | 16 ++++++++++++++++ TombEngine/Game/Lara/lara_collide.h | 1 + TombEngine/Game/Lara/lara_objects.cpp | 7 +++++++ TombEngine/Game/Lara/lara_objects.h | 1 + 7 files changed, 29 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be12a6acd..3b7c54e6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed weapons not properly hitting enemies. * Fixed laserhead teleporting Lara and making her invisible on death. * Fixed sarcophagus pick-ups. +* Fixed issue with Lara not rotating together with bridges while picking up items. * Fixed several binocular bugs. * Fixed incorrect climbing out of water on bridge objects. * Fixed faulty death sectors. diff --git a/TombEngine/Game/Lara/PlayerStateMachine.cpp b/TombEngine/Game/Lara/PlayerStateMachine.cpp index feab50981..84cc003f9 100644 --- a/TombEngine/Game/Lara/PlayerStateMachine.cpp +++ b/TombEngine/Game/Lara/PlayerStateMachine.cpp @@ -71,7 +71,7 @@ namespace TEN::Entities::Player PlayerBehaviorStateRoutines[LS_PUSHABLE_PUSH] = std::pair(lara_as_pushable_push, lara_default_col); PlayerBehaviorStateRoutines[LS_PUSHABLE_PULL] = std::pair(lara_as_pushable_pull, lara_default_col); PlayerBehaviorStateRoutines[LS_PUSHABLE_GRAB] = std::pair(lara_as_pushable_grab, lara_default_col); - PlayerBehaviorStateRoutines[LS_PICKUP] = std::pair(lara_as_pickup, lara_default_col); + PlayerBehaviorStateRoutines[LS_PICKUP] = std::pair(lara_as_pickup, lara_col_pickup); PlayerBehaviorStateRoutines[LS_SWITCH_DOWN] = std::pair(lara_as_switch_on, lara_default_col); PlayerBehaviorStateRoutines[LS_SWITCH_UP] = std::pair(lara_as_switch_off, lara_default_col); PlayerBehaviorStateRoutines[LS_INSERT_KEY] = std::pair(lara_as_use_key, lara_default_col); @@ -99,7 +99,7 @@ namespace TEN::Entities::Player PlayerBehaviorStateRoutines[LS_TEST_3] = std::pair(lara_void_func, lara_void_func); PlayerBehaviorStateRoutines[LS_WADE_FORWARD] = std::pair(lara_as_wade_forward, lara_col_wade_forward); PlayerBehaviorStateRoutines[LS_UNDERWATER_ROLL] = std::pair(lara_as_underwater_roll_180, lara_col_underwater_roll_180); - PlayerBehaviorStateRoutines[LS_PICKUP_FLARE] = std::pair(lara_as_pickup_flare, lara_default_col); + PlayerBehaviorStateRoutines[LS_PICKUP_FLARE] = std::pair(lara_as_pickup_flare, lara_col_pickup); PlayerBehaviorStateRoutines[LS_JUMP_ROLL_180] = std::pair(lara_void_func, lara_void_func); PlayerBehaviorStateRoutines[LS_KICK] = std::pair(lara_void_func, lara_void_func); PlayerBehaviorStateRoutines[LS_ZIP_LINE] = std::pair(lara_as_zip_line, lara_void_func); diff --git a/TombEngine/Game/Lara/lara_basic.cpp b/TombEngine/Game/Lara/lara_basic.cpp index 8fbf4ec2f..5e65451a7 100644 --- a/TombEngine/Game/Lara/lara_basic.cpp +++ b/TombEngine/Game/Lara/lara_basic.cpp @@ -39,17 +39,7 @@ void lara_void_func(ItemInfo* item, CollisionInfo* coll) void lara_default_col(ItemInfo* item, CollisionInfo* coll) { - auto& player = GetLaraInfo(*item); - - player.Control.MoveAngle = item->Pose.Orientation.y; - coll->Setup.LowerFloorBound = STEPUP_HEIGHT; - coll->Setup.UpperFloorBound = -STEPUP_HEIGHT; - coll->Setup.LowerCeilingBound = 0; - coll->Setup.BlockFloorSlopeDown = true; - coll->Setup.BlockFloorSlopeUp = true; - coll->Setup.ForwardAngle = player.Control.MoveAngle; - GetCollisionInfo(coll, item); - LaraResetGravityStatus(item, coll); + LaraDefaultCollision(item, coll); } // Boulder death. diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index 377d0ee7b..7e38ded7a 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -507,6 +507,22 @@ void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll) } } + +void LaraDefaultCollision(ItemInfo* item, CollisionInfo* coll) +{ + auto& player = GetLaraInfo(*item); + + player.Control.MoveAngle = item->Pose.Orientation.y; + coll->Setup.LowerFloorBound = STEPUP_HEIGHT; + coll->Setup.UpperFloorBound = -STEPUP_HEIGHT; + coll->Setup.LowerCeilingBound = 0; + coll->Setup.BlockFloorSlopeDown = true; + coll->Setup.BlockFloorSlopeUp = true; + coll->Setup.ForwardAngle = player.Control.MoveAngle; + GetCollisionInfo(coll, item); + LaraResetGravityStatus(item, coll); +} + void LaraSwimCollision(ItemInfo* item, CollisionInfo* coll) { auto* lara = GetLaraInfo(item); diff --git a/TombEngine/Game/Lara/lara_collide.h b/TombEngine/Game/Lara/lara_collide.h index 41a6bf3b1..705cb373c 100644 --- a/TombEngine/Game/Lara/lara_collide.h +++ b/TombEngine/Game/Lara/lara_collide.h @@ -25,6 +25,7 @@ void GetLaraDeadlyBounds(); void LaraJumpCollision(ItemInfo* item, CollisionInfo* coll, short moveAngle); void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll); void LaraSwimCollision(ItemInfo* item, CollisionInfo* coll); +void LaraDefaultCollision(ItemInfo* item, CollisionInfo* coll); void LaraWaterCurrent(ItemInfo* item, CollisionInfo* coll); diff --git a/TombEngine/Game/Lara/lara_objects.cpp b/TombEngine/Game/Lara/lara_objects.cpp index bee098072..3f4989534 100644 --- a/TombEngine/Game/Lara/lara_objects.cpp +++ b/TombEngine/Game/Lara/lara_objects.cpp @@ -8,6 +8,7 @@ #include "Game/items.h" #include "Game/Lara/PlayerContext.h" #include "Game/Lara/lara.h" +#include "Game/Lara/lara_collide.h" #include "Game/Lara/lara_helpers.h" #include "Game/Lara/lara_tests.h" #include "Objects/Generic/Object/rope.h" @@ -45,6 +46,12 @@ void lara_as_pickup(ItemInfo* item, CollisionInfo* coll) item->Animation.TargetState = GetNextAnimState(item); } +void lara_col_pickup(ItemInfo* item, CollisionInfo* coll) +{ + LaraDefaultCollision(item, coll); + ShiftItem(item, coll); +} + // State: LS_PICKUP_FLARE (67) // Collision: lara_default_col() void lara_as_pickup_flare(ItemInfo* item, CollisionInfo* coll) diff --git a/TombEngine/Game/Lara/lara_objects.h b/TombEngine/Game/Lara/lara_objects.h index 18636c583..c53ffd84d 100644 --- a/TombEngine/Game/Lara/lara_objects.h +++ b/TombEngine/Game/Lara/lara_objects.h @@ -14,6 +14,7 @@ struct CollisionInfo; void lara_as_pickup(ItemInfo* item, CollisionInfo* coll); void lara_as_pickup_flare(ItemInfo* item, CollisionInfo* coll); +void lara_col_pickup(ItemInfo* item, CollisionInfo* coll); // ------ // SWITCH From 0638756d908e5a79deabeb654a36194c8ebdc688 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:59:37 +0200 Subject: [PATCH 318/410] Fixed ghost collision with moveables with zero bounds --- CHANGELOG.md | 1 + TombEngine/Game/collision/collide_item.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b7c54e6a..eba472893 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed laserhead teleporting Lara and making her invisible on death. * Fixed sarcophagus pick-ups. * Fixed issue with Lara not rotating together with bridges while picking up items. +* Fixed ghost collision with moveables with zero bounds. * Fixed several binocular bugs. * Fixed incorrect climbing out of water on bridge objects. * Fixed faulty death sectors. diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 502d36654..b4e9035a2 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -566,6 +566,9 @@ bool TestBoundsCollide(ItemInfo* item, ItemInfo* laraItem, int radius) const auto& bounds = GetBestFrame(*item).BoundingBox; const auto& playerBounds = GetBestFrame(*laraItem).BoundingBox; + if (bounds.GetExtents() == Vector3::Zero || playerBounds.GetExtents() == Vector3::Zero) + return false; + if ((item->Pose.Position.y + bounds.Y2) <= (laraItem->Pose.Position.y + playerBounds.Y1)) return false; From f7a22ea1a75eb77b5a1a90427996925cd7e4c7e5 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Fri, 18 Oct 2024 00:14:02 +0100 Subject: [PATCH 319/410] Clarify Lua API for SetOnCollidedWithObject() --- .../Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index e808c33f4..b54b8bf96 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -428,6 +428,9 @@ ScriptReserved_GetSlotHP, & Moveable::GetSlotHP, // @function Moveable:SetOnCollidedWithObject // @tparam function func callback function to be called (must be in LevelFuncs hierarchy). This function can take two arguments; these will store the two @{Moveable}s taking part in the collision. // @usage +// -- obj1 is the collision moveable +// -- obj2 is the collider moveable +// // LevelFuncs.objCollided = function(obj1, obj2) // print(obj1:GetName() .. " collided with " .. obj2:GetName()) // end From 521fdbfa8bf10b4ecab4331843be27c9d50f6883 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:22:49 +0100 Subject: [PATCH 320/410] Changed hardcoded sound for RAISING_BLOCKS back to the soundID used in TRLE (ID 149) --- CHANGELOG.md | 1 + TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp | 2 +- TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp | 4 ++-- TombEngine/Sound/sound_effects.h | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eba472893..ff0da9c77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Changed Rome Hammer to not hurt player whilst deactivated. * Changed Statue with blade damage, from 20 to 200. * Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed. +* Changed hardcoded sound for RAISING_BLOCKS back to the soundID used in TRLE (ID 149) * Changed Water sound condition to ShallowWater. * Enhanced Rolling Spindle detection to avoid them going down through pits. * Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) diff --git a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp index ac204e528..ee5c2883d 100644 --- a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp @@ -93,7 +93,7 @@ namespace TEN::Entities::Generic void ShakeRaisingBlock(ItemInfo* item) { - SoundEffect(SFX_TR4_RAISING_BLOCK, &item->Pose); + SoundEffect(SFX_TR4_RAISING_BLOCK2, &item->Pose); if (item->TriggerFlags == 0) return; diff --git a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp index a60aaede0..9daf6b2c3 100644 --- a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp @@ -128,7 +128,7 @@ namespace TEN::Entities::Generic } else { - SoundEffect(SFX_TR4_RUMBLE_NEXTDOOR, &item->Pose); + SoundEffect(SFX_TR4_RAISING_BLOCK2, &item->Pose); item->Pose.Position.y -= 4; } } @@ -140,7 +140,7 @@ namespace TEN::Entities::Generic } else { - SoundEffect(SFX_TR4_RUMBLE_NEXTDOOR, &item->Pose); + SoundEffect(SFX_TR4_RAISING_BLOCK2, &item->Pose); item->Pose.Position.y += 4; } } diff --git a/TombEngine/Sound/sound_effects.h b/TombEngine/Sound/sound_effects.h index eb21f8e53..7cb61e0da 100644 --- a/TombEngine/Sound/sound_effects.h +++ b/TombEngine/Sound/sound_effects.h @@ -151,7 +151,7 @@ enum SOUND_EFFECTS SFX_TR4_LARA_DEATH3 = 146, SFX_TR4_ROLLING_BALL = 147, SFX_TR4_RAISING_BLOCK = 148, - SFX_TR4_RUMBLE_NEXTDOOR = 149, + SFX_TR4_RAISING_BLOCK2 = 149, SFX_TR4_LOOP_FOR_SMALL_FIRES = 150, SFX_TR4_CHAINS_LIBRARY = 151, SFX_TR4_VEHICLE_JEEP_START = 152, From 3f33021869d6779729de15a40992739695833521 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:22:52 +0200 Subject: [PATCH 321/410] Fix TargetNearestEntity, refactor box flags, extend search LOT range to 32-bit --- TombEngine/Game/control/box.cpp | 2 +- TombEngine/Game/control/box.h | 37 ++++++++++--------- TombEngine/Game/control/lot.cpp | 37 +++++++++++++++++++ TombEngine/Game/control/lot.h | 1 + TombEngine/Game/control/trigger.cpp | 2 +- TombEngine/Game/misc.cpp | 26 ------------- TombEngine/Game/misc.h | 1 - TombEngine/Objects/TR3/Entity/SealMutant.cpp | 1 + TombEngine/Objects/TR4/Entity/tr4_mutant.cpp | 1 + .../Objects/TR5/Shatter/tr5_smashobject.cpp | 2 +- 10 files changed, 63 insertions(+), 47 deletions(-) diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index a2b12fdc8..df31ef167 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -895,7 +895,7 @@ int CreatureCreature(short itemNumber) { auto* linked = &g_Level.Items[link]; - if (link != itemNumber && linked != LaraItem && linked->Status == ITEM_ACTIVE && linked->HitPoints > 0) // TODO: deal with LaraItem global. + if (link != itemNumber && linked != LaraItem && linked->IsCreature() && linked->Status == ITEM_ACTIVE && linked->HitPoints > 0) // TODO: deal with LaraItem global. { int xDistance = abs(linked->Pose.Position.x - x); int zDistance = abs(linked->Pose.Position.z - z); diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 7bf26d8c2..0a6292fda 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -55,30 +55,33 @@ struct OVERLAP #define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber) -constexpr auto BOX_BLOCKED = (1 << 14); // unpassable for other enemies, always set for movable blocks & closed doors -constexpr auto BOX_LAST = (1 << 15); // unpassable by large enemies (T-Rex, Centaur, etc), always set behind doors - -constexpr auto REVERSE = 0x4000; constexpr auto BLOCKABLE = 0x8000; -constexpr auto BLOCKED = 0x4000; -constexpr auto SEARCH_NUMBER = 0x7FFF; -constexpr auto BLOCKED_SEARCH = 0x8000; -constexpr auto BOX_JUMP = 0x800; -constexpr auto BOX_MONKEY = 0x2000; +constexpr auto BLOCKED = 0x4000; + +constexpr auto BLOCKED_SEARCH = (1 << 31); +constexpr auto SEARCH_NUMBER = INT_MAX; + +constexpr auto BOX_JUMP = 0x800; +constexpr auto BOX_MONKEY = 0x2000; constexpr auto BOX_END_BIT = 0x8000; -constexpr auto EXPAND_LEFT = 0x1; -constexpr auto EXPAND_RIGHT = 0x2; -constexpr auto EXPAND_TOP = 0x4; + +constexpr auto EXPAND_LEFT = 0x1; +constexpr auto EXPAND_RIGHT = 0x2; +constexpr auto EXPAND_TOP = 0x4; constexpr auto EXPAND_BOTTOM = 0x8; + constexpr auto NO_FLYING = 0; -constexpr auto FLY_ZONE = 0x2000; -constexpr auto CLIP_LEFT = 0x1; -constexpr auto CLIP_RIGHT = 0x2; -constexpr auto CLIP_TOP = 0x4; +constexpr auto FLY_ZONE = 0x2000; + +constexpr auto CLIP_LEFT = 0x1; +constexpr auto CLIP_RIGHT = 0x2; +constexpr auto CLIP_TOP = 0x4; constexpr auto CLIP_BOTTOM = 0x8; -constexpr auto SECONDARY_CLIP = 0x10; constexpr auto ALL_CLIP = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM); +constexpr auto SECONDARY_CLIP = 0x10; + + void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); void FindAITargetObject(CreatureInfo* creature, int objectNumber); diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index cff68ce9d..18053e904 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -9,6 +9,7 @@ #include "Game/Lara/lara.h" #include "Game/Setup.h" #include "Specific/level.h" +#include "Specific/trutils.h" using namespace TEN::Collision::Room; @@ -205,6 +206,42 @@ void InitializeSlot(short itemNumber, bool makeTarget) SlotsUsed++; } + +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds, bool ignoreKeyObjectIds) +{ + float closestDistSqr = INFINITY; + + for (auto& creature : ActiveCreatures) + { + auto* targetItem = &g_Level.Items[creature->ItemNumber]; + + if (targetItem->Index == item->Index) + continue; + + // Ignore or specifically target key object IDs. + if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem->ObjectNumber) : !Contains(keyObjectIds, targetItem->ObjectNumber))) + continue; + + if (targetItem != item && targetItem->HitPoints > 0 && targetItem->Status != ITEM_INVISIBLE) + { + float distSqr = Vector3i::DistanceSquared(item->Pose.Position, targetItem->Pose.Position); + if (distSqr < closestDistSqr) + { + creature->Enemy = targetItem; + closestDistSqr = distSqr; + } + } + } + + // Handle Lara as a special case. + if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, ID_LARA) : !Contains(keyObjectIds, ID_LARA))) + return; + + float distToLara = Vector3i::DistanceSquared(item->Pose.Position, LaraItem->Pose.Position); + if (distToLara < closestDistSqr) + creature->Enemy = LaraItem; +} + void SetEntityTarget(short itemNum, short target) { auto* item = &g_Level.Items[itemNum]; diff --git a/TombEngine/Game/control/lot.h b/TombEngine/Game/control/lot.h index 273b3bfc8..d644c6ea9 100644 --- a/TombEngine/Game/control/lot.h +++ b/TombEngine/Game/control/lot.h @@ -7,6 +7,7 @@ void InitializeLOTarray(int allocMem); bool EnableEntityAI(short itemNum, bool always, bool makeTarget = true); void InitializeSlot(short itemNum, bool makeTarget); void SetEntityTarget(short itemNum, short target); +void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds = {}, bool ignoreKeyObjectIds = true); void DisableEntityAI(short itemNumber); void ClearLOT(LOTInfo* LOT); void CreateZone(ItemInfo* item); diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index fdcb29a2c..920b556bb 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -339,7 +339,7 @@ void Antitrigger(short const value, short const flags) item->ItemFlags[1] = 100; } - item->Flags &= ~(CODE_BITS | REVERSE); + item->Flags &= ~(CODE_BITS | IFLAG_REVERSE); if (flags & ONESHOT) item->Flags |= ATONESHOT; diff --git a/TombEngine/Game/misc.cpp b/TombEngine/Game/misc.cpp index 1d7ea6785..7fe379a31 100644 --- a/TombEngine/Game/misc.cpp +++ b/TombEngine/Game/misc.cpp @@ -8,7 +8,6 @@ #include "Game/items.h" #include "Game/Setup.h" #include "Specific/level.h" -#include "Specific/trutils.h" using namespace TEN::Collision::Point; using namespace TEN::Utils; @@ -18,31 +17,6 @@ CreatureInfo* GetCreatureInfo(ItemInfo* item) return (CreatureInfo*)item->Data; } -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds, bool ignoreKeyObjectIds) -{ - float closestDistSqr = INFINITY; - for (int itemNumber = 0; itemNumber < g_Level.NumItems; itemNumber++) - { - auto* targetItem = &g_Level.Items[itemNumber]; - if (targetItem == nullptr || targetItem->Index == item->Index) - continue; - - // Ignore or specifically target key object IDs. - if (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem->ObjectNumber) : !Contains(keyObjectIds, targetItem->ObjectNumber)) - continue; - - if (targetItem != item && targetItem->HitPoints > 0 && targetItem->Status != ITEM_INVISIBLE) - { - float distSqr = Vector3i::DistanceSquared(item->Pose.Position, targetItem->Pose.Position); - if (distSqr < closestDistSqr) - { - creature->Enemy = targetItem; - closestDistSqr = distSqr; - } - } - } -} - bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat) { auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, dist); diff --git a/TombEngine/Game/misc.h b/TombEngine/Game/misc.h index 54defb43e..3981f8fc6 100644 --- a/TombEngine/Game/misc.h +++ b/TombEngine/Game/misc.h @@ -18,5 +18,4 @@ enum LaraMeshMask }; CreatureInfo* GetCreatureInfo(ItemInfo* item); -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds = {}, bool ignoreKeyObjectIds = true); bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat); diff --git a/TombEngine/Objects/TR3/Entity/SealMutant.cpp b/TombEngine/Objects/TR3/Entity/SealMutant.cpp index 1d7198dee..690a2c1eb 100644 --- a/TombEngine/Objects/TR3/Entity/SealMutant.cpp +++ b/TombEngine/Objects/TR3/Entity/SealMutant.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/control/box.h" +#include "Game/control/lot.h" #include "Game/effects/effects.h" #include "Game/effects/tomb4fx.h" #include "Game/Lara/lara.h" diff --git a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp index 3db6fd88a..2530f01e5 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp @@ -3,6 +3,7 @@ #include "Game/animation.h" #include "Game/control/control.h" +#include "Game/control/lot.h" #include "Game/effects/effects.h" #include "Game/itemdata/creature_info.h" #include "Game/items.h" diff --git a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp index eba80f23b..04ede674b 100644 --- a/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp +++ b/TombEngine/Objects/TR5/Shatter/tr5_smashobject.cpp @@ -38,7 +38,7 @@ void SmashObject(short itemNumber) auto* box = &g_Level.PathfindingBoxes[room->Sectors[sector].PathfindingBoxID]; if (box->flags & 0x8000) - box->flags &= ~BOX_BLOCKED; + box->flags &= ~BLOCKED; SoundEffect(SFX_TR5_SMASH_GLASS, &item->Pose); From b7d9d994c2d1a57e913c5afe24d0f6910b28d831 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:28:51 +0200 Subject: [PATCH 322/410] Rename other constants in box.h --- TombEngine/Game/control/box.cpp | 44 ++++++++++++++++----------------- TombEngine/Game/control/box.h | 6 ++--- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index df31ef167..6d838691d 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -1043,7 +1043,7 @@ bool SearchLOT(LOTInfo* LOT, int depth) if ((node->searchNumber & SEARCH_NUMBER) < (expand->searchNumber & SEARCH_NUMBER)) continue; - if (node->searchNumber & BLOCKED_SEARCH) + if (node->searchNumber & SEARCH_BLOCKED) { if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER)) continue; @@ -1052,12 +1052,12 @@ bool SearchLOT(LOTInfo* LOT, int depth) } else { - if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & BLOCKED_SEARCH)) + if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & SEARCH_BLOCKED)) continue; if (g_Level.PathfindingBoxes[boxNumber].flags & LOT->BlockMask) { - expand->searchNumber = node->searchNumber | BLOCKED_SEARCH; + expand->searchNumber = node->searchNumber | SEARCH_BLOCKED; } else { @@ -1557,7 +1557,7 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI) AI->enemyZone |= BLOCKED; } else if (item->BoxNumber != NO_VALUE && - creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH)) + creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | SEARCH_BLOCKED)) { AI->enemyZone |= BLOCKED; } @@ -1786,7 +1786,7 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent) auto* enemy = creature->Enemy; auto* LOT = &creature->LOT; - if (item->BoxNumber == NO_VALUE || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH)) + if (item->BoxNumber == NO_VALUE || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | SEARCH_BLOCKED)) creature->LOT.RequiredBox = NO_VALUE; if (creature->Mood != MoodType::Attack && creature->LOT.RequiredBox != NO_VALUE && !ValidBox(item, AI->zoneNumber, creature->LOT.TargetBox)) @@ -1909,7 +1909,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) int right = boxRight; int top = boxTop; int bottom = boxBottom; - int direction = ALL_CLIP; + int direction = CLIP_ALL; do { @@ -1949,7 +1949,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) if (target->z < (boxLeft + CLICK(2))) target->z = boxLeft + CLICK(2); - if (direction & SECONDARY_CLIP) + if (direction & CLIP_SECONDARY) return TARGET_TYPE::SECONDARY_TARGET; if (boxTop > top) @@ -1964,10 +1964,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) { target->z = (right - CLICK(2)); - if (direction != ALL_CLIP) + if (direction != CLIP_ALL) return TARGET_TYPE::SECONDARY_TARGET; - direction |= (ALL_CLIP | SECONDARY_CLIP); + direction |= (CLIP_ALL | CLIP_SECONDARY); } } else if (item->Pose.Position.z > boxRight && direction != CLIP_LEFT) @@ -1979,7 +1979,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) if (target->z > boxRight - CLICK(2)) target->z = boxRight - CLICK(2); - if (direction & SECONDARY_CLIP) + if (direction & CLIP_SECONDARY) return TARGET_TYPE::SECONDARY_TARGET; if (boxTop > top) @@ -1994,10 +1994,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) { target->z = left + CLICK(2); - if (direction != ALL_CLIP) + if (direction != CLIP_ALL) return TARGET_TYPE::SECONDARY_TARGET; - direction |= (ALL_CLIP | SECONDARY_CLIP); + direction |= (CLIP_ALL | CLIP_SECONDARY); } } @@ -2010,7 +2010,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) if (target->x < boxTop + CLICK(2)) target->x = boxTop + CLICK(2); - if (direction & SECONDARY_CLIP) + if (direction & CLIP_SECONDARY) return TARGET_TYPE::SECONDARY_TARGET; if (boxLeft > left) @@ -2025,10 +2025,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) { target->x = bottom - CLICK(2); - if (direction != ALL_CLIP) + if (direction != CLIP_ALL) return TARGET_TYPE::SECONDARY_TARGET; - direction |= (ALL_CLIP | SECONDARY_CLIP); + direction |= (CLIP_ALL | CLIP_SECONDARY); } } else if (item->Pose.Position.x > boxBottom && direction != CLIP_TOP) @@ -2040,7 +2040,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) if (target->x > (boxBottom - CLICK(2))) target->x = (boxBottom - CLICK(2)); - if (direction & SECONDARY_CLIP) + if (direction & CLIP_SECONDARY) return TARGET_TYPE::SECONDARY_TARGET; if (boxLeft > left) @@ -2055,10 +2055,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) { target->x = top + CLICK(2); - if (direction != ALL_CLIP) + if (direction != CLIP_ALL) return TARGET_TYPE::SECONDARY_TARGET; - direction |= (ALL_CLIP | SECONDARY_CLIP); + direction |= (CLIP_ALL | CLIP_SECONDARY); } } } @@ -2069,7 +2069,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) { target->z = LOT->Target.z; } - else if (!(direction & SECONDARY_CLIP)) + else if (!(direction & CLIP_SECONDARY)) { if (target->z < (boxLeft + CLICK(2))) target->z = boxLeft + CLICK(2); @@ -2081,7 +2081,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) { target->x = LOT->Target.x; } - else if (!(direction & SECONDARY_CLIP)) + else if (!(direction & CLIP_SECONDARY)) { if (target->x < (boxTop + CLICK(2))) target->x = boxTop + CLICK(2); @@ -2098,7 +2098,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) break; } while (boxNumber != NO_VALUE); - if (!(direction & SECONDARY_CLIP)) + if (!(direction & CLIP_SECONDARY)) { if (target->z < (boxLeft + CLICK(2))) target->z = boxLeft + CLICK(2); @@ -2106,7 +2106,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT) target->z = boxRight - CLICK(2); } - if (!(direction & SECONDARY_CLIP)) + if (!(direction & CLIP_SECONDARY)) { if (target->x < (boxTop + CLICK(2))) target->x = boxTop + CLICK(2); diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 0a6292fda..973975bf6 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -58,8 +58,8 @@ struct OVERLAP constexpr auto BLOCKABLE = 0x8000; constexpr auto BLOCKED = 0x4000; -constexpr auto BLOCKED_SEARCH = (1 << 31); constexpr auto SEARCH_NUMBER = INT_MAX; +constexpr auto SEARCH_BLOCKED = (1 << 31); constexpr auto BOX_JUMP = 0x800; constexpr auto BOX_MONKEY = 0x2000; @@ -77,9 +77,9 @@ constexpr auto CLIP_LEFT = 0x1; constexpr auto CLIP_RIGHT = 0x2; constexpr auto CLIP_TOP = 0x4; constexpr auto CLIP_BOTTOM = 0x8; -constexpr auto ALL_CLIP = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM); +constexpr auto CLIP_ALL = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM); -constexpr auto SECONDARY_CLIP = 0x10; +constexpr auto CLIP_SECONDARY = 0x10; void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); From 4c42cb871a95617fa9de6d06db007f2a788cc6ec Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:49:23 +0200 Subject: [PATCH 323/410] Fix door height and floordata precision loss with NO_HEIGHT variable --- TombEngine/Game/collision/floordata.cpp | 4 ++++ TombEngine/Objects/Generic/Doors/generic_doors.cpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 525a64209..0037f8661 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -182,6 +182,10 @@ int FloorInfo::GetSurfaceHeight(int x, int z, bool isFloor) const auto normal = tri.Plane.Normal(); float relPlaneHeight = -((normal.x * sectorPoint.x) + (normal.z * sectorPoint.y)) / normal.y; + // Due to precision loss, we can't recover NO_HEIGHT constant from the plane, and must return original integer constant. + if (tri.Plane.D() == float(NO_HEIGHT)) + return NO_HEIGHT; + // Return sector floor or ceiling height. NOTE: Bridges ignored. return (tri.Plane.D() + relPlaneHeight); } diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index ebb460372..668871c9a 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -411,7 +411,7 @@ namespace TEN::Entities::Doors void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd) { - static const auto WALL_PLANE = Plane(-Vector3::UnitY, -CLICK(127)); + static const auto WALL_PLANE = Plane(-Vector3::UnitY, float(NO_HEIGHT)); FloorInfo* floor = doorPos->floor; From 6278b59a1d4a8523db374efae4313f91c3b6742b Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:53:05 +0200 Subject: [PATCH 324/410] Rollback Tokyo's jump distance constant and add no box checks to CanCreatureJump --- TombEngine/Game/control/box.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 6d838691d..cd1aca636 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -27,13 +27,11 @@ using namespace TEN::Effects::Smoke; constexpr auto ESCAPE_DIST = BLOCK(5); constexpr auto STALK_DIST = BLOCK(3); -constexpr auto REACHED_GOAL_RADIUS = 640; +constexpr auto REACHED_GOAL_RADIUS = BLOCK(0.625); constexpr auto ATTACK_RANGE = SQUARE(BLOCK(3)); constexpr auto ESCAPE_CHANCE = 0x800; constexpr auto RECOVER_CHANCE = 0x100; constexpr auto BIFF_AVOID_TURN = ANGLE(11.25f); -constexpr auto FEELER_DISTANCE = CLICK(2); -constexpr auto FEELER_ANGLE = ANGLE(45.0f); constexpr auto CREATURE_AI_ROTATION_MAX = ANGLE(90.0f); constexpr auto CREATURE_JOINT_ROTATION_MAX = ANGLE(70.0f); @@ -2183,7 +2181,20 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) if (creature.Enemy == nullptr) return false; - float stepDist = BLOCK(0.92f); + float stepDist = 0.0f; + + switch (jumpDistType) + { + default: + case JumpDistance::Block1: + stepDist = BLOCK(0.51f); + break; + + case JumpDistance::Block2: + stepDist = BLOCK(0.76f); + break; + } + int vPos = item.Pose.Position.y; auto pointCollA = GetPointCollision(item, item.Pose.Orientation.y, stepDist); auto pointCollB = GetPointCollision(item, item.Pose.Orientation.y, stepDist * 2); @@ -2196,7 +2207,9 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) if (item.BoxNumber == creature.Enemy->BoxNumber || vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) || vPos >= (pointCollB.GetFloorHeight() + CLICK(1)) || - vPos <= (pointCollB.GetFloorHeight() - CLICK(1))) + vPos <= (pointCollB.GetFloorHeight() - CLICK(1)) || + pointCollA.GetSector().PathfindingBoxID == NO_VALUE || + pointCollB.GetSector().PathfindingBoxID == NO_VALUE) { return false; } @@ -2208,7 +2221,10 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) || vPos >= (pointCollB.GetFloorHeight() - STEPUP_HEIGHT) || vPos >= (pointCollC.GetFloorHeight() + CLICK(1)) || - vPos <= (pointCollC.GetFloorHeight() - CLICK(1))) + vPos <= (pointCollC.GetFloorHeight() - CLICK(1)) || + pointCollA.GetSector().PathfindingBoxID == NO_VALUE || + pointCollB.GetSector().PathfindingBoxID == NO_VALUE || + pointCollC.GetSector().PathfindingBoxID == NO_VALUE) { return false; } From a2812d5b341c1ec0b80e7f064536d6c3903206e0 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:28:36 +0200 Subject: [PATCH 325/410] Unrollback Tokyo's value --- TombEngine/Game/control/box.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index cd1aca636..058e9631e 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -2181,19 +2181,7 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType) if (creature.Enemy == nullptr) return false; - float stepDist = 0.0f; - - switch (jumpDistType) - { - default: - case JumpDistance::Block1: - stepDist = BLOCK(0.51f); - break; - - case JumpDistance::Block2: - stepDist = BLOCK(0.76f); - break; - } + float stepDist = BLOCK(0.92f); int vPos = item.Pose.Position.y; auto pointCollA = GetPointCollision(item, item.Pose.Orientation.y, stepDist); From 4a64e73648343ce325d8156618c7e095c628bd94 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 24 Oct 2024 15:02:36 +1100 Subject: [PATCH 326/410] Enforce some conventions with recent changes --- TombEngine/Game/collision/floordata.cpp | 2 +- TombEngine/Game/control/box.h | 3 ++- TombEngine/Game/control/lot.cpp | 27 +++++++++---------- TombEngine/Game/control/lot.h | 2 +- .../Objects/Generic/Doors/generic_doors.cpp | 2 +- TombEngine/Objects/TR3/Entity/Raptor.cpp | 2 +- TombEngine/Objects/TR3/Entity/SealMutant.cpp | 2 +- .../Objects/TR3/Entity/tr3_flamethrower.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_mutant.cpp | 2 +- .../Objects/TR5/Object/tr5_raisingblock.cpp | 2 +- .../TR5/Object/tr5_twoblockplatform.cpp | 4 +-- TombEngine/Sound/sound_effects.h | 2 +- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 0037f8661..04adbcdda 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -183,7 +183,7 @@ int FloorInfo::GetSurfaceHeight(int x, int z, bool isFloor) const float relPlaneHeight = -((normal.x * sectorPoint.x) + (normal.z * sectorPoint.y)) / normal.y; // Due to precision loss, we can't recover NO_HEIGHT constant from the plane, and must return original integer constant. - if (tri.Plane.D() == float(NO_HEIGHT)) + if (tri.Plane.D() == (float)NO_HEIGHT) return NO_HEIGHT; // Return sector floor or ceiling height. NOTE: Bridges ignored. diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 973975bf6..25396411b 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -55,6 +55,8 @@ struct OVERLAP #define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber) +// TODO: Following constants can be moved to new flag enums for improved clarity. + constexpr auto BLOCKABLE = 0x8000; constexpr auto BLOCKED = 0x4000; @@ -81,7 +83,6 @@ constexpr auto CLIP_ALL = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM); constexpr auto CLIP_SECONDARY = 0x10; - void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); void FindAITargetObject(CreatureInfo* creature, int objectNumber); diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 18053e904..1ba450104 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -206,40 +206,39 @@ void InitializeSlot(short itemNumber, bool makeTarget) SlotsUsed++; } - -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds, bool ignoreKeyObjectIds) +void TargetNearestEntity(ItemInfo& item, const std::vector& keyObjectIds, bool ignoreKeyObjectIds) { - float closestDistSqr = INFINITY; + auto& creature = *GetCreatureInfo(&item); + float closestDistSqr = INFINITY; for (auto& creature : ActiveCreatures) { - auto* targetItem = &g_Level.Items[creature->ItemNumber]; - - if (targetItem->Index == item->Index) + auto& targetItem = g_Level.Items[creature->ItemNumber]; + if (targetItem.Index == item.Index) continue; // Ignore or specifically target key object IDs. - if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem->ObjectNumber) : !Contains(keyObjectIds, targetItem->ObjectNumber))) + if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem.ObjectNumber) : !Contains(keyObjectIds, targetItem.ObjectNumber))) continue; - if (targetItem != item && targetItem->HitPoints > 0 && targetItem->Status != ITEM_INVISIBLE) + if (&targetItem != &item && targetItem.HitPoints > 0 && targetItem.Status != ITEM_INVISIBLE) { - float distSqr = Vector3i::DistanceSquared(item->Pose.Position, targetItem->Pose.Position); + float distSqr = Vector3i::DistanceSquared(item.Pose.Position, targetItem.Pose.Position); if (distSqr < closestDistSqr) { - creature->Enemy = targetItem; + creature->Enemy = &targetItem; closestDistSqr = distSqr; } } } - // Handle Lara as a special case. + // Handle player as special case. if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, ID_LARA) : !Contains(keyObjectIds, ID_LARA))) return; - float distToLara = Vector3i::DistanceSquared(item->Pose.Position, LaraItem->Pose.Position); - if (distToLara < closestDistSqr) - creature->Enemy = LaraItem; + float distToPlayerSqr = Vector3i::DistanceSquared(item.Pose.Position, LaraItem->Pose.Position); + if (distToPlayerSqr < closestDistSqr) + creature.Enemy = LaraItem; } void SetEntityTarget(short itemNum, short target) diff --git a/TombEngine/Game/control/lot.h b/TombEngine/Game/control/lot.h index d644c6ea9..251adea17 100644 --- a/TombEngine/Game/control/lot.h +++ b/TombEngine/Game/control/lot.h @@ -7,7 +7,7 @@ void InitializeLOTarray(int allocMem); bool EnableEntityAI(short itemNum, bool always, bool makeTarget = true); void InitializeSlot(short itemNum, bool makeTarget); void SetEntityTarget(short itemNum, short target); -void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector& keyObjectIds = {}, bool ignoreKeyObjectIds = true); +void TargetNearestEntity(ItemInfo& item, const std::vector& keyObjectIds = {}, bool ignoreKeyObjectIds = true); void DisableEntityAI(short itemNumber); void ClearLOT(LOTInfo* LOT); void CreateZone(ItemInfo* item); diff --git a/TombEngine/Objects/Generic/Doors/generic_doors.cpp b/TombEngine/Objects/Generic/Doors/generic_doors.cpp index 668871c9a..756dfd0c2 100644 --- a/TombEngine/Objects/Generic/Doors/generic_doors.cpp +++ b/TombEngine/Objects/Generic/Doors/generic_doors.cpp @@ -411,7 +411,7 @@ namespace TEN::Entities::Doors void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd) { - static const auto WALL_PLANE = Plane(-Vector3::UnitY, float(NO_HEIGHT)); + static const auto WALL_PLANE = Plane(-Vector3::UnitY, (float)NO_HEIGHT); FloorInfo* floor = doorPos->floor; diff --git a/TombEngine/Objects/TR3/Entity/Raptor.cpp b/TombEngine/Objects/TR3/Entity/Raptor.cpp index 084fee14a..b74994521 100644 --- a/TombEngine/Objects/TR3/Entity/Raptor.cpp +++ b/TombEngine/Objects/TR3/Entity/Raptor.cpp @@ -123,7 +123,7 @@ namespace TEN::Entities::Creatures::TR3 else { // NOTE: Ignores other small dinosaurs. - TargetNearestEntity(&item, &creature, RaptorIgnoredObjectIds); + TargetNearestEntity(item, RaptorIgnoredObjectIds); AI_INFO ai; if (item.AIBits) diff --git a/TombEngine/Objects/TR3/Entity/SealMutant.cpp b/TombEngine/Objects/TR3/Entity/SealMutant.cpp index 690a2c1eb..0050fa143 100644 --- a/TombEngine/Objects/TR3/Entity/SealMutant.cpp +++ b/TombEngine/Objects/TR3/Entity/SealMutant.cpp @@ -206,7 +206,7 @@ namespace TEN::Entities::Creatures::TR3 } else { - TargetNearestEntity(&item, &creature, SealMutantAttackTargetObjectIds, false); + TargetNearestEntity(item, SealMutantAttackTargetObjectIds, false); } AI_INFO ai; diff --git a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp index 15cc2f64b..4c1c60021 100644 --- a/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp +++ b/TombEngine/Objects/TR3/Entity/tr3_flamethrower.cpp @@ -95,7 +95,7 @@ namespace TEN::Entities::Creatures::TR3 } else { - TargetNearestEntity(item, creature, FlamethrowerTargetIds, false); + TargetNearestEntity(*item, FlamethrowerTargetIds, false); } AI_INFO AI; diff --git a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp index 2530f01e5..60d8cd8d8 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mutant.cpp @@ -287,7 +287,7 @@ namespace TEN::Entities::TR4 } else { - TargetNearestEntity(item, creature); + TargetNearestEntity(*item); } AI_INFO ai; diff --git a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp index ee5c2883d..94fc6c279 100644 --- a/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_raisingblock.cpp @@ -93,7 +93,7 @@ namespace TEN::Entities::Generic void ShakeRaisingBlock(ItemInfo* item) { - SoundEffect(SFX_TR4_RAISING_BLOCK2, &item->Pose); + SoundEffect(SFX_TR4_RAISING_BLOCK_2, &item->Pose); if (item->TriggerFlags == 0) return; diff --git a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp index 9daf6b2c3..99bfeee01 100644 --- a/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_twoblockplatform.cpp @@ -128,7 +128,7 @@ namespace TEN::Entities::Generic } else { - SoundEffect(SFX_TR4_RAISING_BLOCK2, &item->Pose); + SoundEffect(SFX_TR4_RAISING_BLOCK_2, &item->Pose); item->Pose.Position.y -= 4; } } @@ -140,7 +140,7 @@ namespace TEN::Entities::Generic } else { - SoundEffect(SFX_TR4_RAISING_BLOCK2, &item->Pose); + SoundEffect(SFX_TR4_RAISING_BLOCK_2, &item->Pose); item->Pose.Position.y += 4; } } diff --git a/TombEngine/Sound/sound_effects.h b/TombEngine/Sound/sound_effects.h index 7cb61e0da..e4cbe98a5 100644 --- a/TombEngine/Sound/sound_effects.h +++ b/TombEngine/Sound/sound_effects.h @@ -151,7 +151,7 @@ enum SOUND_EFFECTS SFX_TR4_LARA_DEATH3 = 146, SFX_TR4_ROLLING_BALL = 147, SFX_TR4_RAISING_BLOCK = 148, - SFX_TR4_RAISING_BLOCK2 = 149, + SFX_TR4_RAISING_BLOCK_2 = 149, SFX_TR4_LOOP_FOR_SMALL_FIRES = 150, SFX_TR4_CHAINS_LIBRARY = 151, SFX_TR4_VEHICLE_JEEP_START = 152, From 9a3166b9a1efb27d6f244a40ae394721b799c602 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 24 Oct 2024 15:33:42 +1100 Subject: [PATCH 327/410] Final code cleanup --- TombEngine/Game/camera.cpp | 4 +-- TombEngine/Game/camera.h | 5 +-- TombEngine/Game/control/control.cpp | 8 ++--- TombEngine/Game/spotcam.cpp | 5 +-- TombEngine/Renderer/RendererDrawEffect.cpp | 38 ++++++++++------------ 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 7453b683e..38c806fb9 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -194,8 +194,8 @@ void LookCamera(ItemInfo& item, const CollisionInfo& coll) void LookAt(CAMERA_INFO* cam, short roll) { - cam->currentFov = TO_RAD(CurrentFOV / 1.333333f); - cam->currentRoll = TO_RAD(roll); + cam->Fov = TO_RAD(CurrentFOV / 1.333333f); + cam->Roll = TO_RAD(roll); } void AlterFOV(short value, bool store) diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 1c643548e..5f41c7588 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -46,8 +46,9 @@ struct CAMERA_INFO ItemInfo* lastItem; int mikeAtLara; Vector3i mikePos; - float currentRoll; - float currentFov; + + float Roll = 0.0f; + float Fov = 0.0f; bool DisableInterpolation = false; }; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 99958739f..13573a0d6 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -253,12 +253,12 @@ GameStatus ControlPhase() // Post-loop script and event handling. g_GameScript->OnLoop(DELTA_TIME, true); - // Update cameras matrices there, after having done all the possible camera logic + // Update cameras matrices. NOTE: Must be after handling all camera logic. g_Renderer.UpdateCameraMatrices( &Camera, - Camera.currentRoll, - Camera.currentFov, - g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * BLOCK(1)); + Camera.Roll, + Camera.Fov, + BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView())); // Clear savegame loaded flag. JustLoaded = false; diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index d4bd804a2..e66343a87 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -491,18 +491,15 @@ void CalculateSpotCameras() if (outsideRoom == NO_VALUE) { if (Camera.pos.RoomNumber != SpotCam[CurrentSplineCamera].roomNumber) - { Camera.DisableInterpolation = true; - } + Camera.pos.RoomNumber = SpotCam[CurrentSplineCamera].roomNumber; GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.RoomNumber); } else { if (Camera.pos.RoomNumber != outsideRoom) - { Camera.DisableInterpolation = true; - } Camera.pos.RoomNumber = outsideRoom; } diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 0d0f6ca3b..e4f68906e 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -400,9 +400,7 @@ namespace TEN::Renderer void Renderer::PrepareParticles(RenderView& view) { for (int i = 0; i < ParticleNodeOffsetIDs::NodeMax; i++) - { NodeOffsets[i].gotIt = false; - } for (auto& particle : Particles) { @@ -420,27 +418,27 @@ namespace TEN::Renderer { const auto& fx = EffectList[particle.fxObj]; - RendererEffect* newEffect = &_effects[particle.fxObj]; + auto& newEffect = _effects[particle.fxObj]; - newEffect->Translation = Matrix::CreateTranslation(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z); - newEffect->Rotation = fx.pos.Orientation.ToRotationMatrix(); - newEffect->Scale = Matrix::CreateScale(1.0f); - newEffect->World = newEffect->Rotation * newEffect->Translation; - newEffect->ObjectID = fx.objectNumber; - newEffect->RoomNumber = fx.roomNumber; - newEffect->Position = fx.pos.Position.ToVector3(); + newEffect.Translation = Matrix::CreateTranslation(fx.pos.Position.ToVector3()); + newEffect.Rotation = fx.pos.Orientation.ToRotationMatrix(); + newEffect.Scale = Matrix::CreateScale(1.0f); + newEffect.World = newEffect.Rotation * newEffect.Translation; + newEffect.ObjectID = fx.objectNumber; + newEffect.RoomNumber = fx.roomNumber; + newEffect.Position = fx.pos.Position.ToVector3(); - newEffect->InterpolatedPosition = Vector3::Lerp(newEffect->PrevPosition, newEffect->Position, _interpolationFactor); - newEffect->InterpolatedTranslation = Matrix::Lerp(newEffect->PrevTranslation, newEffect->Translation, _interpolationFactor); - newEffect->InterpolatedRotation = Matrix::Lerp(newEffect->InterpolatedRotation, newEffect->Rotation, _interpolationFactor); - newEffect->InterpolatedWorld = Matrix::Lerp(newEffect->PrevWorld, newEffect->World, _interpolationFactor); - newEffect->InterpolatedScale = Matrix::Lerp(newEffect->PrevScale, newEffect->Scale, _interpolationFactor); + newEffect.InterpolatedPosition = Vector3::Lerp(newEffect.PrevPosition, newEffect.Position, _interpolationFactor); + newEffect.InterpolatedTranslation = Matrix::Lerp(newEffect.PrevTranslation, newEffect.Translation, _interpolationFactor); + newEffect.InterpolatedRotation = Matrix::Lerp(newEffect.InterpolatedRotation, newEffect.Rotation, _interpolationFactor); + newEffect.InterpolatedWorld = Matrix::Lerp(newEffect.PrevWorld, newEffect.World, _interpolationFactor); + newEffect.InterpolatedScale = Matrix::Lerp(newEffect.PrevScale, newEffect.Scale, _interpolationFactor); - pos += newEffect->InterpolatedPosition; + pos += newEffect.InterpolatedPosition; if ((particle.sLife - particle.life) > Random::GenerateInt(8, 12)) { - // Particle becomes autonome + // Particle becomes autonome. particle.flags &= ~SP_FX; particle.x = particle.PrevX = pos.x; @@ -450,7 +448,7 @@ namespace TEN::Renderer } else if (!(particle.flags & SP_ITEM)) { - // NOTE: pos already set before... + // NOTE: pos already set previously. //pos.x = particle.x; //pos.y = particle.y; //pos.z = particle.z; @@ -490,7 +488,7 @@ namespace TEN::Renderer if ((particle.sLife - particle.life) > Random::GenerateInt(4, 8)) { - // Particle becomes autonome + // Particle becomes autonome. particle.flags &= ~SP_ITEM; particle.x = particle.PrevX = pos.x; @@ -504,7 +502,7 @@ namespace TEN::Renderer } } - // Don't allow sprites out of bounds. + // Disallow sprites out of bounds. int spriteIndex = std::clamp((int)particle.spriteIndex, 0, (int)_sprites.size()); AddSpriteBillboard( From e4098c458f549b169f8a0a2e7378f16b308395da Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 24 Oct 2024 08:23:50 +0200 Subject: [PATCH 328/410] Fix typo --- TombEngine/Game/control/lot.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 1ba450104..5983a9b57 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -211,9 +211,9 @@ void TargetNearestEntity(ItemInfo& item, const std::vector& keyO auto& creature = *GetCreatureInfo(&item); float closestDistSqr = INFINITY; - for (auto& creature : ActiveCreatures) + for (auto& target : ActiveCreatures) { - auto& targetItem = g_Level.Items[creature->ItemNumber]; + auto& targetItem = g_Level.Items[target->ItemNumber]; if (targetItem.Index == item.Index) continue; @@ -226,7 +226,7 @@ void TargetNearestEntity(ItemInfo& item, const std::vector& keyO float distSqr = Vector3i::DistanceSquared(item.Pose.Position, targetItem.Pose.Position); if (distSqr < closestDistSqr) { - creature->Enemy = &targetItem; + creature.Enemy = &targetItem; closestDistSqr = distSqr; } } From 53e7ca0972b21b954cb4606f896476e6295a787c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 25 Oct 2024 08:43:45 +0200 Subject: [PATCH 329/410] Decopypaste sync code, rename variable framerate to high, remove unused variables --- Scripts/SystemStrings.lua | 2 +- TombEngine/Game/Lara/lara.cpp | 1 - TombEngine/Game/Lara/lara.h | 1 - TombEngine/Game/control/control.cpp | 90 ++--------- TombEngine/Game/control/control.h | 2 +- TombEngine/Game/gui.cpp | 143 ++++-------------- TombEngine/Game/gui.h | 3 - TombEngine/Game/savegame.cpp | 4 + TombEngine/Objects/Effects/LensFlare.cpp | 11 +- TombEngine/Objects/Effects/LensFlare.h | 3 +- TombEngine/Renderer/Renderer.cpp | 4 +- TombEngine/Renderer/Renderer.h | 5 +- TombEngine/Renderer/RendererDrawMenu.cpp | 8 +- TombEngine/Renderer/RendererHelper.cpp | 11 +- TombEngine/Renderer/RendererInit.cpp | 2 +- .../Scripting/Internal/LanguageScript.h | 2 +- .../TEN/Objects/Moveable/MoveableObject.cpp | 8 +- TombEngine/Specific/clock.cpp | 74 ++++++++- TombEngine/Specific/clock.h | 21 ++- TombEngine/Specific/configuration.cpp | 10 +- TombEngine/Specific/configuration.h | 4 +- 21 files changed, 181 insertions(+), 228 deletions(-) diff --git a/Scripts/SystemStrings.lua b/Scripts/SystemStrings.lua index 7ad9d3f15..fdd9821c2 100644 --- a/Scripts/SystemStrings.lua +++ b/Scripts/SystemStrings.lua @@ -75,6 +75,7 @@ local strings = exit_to_title = { "Exit to Title" }, general_actions = { "General Actions" }, high = { "High" }, + high_framerate = { "High Framerate" }, level_secrets_found = { "Secrets Found in Level" }, load_game = { "Load Game" }, low = { "Low" }, @@ -114,7 +115,6 @@ local strings = total_secrets_found = { "Secrets Found Total" }, use = { "Use" }, used_medipacks = { "Medipacks Used" }, - variable_framerate = { "Variable Framerate" }, vehicle_actions = { "Vehicle Actions" }, view = { "View" }, volumetric_fog = { "Volumetric Fog" }, diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 9095efe04..957c96890 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -60,7 +60,6 @@ using namespace TEN::Gui; using TEN::Renderer::g_Renderer; LaraInfo Lara = {}; -LaraInfo PrevLara = {}; ItemInfo* LaraItem = nullptr; CollisionInfo LaraCollision = {}; diff --git a/TombEngine/Game/Lara/lara.h b/TombEngine/Game/Lara/lara.h index fda62282c..5e35047bf 100644 --- a/TombEngine/Game/Lara/lara.h +++ b/TombEngine/Game/Lara/lara.h @@ -94,7 +94,6 @@ constexpr auto SWIM_WATER_DEPTH = CLICK(2.75f); constexpr auto SLOPE_DIFFERENCE = 60; extern LaraInfo Lara; -extern LaraInfo PrevLara; extern ItemInfo* LaraItem; extern CollisionInfo LaraCollision; diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 13573a0d6..b03b9b405 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -1,7 +1,6 @@ #include "framework.h" #include "Game/control/control.h" -#include #include #include "Game/camera.h" @@ -60,7 +59,6 @@ #include "Specific/Input/Input.h" #include "Specific/level.h" #include "Specific/winmain.h" -#include "Game/Lara/lara_initialise.h" using namespace std::chrono; using namespace TEN::Effects; @@ -131,8 +129,6 @@ void DrawPhase(bool isTitle, float interpolationFactor) GameStatus ControlPhase() { - static int framesCount = 0; - auto time1 = std::chrono::high_resolution_clock::now(); bool isTitle = (CurrentLevel == 0); @@ -157,7 +153,7 @@ GameStatus ControlPhase() HandleControls(isTitle); // Pre-loop script and event handling. - g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with variable framerate + g_GameScript->OnLoop(DELTA_TIME, false); // TODO: Don't use DELTA_TIME constant with high framerate. HandleAllGlobalEvents(EventType::Loop, (Activator)LaraItem->Index); // Control lock is processed after handling scripts because builder may want to process input externally while locking player from input. @@ -228,14 +224,7 @@ GameStatus ControlPhase() UpdateLocusts(); UpdateUnderwaterBloodParticles(); UpdateFishSwarm(); - - if (g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareEnabled()) - { - SetupGlobalLensFlare( - EulerAngles(g_GameFlow->GetLevel(CurrentLevel)->GetLensFlarePitch(), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareYaw(), 0), - g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareColor(), - g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSunSpriteID()); - } + UpdateGlobalLensFlare(); // Update HUD. g_Hud.Update(*LaraItem); @@ -245,21 +234,17 @@ GameStatus ControlPhase() if (g_GameFlow->GetLevel(CurrentLevel)->Rumble) RumbleScreen(); - PlaySoundSources(); + // Update cameras matrices there, after having done all the possible camera logic. + g_Renderer.UpdateCameraMatrices(&Camera, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView())); + DoFlipEffect(FlipEffect, LaraItem); + PlaySoundSources(); Sound_UpdateScene(); // Post-loop script and event handling. g_GameScript->OnLoop(DELTA_TIME, true); - // Update cameras matrices. NOTE: Must be after handling all camera logic. - g_Renderer.UpdateCameraMatrices( - &Camera, - Camera.Roll, - Camera.Fov, - BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView())); - // Clear savegame loaded flag. JustLoaded = false; @@ -267,11 +252,8 @@ GameStatus ControlPhase() GameTimer++; GlobalCounter++; - using ns = std::chrono::nanoseconds; - using get_time = std::chrono::steady_clock; - auto time2 = std::chrono::high_resolution_clock::now(); - ControlPhaseTime = (std::chrono::duration_cast(time2 - time1)).count() / 1000000; + ControlPhaseTime = (std::chrono::duration_cast(time2 - time1)).count() / 1000000; return GameStatus::Normal; } @@ -556,10 +538,6 @@ void InitializeOrLoadGame(bool loadGame) { SaveGame::LoadHub(CurrentLevel); TENLog("Starting new level.", LogLevel::Info); - - // Restore vehicle. - auto* item = FindItem(ID_LARA); - InitializePlayerVehicle(*item); } g_GameScript->OnStart(); @@ -569,8 +547,6 @@ void InitializeOrLoadGame(bool loadGame) GameStatus DoGameLoop(int levelIndex) { - constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; - int frameCount = LOOP_FRAME_COUNT; auto& status = g_GameFlow->LastGameStatus; @@ -578,54 +554,17 @@ GameStatus DoGameLoop(int levelIndex) // called once to sort out various runtime shenanigangs (e.g. hair). status = ControlPhase(); - LARGE_INTEGER lastTime; - LARGE_INTEGER currentTime; - double controlLag = 0; - double frameTime = 0; - - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter(&lastTime); - - int controlCalls = 0; - int drawCalls = 0; - + g_Synchronizer.Init(); bool legacy30FpsDoneDraw = false; while (DoTheGame) { - if (App.ResetClock) - { - App.ResetClock = false; - QueryPerformanceCounter(&lastTime); - currentTime = lastTime; - controlLag = 0; - frameTime = 0; - } - else - { - QueryPerformanceCounter(¤tTime); - frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; - lastTime = currentTime; - controlLag += frameTime; - } + g_Synchronizer.Sync(); - while (controlLag >= CONTROL_FRAME_TIME) + while (g_Synchronizer.Synced()) { -#if _DEBUG - constexpr auto DEBUG_SKIP_FRAMES = 10; - - if (controlLag >= DEBUG_SKIP_FRAMES * CONTROL_FRAME_TIME) - { - TENLog("Game loop is running too slow.", LogLevel::Warning); - App.ResetClock = true; - break; - } -#endif - status = ControlPhase(); - controlLag -= CONTROL_FRAME_TIME; - controlCalls++; + g_Synchronizer.Step(); legacy30FpsDoneDraw = false; } @@ -633,20 +572,17 @@ GameStatus DoGameLoop(int levelIndex) if (status != GameStatus::Normal) break; - if (!g_Configuration.EnableVariableFramerate) + if (!g_Configuration.EnableHighFramerate) { if (!legacy30FpsDoneDraw) { DrawPhase(!levelIndex, 0.0f); - drawCalls++; legacy30FpsDoneDraw = true; } } else { - float interpolationFactor = std::min((float)controlLag / (float)CONTROL_FRAME_TIME, 1.0f); - DrawPhase(!levelIndex, interpolationFactor); - drawCalls++; + DrawPhase(!levelIndex, g_Synchronizer.GetInterpolationFactor()); } } diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index a76b0b564..a51893e5d 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -50,7 +50,7 @@ enum FadeStatus constexpr int MAX_ROOMS = 1024; -constexpr int LOOP_FRAME_COUNT = 2; +constexpr auto LOOP_FRAME_COUNT = 2; extern int GameTimer; extern int RumbleTimer; diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 47dcca471..56c924a11 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -193,11 +193,6 @@ namespace TEN::Gui return false; } - float GuiController::GetSpinSpeed() - { - return g_Configuration.EnableVariableFramerate ? (g_Renderer.GetScreenRefreshRate() / 30.0f) : 1.0f; - } - bool GuiController::CanDeselect() const { return !(IsHeld(In::Select) || IsHeld(In::Action)); @@ -488,7 +483,7 @@ namespace TEN::Gui Caustics, Antialiasing, AmbientOcclusion, - VariableFramerate, + HighFramerate, Save, Cancel }; @@ -551,9 +546,9 @@ namespace TEN::Gui CurrentSettings.Configuration.EnableAmbientOcclusion = !CurrentSettings.Configuration.EnableAmbientOcclusion; break; - case DisplaySettingsOption::VariableFramerate: + case DisplaySettingsOption::HighFramerate: SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - CurrentSettings.Configuration.EnableVariableFramerate = !CurrentSettings.Configuration.EnableVariableFramerate; + CurrentSettings.Configuration.EnableHighFramerate = !CurrentSettings.Configuration.EnableHighFramerate; break; } @@ -603,9 +598,9 @@ namespace TEN::Gui CurrentSettings.Configuration.EnableAmbientOcclusion = !CurrentSettings.Configuration.EnableAmbientOcclusion; break; - case DisplaySettingsOption::VariableFramerate: + case DisplaySettingsOption::HighFramerate: SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - CurrentSettings.Configuration.EnableVariableFramerate = !CurrentSettings.Configuration.EnableVariableFramerate; + CurrentSettings.Configuration.EnableHighFramerate = !CurrentSettings.Configuration.EnableHighFramerate; break; } } @@ -745,7 +740,7 @@ namespace TEN::Gui if (fromPauseMenu) { g_Renderer.RenderInventory(); - if (!g_Configuration.EnableVariableFramerate) + if (!g_Configuration.EnableHighFramerate) { g_Renderer.Synchronize(); } @@ -753,7 +748,7 @@ namespace TEN::Gui else { g_Renderer.RenderTitle(0); - if (!g_Configuration.EnableVariableFramerate) + if (!g_Configuration.EnableHighFramerate) { g_Renderer.Synchronize(); } @@ -1995,7 +1990,7 @@ namespace TEN::Gui else if (AmmoSelectorFadeDir == 1) { if (AmmoSelectorFadeVal < 128) - AmmoSelectorFadeVal += 32 / GetSpinSpeed(); + AmmoSelectorFadeVal += 32 / g_Renderer.GetFramerateMultiplier(); if (AmmoSelectorFadeVal > 128) { @@ -2006,7 +2001,7 @@ namespace TEN::Gui else if (AmmoSelectorFadeDir == 2) { if (AmmoSelectorFadeVal > 0) - AmmoSelectorFadeVal -= 32 / GetSpinSpeed(); + AmmoSelectorFadeVal -= 32 / g_Renderer.GetFramerateMultiplier(); if (AmmoSelectorFadeVal < 0) { @@ -2649,7 +2644,7 @@ namespace TEN::Gui void GuiController::SpinBack(EulerAngles& orient) { - orient.Lerp(EulerAngles::Identity, 1.0f / (8.0f * GetSpinSpeed())); + orient.Lerp(EulerAngles::Identity, 1.0f / (8.0f * g_Renderer.GetFramerateMultiplier())); } void GuiController::DrawAmmoSelector() @@ -2672,13 +2667,13 @@ namespace TEN::Gui if (n == *CurrentAmmoType) { if (invObject->RotFlags & INV_ROT_X) - AmmoObjectList[n].Orientation.x += ANGLE(5.0f / GetSpinSpeed()); + AmmoObjectList[n].Orientation.x += ANGLE(5.0f / g_Renderer.GetFramerateMultiplier()); if (invObject->RotFlags & INV_ROT_Y) - AmmoObjectList[n].Orientation.y += ANGLE(5.0f / GetSpinSpeed()); + AmmoObjectList[n].Orientation.y += ANGLE(5.0f / g_Renderer.GetFramerateMultiplier()); if (invObject->RotFlags & INV_ROT_Z) - AmmoObjectList[n].Orientation.z += ANGLE(5.0f / GetSpinSpeed()); + AmmoObjectList[n].Orientation.z += ANGLE(5.0f / g_Renderer.GetFramerateMultiplier()); } else SpinBack(AmmoObjectList[n].Orientation); @@ -3050,13 +3045,13 @@ namespace TEN::Gui if (!i && !ring.ObjectListMovement) { if (invObject.RotFlags & INV_ROT_X) - listObject.Orientation.x += ANGLE(5.0f / GetSpinSpeed()); + listObject.Orientation.x += ANGLE(5.0f / g_Renderer.GetFramerateMultiplier()); if (invObject.RotFlags & INV_ROT_Y) - listObject.Orientation.y += ANGLE(5.0f / GetSpinSpeed()); + listObject.Orientation.y += ANGLE(5.0f / g_Renderer.GetFramerateMultiplier()); if (invObject.RotFlags & INV_ROT_Z) - listObject.Orientation.z += ANGLE(5.0f / GetSpinSpeed()); + listObject.Orientation.z += ANGLE(5.0f / g_Renderer.GetFramerateMultiplier()); } else { @@ -3112,17 +3107,17 @@ namespace TEN::Gui if (ring.NumObjectsInList != 1 && (ringType != RingTypes::Ammo || CombineRingFadeVal == 128)) { if (ring.ObjectListMovement > 0) - ring.ObjectListMovement += ANGLE(45.0f / GetSpinSpeed()); + ring.ObjectListMovement += ANGLE(45.0f / g_Renderer.GetFramerateMultiplier()); if (ring.ObjectListMovement < 0) - ring.ObjectListMovement -= ANGLE(45.0f / GetSpinSpeed()); + ring.ObjectListMovement -= ANGLE(45.0f / g_Renderer.GetFramerateMultiplier()); if (IsHeld(In::Left)) { if (!ring.ObjectListMovement) { SoundEffect(SFX_TR4_MENU_ROTATE, nullptr, SoundEnvironment::Always); - ring.ObjectListMovement += ANGLE(45.0f / GetSpinSpeed()); + ring.ObjectListMovement += ANGLE(45.0f / g_Renderer.GetFramerateMultiplier()); if (AmmoSelectorFlag) AmmoSelectorFadeDir = 2; @@ -3134,7 +3129,7 @@ namespace TEN::Gui if (!ring.ObjectListMovement) { SoundEffect(SFX_TR4_MENU_ROTATE, nullptr, SoundEnvironment::Always); - ring.ObjectListMovement -= ANGLE(45.0f / GetSpinSpeed()); + ring.ObjectListMovement -= ANGLE(45.0f / g_Renderer.GetFramerateMultiplier()); if (AmmoSelectorFlag) AmmoSelectorFadeDir = 2; @@ -3175,8 +3170,6 @@ namespace TEN::Gui bool GuiController::CallPause() { - constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; - g_Renderer.DumpGameScene(); PauseAllSounds(SoundPauseMode::Pause); SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); @@ -3187,17 +3180,7 @@ namespace TEN::Gui bool doExitToTitle = false; - LARGE_INTEGER lastTime; - LARGE_INTEGER currentTime; - double controlLag = 0; - double frameTime = 0; - - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter(&lastTime); - - int controlCalls = 0; - int drawCalls = 0; + g_Synchronizer.Init(); bool legacy30FpsDoneDraw = false; @@ -3209,34 +3192,10 @@ namespace TEN::Gui return false; } - if (App.ResetClock) - { - App.ResetClock = false; - QueryPerformanceCounter(&lastTime); - currentTime = lastTime; - controlLag = 0; - frameTime = 0; - } - else - { - QueryPerformanceCounter(¤tTime); - frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; - lastTime = currentTime; - controlLag += frameTime; - } + g_Synchronizer.Sync(); - while (controlLag >= CONTROL_FRAME_TIME) + while (g_Synchronizer.Synced()) { -#if _DEBUG - constexpr auto DEBUG_SKIP_FRAMES = 10; - - if (controlLag >= (DEBUG_SKIP_FRAMES * CONTROL_FRAME_TIME)) - { - TENLog("Game loop is running too slow.", LogLevel::Warning); - App.ResetClock = true; - break; - } -#endif g_Renderer.PrepareScene(); if (g_Gui.DoPauseMenu(LaraItem) == InventoryResult::ExitToTitle) @@ -3245,8 +3204,7 @@ namespace TEN::Gui break; } - controlLag -= CONTROL_FRAME_TIME; - controlCalls++; + g_Synchronizer.Step(); legacy30FpsDoneDraw = false; } @@ -3254,14 +3212,13 @@ namespace TEN::Gui if (doExitToTitle) break; - if (!g_Configuration.EnableVariableFramerate) + if (!g_Configuration.EnableHighFramerate) { if (!legacy30FpsDoneDraw) { g_Renderer.RenderInventory(); g_Renderer.Lock(); g_Renderer.Synchronize(); - drawCalls++; legacy30FpsDoneDraw = true; } } @@ -3269,7 +3226,6 @@ namespace TEN::Gui { g_Renderer.RenderInventory(); g_Renderer.Lock(); - drawCalls++; } } @@ -3289,8 +3245,6 @@ namespace TEN::Gui bool GuiController::CallInventory(ItemInfo* item, bool resetMode) { - constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; - auto& player = GetLaraInfo(*item); bool doLoad = false; @@ -3306,17 +3260,7 @@ namespace TEN::Gui InitializeInventory(item); - LARGE_INTEGER lastTime; - LARGE_INTEGER currentTime; - double controlLag = 0; - double frameTime = 0; - - LARGE_INTEGER frequency; - QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter(&lastTime); - - int controlCalls = 0; - int drawCalls = 0; + g_Synchronizer.Init(); bool legacy30FpsDoneDraw = false; bool exitLoop = false; @@ -3329,34 +3273,10 @@ namespace TEN::Gui return false; } - if (App.ResetClock) - { - App.ResetClock = false; - QueryPerformanceCounter(&lastTime); - currentTime = lastTime; - controlLag = 0; - frameTime = 0; - } - else - { - QueryPerformanceCounter(¤tTime); - frameTime = (currentTime.QuadPart - lastTime.QuadPart) * 1000.0 / frequency.QuadPart; - lastTime = currentTime; - controlLag += frameTime; - } + g_Synchronizer.Sync(); - while (controlLag >= CONTROL_FRAME_TIME) + while (g_Synchronizer.Synced()) { -#if _DEBUG - constexpr auto DEBUG_SKIP_FRAME_COUNT = 10; - - if (controlLag >= (DEBUG_SKIP_FRAME_COUNT * CONTROL_FRAME_TIME)) - { - TENLog("Game loop is running too slow.", LogLevel::Warning); - App.ResetClock = true; - break; - } -#endif TimeInMenu++; GameTimer++; @@ -3425,20 +3345,18 @@ namespace TEN::Gui exitLoop = true; SetEnterInventory(NO_VALUE); - controlLag -= CONTROL_FRAME_TIME; - controlCalls++; + g_Synchronizer.Step(); legacy30FpsDoneDraw = false; } - if (!g_Configuration.EnableVariableFramerate) + if (!g_Configuration.EnableHighFramerate) { if (!legacy30FpsDoneDraw) { g_Renderer.RenderInventory(); g_Renderer.Lock(); g_Renderer.Synchronize(); - drawCalls++; legacy30FpsDoneDraw = true; } } @@ -3446,7 +3364,6 @@ namespace TEN::Gui { g_Renderer.RenderInventory(); g_Renderer.Lock(); - drawCalls++; } } diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h index dad67bcc0..3dda2f61c 100644 --- a/TombEngine/Game/gui.h +++ b/TombEngine/Game/gui.h @@ -128,9 +128,6 @@ namespace TEN::Gui bool CanSelect() const; bool CanDeselect() const; - // Variable FPS - float GetSpinSpeed(); - // GUI variables Menu MenuToDisplay = Menu::Title; int SelectedOption; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 0264a59e3..4a2c65f34 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -15,6 +15,7 @@ #include "Game/items.h" #include "Game/itemdata/creature_info.h" #include "Game/Lara/lara.h" +#include "Game/Lara/lara_initialise.h" #include "Game/misc.h" #include "Game/spotcam.h" #include "Game/room.h" @@ -1492,6 +1493,9 @@ void SaveGame::LoadHub(int index) // Load hub data. TENLog("Loading hub data for level #" + std::to_string(index), LogLevel::Info); Parse(Hub[index], true); + + // Restore vehicle. + InitializePlayerVehicle(*LaraItem); } bool SaveGame::IsOnHub(int index) diff --git a/TombEngine/Objects/Effects/LensFlare.cpp b/TombEngine/Objects/Effects/LensFlare.cpp index 6e0677fe0..788b64c75 100644 --- a/TombEngine/Objects/Effects/LensFlare.cpp +++ b/TombEngine/Objects/Effects/LensFlare.cpp @@ -4,6 +4,8 @@ #include "Game/camera.h" #include "Game/control/los.h" #include "Math/Math.h" +#include "Scripting/Include/ScriptInterfaceLevel.h" +#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h" #include "Specific/level.h" using namespace TEN::Math; @@ -75,10 +77,17 @@ namespace TEN::Entities::Effects LensFlares.push_back(lensFlare); } - void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID) + void UpdateGlobalLensFlare() { constexpr auto BASE_POS = Vector3(0.0f, 0.0f, BLOCK(256)); + if (!g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareEnabled()) + return; + + auto orient = EulerAngles(g_GameFlow->GetLevel(CurrentLevel)->GetLensFlarePitch(), g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareYaw(), 0); + auto color = g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareColor(); + auto spriteID = g_GameFlow->GetLevel(CurrentLevel)->GetLensFlareSunSpriteID(); + auto pos = Camera.pos.ToVector3(); auto rotMatrix = orient.ToRotationMatrix(); diff --git a/TombEngine/Objects/Effects/LensFlare.h b/TombEngine/Objects/Effects/LensFlare.h index 3440e5ad8..0f384591f 100644 --- a/TombEngine/Objects/Effects/LensFlare.h +++ b/TombEngine/Objects/Effects/LensFlare.h @@ -17,8 +17,7 @@ namespace TEN::Entities::Effects extern std::vector LensFlares; - void SetupGlobalLensFlare(const EulerAngles& orient, const Color& color, int spriteID); - void ControlLensFlare(int itemNumber); void ClearLensFlares(); + void UpdateGlobalLensFlare(); } diff --git a/TombEngine/Renderer/Renderer.cpp b/TombEngine/Renderer/Renderer.cpp index 144eb2542..862d42b9c 100644 --- a/TombEngine/Renderer/Renderer.cpp +++ b/TombEngine/Renderer/Renderer.cpp @@ -66,14 +66,14 @@ namespace TEN::Renderer int Renderer::Synchronize() { // Sync the renderer - int nf = Sync(); + int nf = TimeSync(); if (nf < 2) { int i = 2 - nf; nf = 2; do { - while (!Sync()); + while (!TimeSync()); i--; } while (i); diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index b9e6e90a6..e38ff2fad 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -381,7 +381,7 @@ namespace TEN::Renderer VertexBuffer _sortedPolygonsVertexBuffer; IndexBuffer _sortedPolygonsIndexBuffer; - // Variable framerate. + // High framerate. float _interpolationFactor = 0.0f; // Private functions @@ -594,7 +594,7 @@ namespace TEN::Renderer void RenderTitle(float interpFactor); void Lock(); bool PrepareDataForTheRenderer(); - void UpdateCameraMatrices(CAMERA_INFO* cam, float roll, float fov, float farView); + void UpdateCameraMatrices(CAMERA_INFO* cam, float farView); void RenderSimpleSceneToParaboloid(RenderTarget2D* renderTarget, Vector3 position, int emisphere); void DumpGameScene(); void RenderInventory(); @@ -646,6 +646,7 @@ namespace TEN::Renderer std::string GetDefaultAdapterName(); void SaveOldState(); + float GetFramerateMultiplier() const; float GetInterpolationFactor() const; Vector2i GetScreenResolution() const; int GetScreenRefreshRate() const; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index daaf21e78..8ed14406e 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -206,9 +206,9 @@ namespace TEN::Renderer AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableAmbientOcclusion), PRINTSTRING_COLOR_WHITE, SF(titleOption == 5)); GetNextLinePosition(&y); - // Enable variable framerate - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_VARIABLE_FRAMERATE), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 6)); - AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableVariableFramerate), PRINTSTRING_COLOR_WHITE, SF(titleOption == 6)); + // Enable high framerate + AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_HIGH_FRAMERATE), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 6)); + AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().Configuration.EnableHighFramerate), PRINTSTRING_COLOR_WHITE, SF(titleOption == 6)); GetNextBlockPosition(&y); // Apply @@ -924,7 +924,7 @@ namespace TEN::Renderer static EulerAngles orient = EulerAngles::Identity; static float scaler = 1.2f; - float multiplier = g_Configuration.EnableVariableFramerate ? g_Renderer.GetScreenRefreshRate() / 30.0f : 1.0f; + float multiplier = g_Renderer.GetFramerateMultiplier(); short invItem = g_Gui.GetRing(RingTypes::Inventory).CurrentObjectList[g_Gui.GetRing(RingTypes::Inventory).CurrentObjectInList].InventoryItem; diff --git a/TombEngine/Renderer/RendererHelper.cpp b/TombEngine/Renderer/RendererHelper.cpp index 43ecc612b..7a2544541 100644 --- a/TombEngine/Renderer/RendererHelper.cpp +++ b/TombEngine/Renderer/RendererHelper.cpp @@ -361,13 +361,13 @@ namespace TEN::Renderer return (!_isWindowed); } - void Renderer::UpdateCameraMatrices(CAMERA_INFO *cam, float roll, float fov, float farView) + void Renderer::UpdateCameraMatrices(CAMERA_INFO *cam, float farView) { if (farView < MIN_FAR_VIEW) farView = DEFAULT_FAR_VIEW; - _currentGameCamera = RenderView(cam, roll, fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); - _gameCamera = RenderView(cam, roll, fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); + _currentGameCamera = RenderView(cam, cam->Roll, cam->Fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); + _gameCamera = RenderView(cam, cam->Roll, cam->Fov, 32, farView, g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); } bool Renderer::SphereBoxIntersection(BoundingBox box, Vector3 sphereCentre, float sphereRadius) @@ -508,6 +508,11 @@ namespace TEN::Renderer return s; } + float Renderer::GetFramerateMultiplier() const + { + return g_Configuration.EnableHighFramerate ? (g_Renderer.GetScreenRefreshRate() / (float)FPS) : 1.0f; + } + float Renderer::GetInterpolationFactor() const { return _interpolationFactor; diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp index 78f714ed0..86fb7ced3 100644 --- a/TombEngine/Renderer/RendererInit.cpp +++ b/TombEngine/Renderer/RendererInit.cpp @@ -464,7 +464,7 @@ namespace TEN::Renderer DXGI_SWAP_CHAIN_DESC sd; sd.BufferDesc.Width = w; sd.BufferDesc.Height = h; - if (!g_Configuration.EnableVariableFramerate) + if (!g_Configuration.EnableHighFramerate) { _refreshRate = 30; diff --git a/TombEngine/Scripting/Internal/LanguageScript.h b/TombEngine/Scripting/Internal/LanguageScript.h index 491bd58ad..69d63698b 100644 --- a/TombEngine/Scripting/Internal/LanguageScript.h +++ b/TombEngine/Scripting/Internal/LanguageScript.h @@ -71,7 +71,7 @@ #define STRING_VOLUMETRIC_FOG "volumetric_fog" #define STRING_ANTIALIASING "antialiasing" #define STRING_AMBIENT_OCCLUSION "ambient_occlusion" -#define STRING_VARIABLE_FRAMERATE "variable_framerate" +#define STRING_HIGH_FRAMERATE "high_framerate" #define STRING_ANTIALIASING_NONE "none" #define STRING_ANTIALIASING_LOW "low" #define STRING_ANTIALIASING_MEDIUM "medium" diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index c20a9a280..509bb0c40 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -580,8 +580,10 @@ Vec3 Moveable::GetPos() const // @bool[opt] updateRoom Will room changes be automatically detected? Set to false if you are using overlapping rooms (default: true) void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) { + constexpr auto BIG_DISTANCE_THRESHOLD = BLOCK(1); + auto newPos = pos.ToVector3i(); - bool bigDistance = Vector3i::Distance(newPos, m_item->Pose.Position) > BLOCK(1); + bool bigDistance = Vector3i::Distance(newPos, m_item->Pose.Position) > BIG_DISTANCE_THRESHOLD; m_item->Pose.Position = newPos; @@ -629,8 +631,10 @@ Rotation Moveable::GetRot() const void Moveable::SetRot(const Rotation& rot) { + constexpr auto BIG_ANGLE_THRESHOLD = ANGLE(30.0f); + auto newRot = rot.ToEulerAngles(); - bool bigRotation = !EulerAngles::Compare(newRot, m_item->Pose.Orientation, ANGLE(30.0f)); + bool bigRotation = !EulerAngles::Compare(newRot, m_item->Pose.Orientation, BIG_ANGLE_THRESHOLD); m_item->Pose.Orientation = newRot; diff --git a/TombEngine/Specific/clock.cpp b/TombEngine/Specific/clock.cpp index 6f79c529c..854ecd4ec 100644 --- a/TombEngine/Specific/clock.cpp +++ b/TombEngine/Specific/clock.cpp @@ -1,12 +1,76 @@ #include "framework.h" + +#include #include "Specific/clock.h" +#include "winmain.h" + +constexpr auto CONTROL_FRAME_TIME = 1000.0f / 30.0f; +constexpr auto DEBUG_SKIP_FRAME_TIME = 10 * CONTROL_FRAME_TIME; // Globals -LARGE_INTEGER PerformanceCount = {}; -double LdFreq = 0.0; -double LdSync = 0.0; +double LdFreq = 0.0; +double LdSync = 0.0; -int Sync() +HighFramerateSynchronizer g_Synchronizer; + +void HighFramerateSynchronizer::Init() +{ + _controlDelay = 0; + _frameTime = 0; + + _lastTime.QuadPart = 0; + _currentTime.QuadPart = 0; + _frequency.QuadPart = 0; + + QueryPerformanceFrequency(&_frequency); + QueryPerformanceCounter(&_lastTime); +} + +void HighFramerateSynchronizer::Sync() +{ + if (App.ResetClock) + { + App.ResetClock = false; + QueryPerformanceCounter(&_lastTime); + _currentTime = _lastTime; + _controlDelay = 0; + _frameTime = 0; + } + else + { + QueryPerformanceCounter(&_currentTime); + _frameTime = (_currentTime.QuadPart - _lastTime.QuadPart) * 1000.0 / _frequency.QuadPart; + _lastTime = _currentTime; + _controlDelay += _frameTime; + } +} + +bool HighFramerateSynchronizer::Synced() +{ +#if _DEBUG + if (_controlDelay >= DEBUG_SKIP_FRAME_TIME) + { + TENLog("Game loop is running too slow.", LogLevel::Warning); + App.ResetClock = true; + return false; + } +#endif + + return (_controlDelay >= CONTROL_FRAME_TIME); +} + +void HighFramerateSynchronizer::Step() +{ + _controlDelay -= CONTROL_FRAME_TIME; +} + +float HighFramerateSynchronizer::GetInterpolationFactor() +{ + return std::min((float)_controlDelay / (float)CONTROL_FRAME_TIME, 1.0f); +} + + +int TimeSync() { auto ct = LARGE_INTEGER{}; QueryPerformanceCounter(&ct); @@ -65,4 +129,4 @@ bool TestGlobalTimeInterval(float intervalSecs, float offsetSecs) } return ((GlobalCounter % intervalGameFrames) == offsetGameFrames); -} +} \ No newline at end of file diff --git a/TombEngine/Specific/clock.h b/TombEngine/Specific/clock.h index 883b89085..5d59e3856 100644 --- a/TombEngine/Specific/clock.h +++ b/TombEngine/Specific/clock.h @@ -17,10 +17,29 @@ struct GameTime int Seconds = 0; }; -int Sync(); +class HighFramerateSynchronizer +{ +private: + LARGE_INTEGER _lastTime; + LARGE_INTEGER _currentTime; + LARGE_INTEGER _frequency; + double _controlDelay = 0.0; + double _frameTime = 0.0; + +public: + void Init(); + void Sync(); + void Step(); + bool Synced(); + float GetInterpolationFactor(); +}; + +int TimeSync(); bool TimeInit(); bool TimeReset(); GameTime GetGameTime(int ticks); bool TestGlobalTimeInterval(float intervalSecs, float offsetSecs = 0.0f); + +extern HighFramerateSynchronizer g_Synchronizer; \ No newline at end of file diff --git a/TombEngine/Specific/configuration.cpp b/TombEngine/Specific/configuration.cpp index 7f6450624..7cec85e39 100644 --- a/TombEngine/Specific/configuration.cpp +++ b/TombEngine/Specific/configuration.cpp @@ -188,7 +188,7 @@ bool SaveConfiguration() SetBoolRegKey(graphicsKey, REGKEY_ENABLE_CAUSTICS, g_Configuration.EnableCaustics) != ERROR_SUCCESS || SetDWORDRegKey(graphicsKey, REGKEY_ANTIALIASING_MODE, (DWORD)g_Configuration.AntialiasingMode) != ERROR_SUCCESS || SetBoolRegKey(graphicsKey, REGKEY_AMBIENT_OCCLUSION, g_Configuration.EnableAmbientOcclusion) != ERROR_SUCCESS || - SetBoolRegKey(graphicsKey, REGKEY_VARIABLE_FRAMERATE, g_Configuration.EnableVariableFramerate) != ERROR_SUCCESS) + SetBoolRegKey(graphicsKey, REGKEY_HIGH_FRAMERATE, g_Configuration.EnableHighFramerate) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -316,7 +316,7 @@ void InitDefaultConfiguration() g_Configuration.EnableCaustics = true; g_Configuration.AntialiasingMode = AntialiasingMode::Medium; g_Configuration.EnableAmbientOcclusion = true; - g_Configuration.EnableVariableFramerate = true; + g_Configuration.EnableHighFramerate = true; g_Configuration.SoundDevice = 1; g_Configuration.EnableSound = true; @@ -366,7 +366,7 @@ bool LoadConfiguration() bool enableCaustics = false; DWORD antialiasingMode = 1; bool enableAmbientOcclusion = false; - bool enableVariableFramerate = false; + bool enableHighFramerate = false; // Load Graphics keys. if (GetDWORDRegKey(graphicsKey, REGKEY_SCREEN_WIDTH, &screenWidth, 0) != ERROR_SUCCESS || @@ -378,7 +378,7 @@ bool LoadConfiguration() GetBoolRegKey(graphicsKey, REGKEY_ENABLE_CAUSTICS, &enableCaustics, true) != ERROR_SUCCESS || GetDWORDRegKey(graphicsKey, REGKEY_ANTIALIASING_MODE, &antialiasingMode, true) != ERROR_SUCCESS || GetBoolRegKey(graphicsKey, REGKEY_AMBIENT_OCCLUSION, &enableAmbientOcclusion, false) != ERROR_SUCCESS || - GetBoolRegKey(graphicsKey, REGKEY_VARIABLE_FRAMERATE, &enableVariableFramerate, false) != ERROR_SUCCESS) + GetBoolRegKey(graphicsKey, REGKEY_HIGH_FRAMERATE, &enableHighFramerate, false) != ERROR_SUCCESS) { RegCloseKey(rootKey); RegCloseKey(graphicsKey); @@ -508,7 +508,7 @@ bool LoadConfiguration() g_Configuration.AntialiasingMode = AntialiasingMode(antialiasingMode); g_Configuration.ShadowMapSize = shadowMapSize; g_Configuration.EnableAmbientOcclusion = enableAmbientOcclusion; - g_Configuration.EnableVariableFramerate = enableVariableFramerate; + g_Configuration.EnableHighFramerate = enableHighFramerate; g_Configuration.EnableSound = enableSound; g_Configuration.EnableReverb = enableReverb; diff --git a/TombEngine/Specific/configuration.h b/TombEngine/Specific/configuration.h index a7ec2fa81..51f70ca4e 100644 --- a/TombEngine/Specific/configuration.h +++ b/TombEngine/Specific/configuration.h @@ -25,7 +25,7 @@ constexpr auto REGKEY_SHADOW_BLOBS_MAX = "ShadowBlobsMax"; constexpr auto REGKEY_ENABLE_CAUSTICS = "EnableCaustics"; constexpr auto REGKEY_ANTIALIASING_MODE = "AntialiasingMode"; constexpr auto REGKEY_AMBIENT_OCCLUSION = "AmbientOcclusion"; -constexpr auto REGKEY_VARIABLE_FRAMERATE = "EnableVariableFramerate"; +constexpr auto REGKEY_HIGH_FRAMERATE = "EnableHighFramerate"; // Sound keys @@ -72,7 +72,7 @@ struct GameConfiguration int ShadowBlobsMax = DEFAULT_SHADOW_BLOBS_MAX; bool EnableCaustics = false; bool EnableAmbientOcclusion = false; - bool EnableVariableFramerate = true; + bool EnableHighFramerate = true; AntialiasingMode AntialiasingMode = AntialiasingMode::None; // Sound From 5f008f4562fb7df60d7c5e713db92904def69723 Mon Sep 17 00:00:00 2001 From: "l.m. (Leif Melles)" <75839472+goldlife2904@users.noreply.github.com> Date: Fri, 25 Oct 2024 20:37:42 +0200 Subject: [PATCH 330/410] Movable GetStatus() fix for antitrigger (#1421) * Update to bug report form * Update bug_report.yaml * get movable status fix * get movable status fix * Update CHANGELOG.md --------- Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com> --- CHANGELOG.md | 1 + TombEngine/Game/control/trigger.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff0da9c77..9e8c9a0e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Bug fixes * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. +* Fixed moveable status after antitriggering. * Fixed leveljump vehicle transfer. * Fixed weapons not properly hitting enemies. * Fixed laserhead teleporting Lara and making her invisible on death. diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 920b556bb..83a5fcaa7 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -344,12 +344,18 @@ void Antitrigger(short const value, short const flags) if (flags & ONESHOT) item->Flags |= ATONESHOT; - if (item->Active && Objects[item->ObjectNumber].intelligent) + if (item->Active) { - DisableEntityAI(value); - RemoveActiveItem(value, false); item->Active = false; - item->Status = ITEM_INVISIBLE; + item->Status = ITEM_DEACTIVATED; + + if (Objects[item->ObjectNumber].intelligent) + { + DisableEntityAI(value); + RemoveActiveItem(value, false); + + item->Status = ITEM_INVISIBLE; + } } } From ff0b1cc08522943376be3bc17bda7647bf265554 Mon Sep 17 00:00:00 2001 From: "l.m. (Leif Melles)" <75839472+goldlife2904@users.noreply.github.com> Date: Fri, 25 Oct 2024 20:38:10 +0200 Subject: [PATCH 331/410] Replaced static limiting array for Flame Emitters to unlimited std::vector (#1424) * Increase active Flame Emitters from 32 to 128 * Replaced static limiting array for Flame Emitters to unlimited std::vector * Flame Emitter Vector changes * Update vector for flame * Include vector * Remove Default Fire Count * Remove it again * Rename on field to fade --------- Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com> --- CHANGELOG.md | 1 + TombEngine/Game/effects/tomb4fx.cpp | 30 ++++++------------ TombEngine/Game/effects/tomb4fx.h | 7 ++--- TombEngine/Objects/Effects/flame_emitters.cpp | 2 +- TombEngine/Renderer/RendererDrawEffect.cpp | 31 ++++++++----------- .../Internal/TEN/Effects/EffectsFunctions.cpp | 2 +- 6 files changed, 29 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e8c9a0e5..f854e0ed8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing-dart emitter ). * Enhanced raptor behaviour and handling. https://tombengine.com/docs/ocb-and-setup-instructions/#raptor - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2 +* The limit of 32 active Flame Emitters has been removed. ### Lua API changes diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp index 2e77628d8..97ad355ae 100644 --- a/TombEngine/Game/effects/tomb4fx.cpp +++ b/TombEngine/Game/effects/tomb4fx.cpp @@ -53,7 +53,7 @@ SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; -FIRE_LIST Fires[MAX_FIRE_LIST]; +std::vector Fires; int GetFreeFireSpark() { @@ -371,31 +371,21 @@ void UpdateFireProgress() void AddFire(int x, int y, int z, short roomNum, float size, short fade) { - FIRE_LIST* fptr = &Fires[0]; - int i = 0; - while (fptr->on) - { - fptr++; - if (++i >= MAX_FIRE_LIST) - return; - } + FIRE_LIST newFire; - if (fade) - fptr->on = fade; - else - fptr->on = 1; + newFire.fade = (fade == 0 ? 1 : (unsigned char)fade); + newFire.x = x; + newFire.y = y; + newFire.z = z; + newFire.roomNumber = roomNum; + newFire.size = size; - fptr->x = x; - fptr->y = y; - fptr->z = z; - fptr->roomNumber = roomNum; - fptr->size = size; + Fires.push_back(newFire); } void ClearFires() { - for (int i = 0; i < MAX_FIRE_LIST; i++) - Fires[i].on = false; + Fires.clear(); } void UpdateFireSparks() diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h index 4281e0de5..3533a6387 100644 --- a/TombEngine/Game/effects/tomb4fx.h +++ b/TombEngine/Game/effects/tomb4fx.h @@ -119,7 +119,7 @@ struct FIRE_LIST int x; int y; int z; - byte on; + unsigned char fade; float size; short roomNumber; }; @@ -209,7 +209,6 @@ extern int NextSpider; extern int NextGunShell; constexpr auto MAX_SPARKS_FIRE = 20; -constexpr auto MAX_FIRE_LIST = 32; constexpr auto MAX_SPARKS_SMOKE = 32; constexpr auto MAX_SPARKS_BLOOD = 32; constexpr auto MAX_GUNFLASH = 4; @@ -221,7 +220,7 @@ extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL]; extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; -extern FIRE_LIST Fires[MAX_FIRE_LIST]; +extern std::vector Fires; void TriggerBlood(int x, int y, int z, int unk, int num); void TriggerExplosionBubble(int x, int y, int z, short roomNumber); @@ -236,7 +235,7 @@ void ThrowPoison(const ItemInfo& item, int boneID, const Vector3& offset, const void ThrowPoison(const ItemInfo& item, const CreatureBiteInfo& bite, const Vector3& vel, const Color& colorStart, const Color& colorEnd, int spriteID = 0); void UpdateFireProgress(); void ClearFires(); -void AddFire(int x, int y, int z, short roomNum, float size, short fade); +void AddFire(int x, int y, int z, short roomNum, float size, short fade = 1); void UpdateFireSparks(); int GetFreeSmokeSpark(); void UpdateSmoke(); diff --git a/TombEngine/Objects/Effects/flame_emitters.cpp b/TombEngine/Objects/Effects/flame_emitters.cpp index 725afb751..12319e2d1 100644 --- a/TombEngine/Objects/Effects/flame_emitters.cpp +++ b/TombEngine/Objects/Effects/flame_emitters.cpp @@ -182,7 +182,7 @@ namespace TEN::Entities::Effects else { // Normal flames. - AddFire(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber, 2.0f, 0); + AddFire(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber, 2.0f); TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 16 - (GetRandomControl() & 1), diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index b515bebe4..1311bb262 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -50,7 +50,6 @@ extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; -extern FIRE_LIST Fires[MAX_FIRE_LIST]; extern Particle Particles[MAX_PARTICLES]; extern SPLASH_STRUCT Splashes[MAX_SPLASHES]; extern std::array DebrisFragments; @@ -293,26 +292,22 @@ namespace TEN::Renderer void Renderer::PrepareFires(RenderView& view) { - for (int k = 0; k < MAX_FIRE_LIST; k++) + for (const auto& fire : Fires) { - auto* fire = &Fires[k]; - if (fire->on) - { - auto fade = fire->on == 1 ? 1.0f : (float)(255 - fire->on) / 255.0f; + auto fade = (fire.fade == 1 ? 1.0f : (float)(255 - fire.fade) / 255.0f); - for (int i = 0; i < MAX_SPARKS_FIRE; i++) + for (int i = 0; i < MAX_SPARKS_FIRE; i++) + { + auto* spark = &FireSparks[i]; + if (spark->on) { - auto* spark = &FireSparks[i]; - if (spark->on) - { - AddSpriteBillboard( - &_sprites[spark->def], - Vector3(fire->x + spark->x * fire->size / 2, fire->y + spark->y * fire->size / 2, fire->z + spark->z * fire->size / 2), - Vector4(spark->r / 255.0f * fade, spark->g / 255.0f * fade, spark->b / 255.0f * fade, 1.0f), - TO_RAD(spark->rotAng << 4), - spark->scalar, - Vector2(spark->size * fire->size, spark->size * fire->size), BlendMode::Additive, true, view); - } + AddSpriteBillboard( + &_sprites[spark->def], + Vector3(fire.x + spark->x * fire.size / 2, fire.y + spark->y * fire.size / 2, fire.z + spark->z * fire.size / 2), + Vector4(spark->r / 255.0f * fade, spark->g / 255.0f * fade, spark->b / 255.0f * fade, 1.0f), + TO_RAD(spark->rotAng << 4), + spark->scalar, + Vector2(spark->size * fire.size, spark->size * fire.size), BlendMode::Additive, true, view); } } } diff --git a/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp b/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp index e76903b6b..9514e38e8 100644 --- a/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp +++ b/TombEngine/Scripting/Internal/TEN/Effects/EffectsFunctions.cpp @@ -284,7 +284,7 @@ namespace TEN::Scripting::Effects */ static void EmitFire(Vec3 pos, TypeOrNil size) { - AddFire(pos.x, pos.y, pos.z, FindRoomNumber(Vector3i(pos.x, pos.y, pos.z)), USE_IF_HAVE(float, size, 1), 0); + AddFire(pos.x, pos.y, pos.z, FindRoomNumber(Vector3i(pos.x, pos.y, pos.z)), USE_IF_HAVE(float, size, 1)); } /***Make an explosion. Does not hurt Lara From 0c15fdbe61f9b13cfe959ee53a469c5ac40b4638 Mon Sep 17 00:00:00 2001 From: porzell Date: Fri, 25 Oct 2024 15:19:47 -0400 Subject: [PATCH 332/410] Allow more access to Moveable joint info in Lua (#1386) * Allow more access to Moveable joint info in Lua - Added Lua support to correspond with optional 'offset' parameter in GetJointPosition() for moveables - Added Lua support for GetJointRotation() for moveables * Update CHANGELOG.md * Update MoveableObject.cpp - Fixed typos and clarified doc comments * Update MoveableObject.cpp --------- Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com> --- CHANGELOG.md | 4 ++-- .../Scripting/Internal/ReservedScriptNames.h | 1 + .../TEN/Objects/Moveable/MoveableObject.cpp | 23 +++++++++++++++---- .../TEN/Objects/Moveable/MoveableObject.h | 3 ++- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f854e0ed8..bdfcbfb68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,12 +66,12 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * The limit of 32 active Flame Emitters has been removed. ### Lua API changes - * Added Flow.EnableHomeLevel() function. * Added Flow.IsStringPresent() function. -* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Flow.LensFlare() and Flow.Starfield() classes. +* Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() function. +* Added Moveable.GetJointRotation() and optional 'offset' parameter for Moveable.GetJointPosition(). * Added Room:GetRoomNumber() function. * Removed anims.monkeyAutoJump. It is now a player menu configuration. * Fixed Volume:GetActive() method. diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 4ad0effd9..26f762c52 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -120,6 +120,7 @@ static constexpr char ScriptReserved_SetFlags[] = "SetFlags"; static constexpr char ScriptReserved_SetTranslated[] = "SetTranslated"; static constexpr char ScriptReserved_GetPosition[] = "GetPosition"; static constexpr char ScriptReserved_GetJointPosition[] = "GetJointPosition"; +static constexpr char ScriptReserved_GetJointRotation[] = "GetJointRotation"; static constexpr char ScriptReserved_SetPosition[] = "SetPosition"; static constexpr char ScriptReserved_GetRotation[] = "GetRotation"; static constexpr char ScriptReserved_SetRotation[] = "SetRotation"; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index b54b8bf96..ef99036db 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -179,14 +179,14 @@ void Moveable::Register(sol::state& state, sol::table& parent) /// Set effect to moveable // @function Moveable:SetEffect // @tparam Effects.EffectID effect Type of effect to assign. -// @tparam float timeout time (in seconds) after which effect turns off (optional). +// @tparam[opt] float timeout time (in seconds) after which effect turns off. ScriptReserved_SetEffect, &Moveable::SetEffect, /// Set custom colored burn effect to moveable // @function Moveable:SetCustomEffect // @tparam Color Color1 color the primary color of the effect (also used for lighting). // @tparam Color Color2 color the secondary color of the effect. -// @tparam float timeout time (in seconds) after which effect turns off (optional). +// @tparam[opt] float timeout time (in seconds) after which effect turns off. ScriptReserved_SetCustomEffect, &Moveable::SetCustomEffect, /// Get current moveable effect @@ -365,9 +365,16 @@ ScriptReserved_GetSlotHP, & Moveable::GetSlotHP, /// Get the object's joint position // @function Moveable:GetJointPosition // @tparam int index of a joint to get position -// @treturn Vec3 a copy of the moveable's position +// @tparam[opt] Vec3 offset a pre-rotation offset to the joint +// @treturn Vec3 a copy of the moveable's joint position ScriptReserved_GetJointPosition, & Moveable::GetJointPos, +/// Get the object's joint rotation +// @function Moveable:GetJointRotation +// @tparam int index of a joint to get rotation +// @treturn Rotation a calculated copy of the moveable's joint rotation + ScriptReserved_GetJointRotation, & Moveable::GetJointRot, + ScriptReserved_SetPosition, & Moveable::SetPos, /// Get the moveable's rotation @@ -606,12 +613,18 @@ void Moveable::SetPos(const Vec3& pos, sol::optional updateRoom) UpdateBridgeItem(*m_item); } -Vec3 Moveable::GetJointPos(int jointIndex) const +Vec3 Moveable::GetJointPos(int jointIndex, sol::optional offset) const { - auto result = GetJointPosition(m_item, jointIndex); + Vector3i vec = offset.has_value() ? offset->ToVector3i() : Vector3i(0, 0, 0); + auto result = GetJointPosition(m_item, jointIndex, vec); return Vec3(result.x, result.y, result.z); } +Rotation Moveable::GetJointRot(int jointIndex) const +{ + return GetBoneOrientation(*m_item, jointIndex); +} + // This does not guarantee that the returned value will be identical // to a value written in via SetRot - only that the angle measures // will be mathematically equal diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h index 63854ee27..d3c0867fd 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h @@ -48,9 +48,10 @@ public: void Destroy(); [[nodiscard]] Vec3 GetPos() const; - [[nodiscard]] Vec3 GetJointPos(int index) const; + [[nodiscard]] Vec3 GetJointPos(int index, sol::optional offset) const; void SetPos(const Vec3& pos, sol::optional updateRoom); + [[nodiscard]] Rotation GetJointRot(int index) const; [[nodiscard]] Rotation GetRot() const; void SetRot(const Rotation& rot); From 60f3c3d8c5bd1fe40337ff2c52be55b4bd905fab Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 20:43:03 +0200 Subject: [PATCH 333/410] Fix shaky track camera --- TombEngine/Game/control/control.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 204324201..cdf2535f9 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -185,11 +185,12 @@ GameStatus ControlPhase(int numFrames) ApplyActionQueue(); ClearActionQueue(); - UpdateCamera(); UpdateAllItems(); UpdateAllEffects(); UpdateLara(LaraItem, isTitle); + UpdateCamera(); + g_GameScriptEntities->TestCollidingObjects(); // Smash shatters and clear stopper flags under them. From 267fecb063e6f9b6437eaafb044d3f978ea0ae4b Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Sat, 26 Oct 2024 20:50:37 +0200 Subject: [PATCH 334/410] Changed/Fixed enemy jeep behaviour (#1395) * Enemy Jeep WIP * Update EnemyJeep.cpp * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * Fix CreatureBiteInfo requiring vector3 instead * Re-enable collision with enemy jeep. - But still avoid him getting killed with vehicle colliding him ! * Fix formatting * Formatting * Update to bug report form * Update bug_report.yaml * Revert rename * Fix errors and typos * Update effects.cpp * Remove redundant FindAiTargetObject variation, rename struct * Fix typo * Remove jeep hack from DoObjectCollision and replace it with other solution --------- Co-authored-by: Sezz Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yaml | 21 +- TombEngine/Game/Setup.cpp | 9 +- TombEngine/Game/Setup.h | 19 +- TombEngine/Game/collision/collide_item.cpp | 5 +- TombEngine/Game/control/box.cpp | 154 ++-- TombEngine/Game/control/box.h | 17 +- TombEngine/Game/control/lot.cpp | 7 + TombEngine/Game/effects/effects.cpp | 2 +- TombEngine/Objects/TR3/Entity/FishSwarm.cpp | 2 +- TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_baddy.cpp | 2 +- .../Objects/TR4/Entity/tr4_enemy_jeep.cpp | 686 ++++++++++-------- .../Objects/TR4/Entity/tr4_enemy_jeep.h | 3 +- TombEngine/Objects/TR4/tr4_objects.cpp | 8 +- 14 files changed, 528 insertions(+), 409 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 9b3f25f37..3f31d49cc 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -1,5 +1,5 @@ name: Bug report -description: Create a report to help us improve +description: Create a report to help us understand and diagnose your issue. Your contribution is welcomed and valued! title: "[ bug Report ]" labels: Awaiting Triage @@ -16,10 +16,8 @@ body: description: | Please select the TombEngine Version from the dropdown list. options: + - v1.5 (development build) - v1.4 - - v1.3 - - v1.2 - - v1.1 validations: required: true @@ -29,10 +27,9 @@ body: description: | Please select the Tomb Editor version used from the dropdown list. options: + - v1.7.2 (development version) - v1.7.1 - v1.7.0 - - v1.6.9 - - v1.6.8 validations: required: true @@ -68,18 +65,6 @@ body: validations: required: true -- type: textarea - attributes: - label: Screenshots - description: | - Please check this box if you have provided screenshots or any other media for this issue - **note** If you do not provide screenshots or anything else, it may be hard for devs to investigate - provide a link to your screenshot here or simply drag and drop your screenshot into this textbox - placeholder: | - A description of any additional content here. - validations: - required: true - - type: textarea attributes: label: Additional Content diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp index 3f09147c6..0f5b82874 100644 --- a/TombEngine/Game/Setup.cpp +++ b/TombEngine/Game/Setup.cpp @@ -79,7 +79,14 @@ ObjectInfo& ObjectHandler::GetFirstAvailableObject() // NOTE: JointRotationFlags allows bones to be rotated with CreatureJoint(). void ObjectInfo::SetBoneRotationFlags(int boneID, int flags) { - g_Level.Bones[boneIndex + (boneID * 4)] |= flags; + int index = boneIndex + (boneID * 4); + if (index < 0 || index >= g_Level.Bones.size()) + { + TENLog("Failed to set rotation flag for bone ID " + std::to_string(boneID), LogLevel::Warning); + return; + } + + g_Level.Bones[index] |= flags; } void ObjectInfo::SetHitEffect(HitEffect hitEffect) diff --git a/TombEngine/Game/Setup.h b/TombEngine/Game/Setup.h index 7873eb168..824426e10 100644 --- a/TombEngine/Game/Setup.h +++ b/TombEngine/Game/Setup.h @@ -16,16 +16,16 @@ constexpr auto MAX_STATICS = 1000; enum JointRotationFlags { - ROT_X = (1 << 2), - ROT_Y = (1 << 3), - ROT_Z = (1 << 4) + ROT_X = 1 << 2, + ROT_Y = 1 << 3, + ROT_Z = 1 << 4 }; // Unused. enum ShatterFlags { - NoCollision = (1 << 0), - Shatterable = (1 << 1) + NoCollision = 1 << 0, + Shatterable = 1 << 1 }; // Custom LOT definition for Creature. Used in InitializeSlot() in lot.cpp. @@ -39,10 +39,11 @@ enum class LotType HumanPlusJump, HumanPlusJumpAndMonkey, Flyer, - Blockable, // For large creatures such as trex and shiva. - Spider, // Only 2 block vault allowed. - Ape, // Only 2 block vault allowed. - SnowmobileGun // Only 1 block vault allowed and 4 block drop max. + Blockable, // For large creatures such as trex and shiva. + Spider, // Only 2 block vault allowed. + Ape, // Only 2 block vault allowed. + SnowmobileGun, // Only 1 block vault allowed and 4 block drop max. + EnemyJeep }; enum class HitEffect diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index b4e9035a2..8b8693009 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -1863,9 +1863,10 @@ void DoObjectCollision(ItemInfo* item, CollisionInfo* coll) if (linkItem.HitPoints <= 0 || linkItem.HitPoints == NOT_TARGETABLE) continue; - if (isHarmless || abs(item->Animation.Velocity.z) < VEHICLE_COLLISION_TERMINAL_VELOCITY) + if (isHarmless || abs(item->Animation.Velocity.z) < VEHICLE_COLLISION_TERMINAL_VELOCITY || + object.damageType == DamageMode::None) { - // If vehicle is harmless or speed is too low, just push enemy. + // If vehicle is harmless, enemy is non-damageable, or speed is too low, push enemy. ItemPushItem(&linkItem, item, coll, false, 0); continue; } diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp index 058e9631e..998794061 100644 --- a/TombEngine/Game/control/box.cpp +++ b/TombEngine/Game/control/box.cpp @@ -1297,11 +1297,15 @@ void GetAITarget(CreatureInfo* creature) { auto* enemy = creature->Enemy; - short enemyObjectNumber; + int enemyObjectID = 0; if (enemy) - enemyObjectNumber = enemy->ObjectNumber; + { + enemyObjectID = enemy->ObjectNumber; + } else - enemyObjectNumber = NO_VALUE; + { + enemyObjectID = NO_VALUE; + } auto* item = &g_Level.Items[creature->ItemNumber]; @@ -1329,12 +1333,12 @@ void GetAITarget(CreatureInfo* creature) } else if (!creature->Patrol) { - if (enemyObjectNumber != ID_AI_PATROL1) - FindAITargetObject(creature, ID_AI_PATROL1); + if (enemyObjectID != ID_AI_PATROL1) + FindAITargetObject(*item, ID_AI_PATROL1); } - else if (enemyObjectNumber != ID_AI_PATROL2) + else if (enemyObjectID != ID_AI_PATROL2) { - FindAITargetObject(creature, ID_AI_PATROL2); + FindAITargetObject(*item, ID_AI_PATROL2); } else if (abs(enemy->Pose.Position.x - item->Pose.Position.x) < REACHED_GOAL_RADIUS && abs(enemy->Pose.Position.y - item->Pose.Position.y) < REACHED_GOAL_RADIUS && @@ -1350,8 +1354,8 @@ void GetAITarget(CreatureInfo* creature) // First if was removed probably after TR3 and was it used by monkeys? /*if (!(item->aiBits & MODIFY) && !creature->hurtByLara) creature->enemy = LaraItem; - else*/ if (enemyObjectNumber != ID_AI_AMBUSH) - FindAITargetObject(creature, ID_AI_AMBUSH); + else*/ if (enemyObjectID != ID_AI_AMBUSH) + FindAITargetObject(*item, ID_AI_AMBUSH); /*else if (item->objectNumber == ID_MONKEY) return;*/ else if (abs(enemy->Pose.Position.x - item->Pose.Position.x) < REACHED_GOAL_RADIUS && @@ -1362,6 +1366,7 @@ void GetAITarget(CreatureInfo* creature) creature->ReachedGoal = true; creature->Enemy = LaraItem; item->AIBits &= ~(AMBUSH /* | MODIFY*/); + if (item->AIBits != MODIFY) { item->AIBits |= GUARD; @@ -1381,9 +1386,9 @@ void GetAITarget(CreatureInfo* creature) { item->AIBits &= ~FOLLOW; } - else if (enemyObjectNumber != ID_AI_FOLLOW) + else if (enemyObjectID != ID_AI_FOLLOW) { - FindAITargetObject(creature, ID_AI_FOLLOW); + FindAITargetObject(*item, ID_AI_FOLLOW); } else if (abs(enemy->Pose.Position.x - item->Pose.Position.x) < REACHED_GOAL_RADIUS && abs(enemy->Pose.Position.y - item->Pose.Position.y) < REACHED_GOAL_RADIUS && @@ -1393,17 +1398,18 @@ void GetAITarget(CreatureInfo* creature) item->AIBits &= ~FOLLOW; } } - /*else if (item->objectNumber == ID_MONKEY && item->carriedItem == NO_VALUE) + + /*else if (item->ObjectNumber == ID_MONKEY && item->CarriedItem == NO_VALUE) { - if (item->aiBits != MODIFY) + if (item->AIBits != MODIFY) { - if (enemyObjectNumber != ID_SMALLMEDI_ITEM) - FindAITargetObject(creature, ID_SMALLMEDI_ITEM); + if (enemyObjectID != ID_SMALLMEDI_ITEM) + FindAITargetObject(*item, ID_SMALLMEDI_ITEM); } else { - if (enemyObjectNumber != ID_KEY_ITEM4) - FindAITargetObject(creature, ID_KEY_ITEM4); + if (enemyObjectID != ID_KEY_ITEM4) + FindAITargetObject(*item, ID_KEY_ITEM4); } }*/ } @@ -1432,69 +1438,101 @@ void FindAITarget(CreatureInfo* creature, short objectNumber) } } -void FindAITargetObject(CreatureInfo* creature, int objectNumber) +void FindAITargetObject(ItemInfo& item, GAME_OBJECT_ID objectID, std::optional ocb, std::optional checkSameZone) { - const auto& item = g_Level.Items[creature->ItemNumber]; + auto& creature = *GetCreatureInfo(&item); - FindAITargetObject(creature, objectNumber, item.ItemFlags[3], true); + auto data = AITargetData{}; + data.CheckDistance = false; + data.CheckOcb = ocb.has_value(); + data.ObjectID = objectID; + data.Ocb = ocb.value_or(item.ItemFlags[3]); + data.CheckSameZone = checkSameZone.value_or(true); + + if (FindAITargetObject(item, data)) + { + *creature.AITarget = data.FoundItem; + creature.Enemy = creature.AITarget; + } } -void FindAITargetObject(CreatureInfo* creature, int objectNumber, int ocb, bool checkSameZone) +bool FindAITargetObject(ItemInfo& item, AITargetData& data) { - auto& item = g_Level.Items[creature->ItemNumber]; - if (g_Level.AIObjects.empty()) - return; + return false; - AI_OBJECT* foundObject = nullptr; + auto& creature = *GetCreatureInfo(&item); - for (auto& aiObject : g_Level.AIObjects) + const AI_OBJECT* foundAIObject = nullptr; + + for (const auto& aiObject : g_Level.AIObjects) { - if (aiObject.objectNumber == objectNumber && - aiObject.triggerFlags == ocb && - aiObject.roomNumber != NO_VALUE) + // Check if object IDs match. + if (aiObject.objectNumber != data.ObjectID) + continue; + + // Check if room is valid. + if (aiObject.roomNumber == NO_VALUE) + continue; + + // Check if distance is valid. + if (data.CheckDistance) { - int* zone = g_Level.Zones[(int)creature->LOT.Zone][(int)FlipStatus].data(); + if (Vector3i::Distance(item.Pose.Position, aiObject.pos.Position) > data.DistanceMax) + continue; + } + + // Check if OCBs match (useful for pathfinding). + if (data.CheckOcb) + { + if (aiObject.triggerFlags != data.Ocb) + continue; + } + + // Check if zone IDs match. + if (data.CheckSameZone) + { + int* zone = g_Level.Zones[(int)creature.LOT.Zone][(int)FlipStatus].data(); auto* room = &g_Level.Rooms[item.RoomNumber]; - item.BoxNumber = GetSector(room, item.Pose.Position.x - room->Position.x, item.Pose.Position.z - room->Position.z)->PathfindingBoxID; + // NOTE: Avoid changing box ID of item or AI item so a local variable isn't required when searching for AI object near it. + int boxID = GetSector(room, item.Pose.Position.x - room->Position.x, item.Pose.Position.z - room->Position.z)->PathfindingBoxID; room = &g_Level.Rooms[aiObject.roomNumber]; - aiObject.boxNumber = GetSector(room, aiObject.pos.Position.x - room->Position.x, aiObject.pos.Position.z - room->Position.z)->PathfindingBoxID; + int aiBoxID = GetSector(room, aiObject.pos.Position.x - room->Position.x, aiObject.pos.Position.z - room->Position.z)->PathfindingBoxID; - if (item.BoxNumber == NO_VALUE || aiObject.boxNumber == NO_VALUE) - return; + // Box is invalid or zones don't match; continue. + if (boxID == NO_VALUE || aiBoxID == NO_VALUE) + continue; - if (checkSameZone && (zone[item.BoxNumber] != zone[aiObject.boxNumber])) - return; - - // Don't check for same zone. Needed for Sophia Leigh. - foundObject = &aiObject; + // Zone is invalid; continue. + if (zone[boxID] != zone[aiBoxID]) + continue; } + + // HACK: Don't check for matching zone. Needed for Sophia Leigh. + foundAIObject = &aiObject; } - if (foundObject == nullptr) - return; + if (foundAIObject == nullptr) + return false; - auto& aiItem = *creature->AITarget; + auto aiItem = ItemInfo{}; + aiItem.ObjectNumber = foundAIObject->objectNumber; + aiItem.RoomNumber = foundAIObject->roomNumber; + aiItem.Pose.Position = foundAIObject->pos.Position; + aiItem.Pose.Orientation.y = foundAIObject->pos.Orientation.y; + aiItem.Flags = foundAIObject->flags; + aiItem.TriggerFlags = foundAIObject->triggerFlags; + aiItem.BoxNumber = foundAIObject->boxNumber; - creature->Enemy = &aiItem; - - aiItem.ObjectNumber = foundObject->objectNumber; - aiItem.RoomNumber = foundObject->roomNumber; - aiItem.Pose.Position = foundObject->pos.Position; - aiItem.Pose.Orientation.y = foundObject->pos.Orientation.y; - aiItem.Flags = foundObject->flags; - aiItem.TriggerFlags = foundObject->triggerFlags; - aiItem.BoxNumber = foundObject->boxNumber; - - if (!(creature->AITarget->Flags & ItemFlags::IFLAG_TRIGGERED)) + if (!(aiItem.Flags & IFLAG_TRIGGERED)) { - float sinY = phd_sin(creature->AITarget->Pose.Orientation.y); - float cosY = phd_cos(creature->AITarget->Pose.Orientation.y); - - creature->AITarget->Pose.Position.x += CLICK(1) * sinY; - creature->AITarget->Pose.Position.z += CLICK(1) * cosY; + aiItem.Pose.Position.x += CLICK(1) * phd_sin(aiItem.Pose.Orientation.y); + aiItem.Pose.Position.z += CLICK(1) * phd_cos(aiItem.Pose.Orientation.y); } + + data.FoundItem = aiItem; + return true; } int TargetReachable(ItemInfo* item, ItemInfo* enemy) diff --git a/TombEngine/Game/control/box.h b/TombEngine/Game/control/box.h index 25396411b..1152ec78b 100644 --- a/TombEngine/Game/control/box.h +++ b/TombEngine/Game/control/box.h @@ -83,10 +83,23 @@ constexpr auto CLIP_ALL = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM); constexpr auto CLIP_SECONDARY = 0x10; +struct AITargetData +{ + ItemInfo FoundItem = {}; + GAME_OBJECT_ID ObjectID = GAME_OBJECT_ID::ID_NO_OBJECT; + float DistanceMax = 0.0f; + int Ocb = NO_VALUE; + + bool CheckDistance = false; + bool CheckSameZone = true; + bool CheckOcb = false; +}; + void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent); -void FindAITargetObject(CreatureInfo* creature, int objectNumber); -void FindAITargetObject(CreatureInfo* creature, int objectNumber, int ocb, bool checkSameZone = true); +void FindAITargetObject(ItemInfo& item, GAME_OBJECT_ID objectID, std::optional ocb = std::nullopt, std::optional checkSameZone = std::nullopt); +bool FindAITargetObject(ItemInfo& item, AITargetData& data); + void GetAITarget(CreatureInfo* creature); int CreatureVault(short itemNumber, short angle, int vault, int shift); bool MoveCreature3DPos(Pose* fromPose, Pose* toPose, int velocity, short angleDif, int angleAdd); diff --git a/TombEngine/Game/control/lot.cpp b/TombEngine/Game/control/lot.cpp index 5983a9b57..b1168618d 100644 --- a/TombEngine/Game/control/lot.cpp +++ b/TombEngine/Game/control/lot.cpp @@ -197,6 +197,13 @@ void InitializeSlot(short itemNumber, bool makeTarget) creature->LOT.Drop = -BLOCK(1); creature->LOT.Zone = ZoneType::Human; break; + + case LotType::EnemyJeep: + creature->LOT.Step = BLOCK(4); + creature->LOT.Drop = -BLOCK(4); + creature->LOT.CanJump = true; + creature->LOT.Zone = ZoneType::Human; + break; } ClearLOT(&creature->LOT); diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index b303fadb7..991823f68 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -1246,7 +1246,7 @@ void KillAllCurrentItems(short itemNumber) // TODO: Reimplement this functionality. } -// TODO: Rname to SpawnDynamicLight(). +// TODO: Rename to SpawnDynamicLight(). void TriggerDynamicLight(const Vector3& pos, const Color& color, float falloff) { g_Renderer.AddDynamicLight( diff --git a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp index bcab64a3b..520a5c009 100644 --- a/TombEngine/Objects/TR3/Entity/FishSwarm.cpp +++ b/TombEngine/Objects/TR3/Entity/FishSwarm.cpp @@ -184,7 +184,7 @@ namespace TEN::Entities::Creatures::TR3 // Follow path. if (item.AIBits && !item.ItemFlags[4]) { - FindAITargetObject(&creature, ID_AI_FOLLOW, item.ItemFlags[3] + item.ItemFlags[2], false); + FindAITargetObject(item, ID_AI_FOLLOW, item.ItemFlags[3] + item.ItemFlags[2], false); if (creature.AITarget->TriggerFlags == (item.ItemFlags[3] + item.ItemFlags[2]) && creature.AITarget->ObjectNumber == ID_AI_FOLLOW) diff --git a/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp b/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp index ea752dae8..d4ae15027 100644 --- a/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp +++ b/TombEngine/Objects/TR3/Entity/SophiaLeigh.cpp @@ -289,7 +289,7 @@ namespace TEN::Entities::Creatures::TR3 // Check the previous and next position of AI object to // allow Sophia to go up or down based on enemy's vertical position. - FindAITargetObject(creature, ID_AI_X1, creature->LocationAI, false); + FindAITargetObject(item, ID_AI_X1, creature->LocationAI, false); if (Vector3i::Distance(item.Pose.Position, creature->Enemy->Pose.Position) < SOPHIALEIGH_REACHED_GOAL_RANGE) { diff --git a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp index c806981f5..80c1036ef 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_baddy.cpp @@ -345,7 +345,7 @@ namespace TEN::Entities::TR4 if (item->TriggerFlags % 1000 > 100) { item->ItemFlags[0] = -80; - FindAITargetObject(creature, ID_AI_X1); + FindAITargetObject(*item, ID_AI_X1); } item->TriggerFlags = 1000 * (item->TriggerFlags / 1000); diff --git a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp index 98791d0f5..3930f6872 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.cpp @@ -8,375 +8,441 @@ #include "Game/control/lot.h" #include "Game/control/trigger.h" #include "Game/effects/effects.h" +#include "Game/effects/smoke.h" #include "Game/effects/tomb4fx.h" #include "Game/itemdata/creature_info.h" #include "Game/items.h" #include "Game/Lara/lara.h" +#include "Game/Lara/lara_one_gun.h" #include "Game/misc.h" +#include "Game/people.h" #include "Game/Setup.h" #include "Math/Math.h" +#include "Renderer/Renderer.h" #include "Sound/sound.h" #include "Specific/level.h" using namespace TEN::Collision::Point; +using namespace TEN::Effects::Smoke; using namespace TEN::Math; +using namespace TEN::Renderer; + +/// item.ItemFlags[1] = AI_X2 behaviour +/// item.ItemFlags[2] = Wheel rotation +/// item.ItemFlags[3] = Grenade cooldown +/// item.ItemFlags[4] = Behaviour when idle +/// item.ItemFlags[5] = Wait radius namespace TEN::Entities::TR4 { - void EnemyJeepLaunchGrenade(ItemInfo* item) + enum EnemyJeepAnim { - short grenadeItemNumber = CreateItem(); + ENEMY_JEEP_ANIM_MOVE_START = 0, + ENEMY_JEEP_ANIM_MOVE_STOP = 1, + ENEMY_JEEP_ANIM_MOVE = 2, + ENEMY_JEEP_ANIM_TURN_LEFT_START = 3, + ENEMY_JEEP_ANIM_TURN_LEFT = 4, + ENEMY_JEEP_ANIM_TURN_LEFT_END = 5, + ENEMY_JEEP_ANIM_FALL_END = 6, + ENEMY_JEEP_ANIM_FALL_2_STEPS = 7, + ENEMY_JEEP_ANIM_JUMP_2_STEP_PIT = 8, + ENEMY_JEEP_ANIM_IDLE = 9, + ENEMY_JEEP_ANIM_TURN_RIGHT_START = 10, + ENEMY_JEEP_ANIM_TURN_RIGHT = 11, + ENEMY_JEEP_ANIM_TURN_RIGHT_END = 12 + }; - if (grenadeItemNumber != NO_VALUE) + enum EnemyJeepState + { + ENEMY_JEEP_STATE_IDLE = 0, + ENEMY_JEEP_STATE_MOVE = 1, + ENEMY_JEEP_STATE_STOP = 2, + ENEMY_JEEP_STATE_TURN_LEFT = 3, + ENEMY_JEEP_STATE_TURN_RIGHT = 4, + ENEMY_JEEP_STATE_DROP_LAND = 5, + + // States to allow customization. + + ENEMY_JEEP_STATE_DROP = 6, + ENEMY_JEEP_STATE_JUMP_PIT = 7, + ENEMY_JEEP_STATE_CUSTOM_DROP = 8, + ENEMY_JEEP_STATE_CUSTOM_JUMP_PIT = 9 + }; + + enum EnemyJeepOcb + { + EJ_NO_PLAYER_VEHICLE_REQUIRED = 1 // Starts immediately instead of waiting for player to enter vehicle. + }; + + enum EnemyJeepX2Ocb + { + X2_DROP_GRENADE = 1, + X2_DROP = 2, + X2_JUMP_PIT = 3, + // Need ocb 4 + block distance + // Example: 4 + 1024 = 4 block distance + wait behaviour. + X2_WAIT_UNTIL_PLAYER_NEAR = 4, + X2_DISAPPEAR = 5, + X2_ACTIVATE_HEAVY_TRIGGER = 6, + X2_CUSTOM_DROP = 7, // Another drop step for customization. + X2_CUSTOM_JUMP_PIT = 8, // Another jump steps for customization. + }; + + constexpr auto ENEMY_JEEP_GRENADE_VELOCITY = 32.0f; + constexpr auto ENEMY_JEEP_GRENADE_TIMER = 150; + + constexpr auto ENEMY_JEEP_RIGHT_LIGHT_MESHBITS = 15; + constexpr auto ENEMY_JEEP_LEFT_LIGHT_MESHBITS = 17; + constexpr auto ENEMY_JEEP_GRENADE_COOLDOWN_TIME = 15; + constexpr auto ENEMY_JEEP_PLAYER_IS_NEAR = BLOCK(6.0f); + constexpr auto ENEMY_JEEP_NEAR_X1_NODE_DISTANCE = BLOCK(1); + constexpr auto ENEMY_JEEP_NEAR_X2_NODE_DISTANCE = BLOCK(0.3f); + constexpr auto ENEMY_JEEP_PITCH_MAX = 120.0f; + constexpr auto ENEMY_JEEP_PITCH_WHEEL_SPEED_MULTIPLIER = 12.0f; + + constexpr auto ENEMY_JEEP_WHEEL_LEFTRIGHT_TURN_MINIMUM = ANGLE(12.0f); + + constexpr auto ENEMY_JEEP_CENTER_MESH = 11; + + const auto EnemyJeepGrenadeBite = CreatureBiteInfo(Vector3(0.0f, -640.0f, -768.0f), ENEMY_JEEP_CENTER_MESH); + const auto EnemyJeepRightLightBite = CreatureBiteInfo(Vector3(200.0f, -144.0f, -768.0f), ENEMY_JEEP_CENTER_MESH); + const auto EnemyJeepLeftLightBite = CreatureBiteInfo(Vector3(-200.0f, -144.0f, -768.0f), ENEMY_JEEP_CENTER_MESH); + + static void DrawEnemyJeepLightMesh(ItemInfo& item, bool isBraking) + { + if (isBraking) { - auto* grenadeItem = &g_Level.Items[grenadeItemNumber]; + item.MeshBits.Set(ENEMY_JEEP_RIGHT_LIGHT_MESHBITS); + item.MeshBits.Set(ENEMY_JEEP_LEFT_LIGHT_MESHBITS); + } + else + { + item.MeshBits.Clear(ENEMY_JEEP_RIGHT_LIGHT_MESHBITS); + item.MeshBits.Clear(ENEMY_JEEP_LEFT_LIGHT_MESHBITS); + } + } - grenadeItem->Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f); - grenadeItem->ObjectNumber = ID_GRENADE; - grenadeItem->RoomNumber = item->RoomNumber; + static void SpawnEnemyJeepBrakeLights(const ItemInfo& item) + { + constexpr auto COLOR = Color(0.25f, 0.0f, 0.0f); + constexpr auto FALLOFF = 0.04f; - InitializeItem(grenadeItemNumber); + auto leftPos = GetJointPosition(item, EnemyJeepLeftLightBite).ToVector3(); + TriggerDynamicLight(leftPos, COLOR, FALLOFF); - grenadeItem->Pose.Orientation.x = item->Pose.Orientation.x; - grenadeItem->Pose.Orientation.y = item->Pose.Orientation.y - ANGLE(180.0f); - grenadeItem->Pose.Orientation.z = 0; + auto rightPos = GetJointPosition(item, EnemyJeepRightLightBite).ToVector3(); + TriggerDynamicLight(rightPos, COLOR, FALLOFF); + } - grenadeItem->Pose.Position.x = item->Pose.Position.x + BLOCK(1) * phd_sin(grenadeItem->Pose.Orientation.y); - grenadeItem->Pose.Position.y = item->Pose.Position.y - CLICK(3); - grenadeItem->Pose.Position.z = item->Pose.Position.x + BLOCK(1) * phd_cos(grenadeItem->Pose.Orientation.y); + static void SpawnEnemyJeepGrenade(ItemInfo& item) + { + int grenadeItemNumber = CreateItem(); + if (grenadeItemNumber == NO_VALUE || item.ItemFlags[3] > 0) + return; - for (int i = 0; i < 5; i++) - TriggerGunSmoke(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 0, 0, 0, 1, LaraWeaponType::GrenadeLauncher, 32); + auto& grenadeItem = g_Level.Items[grenadeItemNumber]; - if (Random::TestProbability(0.75f)) - grenadeItem->ItemFlags[0] = 1; - else - grenadeItem->ItemFlags[0] = 2; + grenadeItem.ObjectNumber = ID_GRENADE; + grenadeItem.RoomNumber = item.RoomNumber; + grenadeItem.Model.Color = Color(0.5f, 0.5f, 0.5f, 1.0f); - grenadeItem->Animation.ActiveState = grenadeItem->Pose.Orientation.x; - grenadeItem->Animation.TargetState = grenadeItem->Pose.Orientation.y; - grenadeItem->Animation.RequiredState = NO_VALUE; - grenadeItem->Animation.Velocity.z = 32; - grenadeItem->Animation.Velocity.y = -32 * phd_sin(grenadeItem->Pose.Orientation.x); - grenadeItem->HitPoints = 120; + auto grenadePos = GetJointPosition(item, EnemyJeepGrenadeBite); + auto grenadeposF = Vector3(grenadePos.x, grenadePos.y, grenadePos.z); - AddActiveItem(grenadeItemNumber); + grenadeItem.Pose.Orientation = EulerAngles(item.Pose.Orientation.x, item.Pose.Orientation.y + ANGLE(180.0f), 0); + grenadeItem.Pose.Position = grenadePos + Vector3i(BLOCK(0.1f) * phd_sin(grenadeItem.Pose.Orientation.y), 0, BLOCK(0.1f) * phd_cos(grenadeItem.Pose.Orientation.y)); + + InitializeItem(grenadeItemNumber); + + for (int i = 0; i < 9; i++) + SpawnGunSmokeParticles(grenadeposF, Vector3(0, 0, 1), item.RoomNumber, 1, LaraWeaponType::RocketLauncher, 32); + + if (GetRandomControl() & 3) + { + grenadeItem.ItemFlags[0] = (int)ProjectileType::Grenade; + } + else + { + grenadeItem.ItemFlags[0] = (int)ProjectileType::FragGrenade; + } + + grenadeItem.Animation.Velocity.z = ENEMY_JEEP_GRENADE_VELOCITY; + grenadeItem.Animation.Velocity.y = CLICK(1) * phd_sin(grenadeItem.Pose.Orientation.x); + grenadeItem.Animation.ActiveState = grenadeItem.Pose.Orientation.x; + grenadeItem.Animation.TargetState = grenadeItem.Pose.Orientation.y; + grenadeItem.Animation.RequiredState = NO_VALUE; + grenadeItem.HitPoints = ENEMY_JEEP_GRENADE_TIMER; + + item.ItemFlags[3] = ENEMY_JEEP_GRENADE_COOLDOWN_TIME; + + AddActiveItem(grenadeItemNumber); + SoundEffect(SFX_TR4_GRENADEGUN_FIRE, &item.Pose); +; } + + static void RotateTowardTarget(ItemInfo& item, const short angle, short turnRate) + { + if (abs(angle) < turnRate) + { + item.Pose.Orientation.y += angle; + } + else if (angle < 0) + { + item.Pose.Orientation.y -= turnRate; + } + else + { + item.Pose.Orientation.y += turnRate; + } + } + + // Check for X1 and X2 AI object and do a path based on X1 ocb, check behaviour with X2 like throw grenade or stop and wait for X sec... + static void DoNodePath(ItemInfo& item) + { + auto& creature = *GetCreatureInfo(&item); + + // Use it to setup the path + FindAITargetObject(item, ID_AI_X1, creature.LocationAI, false); + if (Vector3i::Distance(item.Pose.Position, creature.Enemy->Pose.Position) <= ENEMY_JEEP_NEAR_X1_NODE_DISTANCE) + creature.LocationAI++; + + // Use it to get behaviour if you arrive on X2 ai without modifing the creature.Enemy. + auto data = AITargetData{}; + data.CheckDistance = true; + data.CheckOcb = false; + data.ObjectID = ID_AI_X2; + data.Ocb = NO_VALUE; + data.CheckSameZone = false; + data.DistanceMax = ENEMY_JEEP_NEAR_X2_NODE_DISTANCE; + + if (FindAITargetObject(item, data)) + { + DrawDebugSphere(data.FoundItem.Pose.Position.ToVector3(), 128.0f, Color(1, 1, 0), RendererDebugPage::WireframeMode, true); + item.ItemFlags[1] = data.FoundItem.TriggerFlags; + } + } + + // Process the AI_X2 ocb and do any required query, like drop grenade or jump pit. + static void ProcessBehaviour(ItemInfo& item) + { + switch (item.ItemFlags[1]) + { + // Drop grenade. + case X2_DROP_GRENADE: + SpawnEnemyJeepGrenade(item); + break; + + // Drop 2 step or more. + case X2_DROP: + item.Animation.TargetState = ENEMY_JEEP_STATE_DROP; + break; + + // Jump 2 step pit. + case X2_JUMP_PIT: + item.Animation.TargetState = ENEMY_JEEP_STATE_JUMP_PIT; + break; + + // Make the entity disappear/kill itself. + case X2_DISAPPEAR: + item.Status = ITEM_INVISIBLE; + item.Flags |= IFLAG_INVISIBLE; + RemoveActiveItem(item.Index); + DisableEntityAI(item.Index); + break; + + // Make the entity start heavy trigger below it. + case X2_ACTIVATE_HEAVY_TRIGGER: + TestTriggers(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber, true, 0); + break; + + case X2_CUSTOM_DROP: + item.Animation.TargetState = ENEMY_JEEP_STATE_CUSTOM_DROP; + break; + + case X2_CUSTOM_JUMP_PIT: + item.Animation.TargetState = ENEMY_JEEP_STATE_CUSTOM_JUMP_PIT; + break; + + default: + bool waitBehaviour = (item.ItemFlags[1] & X2_WAIT_UNTIL_PLAYER_NEAR) != 0; + if (waitBehaviour) + { + item.Animation.TargetState = ENEMY_JEEP_STATE_STOP; + item.ItemFlags[4] = 1; + item.ItemFlags[5] = item.ItemFlags[1] - X2_WAIT_UNTIL_PLAYER_NEAR; + } + + break; + } + + item.ItemFlags[1] = 0; // Reset X2 flags to avoid behaviour loop. + } + + static bool IsJeepIdle(int activeState) + { + return (activeState == ENEMY_JEEP_STATE_IDLE || + activeState == ENEMY_JEEP_STATE_STOP); + } + + static bool IsJeepMoving(int activeState) + { + return (activeState == ENEMY_JEEP_STATE_MOVE || + activeState == ENEMY_JEEP_STATE_TURN_LEFT || + activeState == ENEMY_JEEP_STATE_TURN_RIGHT); + } + + static bool IsJeepJumpingOrDropping(int activeState, bool onlyJump = false) + { + if (onlyJump) + { + return (activeState == ENEMY_JEEP_STATE_JUMP_PIT || + activeState == ENEMY_JEEP_STATE_CUSTOM_JUMP_PIT); + } + else + { + return (activeState == ENEMY_JEEP_STATE_JUMP_PIT || + activeState == ENEMY_JEEP_STATE_DROP || + activeState == ENEMY_JEEP_STATE_CUSTOM_DROP || + activeState == ENEMY_JEEP_STATE_CUSTOM_JUMP_PIT); } } void InitializeEnemyJeep(short itemNumber) { - auto* item = &g_Level.Items[itemNumber]; + auto& item = g_Level.Items[itemNumber]; + item.ItemFlags[2] = 0; + item.ItemFlags[3] = 0; + item.ItemFlags[4] = NO_VALUE; + item.ItemFlags[5] = NO_VALUE; - item->ItemFlags[0] = -80; - - if (g_Level.NumItems > 0) - { - for (int i = 0; i < g_Level.NumItems; i++) - { - auto* other = &g_Level.Items[i]; - - if (other == item || other->TriggerFlags != item->TriggerFlags) - continue; - - item->ItemFlags[1] = i; - other->ItemFlags[0] = -80; - other->Pose.Position.y = item->Pose.Position.y - BLOCK(1); - } - } + InitializeCreature(itemNumber); + SetAnimation(item, ENEMY_JEEP_ANIM_IDLE); + DrawEnemyJeepLightMesh(item, true); } - void EnemyJeepControl(short itemNumber) + void ControlEnemyJeep(short itemNumber) { - if (CreatureActive(itemNumber)) + if (!CreatureActive(itemNumber)) + return; + + auto& item = g_Level.Items[itemNumber]; + auto& creature = *GetCreatureInfo(&item); + auto& object = Objects[item.ObjectNumber]; + + AI_INFO ai = {}; + + if (item.ItemFlags[3] > 0) + item.ItemFlags[3]--; + item.ItemFlags[3] = std::clamp(item.ItemFlags[3], 0, ENEMY_JEEP_GRENADE_COOLDOWN_TIME); + + if (item.HitPoints <= 0) { - auto* item = &g_Level.Items[itemNumber]; - auto* creature = GetCreatureInfo(item); - int x = item->Pose.Position.x; - int y = item->Pose.Position.y; - int z = item->Pose.Position.z; + } + else + { + CreatureAIInfo(&item, &ai); - int dx = 682 * phd_sin(item->Pose.Orientation.y); - int dz = 682 * phd_cos(item->Pose.Orientation.y); - - int height1 = GetPointCollision(Vector3i(x - dz, y, z - dx), item->RoomNumber).GetFloorHeight(); - if (abs(item->Pose.Position.y - height1) > CLICK(3)) + // Manage light mesh and dynamic light based on state. + if (IsJeepIdle(item.Animation.ActiveState)) { - item->Pose.Position.x += dz / 64; - item->Pose.Position.z += dx / 64; - item->Pose.Orientation.y += ANGLE(2.0f); - height1 = y; - } - - int height2 = GetPointCollision(Vector3i(x + dz, y, z - dx), item->RoomNumber).GetFloorHeight(); - if (abs(item->Pose.Position.y - height2) > CLICK(3)) - { - item->Pose.Orientation.y -= ANGLE(2.0f); - item->Pose.Position.x -= dz / 64; - item->Pose.Position.z += dx / 64; - height2 = y; - } - - short zRot = phd_atan(1364, height2 - height1); - - int height3 = GetPointCollision(Vector3i(x + dx, y, z + dz), item->RoomNumber).GetFloorHeight(); - if (abs(y - height3) > CLICK(3)) - height3 = y; - - int height4 = GetPointCollision(Vector3i(x - dx, y, z - dz), item->RoomNumber).GetFloorHeight(); - if (abs(y - height4) > CLICK(3)) - height4 = y; - - short xRot = phd_atan(1364, height4 - height3); - - AI_INFO AI; - CreatureAIInfo(item, &AI); - - creature->Enemy = creature->AITarget; - - auto* target = creature->AITarget; - - dx = LaraItem->Pose.Position.x - item->Pose.Position.x; - dz = LaraItem->Pose.Position.z - item->Pose.Position.z; - short angle = phd_atan(dz, dx) - item->Pose.Orientation.y; - - int distance; - if (dx > BLOCK(31.25f) || dx < -BLOCK(31.25f) || - dz > BLOCK(31.25f) || dz < -BLOCK(31.25f)) - { - distance = INT_MAX; - } - else - distance = pow(dx, 2) + pow(dz, 2); - - auto pos = Vector3i::Zero; - switch (item->Animation.ActiveState) - { - case 0: - case 2: - item->ItemFlags[0] -= 128; - item->MeshBits = -98305; - - pos = GetJointPosition(item, 11, Vector3i(0, -144, -1024)); - TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 64, 0, 0); - - if (item->ItemFlags[0] < 0) - item->ItemFlags[0] = 0; - - if (item->Animation.RequiredState != NO_VALUE) - item->Animation.TargetState = item->Animation.RequiredState; - else if (AI.distance > pow(BLOCK(1), 2) || Lara.Location >= item->ItemFlags[3]) - item->Animation.TargetState = 1; - - break; - - case 1: - item->ItemFlags[0] += 37; - item->MeshBits = 0xFFFDBFFF; - creature->MaxTurn = item->ItemFlags[0] / 16; - - if (item->ItemFlags[0] > 8704) - item->ItemFlags[0] = 8704; - - if (AI.angle <= ANGLE(1.4f)) - { - if (AI.angle < -ANGLE(1.4f)) - item->Animation.TargetState = 3; - } - else - item->Animation.TargetState = 4; - - break; - - case 3: - case 4: - item->Animation.TargetState = 1; - item->ItemFlags[0] += 18; - - if (item->ItemFlags[0] > 8704) - item->ItemFlags[0] = 8704; - - break; - - case 5: - if (item->ItemFlags[0] < 1184) - item->ItemFlags[0] = 1184; - - break; - - default: - break; - } - - if (height3 <= (item->Floor + CLICK(2))) - { - if (height4 > (item->Floor + CLICK(2)) && item->Animation.ActiveState != 5) - { - item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex + 8; - item->Animation.FrameNumber = GetAnimData(item).frameBase; - item->Animation.ActiveState = 5; - item->Animation.TargetState = 1; - item->ItemFlags[1] = 0; - } + DrawEnemyJeepLightMesh(item, true); + SpawnEnemyJeepBrakeLights(item); } else { - creature->LOT.RequiredBox |= 8; - - if (item->ItemFlags[1] > 0) - { - item->ItemFlags[1] -= 8; - item->Pose.Position.y += item->ItemFlags[1] / 64; - - if (item->ItemFlags[1] < 0) - creature->LOT.RequiredBox &= ~8; - } - else - { - item->ItemFlags[1] = 2 * xRot; - creature->LOT.RequiredBox |= 8u; - } - - if (creature->LOT.RequiredBox & 8) - { - item->Animation.TargetState = 1; - creature->MaxTurn = 0; - } + DrawEnemyJeepLightMesh(item, false); } - if (AI.distance < pow(BLOCK(1.5f), 2) || item->ItemFlags[3] == -2) - creature->ReachedGoal = true; - - if (creature->ReachedGoal) + // This jump/drop check need to be there or else the jeep could miss a AI_X1 + // and potentially could break, anyway it's still weird + // to see it going back to valid the missed AI. + if (IsJeepMoving(item.Animation.ActiveState) || + IsJeepJumpingOrDropping(item.Animation.ActiveState)) { - TestTriggers(target, true); + DoNodePath(item); + } + + if (IsJeepMoving(item.Animation.ActiveState)) + RotateTowardTarget(item, ai.angle, ANGLE(5.0f)); - if (Lara.Location < item->ItemFlags[3] && item->Animation.ActiveState != 2 && item->Animation.TargetState != 2) + switch (item.Animation.ActiveState) + { + case ENEMY_JEEP_STATE_IDLE: + switch (item.ItemFlags[4]) { - item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex + 1; - item->Animation.FrameNumber = GetAnimData(item).frameBase; - item->Animation.TargetState = 2; - item->Animation.ActiveState = 2; + // Wait for player to enter a vehicle. + default: + case 0: + if ((item.TriggerFlags & EJ_NO_PLAYER_VEHICLE_REQUIRED) != 0 || + Lara.Context.Vehicle != NO_VALUE) + item.Animation.TargetState = ENEMY_JEEP_STATE_MOVE; + break; - if (target->Flags & 4) + // Wait until player is near. + case 1: + if (item.ItemFlags[5] != NO_VALUE && + Vector3i::Distance(LaraItem->Pose.Position, item.Pose.Position) <= item.ItemFlags[5]) { - item->Pose = target->Pose; - - if (item->RoomNumber != target->RoomNumber) - ItemNewRoom(itemNumber, target->RoomNumber); - } - } - - if (distance > pow(BLOCK(2), 2) && - distance < pow(BLOCK(10), 2) && - !item->ItemFlags[2] && - (angle < -ANGLE(112.5f) || angle > ANGLE(112.5f))) - { - EnemyJeepLaunchGrenade(item); - item->ItemFlags[2] = 150; - } - - if (target->Flags == 62) - { - item->Status = ITEM_INVISIBLE; - RemoveActiveItem(itemNumber); - DisableEntityAI(itemNumber); - } - - if (Lara.Location >= item->ItemFlags[3] || !(target->Flags & 4)) - { - creature->ReachedGoal = false; - item->ItemFlags[3]++; - - creature->Enemy = nullptr; - AI_OBJECT* aiObject = nullptr; - - for (int i = 0; i < g_Level.AIObjects.size(); i++) - { - aiObject = &g_Level.AIObjects[i]; - - if (g_Level.AIObjects[i].triggerFlags == item->ItemFlags[3] && g_Level.AIObjects[i].roomNumber != NO_VALUE) - { - aiObject = &g_Level.AIObjects[i]; - break; - } + item.Animation.TargetState = ENEMY_JEEP_STATE_MOVE; + item.ItemFlags[4] = NO_VALUE; // Remove state. + item.ItemFlags[5] = NO_VALUE; // Remove radius. } - if (aiObject != nullptr) - { - creature->Enemy = nullptr; - target->ObjectNumber = aiObject->objectNumber; - target->RoomNumber = aiObject->roomNumber; - target->Pose.Position = aiObject->pos.Position; - target->Pose.Orientation.y = aiObject->pos.Orientation.y; - target->Flags = aiObject->flags; - target->TriggerFlags = aiObject->triggerFlags; - target->BoxNumber = aiObject->boxNumber; - - if (!(aiObject->flags & 0x20)) - { - target->Pose.Position.x += CLICK(1) * phd_sin(target->Pose.Orientation.y); - target->Pose.Position.z += CLICK(1) * phd_cos(target->Pose.Orientation.y); - } - } + break; } + + break; + + case ENEMY_JEEP_STATE_MOVE: + if (ai.angle < -ENEMY_JEEP_WHEEL_LEFTRIGHT_TURN_MINIMUM) + { + item.Animation.TargetState = ENEMY_JEEP_STATE_TURN_LEFT; + } + else if (ai.angle > ENEMY_JEEP_WHEEL_LEFTRIGHT_TURN_MINIMUM) + { + item.Animation.TargetState = ENEMY_JEEP_STATE_TURN_RIGHT; + } + + break; + + case ENEMY_JEEP_STATE_TURN_LEFT: + case ENEMY_JEEP_STATE_TURN_RIGHT: + if (abs(ai.angle) <= ENEMY_JEEP_WHEEL_LEFTRIGHT_TURN_MINIMUM) + item.Animation.TargetState = ENEMY_JEEP_STATE_MOVE; + + break; } + } - item->ItemFlags[2]--; - if (item->ItemFlags[2] < 0) - item->ItemFlags[2] = 0; + ProcessBehaviour(item); + CreatureAnimation(itemNumber, 0, 0); - if (abs(xRot - item->Pose.Orientation.x) < ANGLE(1.4f)) - item->Pose.Orientation.x = xRot; - else if (xRot < item->Pose.Orientation.x) - item->Pose.Orientation.x -= ANGLE(1.4f); - else - item->Pose.Orientation.x += ANGLE(1.4f); - - if (abs(zRot - item->Pose.Orientation.z) < ANGLE(1.4f)) - item->Pose.Orientation.z = zRot; - else if (zRot < item->Pose.Orientation.z) - item->Pose.Orientation.z -= ANGLE(1.4f); - else - item->Pose.Orientation.z += ANGLE(1.4f); - - item->ItemFlags[0] += -2 - xRot / 512; - if (item->ItemFlags[0] < 0) - item->ItemFlags[0] = 0; - - dx = item->ItemFlags[0] * phd_sin(-2 - xRot / 512); - dz = item->ItemFlags[0] * phd_cos(-2 - xRot / 512); - - item->Pose.Position.x += dx / 64; - item->Pose.Position.z += dz / 64; + if (IsJeepJumpingOrDropping(item.Animation.ActiveState, true)) + { + // Required, else the entity will go back to previous position (before the jump) + creature.LOT.IsJumping = true; + } + else + { + creature.LOT.IsJumping = false; + AlignEntityToSurface(&item, Vector2(object.radius / 3, (object.radius / 3) * 1.33f), 0.8f); + } + // Didn't use Move there because we need the move sound when jump/drop and rotating left/right. + if (!IsJeepIdle(item.Animation.ActiveState)) + { + float pitch = std::clamp(0.4f + (float)abs(item.Animation.Velocity.z) / (float)ENEMY_JEEP_PITCH_MAX, 0.6f, 1.4f); for (int i = 0; i < 4; i++) - creature->JointRotation[i] -= item->ItemFlags[0]; + creature.JointRotation[i] -= ANGLE(pitch * ENEMY_JEEP_PITCH_WHEEL_SPEED_MULTIPLIER); - if (!creature->ReachedGoal) - ClampRotation(item->Pose, AI.angle, item->ItemFlags[0] / 16); + SoundEffect(SFX_TR4_VEHICLE_JEEP_MOVING, &item.Pose, SoundEnvironment::Land, pitch, 1.5f); + } + else + { + for (int i = 0; i < 4; i++) + creature.JointRotation[i] = 0; - creature->MaxTurn = 0; - AnimateItem(item); - - auto probe = GetPointCollision(*item); - item->Floor = probe.GetFloorHeight(); - if (item->RoomNumber != probe.GetRoomNumber()) - ItemNewRoom(itemNumber, probe.GetRoomNumber()); - - if (item->Pose.Position.y < item->Floor) - { - item->Animation.IsAirborne = true; - } - else - { - item->Pose.Position.y = item->Floor; - item->Animation.IsAirborne = false; - item->Animation.Velocity.y = 0; - } - - SoundEffect(SFX_TR4_VEHICLE_JEEP_MOVING, &item->Pose, SoundEnvironment::Land, 1.0f + (float)item->ItemFlags[0] / BLOCK(8)); // TODO: Check actual sound! + SoundEffect(SFX_TR4_VEHICLE_JEEP_IDLE, &item.Pose); } } } diff --git a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.h b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.h index c2a2d0706..53e7ad1ae 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.h +++ b/TombEngine/Objects/TR4/Entity/tr4_enemy_jeep.h @@ -1,8 +1,9 @@ #pragma once + #include "Game/items.h" namespace TEN::Entities::TR4 { void InitializeEnemyJeep(short itemNumber); - void EnemyJeepControl(short itemNumber); + void ControlEnemyJeep(short itemNumber); } diff --git a/TombEngine/Objects/TR4/tr4_objects.cpp b/TombEngine/Objects/TR4/tr4_objects.cpp index f17c818de..9ce44ab8d 100644 --- a/TombEngine/Objects/TR4/tr4_objects.cpp +++ b/TombEngine/Objects/TR4/tr4_objects.cpp @@ -11,7 +11,7 @@ #include "Specific/level.h" // Creatures -#include "Objects/TR4/Entity/Wraith.h" // OFF +#include "Objects/TR4/Entity/Wraith.h" #include "Objects/TR4/Entity/tr4_enemy_jeep.h" #include "Objects/TR4/Entity/tr4_ahmet.h" // OK #include "Objects/TR4/Entity/tr4_baddy.h" // OK @@ -626,7 +626,7 @@ namespace TEN::Entities if (obj->loaded) { obj->Initialize = InitializeEnemyJeep; - obj->control = EnemyJeepControl; + obj->control = ControlEnemyJeep; obj->collision = CreatureCollision; obj->shadowType = ShadowMode::All; obj->HitPoints = 40; @@ -634,8 +634,8 @@ namespace TEN::Entities obj->radius = 512; obj->intelligent = true; obj->damageType = DamageMode::None; // NOTE: Prevents enemy jeep from being killed with skidoo gun or something like that. - obj->LotType = LotType::HumanPlusJumpAndMonkey; - obj->SetBoneRotationFlags(8, ROT_X); + obj->LotType = LotType::EnemyJeep; + obj->SetBoneRotationFlags(8, ROT_X); // Wheel rotation. obj->SetBoneRotationFlags(9, ROT_X); obj->SetBoneRotationFlags(11, ROT_X); obj->SetBoneRotationFlags(12, ROT_X); From ac63d0b1785eb41a11ed0a5da397d284948a4684 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:52:12 +0300 Subject: [PATCH 335/410] Implement pickup count modification via hitpoints (#1426) * Implement pickup count modification via hitpoints * Always show picked up ammo and consumable count --- CHANGELOG.md | 18 +++++------- TombEngine/Game/Hud/PickupSummary.cpp | 16 ++++++++++ TombEngine/Game/Hud/PickupSummary.h | 1 + TombEngine/Game/pickup/pickup.cpp | 31 ++++++++++++-------- TombEngine/Game/pickup/pickup.h | 1 + TombEngine/Game/pickup/pickup_ammo.cpp | 19 ++++++++---- TombEngine/Game/pickup/pickup_ammo.h | 1 + TombEngine/Game/pickup/pickup_consumable.cpp | 15 ++++++++-- TombEngine/Game/pickup/pickup_consumable.h | 1 + TombEngine/Game/pickup/pickuputil.h | 2 +- 10 files changed, 73 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdfcbfb68..2c5bac9e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,6 @@ # Changelog -Here you will find the full changelog of TEN's releases from Version 1.0 and up - -The dates are in European standard format where date is presented as **YYYY-MM-DD** - +The dates are in European standard format where date is presented as **YYYY-MM-DD**. TombEngine releases are located in this repository (alongside with Tomb Editor): https://github.com/TombEngine/TombEditorReleases ## Version 1.5 - xxxx-xx-xx @@ -40,10 +37,11 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Features/Amendments -* Added variable framerate , that allows the engine to run at an unlocked framerate for a much smoother experience. Setting can be toggled on or off in the graphical settings menu. +* Added variable framerate. * Added a customisable global lensflare effect. https://tombengine.com/docs/level-settings/#lensflare * Added a customisable starry sky and meteor effect (based on TR5). https://tombengine.com/docs/level-settings/#stars * Added the ability to display "Lara's Home" entry in the main menu. +* Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. * Added option to enable or disable menu option looping. - Menu scrolling using held inputs will stop at the last option until a new input is made. @@ -78,7 +76,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## [Version 1.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.1) - 2024-04-21 -### Bug Fixes +### Bug fixes * Fixed drawing of display sprites in title level. * Fixed drawing of smoke sprites and various other sprites. * Fixed drawing of transparent surfaces when debris are present in scene. @@ -121,7 +119,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## [Version 1.3](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7) - 2024-01-06 -### Bug Fixes +### Bug fixes * Fixed crash if title logo is removed from Textures folder. * Fixed crash if unknown player state ID is encountered. * Fixed bug with OCB 2 on pushables, and some other pushable bugs. @@ -177,7 +175,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## [Version 1.2](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.6.9) - 2023-11-11 -### Bug Fixes +### Bug fixes * Fix burning torch not working properly if there are more than 256 objects in a level. * Fix grenade and rocket projectiles smoke offset in certain directions. * Fix projectiles flying through animating objects. @@ -254,7 +252,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## [Version 1.1.0](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.6.8) - 2023-07-29 -### Bug Fixes +### Bug fixes * Fix enemies shooting Lara through static meshes and moveables. * Fix skeletons and mummies not being affected by explosive weapons. * Fix crash on loading if static meshes with IDs above maximum are present. @@ -465,7 +463,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## [Version 1.0.6](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.6.4) - 2023-01-29 -### Bug FIxes +### Bug fixes * Fix major pathfinding bug which could have caused lots of issues with enemy behaviour. * Fix potential random crashes due to incorrect rendering behaviour. * Fix savegame crash for disabled enemies with partially set activation mask. diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index b10e8bab1..7f932fab4 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -2,6 +2,8 @@ #include "Game/Hud/PickupSummary.h" #include "Game/pickup/pickup.h" +#include "Game/pickup/pickup_ammo.h" +#include "Game/pickup/pickup_consumable.h" #include "Math/Math.h" #include "Renderer/Renderer.h" #include "Specific/clock.h" @@ -122,6 +124,20 @@ namespace TEN::Hud pickup.StringScalar = 0.0f; } + void PickupSummaryController::AddDisplayPickup(ItemInfo& item) + { + // Ammo and consumables are a special case, as internal amount differs from pickup amount. + + int ammoCount = GetDefaultAmmoCount(item.ObjectNumber); + int consumableCount = GetDefaultConsumableCount(item.ObjectNumber); + + int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT; + if (ammoCount != NO_VALUE) count = ammoCount; + if (consumableCount != NO_VALUE) count = consumableCount; + + AddDisplayPickup(item.ObjectNumber, item.Pose.Position.ToVector3(), item.HitPoints > 0 ? item.HitPoints : count); + } + void PickupSummaryController::AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector3& pos, unsigned int count) { // Project 3D position to 2D origin. diff --git a/TombEngine/Game/Hud/PickupSummary.h b/TombEngine/Game/Hud/PickupSummary.h index fc56e09f1..cc64e97ff 100644 --- a/TombEngine/Game/Hud/PickupSummary.h +++ b/TombEngine/Game/Hud/PickupSummary.h @@ -46,6 +46,7 @@ namespace TEN::Hud void AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector2& origin, unsigned int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT); void AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector3& pos, unsigned int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT); + void AddDisplayPickup(ItemInfo& item); void Update(); void Draw() const; diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index d9d2a3dc0..b1824994f 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -160,6 +160,11 @@ void PickedUpObject(GAME_OBJECT_ID objectID, std::optional count) } } +void PickedUpObject(ItemInfo& item) +{ + PickedUpObject(item.ObjectNumber, item.HitPoints > 0 ? std::optional(item.HitPoints) : std::nullopt); +} + int GetInventoryCount(GAME_OBJECT_ID objectID) { auto boolResult = HasWeapon(Lara, objectID); @@ -198,18 +203,18 @@ void RemoveObjectFromInventory(GAME_OBJECT_ID objectID, std::optional count } } -void CollectCarriedItems(ItemInfo* item) +void CollectCarriedItems(ItemInfo* item) { short pickupNumber = item->CarriedItem; while (pickupNumber != NO_VALUE) { - auto* pickupItem = &g_Level.Items[pickupNumber]; + auto& pickupItem = g_Level.Items[pickupNumber]; - PickedUpObject(pickupItem->ObjectNumber); - g_Hud.PickupSummary.AddDisplayPickup(pickupItem->ObjectNumber, pickupItem->Pose.Position.ToVector3()); + PickedUpObject(pickupItem); + g_Hud.PickupSummary.AddDisplayPickup(pickupItem); KillItem(pickupNumber); - pickupNumber = pickupItem->CarriedItem; + pickupNumber = pickupItem.CarriedItem; } item->CarriedItem = NO_VALUE; @@ -247,8 +252,8 @@ void CollectMultiplePickups(int itemNumber) continue; } - PickedUpObject(itemPtr->ObjectNumber); - g_Hud.PickupSummary.AddDisplayPickup(itemPtr->ObjectNumber, itemPtr->Pose.Position.ToVector3()); + PickedUpObject(*itemPtr); + g_Hud.PickupSummary.AddDisplayPickup(*itemPtr); if (itemPtr->TriggerFlags & (1 << 8)) { @@ -318,8 +323,8 @@ void DoPickup(ItemInfo* laraItem) return; } - PickedUpObject(pickupItem->ObjectNumber); - g_Hud.PickupSummary.AddDisplayPickup(pickupItem->ObjectNumber, pickupItem->Pose.Position.ToVector3()); + PickedUpObject(*pickupItem); + g_Hud.PickupSummary.AddDisplayPickup(*pickupItem); HideOrDisablePickup(*pickupItem); pickupItem->Pose.Orientation = prevOrient; @@ -347,8 +352,8 @@ void DoPickup(ItemInfo* laraItem) return; } - PickedUpObject(pickupItem->ObjectNumber); - g_Hud.PickupSummary.AddDisplayPickup(pickupItem->ObjectNumber, pickupItem->Pose.Position.ToVector3()); + PickedUpObject(*pickupItem); + g_Hud.PickupSummary.AddDisplayPickup(*pickupItem); if (pickupItem->TriggerFlags & (1 << 8)) { @@ -1259,8 +1264,8 @@ void SearchObjectControl(short itemNumber) if (Objects[item2->ObjectNumber].isPickup) { - PickedUpObject(item2->ObjectNumber); - g_Hud.PickupSummary.AddDisplayPickup(item2->ObjectNumber, item2->Pose.Position.ToVector3()); + PickedUpObject(*item2); + g_Hud.PickupSummary.AddDisplayPickup(*item2); KillItem(item->ItemFlags[1]); } else diff --git a/TombEngine/Game/pickup/pickup.h b/TombEngine/Game/pickup/pickup.h index 99ce4c71c..0e154da66 100644 --- a/TombEngine/Game/pickup/pickup.h +++ b/TombEngine/Game/pickup/pickup.h @@ -13,6 +13,7 @@ extern Vector3i OldPickupPos; void InitializePickup(short itemNumber); bool SetInventoryCount(GAME_OBJECT_ID objectID, int count); void PickedUpObject(GAME_OBJECT_ID objectID, std::optional count = std::nullopt); +void PickedUpObject(ItemInfo& item); void RemoveObjectFromInventory(GAME_OBJECT_ID objectID, std::optional count = std::nullopt); int GetInventoryCount(GAME_OBJECT_ID objectID); void CollectCarriedItems(ItemInfo* item); diff --git a/TombEngine/Game/pickup/pickup_ammo.cpp b/TombEngine/Game/pickup/pickup_ammo.cpp index 5df02fc06..4aa2fa097 100644 --- a/TombEngine/Game/pickup/pickup_ammo.cpp +++ b/TombEngine/Game/pickup/pickup_ammo.cpp @@ -38,7 +38,7 @@ static constexpr std::array kAmmo bool TryModifyingAmmo(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optional amount, ModificationType modType) { int arrayPos = GetArraySlot(kAmmo, objectID); - if (-1 == arrayPos) + if (arrayPos == NO_VALUE) return false; auto ammoPickup = kAmmo[arrayPos]; @@ -50,7 +50,7 @@ bool TryModifyingAmmo(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optional std::optional GetAmmoCount(LaraInfo& lara, GAME_OBJECT_ID objectID) { int arrayPos = GetArraySlot(kAmmo, objectID); - if (-1 == arrayPos) + if (arrayPos == NO_VALUE) return std::nullopt; AmmoPickupInfo info = kAmmo[arrayPos]; @@ -91,6 +91,15 @@ std::optional GetAmmoCount(LaraInfo& lara, GAME_OBJECT_ID objectID) if (!lara.Weapons[(int)info.LaraWeaponType].Ammo[(int)info.AmmoType].HasInfinite()) return lara.Weapons[(int)info.LaraWeaponType].Ammo[(int)info.AmmoType].GetCount(); - // -1 signifies infinite ammo. - return -1; + // NO_VALUE signifies infinite ammo. + return NO_VALUE; } + +int GetDefaultAmmoCount(GAME_OBJECT_ID objectID) +{ + int arrayPos = GetArraySlot(kAmmo, objectID); + if (arrayPos == NO_VALUE) + return NO_VALUE; + + return kAmmo[arrayPos].Amount; +} \ No newline at end of file diff --git a/TombEngine/Game/pickup/pickup_ammo.h b/TombEngine/Game/pickup/pickup_ammo.h index 4a05e92b2..fb5b2e4bf 100644 --- a/TombEngine/Game/pickup/pickup_ammo.h +++ b/TombEngine/Game/pickup/pickup_ammo.h @@ -8,3 +8,4 @@ bool TryAddingAmmo(LaraInfo&, GAME_OBJECT_ID objectID, std::optional amount bool TryRemovingAmmo(LaraInfo&, GAME_OBJECT_ID objectID, std::optional amount = std::nullopt); bool TryModifyingAmmo(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optional amount, ModificationType modType); std::optional GetAmmoCount(LaraInfo&, GAME_OBJECT_ID objectID); +int GetDefaultAmmoCount(GAME_OBJECT_ID objectID); \ No newline at end of file diff --git a/TombEngine/Game/pickup/pickup_consumable.cpp b/TombEngine/Game/pickup/pickup_consumable.cpp index 582652293..d681b0d45 100644 --- a/TombEngine/Game/pickup/pickup_consumable.cpp +++ b/TombEngine/Game/pickup/pickup_consumable.cpp @@ -30,7 +30,7 @@ static constexpr std::array kConsumables = bool TryModifyingConsumable(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optional amount, ModificationType modType) { int arrayPos = GetArraySlot(kConsumables, objectID); - if (-1 == arrayPos) + if (arrayPos == NO_VALUE) return false; ConsumablePickupInfo info = kConsumables[arrayPos]; @@ -42,7 +42,7 @@ bool TryModifyingConsumable(LaraInfo& lara, GAME_OBJECT_ID objectID, std::option break; default: - if (currentAmt != -1) + if (currentAmt != NO_VALUE) { int defaultModify = ModificationType::Add == modType ? info.Amount : -info.Amount; int newVal = currentAmt + (amount.has_value() ? amount.value() : defaultModify); @@ -70,10 +70,19 @@ bool TryRemovingConsumable(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optiona std::optional GetConsumableCount(LaraInfo& lara, GAME_OBJECT_ID objectID) { int arrayPos = GetArraySlot(kConsumables, objectID); - if (-1 == arrayPos) + if (arrayPos == NO_VALUE) return std::nullopt; ConsumablePickupInfo info = kConsumables[arrayPos]; return lara.Inventory.*(info.Count); } + +int GetDefaultConsumableCount(GAME_OBJECT_ID objectID) +{ + int arrayPos = GetArraySlot(kConsumables, objectID); + if (arrayPos == NO_VALUE) + return NO_VALUE; + + return kConsumables[arrayPos].Amount; +} \ No newline at end of file diff --git a/TombEngine/Game/pickup/pickup_consumable.h b/TombEngine/Game/pickup/pickup_consumable.h index fcf3acf5b..97bf83434 100644 --- a/TombEngine/Game/pickup/pickup_consumable.h +++ b/TombEngine/Game/pickup/pickup_consumable.h @@ -8,3 +8,4 @@ bool TryAddingConsumable(LaraInfo&, GAME_OBJECT_ID objectID, std::optional bool TryRemovingConsumable(LaraInfo&, GAME_OBJECT_ID objectID, std::optional amount = 0); bool TryModifyingConsumable(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optional amount, ModificationType modType); std::optional GetConsumableCount(LaraInfo&, GAME_OBJECT_ID objectID); +int GetDefaultConsumableCount(GAME_OBJECT_ID objectID); diff --git a/TombEngine/Game/pickup/pickuputil.h b/TombEngine/Game/pickup/pickuputil.h index 9f1217459..58b4063cb 100644 --- a/TombEngine/Game/pickup/pickuputil.h +++ b/TombEngine/Game/pickup/pickuputil.h @@ -19,5 +19,5 @@ template int GetArraySlot(std::array const& arr, GA return i; } - return -1; + return NO_VALUE; } From 76dd26bb576fc2d494fefdffaaee332b39154b07 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:19:52 +0200 Subject: [PATCH 336/410] Fix merge errors --- TombEngine/Game/camera.cpp | 3 +++ TombEngine/Renderer/RendererDrawEffect.cpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 38c806fb9..6f082613e 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1528,6 +1528,9 @@ void UpdateCamera() TrackCameraInit = false; CalculateCamera(LaraCollision); } + + // Update cameras matrices there, after having done all the possible camera logic. + g_Renderer.UpdateCameraMatrices(&Camera, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView())); } void UpdateMikePos(const ItemInfo& item) diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index ddfd7ebb1..3f96b7a8b 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -359,13 +359,13 @@ namespace TEN::Renderer &_sprites[spark->def], Vector3::Lerp( Vector3( - fire->oldPosition.x + spark->oldPosition.x * fire->oldSize / 2, - fire->oldPosition.y + spark->oldPosition.y * fire->oldSize / 2, - fire->oldPosition.z + spark->oldPosition.z * fire->oldSize / 2), + fire.oldPosition.x + spark->oldPosition.x * fire.oldSize / 2, + fire.oldPosition.y + spark->oldPosition.y * fire.oldSize / 2, + fire.oldPosition.z + spark->oldPosition.z * fire.oldSize / 2), Vector3( - fire->position.x + spark->position.x * fire->size / 2, - fire->position.y + spark->position.y * fire->size / 2, - fire->position.z + spark->position.z * fire->size / 2), + fire.position.x + spark->position.x * fire.size / 2, + fire.position.y + spark->position.y * fire.size / 2, + fire.position.z + spark->position.z * fire.size / 2), _interpolationFactor), Vector4::Lerp( Vector4( @@ -382,8 +382,8 @@ namespace TEN::Renderer TO_RAD(Lerp(spark->oldRotAng << 4, spark->rotAng << 4, _interpolationFactor)), Lerp(spark->oldScalar, spark->scalar, _interpolationFactor), Vector2::Lerp( - Vector2(fire->oldSize * spark->oldSize, fire->oldSize * spark->oldSize), - Vector2(fire->size * spark->size, fire->size * spark->size), + Vector2(fire.oldSize * spark->oldSize, fire.oldSize * spark->oldSize), + Vector2(fire.size * spark->size, fire.size * spark->size), _interpolationFactor), BlendMode::Additive, true, view); } From 7b7eb8f49f2cf27b40cf5491b093dfbf8d8135b9 Mon Sep 17 00:00:00 2001 From: Adngel <60930991+Adngel@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:28:29 +0200 Subject: [PATCH 337/410] Adngel smoke emitter update (#1377) * Update tr5_smoke_emitter.cpp * Created namespace and more update * Update tr5_smoke_emitter.cpp * Update tr5_smoke_emitter.cpp * New OCBs * Update tr5_smoke_emitter.cpp - Removed displacement (So no more OCB &1) to avoid conflict with other formulas - Removed deprecated OCB 111 - Changed OCB for no Damage from &2 to <0, to avoid conflict with other formulas. - Changed OCB&8 to OCB > 0 to simplify formula - Enhaced steam shot particles direction to accept Pitch rotations - Created ItemFlags[3] to contain bit flags (Fla (0) used for the No-Damage setting) - Created enum for the flags used in ItemFlags[3] * Fix: Pitch <-> Yaw formula * Formatting * Updated feedback * Sounds update * Formatting * Rename file * Constants * SFX Reorganisation (#1384) * Updated SFX for Steam Emitter. Additionally, divided the SFX List with comments for better readability and revised names for custom footstep enums. * Updated sound_effects.h. * Refined comments and names. --------- Co-authored-by: Sezz * Define various constants * Fix Vel Y when pointing downwards * Reduced damage time Interval Reduced damage time Interval to increase the damage received by the steam shot. * Squashed commit of the following: commit bc6bf2c5a4b0dfab70a75c22317367e6763ab6cd Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon Sep 30 11:44:09 2024 +0200 Fix speedboat / rubber boat on leveljumps commit 5f7ac065d140886db5415549b0d479f9292a1e7f Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon Sep 30 11:42:50 2024 +0200 Show relative anim number in stats commit ca87efa4fd14c8b4ff1f8292ee33de35034f372d Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat Sep 28 18:59:09 2024 +0200 Possibly fix minecart wrench commit 3a0e703d1d9811d2f103691195f9a0fd5630f8e5 Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat Sep 28 18:45:34 2024 +0200 Fix Lara meshswaps after kayak dismount after leveljump commit ef751cf236b98fdf4d890690f8150431c441ae08 Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat Sep 28 17:29:27 2024 +0200 Fixed #1405 commit 3dafdf44e3bc174b312b111023abefa8285dae5f Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon Sep 23 19:58:56 2024 +0200 Update kayak.cpp commit 90effcdc588aafed1a380136a8cba9ef03805c0c Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon Sep 23 01:17:15 2024 +0200 Update CHANGELOG.md commit 1b95946db9492538d8d9039bec8088afbe7fff8a Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon Sep 23 01:04:19 2024 +0200 Fix kayak and minecart meshswaps on leveljump commit f8f20a071c68ffcfabea13643c5df1dbff0b80ab Author: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon Sep 23 00:23:49 2024 +0200 Fixed leveljump vehicle transfer commit d62ae232ee3cb6a02292e5fc6887d9ff41f0931f Author: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sun Sep 22 09:48:22 2024 +0100 Change player HAIR enumerations commit 29c2363141c58ac11e3635574f9e6c03cb68e523 Author: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sun Sep 15 21:24:16 2024 +0100 Update CHANGELOG.md commit a98ed141cc498088ec1a9f1c03b0247ff77baa5b Author: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sun Sep 15 15:13:36 2024 +0100 Update CHANGELOG.md Contains listings for branches to be merged for the next release. commit feee7c8285d58cf216c320f0781f249a68dcbf15 Author: Sezz Date: Thu Sep 5 23:02:24 2024 +1000 Update InputAction class commit b318179bb9f12f2bde16b96e084fcb61328825c2 Author: Sezz Date: Sun Sep 1 22:25:40 2024 +1000 Organise Lua room class commit a9516cd7f712075d747d9127eae24eae0cad313b Author: davidmarr <116632612+davidmarr@users.noreply.github.com> Date: Sun Sep 1 13:13:20 2024 +0200 Add Room:GetRoomNumber() method (#1401) * add RoomGetRoomNumber() method * Update CHANGELOG.md * fix GetReverbType() method * Update MoveableObject.cpp Modified Moveable() function description for consistency commit cccd0d9bfb76e514368a301d064148f26e264087 Author: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sat Aug 31 15:23:01 2024 +0100 level.rumble sound effect parameters exposed to user Formally: this was hardcoded in TR5 to the klaxon from the Sinking Submarine level. I have moved this to a new sound enum in the default soundmap and removed the pitch shift as this can be set in the XML by the user. This change has also been documented on the TombEngine website. commit 60b9055d0adf90b02bc0c57ebfded36f7d70dcba Author: Sezz Date: Tue Aug 27 19:17:57 2024 +1000 Add F12 as alternative to PrtSc for screenshots commit 806c052ff560353a979af84f865f2e2ac3e922bc Author: Sezz Date: Sun Aug 18 22:58:50 2024 +1000 Fix GetBoneOrientation() commit f85769f3ca22bb89c562603db86aefd70b22a7b7 Author: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Sat Aug 17 19:10:04 2024 +0200 Update RendererCompatibility.cpp * Rename PARTICLE_COUNT_MAX to MAX_PARTICLES * Update effects.h * Revert rename * Revert rename * Fix typo --------- Co-authored-by: Sezz Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com> --- CHANGELOG.md | 3 +- TombEngine/Game/effects/effects.cpp | 40 +- TombEngine/Game/effects/footprint.cpp | 16 +- .../Generic/Object/Pushable/PushableSound.cpp | 2 +- .../Objects/TR5/Emitter/tr5_smoke_emitter.cpp | 572 +++++++++++------- .../Objects/TR5/Emitter/tr5_smoke_emitter.h | 7 +- TombEngine/Objects/TR5/tr5_objects.cpp | 9 +- TombEngine/Renderer/RendererDrawEffect.cpp | 1 - TombEngine/Sound/sound_effects.h | 44 +- TombEngine/TombEngine.vcxproj | 4 +- 10 files changed, 427 insertions(+), 271 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c5bac9e2..d35637604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ## Version 1.5 - xxxx-xx-xx ### Bug fixes + * Fixed original issue with classic switch off trigger incorrectly activating some trigger actions. * Fixed moveable status after antitriggering. * Fixed leveljump vehicle transfer. @@ -54,7 +55,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Changed Rome Hammer to not hurt player whilst deactivated. * Changed Statue with blade damage, from 20 to 200. * Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed. -* Changed hardcoded sound for RAISING_BLOCKS back to the soundID used in TRLE (ID 149) +* Changed hardcoded sound for RAISING_BLOCKS back to the soundID used in TRLE (ID 149). * Changed Water sound condition to ShallowWater. * Enhanced Rolling Spindle detection to avoid them going down through pits. * Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) diff --git a/TombEngine/Game/effects/effects.cpp b/TombEngine/Game/effects/effects.cpp index 1ad39e1c7..c64da1969 100644 --- a/TombEngine/Game/effects/effects.cpp +++ b/TombEngine/Game/effects/effects.cpp @@ -126,46 +126,42 @@ void DetatchSpark(int number, SpriteEnumFlag type) Particle* GetFreeParticle() { - int result = -1; - - // Get first free available spark + int partID = NO_VALUE; + // Get first free available particle. for (int i = 0; i < MAX_PARTICLES; i++) { - auto* particle = &Particles[i]; - - if (!particle->on) + const auto& part = Particles[i]; + if (!part.on) { - result = i; + partID = i; break; } } - // No free sparks left, hijack existing one with less possible life - - int life = INT_MAX; - if (result == -1) + // No free particles; get particle with shortest life. + float shortestLife = INFINITY; + if (partID == NO_VALUE) { for (int i = 0; i < MAX_PARTICLES; i++) { - auto* particle = &Particles[i]; + const auto& part = Particles[i]; - if (particle->life < life && particle->dynamic == -1 && !(particle->flags & SP_EXPLOSION)) + if (part.life < shortestLife && part.dynamic == NO_VALUE && !(part.flags & SP_EXPLOSION)) { - result = i; - life = particle->life; + partID = i; + shortestLife = part.life; } } } - auto* spark = &Particles[result]; + auto& part = Particles[partID]; + part.spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex; + part.blendMode = BlendMode::Additive; + part.extras = 0; + part.dynamic = NO_VALUE; - spark->extras = 0; - spark->dynamic = -1; - spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex; - spark->blendMode = BlendMode::Additive; - - return spark; + return ∂ } void SetSpriteSequence(Particle& particle, GAME_OBJECT_ID objectID) diff --git a/TombEngine/Game/effects/footprint.cpp b/TombEngine/Game/effects/footprint.cpp index c31078c47..74b7758e5 100644 --- a/TombEngine/Game/effects/footprint.cpp +++ b/TombEngine/Game/effects/footprint.cpp @@ -60,14 +60,14 @@ namespace TEN::Effects::Footprint { MaterialType::Concrete, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS }, { MaterialType::OldWood, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_WOOD }, { MaterialType::OldMetal, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL }, - { MaterialType::Custom1, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_1 }, - { MaterialType::Custom2, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_2 }, - { MaterialType::Custom3, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_3 }, - { MaterialType::Custom4, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_4 }, - { MaterialType::Custom5, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_5 }, - { MaterialType::Custom6, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_6 }, - { MaterialType::Custom7, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_7 }, - { MaterialType::Custom8, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_8 } + { MaterialType::Custom1, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_1 }, + { MaterialType::Custom2, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_2 }, + { MaterialType::Custom3, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_3 }, + { MaterialType::Custom4, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_4 }, + { MaterialType::Custom5, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_5 }, + { MaterialType::Custom6, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_6 }, + { MaterialType::Custom7, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_7 }, + { MaterialType::Custom8, SOUND_EFFECTS::SFX_TEN_CUSTOM_FOOTSTEPS_8 } }; auto it = SOUND_MAP.find(material); diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp index f5d3592fc..bd11e2fd3 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableSound.cpp @@ -39,7 +39,7 @@ namespace TEN::Entities::Generic { MaterialType::Gravel, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_GRAVEL, SFX_TEN_PUSHABLES_STOP_GRAVEL, SFX_TEN_PUSHABLES_COLLIDE_GRAVEL } }, { MaterialType::Ice, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_ICE, SFX_TEN_PUSHABLES_STOP_ICE, SFX_TEN_PUSHABLES_COLLIDE_ICE } }, { MaterialType::Water, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_WATER, SFX_TEN_PUSHABLES_STOP_WATER, SFX_TEN_PUSHABLES_COLLIDE_WATER } }, - { MaterialType::Stone, PushableSoundData{ SFX_TEN_PUSHABLES_STOP_MOVE_STONE, SFX_TEN_PUSHABLES_STOP_STONE, SFX_TEN_PUSHABLES_COLLIDE_STONE } }, + { MaterialType::Stone, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_STONE, SFX_TEN_PUSHABLES_STOP_STONE, SFX_TEN_PUSHABLES_COLLIDE_STONE } }, { MaterialType::Wood, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_WOOD, SFX_TEN_PUSHABLES_STOP_WOOD, SFX_TEN_PUSHABLES_COLLIDE_WOOD } }, { MaterialType::Metal, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_METAL, SFX_TEN_PUSHABLES_STOP_METAL, SFX_TEN_PUSHABLES_COLLIDE_METAL } }, { MaterialType::Marble, PushableSoundData{ SFX_TEN_PUSHABLES_MOVE_MARBLE, SFX_TEN_PUSHABLES_STOP_MARBLE, SFX_TEN_PUSHABLES_COLLIDE_MARBLE } }, diff --git a/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.cpp b/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.cpp index 7f5294edf..5a432a1e7 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.cpp +++ b/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.cpp @@ -1,265 +1,399 @@ #include "framework.h" -#include "tr5_smoke_emitter.h" +#include "Objects/TR5/Emitter/tr5_smoke_emitter.h" -#include "Game/camera.h" -#include "Game/items.h" -#include "Game/effects/Bubble.h" -#include "Game/effects/effects.h" +#include "Game/collision/collide_room.h" #include "Game/control/control.h" #include "Game/control/trigger.h" -#include "Game/collision/collide_room.h" -#include "Specific/level.h" +#include "Game/effects/Bubble.h" +#include "Game/effects/effects.h" +#include "Game/items.h" #include "Math/Math.h" #include "Objects/objectslist.h" #include "Renderer/RendererEnums.h" +#include "Specific/clock.h" +#include "Specific/level.h" using namespace TEN::Effects::Bubble; +using namespace TEN::Math; -void InitializeSmokeEmitter(short itemNumber) +// NOTES: +// OCB 0: Default smoke behaviour. +// OCB < 0: Disable harm from the steam by setting the NoDamage flag in ItemFlags[3]. +// OCB != 0: Enable horizontal steam effect. +// OCB >> 4: Sets number of game frames it pauses between steam releases. Calculation: x = 16 * gameFrameCount. +// +// item.ItemFlags[0]: Timer in frame time for pause between steam releases +// item.ItemFlags[1]: Timer in frame time for active steam effect. +// item.ItemFlags[2]: Acceleration of steam particles. +// item.ItemFlags[3]: Smoke emiter flags. +// +// In underwater rooms: +// OCB 0: Intermitent bubble emission. +// OCB 1: Continuous bubble emission. +// OCB +2: Spawn large bubbles. +// +// item.ItemFlags[0]: Bubble count. +// item.ItemFlags[1]: Spawn a series of bubbles with no delay (flag). +// item.ItemFlags[2]: Bubble spawn radius on horizontal plane (default is 32). + +namespace TEN::Effects::SmokeEmitter { - auto* item = &g_Level.Items[itemNumber]; + constexpr auto SMOKE_VISIBILITY_DISTANCE_MAX = BLOCK(16); + constexpr auto SMOKE_ACCEL_MAX = BLOCK(4); + constexpr auto BUBBLE_DEFAULT_RADIUS = BLOCK(1 / 32.0f); - if (item->TriggerFlags == 111) + enum SmokeEmitterFlags { - if (item->Pose.Orientation.y > 0) - { - if (item->Pose.Orientation.y == ANGLE(90.0f)) - item->Pose.Position.x += CLICK(2); - } - else if (item->Pose.Orientation.y) - { - if (item->Pose.Orientation.y == -ANGLE(180.0f)) - item->Pose.Position.z -= CLICK(2); - else if (item->Pose.Orientation.y == -ANGLE(90.0f)) - item->Pose.Position.x -= CLICK(2); - } - else - item->Pose.Position.z += CLICK(2); - } - else if (item->ObjectNumber != ID_SMOKE_EMITTER) - return; - else if (item->TriggerFlags & 8) - { - item->ItemFlags[0] = item->TriggerFlags / 16; + NoDamage = 1 << 0 + }; - if (item->Pose.Orientation.y > 0) + static void SpawnSteamParticle(const ItemInfo& item, int currentAccel) + { + constexpr auto COLOR_BLACK = Color(0.4f, 0.4f, 0.4f); + constexpr auto COLOR_WHITE_START = Color(0.4f, 0.4f, 0.4f); + constexpr auto COLOR_WHITE_END = Color(0.25f, 0.25f, 0.25f); + constexpr auto LIFE_MAX = 24; + constexpr auto LIFE_MIN = 16; + constexpr auto PART_SIZE_MAX = 160.0f; + constexpr auto PART_SIZE_MIN = 128.0f; + constexpr auto FADE_SPEED_MAX = 9; + constexpr auto FADE_SPEED_MIN = 6; + constexpr auto DAMAGE_TIME_INTERVAL = 0.02f; + + static const auto SPHERE = BoundingSphere(Vector3::Zero, 32.0f); + + auto& part = *GetFreeParticle(); + part.on = true; + + if (item.ObjectNumber == ID_SMOKE_EMITTER_BLACK) { - if (item->Pose.Orientation.y == ANGLE(90.0f)) - item->Pose.Position.x += CLICK(1); + part.sR = COLOR_BLACK.R() * UCHAR_MAX; + part.sG = COLOR_BLACK.G() * UCHAR_MAX; + part.sB = COLOR_BLACK.B() * UCHAR_MAX; + part.dR = COLOR_BLACK.R() * UCHAR_MAX; + part.dG = COLOR_BLACK.G() * UCHAR_MAX; + part.dB = COLOR_BLACK.B() * UCHAR_MAX; + } + else if (item.ObjectNumber == ID_SMOKE_EMITTER_WHITE) + { + part.sR = COLOR_WHITE_START.R() * UCHAR_MAX; + part.sG = COLOR_WHITE_START.G() * UCHAR_MAX; + part.sB = COLOR_WHITE_START.B() * UCHAR_MAX; + part.dR = COLOR_WHITE_END.R() * UCHAR_MAX; + part.dG = COLOR_WHITE_END.G() * UCHAR_MAX; + part.dB = COLOR_WHITE_END.B() * UCHAR_MAX; } else { - if (item->Pose.Orientation.y == 0) - item->Pose.Position.z += CLICK(1); - else if (item->Pose.Orientation.y == -ANGLE(180.0f)) - item->Pose.Position.z -= CLICK(1); - else if (item->Pose.Orientation.y == -ANGLE(90.0f)) - item->Pose.Position.x -= CLICK(1); + unsigned char r = std::clamp(item.Model.Color.x / 2, 0.0f, 1.0f) * UCHAR_MAX; + unsigned char g = std::clamp(item.Model.Color.y / 2, 0.0f, 1.0f) * UCHAR_MAX; + unsigned char b = std::clamp(item.Model.Color.z / 2, 0.0f, 1.0f) * UCHAR_MAX; + + part.sR = r / 3; + part.sG = g / 3; + part.sB = b / 3; + part.dR = r; + part.dG = g; + part.dB = b; + } + + part.fadeToBlack = 6; + part.colFadeSpeed = Random::GenerateInt(FADE_SPEED_MIN, FADE_SPEED_MAX); + + if (item.ObjectNumber == ID_SMOKE_EMITTER_BLACK) + { + part.blendMode = BlendMode::Subtractive; + } + else + { + part.blendMode = BlendMode::Additive; } - if ((signed short)(item->TriggerFlags / 16) <= 0) + part.life = + part.sLife = Random::GenerateInt(LIFE_MIN, LIFE_MAX); + + auto pos = item.Pose.Position.ToVector3() + Random::GeneratePointInSphere(SPHERE); + part.x = pos.x; + part.y = pos.y; + part.z = pos.z; + + int accel = currentAccel; + if (currentAccel == SMOKE_ACCEL_MAX) + accel = Random::GenerateInt(SMOKE_ACCEL_MAX / 2, SMOKE_ACCEL_MAX - 1); + + int pitchAngle = item.Pose.Orientation.x; + int yawAngle = item.Pose.Orientation.y + ANGLE(180.0f); + + auto dir = Vector3::Zero;; + dir.x = phd_cos(pitchAngle) * phd_sin(yawAngle); + dir.y = phd_sin(pitchAngle); + dir.z = phd_cos(pitchAngle) * phd_cos(yawAngle); + + dir.Normalize(); + int offset = Random::GenerateInt(-8, 8); + part.xVel = (dir.x * accel) + offset; + part.yVel = (dir.y * accel) + offset; + part.zVel = (dir.z * accel) + offset; + + part.friction = 4; + part.flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; + + bool ignoreDamage = item.ItemFlags[3] & SmokeEmitterFlags::NoDamage; + if (!ignoreDamage && TestGlobalTimeInterval(DAMAGE_TIME_INTERVAL)) + part.flags |= SP_DAMAGE; + + part.rotAng = Random::GenerateAngle(ANGLE(0.0f), ANGLE(22.5f)); + part.rotAdd = Random::GenerateAngle(ANGLE(0.04f), ANGLE(0.08f)) * (Random::TestProbability(1 / 2.0f) ? 1 : -1); + + part.scalar = 2; + part.gravity = Random::GenerateFloat(-24.0f, -15.0f); + part.maxYvel = 0; + + float size = Random::GenerateFloat(PART_SIZE_MIN, PART_SIZE_MAX); + part.dSize = size; + part.sSize = + part.size = part.dSize / 2; + } + + static void SpawnSmokeEmitterParticle(const ItemInfo& item) + { + auto& part = *GetFreeParticle(); + part.on = true; + + part.sR = 0; + part.sG = 0; + part.sB = 0; + + if (item.ObjectNumber == ID_SMOKE_EMITTER_BLACK) { - item->ItemFlags[2] = 4096; - item->TriggerFlags |= 4; + part.dR = 0.4f * UCHAR_MAX; + part.dG = 0.4f * UCHAR_MAX; + part.dB = 0.4f * UCHAR_MAX; + } + else if (item.ObjectNumber == ID_SMOKE_EMITTER_WHITE) + { + part.dR = 0.25f * UCHAR_MAX; + part.dG = 0.25f * UCHAR_MAX; + part.dB = 0.25f * UCHAR_MAX; + } + else + { + unsigned char r = std::clamp(item.Model.Color.x / 2.0f, 0.0f, 1.0f) * UCHAR_MAX; + unsigned char g = std::clamp(item.Model.Color.y / 2.0f, 0.0f, 1.0f) * UCHAR_MAX; + unsigned char b = std::clamp(item.Model.Color.z / 2.0f, 0.0f, 1.0f) * UCHAR_MAX; + + part.dR = r; + part.dG = g; + part.dB = b; + } + + part.fadeToBlack = 16; + part.colFadeSpeed = Random::GenerateInt(8, 11); + + if (item.ObjectNumber == ID_SMOKE_EMITTER_BLACK) + { + part.blendMode = BlendMode::Subtractive; + } + else + { + part.blendMode = BlendMode::Additive; + } + + part.sLife = part.life = Random::GenerateInt(28, 35); + + part.x = item.Pose.Position.x + Random::GenerateInt(-32, 32); + part.y = item.Pose.Position.y + Random::GenerateInt(-32, 32); + part.z = item.Pose.Position.z + Random::GenerateInt(-32, 32); + + part.xVel = Random::GenerateInt(-128, 128); + part.yVel = Random::GenerateInt(-16, 0); + part.zVel = Random::GenerateInt(-128, 128); + + part.friction = 3; + part.flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; + + if (TestEnvironment(RoomEnvFlags::ENV_FLAG_OUTSIDE, item.RoomNumber)) + part.flags |= SP_WIND; + + part.rotAng = Random::GenerateInt(0, 4095); + + if (Random::TestProbability(1 / 2.0f)) + { + part.rotAdd = Random::GenerateInt(-15, -7); + } + else + { + part.rotAdd = Random::GenerateInt(7, 15); + } + + part.scalar = 2; + part.gravity = Random::GenerateInt(-24, -15); + part.maxYvel = Random::GenerateInt(-15, -7); + + float size = Random::GenerateFloat(128.0f, 160.0f); + part.dSize = size; + part.sSize = + part.size = size / 4; + + if (item.ObjectNumber == ID_SMOKE_EMITTER) + { + part.gravity /= 2; + part.yVel /= 2; + part.maxYvel /= 2; + part.life += 16; + part.sLife += 16; } } - else if (g_Level.Rooms[item->RoomNumber].flags & 1 && item->TriggerFlags == 1) + + static void SpawnSmokeEmitterBubble(const ItemInfo& item, int radius, bool spawnLargeBubbles) { - item->ItemFlags[0] = 20; - item->ItemFlags[1] = 1; - } -} + auto pos = item.Pose.Position.ToVector3() + Vector3(Random::GenerateInt(-radius, radius), Random::GenerateInt(-16, 16), Random::GenerateInt(-radius, radius)); -void SmokeEmitterControl(short itemNumber) -{ - auto* item = &g_Level.Items[itemNumber]; - - if (!TriggerActive(item)) - return; - - if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item->RoomNumber)) - { - if (item->ItemFlags[0] || !(GetRandomControl() & 0x1F) || item->TriggerFlags == 1) + if (spawnLargeBubbles) { - if (!(GetRandomControl() & 3) || item->ItemFlags[1]) + SpawnBubble(pos, item.RoomNumber, (int)BubbleFlags::HighAmplitude | (int)BubbleFlags::LargeScale); + } + else + { + SpawnBubble(pos, item.RoomNumber); + } + } + + void InitializeSmokeEmitter(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + bool isUnderwater = TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber); + bool isSteamEffect = (item.TriggerFlags != 0); + + if (isUnderwater) + { + auto& bubbleCount = item.ItemFlags[0]; + auto& bubbleForceSpawnFlag = item.ItemFlags[1]; + auto& bubbleSpawnRadius = item.ItemFlags[2]; + + bool spawnContinuousBubbles = (item.TriggerFlags == 1); + if (spawnContinuousBubbles) { - auto pos = Vector3( - (GetRandomControl() & 0x3F) + item->Pose.Position.x - 32, - item->Pose.Position.y - (GetRandomControl() & 0x1F) - 16, - (GetRandomControl() & 0x3F) + item->Pose.Position.z - 32); + bubbleCount = 20; + bubbleForceSpawnFlag = 1; + } - if (item->TriggerFlags == 1) - SpawnBubble(pos, item->RoomNumber); - else - SpawnBubble(pos, item->RoomNumber); + if (bubbleSpawnRadius == 0) + bubbleSpawnRadius = BUBBLE_DEFAULT_RADIUS; + } + else if (isSteamEffect) + { + auto& ocb = item.TriggerFlags; + auto& steamPauseTimer = item.ItemFlags[0]; + auto& steamAccel = item.ItemFlags[2]; + auto& steamFlags = item.ItemFlags[3]; - if (item->ItemFlags[0]) + if (ocb < 0) + { + ocb = -ocb; + steamFlags |= SmokeEmitterFlags::NoDamage; + } + + steamPauseTimer = ocb / 16; + + if (steamPauseTimer <= 0) + steamAccel = SMOKE_ACCEL_MAX; + } + } + + void ControlSmokeEmitter(short itemNumber) + { + auto& item = g_Level.Items[itemNumber]; + + if (!TriggerActive(&item)) + return; + + // Draw underwater bubbles. + if (TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber)) + { + bool spawnContinuousBubbles = (item.TriggerFlags == 1); + bool spawnLargeBubbles = item.TriggerFlags & 2; + + auto& bubbleCount = item.ItemFlags[0]; + auto& bubbleForceSpawnFlag = item.ItemFlags[1]; + auto& bubbleSpawnRadius = item.ItemFlags[2]; + + if (bubbleCount || Random::TestProbability(1 / 30.0f) || spawnContinuousBubbles) + { + if (Random::TestProbability(1 / 3.0f) || bubbleForceSpawnFlag) { - item->ItemFlags[0]--; + SpawnSmokeEmitterBubble(item, bubbleSpawnRadius, spawnLargeBubbles); - if (!item->ItemFlags[0]) - item->ItemFlags[1] = 0; + if (bubbleCount) + { + bubbleCount--; + + if (!bubbleCount) + bubbleForceSpawnFlag = 0; + } } } - } - else if (!(GetRandomControl() & 0x1F)) - { - item->ItemFlags[0] = (GetRandomControl() & 3) + 4; + else if (Random::TestProbability(1 / 30.0f)) + { + bubbleCount = Random::GenerateInt(4, 7); + } + + return; } - return; - } - - if (item->ObjectNumber == ID_SMOKE_EMITTER && item->TriggerFlags & 8) - { - bool normal = false; - - if (item->ItemFlags[0]) + // Draw horizontal steam. + bool isSteamShotEffect = item.TriggerFlags != 0; + if (isSteamShotEffect) { - item->ItemFlags[0]--; + bool drawNormalSmoke = false; - if (!item->ItemFlags[0]) - item->ItemFlags[1] = (GetRandomControl() & 0x3F) + 30; + auto& steamPauseTimer = item.ItemFlags[0]; + auto& steamActiveTimer = item.ItemFlags[1]; + auto& steamAccel = item.ItemFlags[2]; - normal = true; + if (steamPauseTimer != 0) + { + drawNormalSmoke = true; + steamPauseTimer--; - if (item->ItemFlags[2]) - item->ItemFlags[2] -= 256; - } - else if (item->ItemFlags[2] < 4096) - item->ItemFlags[2] += 256; + if (steamPauseTimer <= 0) + { + steamActiveTimer = Random::GenerateInt(30, 94); + SoundEffect(SFX_TR4_STEAM, &item.Pose); + } + + if (steamAccel) + steamAccel -= 256; + } + else if (steamAccel < SMOKE_ACCEL_MAX) + { + steamAccel += 256; + } - if (item->ItemFlags[2]) - { - int dx = Camera.pos.x - item->Pose.Position.x; - int dz = Camera.pos.z - item->Pose.Position.z; + if (steamAccel != 0) + { + SpawnSteamParticle(item, steamAccel); - if (dx < -BLOCK(16) || dx > BLOCK(16) || dz < -BLOCK(16) || dz > BLOCK(16)) + if (steamActiveTimer) + { + steamActiveTimer--; + } + else + { + steamPauseTimer = item.TriggerFlags >> 4; + } + + SoundEffect(SFX_TEN_STEAM_EMITTER_LOOP, &item.Pose); + } + + if (!drawNormalSmoke) return; - - auto* sptr = GetFreeParticle(); - sptr->on = true; - sptr->sR = 96; - sptr->sG = 96; - sptr->sB = 96; - sptr->dR = 48; - sptr->dG = 48; - sptr->dB = 48; - sptr->fadeToBlack = 6; - sptr->colFadeSpeed = (GetRandomControl() & 3) + 6; - sptr->blendMode = BlendMode::Additive; - sptr->life = (GetRandomControl() & 7) + 16; - sptr->sLife = sptr->life; - sptr->x = (GetRandomControl() & 0x3F) + item->Pose.Position.x - 32; - sptr->y = (GetRandomControl() & 0x3F) + item->Pose.Position.y - 32; - sptr->z = (GetRandomControl() & 0x3F) + item->Pose.Position.z - 32; - int size = item->ItemFlags[2]; - - if (item->ItemFlags[2] == 4096) - size = (GetRandomControl() & 0x7FF) + 2048; - - sptr->xVel = (short)((size * phd_sin(item->Pose.Orientation.y - 32768)) / BLOCK(1)); - sptr->yVel = -16 - (GetRandomControl() & 0xF); - sptr->zVel = (short)((size * phd_cos(item->Pose.Orientation.y - 32768)) / BLOCK(1)); - sptr->friction = 4; - sptr->flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; - - if (!(GlobalCounter & 0x03)) - sptr->flags |= SP_DAMAGE; - - sptr->rotAng = GetRandomControl() & 0xFFF; - - if (GetRandomControl() & 1) - sptr->rotAdd = -8 - (GetRandomControl() & 7); - else - sptr->rotAdd = (GetRandomControl() & 7) + 8; - - sptr->scalar = 2; - sptr->gravity = -8 - (GetRandomControl() & 0xF); - sptr->maxYvel = -8 - (GetRandomControl() & 7); - size = (GetRandomControl() & 0x1F) + 128; - sptr->dSize = float(size); - sptr->sSize = sptr->size = sptr->dSize / 2.0f; - - if (item->ItemFlags[1]) - item->ItemFlags[1]--; - else - item->ItemFlags[0] = item->TriggerFlags >> 4; } - if (!normal) - return; - } - - if (!(Wibble & 0x0F) && (item->ObjectNumber != ID_SMOKE_EMITTER || !(Wibble & 0x1F))) - { - int dx = Camera.pos.x - item->Pose.Position.x; - int dz = Camera.pos.z - item->Pose.Position.z; - - if (dx < -BLOCK(16) || dx > BLOCK(16) || dz < -BLOCK(16) || dz > BLOCK(16)) - return; - - auto* sptr = GetFreeParticle(); - sptr->on = 1; - sptr->sR = 0; - sptr->sG = 0; - sptr->sB = 0; - sptr->dR = 64; - sptr->dG = 64; - sptr->dB = 64; - - if (item->ObjectNumber == ID_SMOKE_EMITTER_BLACK) - { - sptr->dR = 96; - sptr->dG = 96; - sptr->dB = 96; - } - - sptr->fadeToBlack = 16; - sptr->colFadeSpeed = (GetRandomControl() & 3) + 8; - sptr->sLife = sptr->life = (GetRandomControl() & 7) + 28; - - if (item->ObjectNumber == ID_SMOKE_EMITTER_BLACK) - sptr->blendMode = BlendMode::Subtractive; - else - sptr->blendMode = BlendMode::Additive; - - sptr->x = (GetRandomControl() & 0x3F) + item->Pose.Position.x - 32; - sptr->y = (GetRandomControl() & 0x3F) + item->Pose.Position.y - 32; - sptr->z = (GetRandomControl() & 0x3F) + item->Pose.Position.z - 32; - sptr->xVel = (GetRandomControl() & 0xFF) - 128; - sptr->yVel = -16 - (GetRandomControl() & 0xF); - sptr->zVel = (GetRandomControl() & 0xFF) - 128; - sptr->friction = 3; - sptr->flags = SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF; - - if (TestEnvironment(RoomEnvFlags::ENV_FLAG_OUTSIDE, item->RoomNumber)) - sptr->flags |= SP_WIND; - - sptr->rotAng = GetRandomControl() & 0xFFF; - - if (GetRandomControl() & 1) - sptr->rotAdd = -8 - (GetRandomControl() & 7); - else - sptr->rotAdd = (GetRandomControl() & 7) + 8; - - sptr->scalar = 2; - sptr->gravity = -8 - (GetRandomControl() & 0xF); - sptr->maxYvel = -8 - (GetRandomControl() & 7); - int size = (GetRandomControl() & 0x1F) + 128; - sptr->dSize = float(size); - sptr->sSize = sptr->size = float(size / 4); - - if (item->ObjectNumber == ID_SMOKE_EMITTER) - { - sptr->gravity /= 2; - sptr->yVel /= 2; - sptr->maxYvel /= 2; - sptr->life += 16; - sptr->sLife += 16; - sptr->dR = 32; - sptr->dG = 32; - sptr->dB = 32; - } + // Draw normal smoke. + bool drawSmoke = (!(Wibble & 0x0F) && (item.ObjectNumber != ID_SMOKE_EMITTER || !(Wibble & 0x1F))); + if (drawSmoke) + SpawnSmokeEmitterParticle(item); } } diff --git a/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.h b/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.h index fe4c57652..11e80a14c 100644 --- a/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.h +++ b/TombEngine/Objects/TR5/Emitter/tr5_smoke_emitter.h @@ -1,4 +1,7 @@ #pragma once -void InitializeSmokeEmitter(short itemNumber); -void SmokeEmitterControl(short itemNumber); +namespace TEN::Effects::SmokeEmitter +{ + void InitializeSmokeEmitter(short itemNumber); + void ControlSmokeEmitter(short itemNumber); +} diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp index 2d0fc9212..42c6add7c 100644 --- a/TombEngine/Objects/TR5/tr5_objects.cpp +++ b/TombEngine/Objects/TR5/tr5_objects.cpp @@ -37,10 +37,10 @@ #include "Objects/TR5/Entity/tr5_willowwisp.h" // OK // Emitters +#include "Objects/TR5/Emitter/tr5_smoke_emitter.h" #include "Objects/TR5/Emitter/tr5_rats_emitter.h" #include "Objects/TR5/Emitter/tr5_bats_emitter.h" #include "Objects/TR5/Emitter/tr5_spider_emitter.h" -#include "Objects/TR5/Emitter/tr5_smoke_emitter.h" // Objects #include "Objects/TR5/Light/tr5_light.h" @@ -74,6 +74,7 @@ #include "Objects/TR5/Shatter/tr5_smashobject.h" using namespace TEN::Effects::EmberEmitter; +using namespace TEN::Effects::SmokeEmitter; using namespace TEN::Entities::Creatures::TR5; using namespace TEN::Entities::Switches; using namespace TEN::Entities::Traps; @@ -733,7 +734,7 @@ static void StartObject(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeSmokeEmitter; - obj->control = SmokeEmitterControl; + obj->control = ControlSmokeEmitter; obj->drawRoutine = nullptr; obj->usingDrawAnimatingItem = false; } @@ -742,7 +743,7 @@ static void StartObject(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeSmokeEmitter; - obj->control = SmokeEmitterControl; + obj->control = ControlSmokeEmitter; obj->drawRoutine = nullptr; obj->usingDrawAnimatingItem = false; } @@ -751,7 +752,7 @@ static void StartObject(ObjectInfo *obj) if (obj->loaded) { obj->Initialize = InitializeSmokeEmitter; - obj->control = SmokeEmitterControl; + obj->control = ControlSmokeEmitter; obj->drawRoutine = nullptr; obj->usingDrawAnimatingItem = false; } diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp index 3f96b7a8b..bd031cee0 100644 --- a/TombEngine/Renderer/RendererDrawEffect.cpp +++ b/TombEngine/Renderer/RendererDrawEffect.cpp @@ -50,7 +50,6 @@ extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD]; extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE]; extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE]; extern SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE]; -extern Particle Particles[MAX_PARTICLES]; extern SPLASH_STRUCT Splashes[MAX_SPLASHES]; extern std::array DebrisFragments; diff --git a/TombEngine/Sound/sound_effects.h b/TombEngine/Sound/sound_effects.h index e4cbe98a5..37b3d2ae2 100644 --- a/TombEngine/Sound/sound_effects.h +++ b/TombEngine/Sound/sound_effects.h @@ -2,6 +2,8 @@ enum SOUND_EFFECTS { + // Default TR4 sounds + SFX_TR4_LARA_FOOTSTEPS = 0, SFX_TR4_LARA_CLIMB2 = 1, SFX_TR4_LARA_NO_ENGLISH = 2, @@ -384,6 +386,9 @@ enum SOUND_EFFECTS SFX_TR4_FLARE_IGNITE_DRY = 379, SFX_TR4_FLARE_IGNITE_UNDERWATER = 380, SFX_TR4_FLARE_BURN_UNDERWATER = 381, + + // TR1 sounds + SFX_TR1_BEAR_GROWL = 382, SFX_TR1_BEAR_FEET = 383, SFX_TR1_BEAR_ATTACK = 384, @@ -476,6 +481,9 @@ enum SOUND_EFFECTS SFX_TR1_PIERRE_DEATH = 471, SFX_TR1_PIERRE_SPEECH = 472, SFX_TR1_PIERRE_MAGNUM_FIRE = 473, + + // TR2 sounds + SFX_TR2_LARA_M16_FIRE = 474, SFX_TR2_LARA_M16_STOP = 475, SFX_TR2_HENCHMAN_BELT_JINGLE = 476, @@ -686,6 +694,9 @@ enum SOUND_EFFECTS SFX_TR2_SLAM_DOOR_CLOSE = 681, SFX_TR2_SWINGING = 682, SFX_TR2_SWINGING_TRAP = 683, + + // TR3 sounds + SFX_TR3_TONY_ATTACK = 684, SFX_TR3_TONY_LAUGH = 685, SFX_TR3_TONY_NORMAL_DEATH = 686, @@ -900,6 +911,9 @@ enum SOUND_EFFECTS SFX_TR3_VERY_SMALL_WINCH = 895, SFX_TR3_WALL_BLADES = 896, SFX_TR3_WATER_MILL = 897, + + // TR5 sounds + SFX_TR5_INSIDEMILL = 898, SFX_TR5_2GUNTEX_LASER_START = 899, SFX_TR5_2GUNTEX_STAIR_FALL = 900, @@ -1150,17 +1164,19 @@ enum SOUND_EFFECTS SFX_TR2_DRAGON_FALL = 1145, SFX_TR2_MARCO_BARTOLLI_TRANSFORM = 1146, - // Custom footsteps - SFX_CUSTOM_FOOTSTEP_1 = 1150, - SFX_CUSTOM_FOOTSTEP_2 = 1151, - SFX_CUSTOM_FOOTSTEP_3 = 1152, - SFX_CUSTOM_FOOTSTEP_4 = 1153, - SFX_CUSTOM_FOOTSTEP_5 = 1154, - SFX_CUSTOM_FOOTSTEP_6 = 1155, - SFX_CUSTOM_FOOTSTEP_7 = 1156, - SFX_CUSTOM_FOOTSTEP_8 = 1157, + // TombEngine sounds + + SFX_TEN_CUSTOM_FOOTSTEPS_1 = 1150, + SFX_TEN_CUSTOM_FOOTSTEPS_2 = 1151, + SFX_TEN_CUSTOM_FOOTSTEPS_3 = 1152, + SFX_TEN_CUSTOM_FOOTSTEPS_4 = 1153, + SFX_TEN_CUSTOM_FOOTSTEPS_5 = 1154, + SFX_TEN_CUSTOM_FOOTSTEPS_6 = 1155, + SFX_TEN_CUSTOM_FOOTSTEPS_7 = 1156, + SFX_TEN_CUSTOM_FOOTSTEPS_8 = 1157, // Custom pushable sounds + SFX_TEN_PUSHABLES_MOVE_MUD = 1158, SFX_TEN_PUSHABLES_STOP_MUD = 1159, SFX_TEN_PUSHABLES_COLLIDE_MUD = 1160, @@ -1179,7 +1195,7 @@ enum SOUND_EFFECTS SFX_TEN_PUSHABLES_MOVE_WATER = 1173, SFX_TEN_PUSHABLES_STOP_WATER = 1174, SFX_TEN_PUSHABLES_COLLIDE_WATER = 1175, - SFX_TEN_PUSHABLES_STOP_MOVE_STONE = 1176, + SFX_TEN_PUSHABLES_MOVE_STONE = 1176, SFX_TEN_PUSHABLES_STOP_STONE = 1177, SFX_TEN_PUSHABLES_COLLIDE_STONE = 1178, SFX_TEN_PUSHABLES_MOVE_WOOD = 1179, @@ -1198,5 +1214,11 @@ enum SOUND_EFFECTS SFX_TEN_PUSHABLES_STOP_CONCRETE = 1192, SFX_TEN_PUSHABLES_COLLIDE_CONCRETE = 1193, - NUM_SFX //Custom Sound Effects from 1158 onwards + // New sounds + + SFX_TEN_STEAM_EMITTER_LOOP = 1194, + + // Custom sounds from 1195 onward + + NUM_SFX }; diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index fb6da9f71..67b70dfb3 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -633,9 +633,9 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + - @@ -1136,9 +1136,9 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + - From e566319f44556c72eafcea0d08713e057af9dba2 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:49:46 +0200 Subject: [PATCH 338/410] Update CHANGELOG.md --- CHANGELOG.md | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d35637604..a07de88df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,33 +38,31 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### Features/Amendments -* Added variable framerate. +* Added high framerate mode (also known as 60 FPS mode). * Added a customisable global lensflare effect. https://tombengine.com/docs/level-settings/#lensflare * Added a customisable starry sky and meteor effect (based on TR5). https://tombengine.com/docs/level-settings/#stars * Added the ability to display "Lara's Home" entry in the main menu. * Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. -* Added option to enable or disable menu option looping. - - Menu scrolling using held inputs will stop at the last option until a new input is made. -* Added TR3 seal mutant. https://tombengine.com/docs/ocb-and-setup-instructions/#sealmutant +* Added TR3 Seal Mutant. https://tombengine.com/docs/ocb-and-setup-instructions/#sealmutant - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Seal_Mutant.wad2 -* Add new sound conditions: Quicksand and Underwater. +* Added new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. -* Added TR4 Enemy_Jeep https://tombengine.com/docs/ocb-and-setup-instructions/#enemy_jeep -* Changed Rome Hammer to not hurt player whilst deactivated. -* Changed Statue with blade damage, from 20 to 200. -* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed. -* Changed hardcoded sound for RAISING_BLOCKS back to the soundID used in TRLE (ID 149). -* Changed Water sound condition to ShallowWater. -* Enhanced Rolling Spindle detection to avoid them going down through pits. -* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 ) -* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots ( by default 32 in dart emitter, and 24 in homing-dart emitter ). -* Enhanced raptor behaviour and handling. https://tombengine.com/docs/ocb-and-setup-instructions/#raptor +* Added TR4 Enemy Jeep. https://tombengine.com/docs/ocb-and-setup-instructions/#enemy_jeep +* Changed TR5 Rome Hammer to not hurt player whilst deactivated. +* Changed Statue with blade damage from 20 to 200. +* Changed sound effect that is triggered when using the `level.rumble` feature in a level (ID 359 in the soundmap). +* Changed hardcoded sound for Raising Block 1/2 back to the ID used in TRLE (ID 149). +* Enhanced TR2 Rolling Spindle detection to avoid them going down through pits. +* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns (Puzzle Item 5 by default). +* Enhanced Dart Emitter, with a new ItemFlags[0], to contain the number of frames between shots (by default 32 in Dart Emitter, and 24 in Homing-Dart Emitter). +* Enhanced Raptor behaviour and handling. https://tombengine.com/docs/ocb-and-setup-instructions/#raptor - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Raptor.wad2 -* The limit of 32 active Flame Emitters has been removed. +* Removed original limit of 32 active Flame Emitters. ### Lua API changes + * Added Flow.EnableHomeLevel() function. * Added Flow.IsStringPresent() function. * Added Flow.LensFlare() and Flow.Starfield() classes. From e89647d1b5c9e992fe8594bad34f8678d7d3d650 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:50:23 +0200 Subject: [PATCH 339/410] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a07de88df..6203238a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,7 +51,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): - Underwater - sound plays when the camera is submerged. * Added TR4 Enemy Jeep. https://tombengine.com/docs/ocb-and-setup-instructions/#enemy_jeep * Changed TR5 Rome Hammer to not hurt player whilst deactivated. -* Changed Statue with blade damage from 20 to 200. +* Changed TR2 Statue with blade damage from 20 to 200. * Changed sound effect that is triggered when using the `level.rumble` feature in a level (ID 359 in the soundmap). * Changed hardcoded sound for Raising Block 1/2 back to the ID used in TRLE (ID 149). * Enhanced TR2 Rolling Spindle detection to avoid them going down through pits. From 2e3fdc2942b8010320b1bdf7307fe8aa6fd24e53 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 21:54:23 +0200 Subject: [PATCH 340/410] Hide menu looping option from UI --- TombEngine/Game/gui.cpp | 43 ------------------------ TombEngine/Renderer/RendererDrawMenu.cpp | 9 ++--- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 56c924a11..d1a35fa2f 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -892,7 +892,6 @@ namespace TEN::Gui ThumbstickCameraControl, MouseSensitivity, - MenuOptionLooping, Apply, Cancel, @@ -996,27 +995,6 @@ namespace TEN::Gui SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); } - break; - - case OtherSettingsOption::MenuOptionLooping: - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - - switch (CurrentSettings.Configuration.MenuOptionLoopingMode) - { - default: - case MenuOptionLoopingMode::AllMenus: - CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::Disabled; - break; - - case MenuOptionLoopingMode::SaveLoadOnly: - CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::AllMenus; - break; - - case MenuOptionLoopingMode::Disabled: - CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::SaveLoadOnly; - break; - } - break; } @@ -1068,27 +1046,6 @@ namespace TEN::Gui SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); } - break; - - case OtherSettingsOption::MenuOptionLooping: - SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always); - - switch (CurrentSettings.Configuration.MenuOptionLoopingMode) - { - default: - case MenuOptionLoopingMode::AllMenus: - CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::SaveLoadOnly; - break; - - case MenuOptionLoopingMode::SaveLoadOnly: - CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::Disabled; - break; - - case MenuOptionLoopingMode::Disabled: - CurrentSettings.Configuration.MenuOptionLoopingMode = MenuOptionLoopingMode::AllMenus; - break; - } - break; } diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 8ed14406e..7c5fbd4f2 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -281,17 +281,12 @@ namespace TEN::Renderer AddString(MenuRightSideEntry, y, std::to_string(g_Gui.GetCurrentSettings().Configuration.MouseSensitivity).c_str(), PRINTSTRING_COLOR_WHITE, SF(titleOption == 9)); GetNextLinePosition(&y); - // Menu option looping - AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_MENU_OPT_LOOP), PRINTSTRING_COLOR_ORANGE, SF(titleOption == 10)); - AddString(MenuRightSideEntry, y, Str_MenuOptionLoopingMode(g_Gui.GetCurrentSettings().Configuration.MenuOptionLoopingMode), PRINTSTRING_COLOR_WHITE, SF(titleOption == 10)); - GetNextBlockPosition(&y); - // Apply - AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_APPLY), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 11)); + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_APPLY), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 10)); GetNextLinePosition(&y); // Cancel - AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_CANCEL), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 12)); + AddString(MenuCenterEntry, y, g_GameFlow->GetString(STRING_CANCEL), PRINTSTRING_COLOR_ORANGE, SF_Center(titleOption == 11)); break; case Menu::GeneralActions: From d08f881d1efb9d801c0716a7f6be4d381a8b61eb Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 26 Oct 2024 22:25:14 +0200 Subject: [PATCH 341/410] Rearrange some control phase calls --- TombEngine/Game/camera.cpp | 9 +++++++++ TombEngine/Game/camera.h | 1 + TombEngine/Game/control/control.cpp | 19 ++++++++----------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 6f082613e..cdfab3dcf 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1515,6 +1515,15 @@ void ItemsCollideCamera() staticList.clear(); } +void PrepareCamera() +{ + if (TrackCameraInit) + { + UseSpotCam = false; + AlterFOV(LastFOV); + } +} + void UpdateCamera() { if (UseSpotCam) diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 5f41c7588..961c00ae9 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -118,6 +118,7 @@ void SetScreenFadeOut(float speed, bool force = false); void SetScreenFadeIn(float speed, bool force = false); void SetCinematicBars(float height, float speed); void ClearCinematicBars(); +void PrepareCamera(); void UpdateCamera(); void UpdateFadeScreenAndCinematicBars(); void UpdateMikePos(const ItemInfo& item); diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 517e45ecb..03cccf2fd 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -133,22 +133,19 @@ GameStatus ControlPhase() bool isTitle = (CurrentLevel == 0); g_Renderer.PrepareScene(); - RegeneratePickups(); + g_Renderer.SaveOldState(); + ClearFires(); ClearLensFlares(); ClearAllDisplaySprites(); - if (TrackCameraInit) - { - UseSpotCam = false; - AlterFOV(LastFOV); - } + SetupInterpolation(); + PrepareCamera(); + + RegeneratePickups(); g_GameStringsHandler->ProcessDisplayStrings(DELTA_TIME); - SetupInterpolation(); - g_Renderer.SaveOldState(); - // Controls are polled before OnLoop to allow input data to be overwritten by script API methods. HandleControls(isTitle); @@ -233,10 +230,10 @@ GameStatus ControlPhase() if (g_GameFlow->GetLevel(CurrentLevel)->Rumble) RumbleScreen(); - UpdateCamera(); - DoFlipEffect(FlipEffect, LaraItem); + UpdateCamera(); + PlaySoundSources(); Sound_UpdateScene(); From e3ca14f84fff822c7a753edb76ab81bf784a3c9c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 08:55:05 +0100 Subject: [PATCH 342/410] Fix problem with player falling through dynamic bridges --- TombEngine/Game/collision/floordata.cpp | 13 +- TombEngine/Game/control/control.cpp | 25 ++- TombEngine/Game/savegame.cpp | 10 ++ TombEngine/Specific/Input/Input.cpp | 3 + .../flatbuffers/ten_savegame_generated.h | 153 ++++++++++++++++-- .../Specific/savegame/schema/ten_savegame.fbs | 6 + 6 files changed, 174 insertions(+), 36 deletions(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index 04adbcdda..cf34916e3 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -204,16 +204,21 @@ int FloorInfo::GetSurfaceHeight(const Vector3i& pos, bool isFloor) const // 2.1) Get bridge surface height. auto bridgeSurfaceHeight = isFloor ? bridge.GetFloorHeight(bridgeItem, pos) : bridge.GetCeilingHeight(bridgeItem, pos); + if (!bridgeSurfaceHeight.has_value()) continue; + // Use bridge midpoint to decide whether to return bridge height or room height, in case probe point + // is located within the bridge. Without it, dynamic bridges may fail while Lara is standing on them. + int midpoint = (bridge.GetFloorBorder(bridgeItem) + bridge.GetCeilingBorder(bridgeItem)) / 2; + // 2.2) Track closest floor or ceiling height. if (isFloor) { // Test if bridge floor height is closer. - if (*bridgeSurfaceHeight >= pos.y && // Bridge floor height is below position. - *bridgeSurfaceHeight < floorHeight && // Bridge floor height is above current closest floor height. - *bridgeSurfaceHeight >= ceilingHeight) // Bridge ceiling height is below sector ceiling height. + if (midpoint >= pos.y && // Bridge midpoint is below position. + *bridgeSurfaceHeight < floorHeight && // Bridge floor height is above current closest floor height. + *bridgeSurfaceHeight >= ceilingHeight) // Bridge ceiling height is below sector ceiling height. { floorHeight = *bridgeSurfaceHeight; } @@ -221,7 +226,7 @@ int FloorInfo::GetSurfaceHeight(const Vector3i& pos, bool isFloor) const else { // Test if bridge ceiling height is closer. - if (*bridgeSurfaceHeight <= pos.y && // Bridge ceiling height is above position. + if (midpoint <= pos.y && // Bridge midpoint is above position. *bridgeSurfaceHeight > ceilingHeight && // Bridge ceiling height is below current closest ceiling height. *bridgeSurfaceHeight <= floorHeight) // Bridge floor height is above sector floor height. { diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 03cccf2fd..d247ba29a 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -157,21 +157,6 @@ GameStatus ControlPhase() if (!isTitle && Lara.Control.IsLocked) ClearAllActions(); - // Handle inventory, pause, load, save screens. - auto result = HandleMenuCalls(isTitle); - if (result != GameStatus::Normal) - return result; - - // Handle global input events. - result = HandleGlobalInputEvents(isTitle); - if (result != GameStatus::Normal) - return result; - - // Queued input actions are read again and cleared after UI interrupts are processed, - // so first game frame after exiting UI will still register it. - ApplyActionQueue(); - ClearActionQueue(); - // Item update should happen before camera update, so potential flyby/track camera triggers are processed correctly. UpdateAllItems(); UpdateAllEffects(); @@ -247,6 +232,16 @@ GameStatus ControlPhase() GameTimer++; GlobalCounter++; + // Handle inventory, pause, load, save screens. + auto result = HandleMenuCalls(isTitle); + if (result != GameStatus::Normal) + return result; + + // Handle global input events. + result = HandleGlobalInputEvents(isTitle); + if (result != GameStatus::Normal) + return result; + auto time2 = std::chrono::high_resolution_clock::now(); ControlPhaseTime = (std::chrono::duration_cast(time2 - time1)).count() / 1000000; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 4a2c65f34..05e8291f6 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -490,6 +490,11 @@ const std::vector SaveGame::Build() status.add_stamina(Lara.Status.Stamina); auto statusOffset = status.Finish(); + Save::CollisionInfoDataBuilder collision{ fbb }; + collision.add_last_bridge_item_number(LaraCollision.LastBridgeItemNumber); + collision.add_last_bridge_item_pose(&FromPose(LaraCollision.LastBridgeItemPose)); + auto collisionOffset = collision.Finish(); + std::vector> carriedWeapons; for (int i = 0; i < (int)LaraWeaponType::NumWeapons; i++) { @@ -536,6 +541,7 @@ const std::vector SaveGame::Build() lara.add_location_pad(Lara.LocationPad); lara.add_right_arm(rightArmOffset); lara.add_status(statusOffset); + lara.add_collision(collisionOffset); lara.add_target_arm_orient(&FromEulerAngles(Lara.TargetArmOrient)); lara.add_target_entity_number(Lara.TargetEntity == nullptr ? -1 : Lara.TargetEntity->Index); lara.add_torch(torchOffset); @@ -1987,6 +1993,10 @@ static void ParsePlayer(const Save::SaveGame* s) AlternatePendulum.rope = rope; } + // Collision + LaraCollision.LastBridgeItemNumber = s->lara()->collision()->last_bridge_item_number(); + LaraCollision.LastBridgeItemPose = ToPose(*s->lara()->collision()->last_bridge_item_pose()); + for (auto& item : g_Level.Items) { if (item.ObjectNumber != ID_LARA || item.Index >= g_Level.NumItems) diff --git a/TombEngine/Specific/Input/Input.cpp b/TombEngine/Specific/Input/Input.cpp index 1365e4fc7..594992735 100644 --- a/TombEngine/Specific/Input/Input.cpp +++ b/TombEngine/Specific/Input/Input.cpp @@ -718,7 +718,10 @@ namespace TEN::Input action.Update(Key((int)action.GetID())); if (applyQueue) + { ApplyActionQueue(); + ClearActionQueue(); + } // Additional handling. HandleHotkeyActions(); diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index de658eaa8..fde07fd5a 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -97,6 +97,10 @@ struct PlayerContextData; struct PlayerContextDataBuilder; struct PlayerContextDataT; +struct CollisionInfoData; +struct CollisionInfoDataBuilder; +struct CollisionInfoDataT; + struct Lara; struct LaraBuilder; struct LaraT; @@ -4049,11 +4053,81 @@ struct PlayerContextData::Traits { flatbuffers::Offset CreatePlayerContextData(flatbuffers::FlatBufferBuilder &_fbb, const PlayerContextDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct CollisionInfoDataT : public flatbuffers::NativeTable { + typedef CollisionInfoData TableType; + int32_t last_bridge_item_number = 0; + std::unique_ptr last_bridge_item_pose{}; +}; + +struct CollisionInfoData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CollisionInfoDataT NativeTableType; + typedef CollisionInfoDataBuilder Builder; + struct Traits; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_LAST_BRIDGE_ITEM_NUMBER = 4, + VT_LAST_BRIDGE_ITEM_POSE = 6 + }; + int32_t last_bridge_item_number() const { + return GetField(VT_LAST_BRIDGE_ITEM_NUMBER, 0); + } + const TEN::Save::Pose *last_bridge_item_pose() const { + return GetStruct(VT_LAST_BRIDGE_ITEM_POSE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_LAST_BRIDGE_ITEM_NUMBER) && + VerifyField(verifier, VT_LAST_BRIDGE_ITEM_POSE) && + verifier.EndTable(); + } + CollisionInfoDataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CollisionInfoDataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CollisionInfoDataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CollisionInfoDataBuilder { + typedef CollisionInfoData Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_last_bridge_item_number(int32_t last_bridge_item_number) { + fbb_.AddElement(CollisionInfoData::VT_LAST_BRIDGE_ITEM_NUMBER, last_bridge_item_number, 0); + } + void add_last_bridge_item_pose(const TEN::Save::Pose *last_bridge_item_pose) { + fbb_.AddStruct(CollisionInfoData::VT_LAST_BRIDGE_ITEM_POSE, last_bridge_item_pose); + } + explicit CollisionInfoDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCollisionInfoData( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t last_bridge_item_number = 0, + const TEN::Save::Pose *last_bridge_item_pose = 0) { + CollisionInfoDataBuilder builder_(_fbb); + builder_.add_last_bridge_item_pose(last_bridge_item_pose); + builder_.add_last_bridge_item_number(last_bridge_item_number); + return builder_.Finish(); +} + +struct CollisionInfoData::Traits { + using type = CollisionInfoData; + static auto constexpr Create = CreateCollisionInfoData; +}; + +flatbuffers::Offset CreateCollisionInfoData(flatbuffers::FlatBufferBuilder &_fbb, const CollisionInfoDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct LaraT : public flatbuffers::NativeTable { typedef Lara TableType; std::unique_ptr context{}; std::unique_ptr control{}; std::unique_ptr effect{}; + std::unique_ptr collision{}; int32_t extra_anim = 0; std::unique_ptr extra_head_rot{}; std::unique_ptr extra_torso_rot{}; @@ -4081,23 +4155,24 @@ struct Lara FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_CONTEXT = 4, VT_CONTROL = 6, VT_EFFECT = 8, - VT_EXTRA_ANIM = 10, - VT_EXTRA_HEAD_ROT = 12, - VT_EXTRA_TORSO_ROT = 14, - VT_FLARE = 16, - VT_HIGHEST_LOCATION = 18, - VT_HIT_DIRECTION = 20, - VT_HIT_FRAME = 22, - VT_INVENTORY = 24, - VT_LEFT_ARM = 26, - VT_LOCATION = 28, - VT_LOCATION_PAD = 30, - VT_RIGHT_ARM = 32, - VT_STATUS = 34, - VT_TARGET_ARM_ORIENT = 36, - VT_TARGET_ENTITY_NUMBER = 38, - VT_TORCH = 40, - VT_WEAPONS = 42 + VT_COLLISION = 10, + VT_EXTRA_ANIM = 12, + VT_EXTRA_HEAD_ROT = 14, + VT_EXTRA_TORSO_ROT = 16, + VT_FLARE = 18, + VT_HIGHEST_LOCATION = 20, + VT_HIT_DIRECTION = 22, + VT_HIT_FRAME = 24, + VT_INVENTORY = 26, + VT_LEFT_ARM = 28, + VT_LOCATION = 30, + VT_LOCATION_PAD = 32, + VT_RIGHT_ARM = 34, + VT_STATUS = 36, + VT_TARGET_ARM_ORIENT = 38, + VT_TARGET_ENTITY_NUMBER = 40, + VT_TORCH = 42, + VT_WEAPONS = 44 }; const TEN::Save::PlayerContextData *context() const { return GetPointer(VT_CONTEXT); @@ -4108,6 +4183,9 @@ struct Lara FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const TEN::Save::PlayerEffectData *effect() const { return GetPointer(VT_EFFECT); } + const TEN::Save::CollisionInfoData *collision() const { + return GetPointer(VT_COLLISION); + } int32_t extra_anim() const { return GetField(VT_EXTRA_ANIM, 0); } @@ -4167,6 +4245,8 @@ struct Lara FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyTable(control()) && VerifyOffset(verifier, VT_EFFECT) && verifier.VerifyTable(effect()) && + VerifyOffset(verifier, VT_COLLISION) && + verifier.VerifyTable(collision()) && VerifyField(verifier, VT_EXTRA_ANIM) && VerifyField(verifier, VT_EXTRA_HEAD_ROT) && VerifyField(verifier, VT_EXTRA_TORSO_ROT) && @@ -4212,6 +4292,9 @@ struct LaraBuilder { void add_effect(flatbuffers::Offset effect) { fbb_.AddOffset(Lara::VT_EFFECT, effect); } + void add_collision(flatbuffers::Offset collision) { + fbb_.AddOffset(Lara::VT_COLLISION, collision); + } void add_extra_anim(int32_t extra_anim) { fbb_.AddElement(Lara::VT_EXTRA_ANIM, extra_anim, 0); } @@ -4279,6 +4362,7 @@ inline flatbuffers::Offset CreateLara( flatbuffers::Offset context = 0, flatbuffers::Offset control = 0, flatbuffers::Offset effect = 0, + flatbuffers::Offset collision = 0, int32_t extra_anim = 0, const TEN::Save::EulerAngles *extra_head_rot = 0, const TEN::Save::EulerAngles *extra_torso_rot = 0, @@ -4314,6 +4398,7 @@ inline flatbuffers::Offset CreateLara( builder_.add_extra_torso_rot(extra_torso_rot); builder_.add_extra_head_rot(extra_head_rot); builder_.add_extra_anim(extra_anim); + builder_.add_collision(collision); builder_.add_effect(effect); builder_.add_control(control); builder_.add_context(context); @@ -4330,6 +4415,7 @@ inline flatbuffers::Offset CreateLaraDirect( flatbuffers::Offset context = 0, flatbuffers::Offset control = 0, flatbuffers::Offset effect = 0, + flatbuffers::Offset collision = 0, int32_t extra_anim = 0, const TEN::Save::EulerAngles *extra_head_rot = 0, const TEN::Save::EulerAngles *extra_torso_rot = 0, @@ -4353,6 +4439,7 @@ inline flatbuffers::Offset CreateLaraDirect( context, control, effect, + collision, extra_anim, extra_head_rot, extra_torso_rot, @@ -8993,6 +9080,35 @@ inline flatbuffers::Offset CreatePlayerContextData(flatbuffer _water_surface_dist); } +inline CollisionInfoDataT *CollisionInfoData::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void CollisionInfoData::UnPackTo(CollisionInfoDataT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = last_bridge_item_number(); _o->last_bridge_item_number = _e; } + { auto _e = last_bridge_item_pose(); if (_e) _o->last_bridge_item_pose = std::unique_ptr(new TEN::Save::Pose(*_e)); } +} + +inline flatbuffers::Offset CollisionInfoData::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CollisionInfoDataT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCollisionInfoData(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCollisionInfoData(flatbuffers::FlatBufferBuilder &_fbb, const CollisionInfoDataT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CollisionInfoDataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _last_bridge_item_number = _o->last_bridge_item_number; + auto _last_bridge_item_pose = _o->last_bridge_item_pose ? _o->last_bridge_item_pose.get() : 0; + return TEN::Save::CreateCollisionInfoData( + _fbb, + _last_bridge_item_number, + _last_bridge_item_pose); +} + inline LaraT *Lara::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); @@ -9005,6 +9121,7 @@ inline void Lara::UnPackTo(LaraT *_o, const flatbuffers::resolver_function_t *_r { auto _e = context(); if (_e) _o->context = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = control(); if (_e) _o->control = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = effect(); if (_e) _o->effect = std::unique_ptr(_e->UnPack(_resolver)); } + { auto _e = collision(); if (_e) _o->collision = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = extra_anim(); _o->extra_anim = _e; } { auto _e = extra_head_rot(); if (_e) _o->extra_head_rot = std::unique_ptr(new TEN::Save::EulerAngles(*_e)); } { auto _e = extra_torso_rot(); if (_e) _o->extra_torso_rot = std::unique_ptr(new TEN::Save::EulerAngles(*_e)); } @@ -9035,6 +9152,7 @@ inline flatbuffers::Offset CreateLara(flatbuffers::FlatBufferBuilder &_fbb auto _context = _o->context ? CreatePlayerContextData(_fbb, _o->context.get(), _rehasher) : 0; auto _control = _o->control ? CreateLaraControlData(_fbb, _o->control.get(), _rehasher) : 0; auto _effect = _o->effect ? CreatePlayerEffectData(_fbb, _o->effect.get(), _rehasher) : 0; + auto _collision = _o->collision ? CreateCollisionInfoData(_fbb, _o->collision.get(), _rehasher) : 0; auto _extra_anim = _o->extra_anim; auto _extra_head_rot = _o->extra_head_rot ? _o->extra_head_rot.get() : 0; auto _extra_torso_rot = _o->extra_torso_rot ? _o->extra_torso_rot.get() : 0; @@ -9057,6 +9175,7 @@ inline flatbuffers::Offset CreateLara(flatbuffers::FlatBufferBuilder &_fbb _context, _control, _effect, + _collision, _extra_anim, _extra_head_rot, _extra_torso_rot, diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index 2c67b42ec..068d26b50 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -274,10 +274,16 @@ table PlayerContextData { water_surface_dist: int32; } +table CollisionInfoData { + last_bridge_item_number: int32; + last_bridge_item_pose: Pose; +} + table Lara { context: PlayerContextData; control: LaraControlData; effect: PlayerEffectData; + collision: CollisionInfoData; extra_anim: int32; extra_head_rot: EulerAngles; extra_torso_rot: EulerAngles; From b3ae5267269256f3f1adf8ab9c3faef7f0eea1ac Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 08:58:07 +0100 Subject: [PATCH 343/410] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6203238a5..ba1e1d2dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed moveable status after antitriggering. * Fixed leveljump vehicle transfer. * Fixed weapons not properly hitting enemies. +* Fixed falling through dynamic bridges that move upwards. * Fixed laserhead teleporting Lara and making her invisible on death. * Fixed sarcophagus pick-ups. * Fixed issue with Lara not rotating together with bridges while picking up items. From cfdf7af404c8db64875c90780957ce1119c70b1a Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 09:30:18 +0100 Subject: [PATCH 344/410] Fix pickups pushed above climbable blocks --- TombEngine/Game/pickup/pickup.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/pickup/pickup.cpp b/TombEngine/Game/pickup/pickup.cpp index b1824994f..3b8f2fd83 100644 --- a/TombEngine/Game/pickup/pickup.cpp +++ b/TombEngine/Game/pickup/pickup.cpp @@ -1090,10 +1090,14 @@ void InitializePickup(short itemNumber) // below pushable or raising block, so ignore its collision. pointColl.GetSector().RemoveBridge(bridgeItemNumber); pointColl = GetPointCollision(*item); + item->Pose.Position.y = pointColl.GetFloorHeight() - bounds.Y2; pointColl.GetSector().AddBridge(bridgeItemNumber); } + else + { + item->Pose.Position.y = pointColl.GetFloorHeight() - bounds.Y2; + } - item->Pose.Position.y = pointColl.GetFloorHeight() - bounds.Y2; AlignEntityToSurface(item, Vector2(Objects[item->ObjectNumber].radius)); } } From 7b5129a6d85005ae6dfb36a8536a82a3e1876101 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 09:33:28 +0100 Subject: [PATCH 345/410] Possibly fix antitriggering --- TombEngine/Game/control/trigger.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 83a5fcaa7..5e9fef795 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -346,16 +346,17 @@ void Antitrigger(short const value, short const flags) if (item->Active) { - item->Active = false; - item->Status = ITEM_DEACTIVATED; + RemoveActiveItem(value, false); if (Objects[item->ObjectNumber].intelligent) { DisableEntityAI(value); - RemoveActiveItem(value, false); - item->Status = ITEM_INVISIBLE; } + else + { + item->Status = ITEM_DEACTIVATED; + } } } From 47088ba978f7edffa8bb67a3925ec4f489f0c01f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 09:53:25 +0100 Subject: [PATCH 346/410] Another attempt at fixing item status bug --- TombEngine/Game/control/trigger.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 5e9fef795..0f949b360 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -344,19 +344,13 @@ void Antitrigger(short const value, short const flags) if (flags & ONESHOT) item->Flags |= ATONESHOT; - if (item->Active) - { - RemoveActiveItem(value, false); + item->Status = ITEM_DEACTIVATED; - if (Objects[item->ObjectNumber].intelligent) - { - DisableEntityAI(value); - item->Status = ITEM_INVISIBLE; - } - else - { - item->Status = ITEM_DEACTIVATED; - } + if (item->Active && Objects[item->ObjectNumber].intelligent) + { + DisableEntityAI(value); + RemoveActiveItem(value, false); + item->Status = ITEM_INVISIBLE; } } From 627a30dc782eba68ca36be5270778aad05bfefef Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 10:32:12 +0100 Subject: [PATCH 347/410] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba1e1d2dc..8adea9cf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed moveable status after antitriggering. * Fixed leveljump vehicle transfer. * Fixed weapons not properly hitting enemies. -* Fixed falling through dynamic bridges that move upwards. +* Fixed falling through dynamic bridges that are moving upwards. * Fixed laserhead teleporting Lara and making her invisible on death. * Fixed sarcophagus pick-ups. * Fixed issue with Lara not rotating together with bridges while picking up items. @@ -45,12 +45,13 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added the ability to display "Lara's Home" entry in the main menu. * Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. -* Added TR3 Seal Mutant. https://tombengine.com/docs/ocb-and-setup-instructions/#sealmutant - - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Seal_Mutant.wad2 * Added new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. +* Added TR3 Seal Mutant. https://tombengine.com/docs/ocb-and-setup-instructions/#sealmutant + - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TEN_Seal_Mutant.wad2 * Added TR4 Enemy Jeep. https://tombengine.com/docs/ocb-and-setup-instructions/#enemy_jeep + - You must use this version: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Enemies/TR4_Enemy_Jeep.wad2 * Changed TR5 Rome Hammer to not hurt player whilst deactivated. * Changed TR2 Statue with blade damage from 20 to 200. * Changed sound effect that is triggered when using the `level.rumble` feature in a level (ID 359 in the soundmap). From 67c8e33570b16fbaf875e7cabff69134d5d5b87c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 11:14:16 +0100 Subject: [PATCH 348/410] Another attempt at fixing item status --- TombEngine/Game/control/trigger.cpp | 39 ++++++++++++++++++----------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 0f949b360..6804e6c45 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -333,7 +333,11 @@ short* GetTriggerIndex(ItemInfo* item) void Antitrigger(short const value, short const flags) { ItemInfo* item = &g_Level.Items[value]; - if (item->ObjectNumber == ID_EARTHQUAKE) + + if (item->Flags & IFLAG_KILLED) + return; + + if (item->ObjectNumber == ID_EARTHQUAKE) // HACK: move to earthquake control function! { item->ItemFlags[0] = 0; item->ItemFlags[1] = 100; @@ -344,25 +348,35 @@ void Antitrigger(short const value, short const flags) if (flags & ONESHOT) item->Flags |= ATONESHOT; - item->Status = ITEM_DEACTIVATED; - - if (item->Active && Objects[item->ObjectNumber].intelligent) + if (Objects[item->ObjectNumber].intelligent) { - DisableEntityAI(value); - RemoveActiveItem(value, false); - item->Status = ITEM_INVISIBLE; + if (item->Active) + { + DisableEntityAI(value); + RemoveActiveItem(value, false); + item->Status = ITEM_INVISIBLE; + } + } + else + { + item->Status = ITEM_DEACTIVATED; } } void Trigger(short const value, short const flags) { ItemInfo* item = &g_Level.Items[value]; + + if (item->Flags & IFLAG_KILLED) + return; + + item->TouchBits = NO_JOINT_BITS; item->Flags |= TRIGGERED; if (flags & ONESHOT) item->Flags |= ONESHOT; - if (!(item->Active) && !(item->Flags & IFLAG_KILLED)) + if (!item->Active) { if (Objects[item->ObjectNumber].intelligent) { @@ -370,33 +384,30 @@ void Trigger(short const value, short const flags) { if (item->Status == ITEM_INVISIBLE) { - item->TouchBits = NO_JOINT_BITS; if (EnableEntityAI(value, false)) { - item->Status = ITEM_ACTIVE; AddActiveItem(value); } else { item->Status = ITEM_INVISIBLE; AddActiveItem(value); + return; } } } else { - item->TouchBits = NO_JOINT_BITS; - item->Status = ITEM_ACTIVE; AddActiveItem(value); EnableEntityAI(value, true); } } else { - item->TouchBits = NO_JOINT_BITS; AddActiveItem(value); - item->Status = ITEM_ACTIVE; } + + item->Status = ITEM_ACTIVE; } } From 317edbf5cb07ed04333afbf30bbad792854cfa72 Mon Sep 17 00:00:00 2001 From: Adngel Date: Sun, 27 Oct 2024 13:00:55 +0100 Subject: [PATCH 349/410] Fix underwater buoyant pushables. Moved the lines: pushableColl.FloorHeight = pointColl.GetFloorHeight(); pushableColl.CeilingHeight = pointColl.GetCeilingHeight(); Inside of the previous if, because if it uses bridge collision, this must be deactivated to avoid wrong results. and "auto pushableColl = PushableCollisionData{};" was moved before the if so it were ready. --- .../Generic/Object/Pushable/PushableCollision.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp index 6314342b7..9af3e76a4 100644 --- a/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp +++ b/TombEngine/Objects/Generic/Object/Pushable/PushableCollision.cpp @@ -305,6 +305,8 @@ namespace TEN::Entities::Generic auto pointColl = GetPointCollision(item); int waterHeight = NO_HEIGHT; + auto pushableColl = PushableCollisionData{}; + if (pushable.UseBridgeCollision) { RemovePushableBridge(item); @@ -317,19 +319,21 @@ namespace TEN::Entities::Generic if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) waterHeight = g_Level.Rooms[item.RoomNumber].TopHeight; + pushableColl.FloorHeight = pointColl.GetFloorHeight(); + pushableColl.CeilingHeight = pointColl.GetCeilingHeight(); + AddPushableBridge(item); } else { waterHeight = pointColl.GetWaterSurfaceHeight(); - + if (waterHeight == NO_HEIGHT && TestEnvironment(ENV_FLAG_SWAMP, item.RoomNumber)) waterHeight = g_Level.Rooms[item.RoomNumber].TopHeight; - } - auto pushableColl = PushableCollisionData{}; - pushableColl.FloorHeight = pointColl.GetFloorHeight(); - pushableColl.CeilingHeight = pointColl.GetCeilingHeight(); + pushableColl.FloorHeight = pointColl.GetFloorHeight(); + pushableColl.CeilingHeight = pointColl.GetCeilingHeight(); + } // Above water. if (TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) || From 5acb5f6483db6818ca6ba58c8f914e48e580cf0d Mon Sep 17 00:00:00 2001 From: TokyoSU <77746747+TokyoSU@users.noreply.github.com> Date: Sun, 27 Oct 2024 17:55:54 +0100 Subject: [PATCH 350/410] Fixed bitwise for itemStatus (#1434) * Fixed bitwise for itemStatus * Update items.h --- TombEngine/Game/items.h | 2 +- TombEngine/Objects/Generic/Object/objects.cpp | 2 +- .../Objects/TR1/Entity/SkateboardKid.cpp | 2 +- TombEngine/Objects/TR2/Entity/tr2_skidman.cpp | 6 +--- .../Objects/TR2/Entity/tr2_spear_guardian.cpp | 2 +- .../Objects/TR2/Entity/tr2_sword_guardian.cpp | 2 +- TombEngine/Objects/TR3/Entity/Shiva.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_dog.cpp | 2 +- TombEngine/Objects/TR4/Entity/tr4_mummy.cpp | 2 +- .../Objects/TR4/Entity/tr4_skeleton.cpp | 2 +- TombEngine/Objects/TR4/Trap/tr4_cog.cpp | 4 +-- TombEngine/Objects/TR5/Entity/tr5_larson.cpp | 36 ++++++++----------- 12 files changed, 27 insertions(+), 37 deletions(-) diff --git a/TombEngine/Game/items.h b/TombEngine/Game/items.h index a43fd690c..2d1d7e438 100644 --- a/TombEngine/Game/items.h +++ b/TombEngine/Game/items.h @@ -109,7 +109,7 @@ struct ItemInfo int Index = 0; // ItemNumber // TODO: Make int. GAME_OBJECT_ID ObjectNumber = ID_NO_OBJECT; // ObjectID - /*ItemStatus*/int Status = ITEM_NOT_ACTIVE; + ItemStatus Status = ITEM_NOT_ACTIVE; bool Active = false; // TODO: Refactor linked list. diff --git a/TombEngine/Objects/Generic/Object/objects.cpp b/TombEngine/Objects/Generic/Object/objects.cpp index 3a109f9b0..9cd125291 100644 --- a/TombEngine/Objects/Generic/Object/objects.cpp +++ b/TombEngine/Objects/Generic/Object/objects.cpp @@ -258,7 +258,7 @@ void AnimatingControl(short itemNumber) else if (item.TriggerFlags == 2) //Make the animating dissapear when anti-triggered. { RemoveActiveItem(itemNumber); - item.Status |= ITEM_INVISIBLE; + item.Status = ITEM_INVISIBLE; } // TODO: ID_SHOOT_SWITCH2 is probably the bell in Trajan Markets, use Lua for that. diff --git a/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp b/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp index 7e9160975..038db2a70 100644 --- a/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp +++ b/TombEngine/Objects/TR1/Entity/SkateboardKid.cpp @@ -77,7 +77,7 @@ namespace TEN::Entities::Creatures::TR1 AddActiveItem(skateItemNumber); skate.Active = false; - skate.Status |= ITEM_INVISIBLE; + skate.Status = ITEM_INVISIBLE; item.ItemFlags[0] = skateItemNumber; } diff --git a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp index bb34b1716..da284a3e4 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp @@ -81,13 +81,9 @@ namespace TEN::Entities::Creatures::TR2 auto& item = g_Level.Items[itemNumber]; if (item.Flags & IFLAG_REVERSE) - { - item.Status &= ~ITEM_INVISIBLE; - } + item.Status = ITEM_NOT_ACTIVE; else - { item.Status = ITEM_INVISIBLE; - } } void SkidooManCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) diff --git a/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp b/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp index cabdd0ee0..c8d31ee1d 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_spear_guardian.cpp @@ -195,7 +195,7 @@ namespace TEN::Entities::Creatures::TR2 InitializeCreature(itemNumber); SetAnimation(&item, SPEAR_GUARDIAN_ANIM_AWAKE); - item.Status &= ~ITEM_INVISIBLE; + item.Status = ITEM_NOT_ACTIVE; item.ItemFlags[0] = 0; // Joint index for mesh swap. item.ItemFlags[1] = 1; // Immune state (bool). diff --git a/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp b/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp index d620b5daf..e3fb2e420 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_sword_guardian.cpp @@ -174,7 +174,7 @@ namespace TEN::Entities::Creatures::TR2 InitializeCreature(itemNumber); SetAnimation(&item, SWORD_GUARDIAN_ANIM_AWAKE); - item.Status &= ~ITEM_INVISIBLE; + item.Status = ITEM_NOT_ACTIVE; item.ItemFlags[0] = 0; // Joint index for mesh swap. item.ItemFlags[1] = 1; // Immune state (bool). diff --git a/TombEngine/Objects/TR3/Entity/Shiva.cpp b/TombEngine/Objects/TR3/Entity/Shiva.cpp index de1c28033..e93810050 100644 --- a/TombEngine/Objects/TR3/Entity/Shiva.cpp +++ b/TombEngine/Objects/TR3/Entity/Shiva.cpp @@ -254,7 +254,7 @@ namespace TEN::Entities::Creatures::TR3 void InitializeShiva(short itemNumber) { auto& item = g_Level.Items[itemNumber]; - item.Status &= ~ITEM_INVISIBLE; // Draw the statue from the start. + item.Status = ITEM_NOT_ACTIVE; // Draw the statue from the start. InitializeCreature(itemNumber); SetAnimation(&item, SHIVA_ANIM_INACTIVE); diff --git a/TombEngine/Objects/TR4/Entity/tr4_dog.cpp b/TombEngine/Objects/TR4/Entity/tr4_dog.cpp index 734f4b192..fa2c37e7f 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_dog.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_dog.cpp @@ -81,7 +81,7 @@ namespace TEN::Entities::TR4 if (item->TriggerFlags) { SetAnimation(item, DOG_ANIM_AWAKEN); - item->Status -= ITEM_INVISIBLE; + item->Status = ITEM_NOT_ACTIVE; } else SetAnimation(item, DOG_ANIM_IDLE); diff --git a/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp b/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp index 84ffb9c7e..2a2d54033 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_mummy.cpp @@ -81,7 +81,7 @@ namespace TEN::Entities::TR4 if (item->TriggerFlags == 2) { SetAnimation(item, MUMMY_ANIM_COLLAPSE_END); - item->Status -= ITEM_INVISIBLE; + item->Status = ITEM_NOT_ACTIVE; } else { diff --git a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp index b530c99b2..df8eaf7d8 100644 --- a/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp +++ b/TombEngine/Objects/TR4/Entity/tr4_skeleton.cpp @@ -136,7 +136,7 @@ namespace TEN::Entities::TR4 case 3: SetAnimation(item, SKELETON_ANIM_STANDING_UP); - item->Status -= ITEM_INVISIBLE; + item->Status = ITEM_NOT_ACTIVE; break; } } diff --git a/TombEngine/Objects/TR4/Trap/tr4_cog.cpp b/TombEngine/Objects/TR4/Trap/tr4_cog.cpp index 514b4bcc9..7a38d104a 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_cog.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_cog.cpp @@ -19,12 +19,12 @@ namespace TEN::Entities::Traps if (TriggerActive(&item)) { - item.Status = ITEM_ACTIVE; + item.Status = ITEM_ACTIVE; AnimateItem(&item); } else if (item.TriggerFlags == 2) { - item.Status |= ITEM_INVISIBLE; + item.Status = ITEM_INVISIBLE; } } diff --git a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp index ec249ed98..e34fbc7d3 100644 --- a/TombEngine/Objects/TR5/Entity/tr5_larson.cpp +++ b/TombEngine/Objects/TR5/Entity/tr5_larson.cpp @@ -18,6 +18,8 @@ using namespace TEN::Math; namespace TEN::Entities::Creatures::TR5 { + constexpr auto LARSON_ALERT_RANGE = SQUARE(BLOCK(2)); + #define STATE_TR5_LARSON_STOP 1 #define STATE_TR5_LARSON_WALK 2 #define STATE_TR5_LARSON_RUN 3 @@ -58,6 +60,8 @@ namespace TEN::Entities::Creatures::TR5 item->Pose.Position.z += STEPUP_HEIGHT; } + // TODO: Make larson 1:1 from TOMB5 code. TokyoSU: 10/27/2024 + // This code is a mess... void LarsonControl(short itemNumber) { if (!CreatureActive(itemNumber)) @@ -73,15 +77,14 @@ namespace TEN::Entities::Creatures::TR5 short joint2 = 0; // TODO: When Larson's HP is below 40, he runs away in Streets of Rome. Keeping block commented for reference. - /*if (item->HitPoints <= TR5_LARSON_MIN_HP && !(item->flags & IFLAG_INVISIBLE)) + if (item->HitPoints <= TR5_LARSON_MIN_HP && !(item->Flags & IFLAG_INVISIBLE)) { item->HitPoints = TR5_LARSON_MIN_HP; - creature->flags++; - }*/ + creature->Flags++; + } if (creature->MuzzleFlash[0].Delay != 0) creature->MuzzleFlash[0].Delay--; - if (creature->MuzzleFlash[1].Delay != 0) creature->MuzzleFlash[1].Delay--; @@ -89,20 +92,13 @@ namespace TEN::Entities::Creatures::TR5 { if (CurrentLevel == 2) { - item->Animation.IsAirborne = false; - item->Status = ITEM_DEACTIVATED; - item->Collidable = false; - item->HitStatus = false; + item->AIBits = AMBUSH; item->ItemFlags[3] = 1; } else { - item->Animation.IsAirborne = false; - item->Status = ITEM_ACTIVE; - item->Collidable = false; - item->HitStatus = false; + item->AIBits = GUARD; } - item->TriggerFlags = 0; } @@ -120,25 +116,23 @@ namespace TEN::Entities::Creatures::TR5 joint2 = AI.angle; // FIXME: This should make Larson run away, but it doesn't work. - /*if (creature->flags) + // FIXME: 10/27/2024 - TokyoSU: Implemented TOMB5 way, should work now but need test. + if (creature->Flags) { item->HitPoints = 60; - item->IsAirborne = false; - item->HitStatus = false; - item->Collidable = false; - item->Status = ITEM_DESACTIVATED; + item->AIBits = AMBUSH; creature->Flags = 0; - }*/ + } GetCreatureMood(item, &AI, true); CreatureMood(item, &AI, true); - if (AI.distance < SQUARE(BLOCK(2)) && + if (AI.distance < LARSON_ALERT_RANGE && LaraItem->Animation.Velocity.z > 20.0f || item->HitStatus || TargetVisible(item, &AI) != 0) { - item->Status &= ~ITEM_ACTIVE; + item->AIBits &= ~GUARD; creature->Alerted = true; } From f85376ddcadb4dcd70f65491bc32ffb444c63f49 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:41:54 +0100 Subject: [PATCH 351/410] Fix garbage frames for newly drawn or triggered items --- TombEngine/Game/control/control.cpp | 4 ++-- TombEngine/Game/control/trigger.cpp | 1 + TombEngine/Renderer/Renderer.cpp | 1 + TombEngine/Renderer/RendererFrame.cpp | 11 +++++++---- TombEngine/Renderer/Structures/RendererItem.h | 1 + 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index d247ba29a..de2121aaf 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -593,8 +593,8 @@ void EndGameLoop(int levelIndex, GameStatus reason) void SetupInterpolation() { - for (int i = 0; i < g_Level.Items.size(); i++) - g_Level.Items[i].DisableInterpolation = false; + for (auto& item : g_Level.Items) + item.DisableInterpolation = false; } void HandleControls(bool isTitle) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index 6804e6c45..aeeacf402 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -408,6 +408,7 @@ void Trigger(short const value, short const flags) } item->Status = ITEM_ACTIVE; + item->DisableInterpolation = true; } } diff --git a/TombEngine/Renderer/Renderer.cpp b/TombEngine/Renderer/Renderer.cpp index 862d42b9c..25a220b53 100644 --- a/TombEngine/Renderer/Renderer.cpp +++ b/TombEngine/Renderer/Renderer.cpp @@ -51,6 +51,7 @@ namespace TEN::Renderer for (auto& item : _items) { + item.DisableInterpolation = true; item.PrevRoomNumber = NO_VALUE; item.RoomNumber = NO_VALUE; item.ItemNumber = NO_VALUE; diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp index bf06ed3bf..64d6bea6e 100644 --- a/TombEngine/Renderer/RendererFrame.cpp +++ b/TombEngine/Renderer/RendererFrame.cpp @@ -417,7 +417,11 @@ namespace TEN::Renderer newItem->Scale = Matrix::CreateScale(1.0f); newItem->World = newItem->Rotation * newItem->Translation; - if (item->DisableInterpolation) + // Disable interpolation either when renderer slot or item slot has flag. + // Renderer slot has no interpolation flag set in case it is fetched for the first time (e.g. item first time in frustum). + newItem->DisableInterpolation = item->DisableInterpolation || newItem->DisableInterpolation; + + if (newItem->DisableInterpolation) { // NOTE: Interpolation alwasy returns same result. newItem->PrevPosition = newItem->Position; @@ -425,9 +429,8 @@ namespace TEN::Renderer newItem->PrevRotation = newItem->Rotation; newItem->PrevWorld = newItem->World; - // Otherwise all frames until the next ControlPhase will not - // be interpolated - item->DisableInterpolation = false; + // Otherwise all frames until the next ControlPhase will not be interpolated. + newItem->DisableInterpolation = false; for (int j = 0; j < MAX_BONES; j++) newItem->PrevAnimTransforms[j] = newItem->AnimTransforms[j]; diff --git a/TombEngine/Renderer/Structures/RendererItem.h b/TombEngine/Renderer/Structures/RendererItem.h index 4430445f0..0924ec4bb 100644 --- a/TombEngine/Renderer/Structures/RendererItem.h +++ b/TombEngine/Renderer/Structures/RendererItem.h @@ -29,6 +29,7 @@ namespace TEN::Renderer::Structures float LightFade = 0.0f; bool DoneAnimations = false; + bool DisableInterpolation = true; Vector3 InterpolatedPosition = Vector3::Zero; Matrix InterpolatedWorld = Matrix::Identity; From 23ab42cfa380ef3ffff8a677514a9c247adf9626 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 20:21:47 +0100 Subject: [PATCH 352/410] Fixed #1435 --- CHANGELOG.md | 1 + TombEngine/Game/collision/collide_item.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8adea9cf7..30b405650 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed several binocular bugs. * Fixed incorrect climbing out of water on bridge objects. * Fixed faulty death sectors. +* Fixed water climbouts in front of static meshes. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 8b8693009..bf1140826 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -283,7 +283,8 @@ bool TestWithGlobalCollisionBounds(ItemInfo* item, ItemInfo* laraItem, Collision void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll) { - int height = GameBoundingBox(item).GetHeight(); + auto bbox = GameBoundingBox(item).ToBoundingOrientedBox(item->Pose); + auto height = (bbox.Center - bbox.Extents).y - CLICK(1); for (int i = 0; i < 3; i++) { @@ -292,8 +293,9 @@ void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll) auto origin = Vector3( item->Pose.Position.x + (sinHeading * (coll->Setup.Radius)), - item->Pose.Position.y - (height + CLICK(1)), + height, item->Pose.Position.z + (cosHeading * (coll->Setup.Radius))); + auto mxR = Matrix::CreateFromYawPitchRoll(TO_RAD(coll->Setup.ForwardAngle), 0.0f, 0.0f); auto direction = (Matrix::CreateTranslation(Vector3::UnitZ) * mxR).Translation(); From 20229be3b1e788870669581e4e8139ebf5319a26 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:12:51 +0100 Subject: [PATCH 353/410] Fixed incorrect detection of death flag in L-shaped portal setups --- TombEngine/Game/control/trigger.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index aeeacf402..adbe0b74c 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -867,11 +867,12 @@ void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFl void ProcessSectorFlags(ItemInfo* item) { - auto pointColl = GetPointCollision(*item); - auto& sector = GetPointCollision(*item).GetBottomSector(); - bool isPlayer = item->IsLara(); + // HACK: because of L-shaped portal configurations, we need to fetch room number from Location struct for player. + auto pointColl = isPlayer ? GetPointCollision(item->Pose.Position, item->Location.RoomNumber) : GetPointCollision(*item); + auto& sector = pointColl.GetBottomSector(); + // Set monkeyswing and wall climb statuses for player. if (isPlayer) { From 1c2945de62bc0a3330257eb2aa7f83130a95f4db Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 21:33:42 +0100 Subject: [PATCH 354/410] Revert "Fixed incorrect detection of death flag in L-shaped portal setups" This reverts commit 20229be3b1e788870669581e4e8139ebf5319a26. --- TombEngine/Game/control/trigger.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index adbe0b74c..aeeacf402 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -867,11 +867,10 @@ void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFl void ProcessSectorFlags(ItemInfo* item) { - bool isPlayer = item->IsLara(); + auto pointColl = GetPointCollision(*item); + auto& sector = GetPointCollision(*item).GetBottomSector(); - // HACK: because of L-shaped portal configurations, we need to fetch room number from Location struct for player. - auto pointColl = isPlayer ? GetPointCollision(item->Pose.Position, item->Location.RoomNumber) : GetPointCollision(*item); - auto& sector = pointColl.GetBottomSector(); + bool isPlayer = item->IsLara(); // Set monkeyswing and wall climb statuses for player. if (isPlayer) From 407ae147bdeabafa91d24167ccf74716f2133ad4 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:28:25 +0100 Subject: [PATCH 355/410] Reapply death block flag fix, because the bug was still present in 1.2 as well --- TombEngine/Game/control/trigger.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/control/trigger.cpp b/TombEngine/Game/control/trigger.cpp index aeeacf402..adbe0b74c 100644 --- a/TombEngine/Game/control/trigger.cpp +++ b/TombEngine/Game/control/trigger.cpp @@ -867,11 +867,12 @@ void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFl void ProcessSectorFlags(ItemInfo* item) { - auto pointColl = GetPointCollision(*item); - auto& sector = GetPointCollision(*item).GetBottomSector(); - bool isPlayer = item->IsLara(); + // HACK: because of L-shaped portal configurations, we need to fetch room number from Location struct for player. + auto pointColl = isPlayer ? GetPointCollision(item->Pose.Position, item->Location.RoomNumber) : GetPointCollision(*item); + auto& sector = pointColl.GetBottomSector(); + // Set monkeyswing and wall climb statuses for player. if (isPlayer) { From 2ded586f1a91f3302d9659af82112ddfa8ee4239 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 28 Oct 2024 00:29:39 +0100 Subject: [PATCH 356/410] Added visible mouse pointer in windowed mode --- CHANGELOG.md | 1 + TombEngine/Specific/winmain.cpp | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30b405650..c97b4be0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added the ability to display "Lara's Home" entry in the main menu. * Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. +* Added visible mouse pointer in windowed mode. * Added new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp index 3e2e7ed5b..a601d0d36 100644 --- a/TombEngine/Specific/winmain.cpp +++ b/TombEngine/Specific/winmain.cpp @@ -156,17 +156,6 @@ void CALLBACK HandleWmCommand(unsigned short wParam) SuspendThread((HANDLE)ThreadHandle); g_Renderer.ToggleFullScreen(); ResumeThread((HANDLE)ThreadHandle); - - if (g_Renderer.IsFullsScreen()) - { - SetCursor(nullptr); - ShowCursor(false); - } - else - { - SetCursor(LoadCursorA(App.hInstance, (LPCSTR)0x68)); - ShowCursor(true); - } } } } @@ -180,6 +169,15 @@ LRESULT CALLBACK WinAppProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { return 0; } + + if (msg == WM_SETCURSOR) + { + if (LOWORD(lParam) == HTCLIENT) + { + SetCursor(g_Renderer.IsFullsScreen() ? nullptr : App.WindowClass.hCursor); + return 1; + } + } if (msg == WM_ACTIVATEAPP) { @@ -370,7 +368,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine App.WindowClass.lpfnWndProc = WinAppProc; App.WindowClass.cbClsExtra = 0; App.WindowClass.cbWndExtra = 0; - App.WindowClass.hCursor = LoadCursor(App.hInstance, IDC_ARROW); + App.WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW); // Register main window. if (!RegisterClass(&App.WindowClass)) @@ -461,8 +459,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine UpdateWindow(WindowsHandle); ShowWindow(WindowsHandle, nShowCmd); - SetCursor(NULL); - ShowCursor(FALSE); hAccTable = LoadAccelerators(hInstance, (LPCSTR)0x65); } catch (std::exception& ex) From 4bbc30b0e572afa951e324105b68b0f9d06dd63d Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Mon, 28 Oct 2024 07:46:28 +0100 Subject: [PATCH 357/410] Decopypaste camera interpolation --- TombEngine/Renderer/Renderer.h | 1 + TombEngine/Renderer/RendererDraw.cpp | 62 +++++++++++++----------- TombEngine/Renderer/RendererDrawMenu.cpp | 32 +----------- 3 files changed, 36 insertions(+), 59 deletions(-) diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index e38ff2fad..f3f50d795 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -507,6 +507,7 @@ namespace TEN::Renderer void ResetScissor(); void ResetDebugVariables(); float CalculateFrameRate(); + void InterpolateCamera(float interpFactor); void CopyRenderTarget(RenderTarget2D* source, RenderTarget2D* dest, RenderView& view); void AddSpriteBillboard(RendererSprite* sprite, const Vector3& pos, const Vector4& color, float orient2D, float scale, diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index c6e7a945a..3961467b5 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -3023,35 +3023,7 @@ namespace TEN::Renderer void Renderer::Render(float interpFactor) { - _interpolationFactor = interpFactor; - - // Interpolate camera. - if (!Camera.DisableInterpolation) - { - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); - _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; - _gameCamera.Camera.FOV = Lerp(_oldGameCamera.Camera.FOV, _currentGameCamera.Camera.FOV,interpFactor); - _gameCamera.Camera.Frustum.Update(_gameCamera.Camera.View, _gameCamera.Camera.Projection); - } - else - { - _gameCamera.Camera.WorldPosition = _currentGameCamera.Camera.WorldPosition; - _gameCamera.Camera.WorldDirection = _currentGameCamera.Camera.WorldDirection; - _gameCamera.Camera.View = _currentGameCamera.Camera.View; - _gameCamera.Camera.Projection = _currentGameCamera.Camera.Projection; - _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; - _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; - _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; - } - - _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; - _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; - _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; - _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - + InterpolateCamera(interpFactor); RenderScene(&_backBuffer, true, _gameCamera); _context->ClearState(); @@ -3679,4 +3651,36 @@ namespace TEN::Renderer DrawTriangles(3, 0); } + + void Renderer::InterpolateCamera(float interpFactor) + { + _interpolationFactor = interpFactor; + + // Interpolate camera. + if (!Camera.DisableInterpolation) + { + _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); + _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); + _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); + _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = Lerp(_oldGameCamera.Camera.FOV, _currentGameCamera.Camera.FOV, interpFactor); + _gameCamera.Camera.Frustum.Update(_gameCamera.Camera.View, _gameCamera.Camera.Projection); + } + else + { + _gameCamera.Camera.WorldPosition = _currentGameCamera.Camera.WorldPosition; + _gameCamera.Camera.WorldDirection = _currentGameCamera.Camera.WorldDirection; + _gameCamera.Camera.View = _currentGameCamera.Camera.View; + _gameCamera.Camera.Projection = _currentGameCamera.Camera.Projection; + _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; + _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; + _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; + } + + _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; + _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; + _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; + _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; + } } diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 7c5fbd4f2..c407a0fc0 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1148,35 +1148,6 @@ namespace TEN::Renderer void Renderer::RenderTitle(float interpFactor) { - _interpolationFactor = interpFactor; - - // Interpolate camera. - if (!Camera.DisableInterpolation) - { - _gameCamera.Camera.WorldPosition = Vector3::Lerp(_oldGameCamera.Camera.WorldPosition, _currentGameCamera.Camera.WorldPosition, interpFactor); - _gameCamera.Camera.WorldDirection = Vector3::Lerp(_oldGameCamera.Camera.WorldDirection, _currentGameCamera.Camera.WorldDirection, interpFactor); - _gameCamera.Camera.View = Matrix::Lerp(_oldGameCamera.Camera.View, _currentGameCamera.Camera.View, interpFactor); - _gameCamera.Camera.Projection = Matrix::Lerp(_oldGameCamera.Camera.Projection, _currentGameCamera.Camera.Projection, interpFactor); - _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; - _gameCamera.Camera.FOV = Lerp(_oldGameCamera.Camera.FOV, _currentGameCamera.Camera.FOV, interpFactor); - _gameCamera.Camera.Frustum.Update(_gameCamera.Camera.View, _gameCamera.Camera.Projection); - } - else - { - _gameCamera.Camera.WorldPosition = _currentGameCamera.Camera.WorldPosition; - _gameCamera.Camera.WorldDirection = _currentGameCamera.Camera.WorldDirection; - _gameCamera.Camera.View = _currentGameCamera.Camera.View; - _gameCamera.Camera.Projection = _currentGameCamera.Camera.Projection; - _gameCamera.Camera.ViewProjection = _gameCamera.Camera.View * _gameCamera.Camera.Projection; - _gameCamera.Camera.FOV = _currentGameCamera.Camera.FOV; - _gameCamera.Camera.Frustum = _currentGameCamera.Camera.Frustum; - } - - _gameCamera.Camera.ViewSize = _currentGameCamera.Camera.ViewSize; - _gameCamera.Camera.InvViewSize = _currentGameCamera.Camera.InvViewSize; - _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; - _gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; - _stringsToDraw.clear(); _isLocked = false; @@ -1185,6 +1156,7 @@ namespace TEN::Renderer _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); + InterpolateCamera(interpFactor); RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 1.0f); _swapChain->Present(1, 0); @@ -1293,7 +1265,7 @@ namespace TEN::Renderer PrintDebugMessage("Orientation: %d, %d, %d", LaraItem->Pose.Orientation.x, LaraItem->Pose.Orientation.y, LaraItem->Pose.Orientation.z); PrintDebugMessage("RoomNumber: %d", LaraItem->RoomNumber); PrintDebugMessage("PathfindingBoxID: %d", LaraItem->BoxNumber); - PrintDebugMessage("WaterSurfaceDist: %d", Lara.Context.WaterSurfaceDist); + PrintDebugMessage((Lara.Context.WaterSurfaceDist == -NO_HEIGHT ? "WaterSurfaceDist: N/A" : "WaterSurfaceDist: %d"), Lara.Context.WaterSurfaceDist); PrintDebugMessage("Room Position: %d, %d, %d, %d", room.Position.z, room.Position.z, room.Position.z + BLOCK(room.XSize), room.Position.z + BLOCK(room.ZSize)); PrintDebugMessage("Room.y, minFloor, maxCeiling: %d, %d, %d ", room.Position.y, room.BottomHeight, room.TopHeight); PrintDebugMessage("Camera Position: %d, %d, %d", Camera.pos.x, Camera.pos.y, Camera.pos.z); From 1e8941609893f9ff1d53b1bf88a1b06d572811e8 Mon Sep 17 00:00:00 2001 From: Sezz Date: Mon, 28 Oct 2024 21:50:08 +1100 Subject: [PATCH 358/410] Fix water tread climb out --- TombEngine/Game/Lara/lara_collide.cpp | 1 - TombEngine/Game/Lara/lara_tests.cpp | 27 ++++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/Lara/lara_collide.cpp b/TombEngine/Game/Lara/lara_collide.cpp index 7e38ded7a..e87e37f00 100644 --- a/TombEngine/Game/Lara/lara_collide.cpp +++ b/TombEngine/Game/Lara/lara_collide.cpp @@ -507,7 +507,6 @@ void LaraSurfaceCollision(ItemInfo* item, CollisionInfo* coll) } } - void LaraDefaultCollision(ItemInfo* item, CollisionInfo* coll) { auto& player = GetLaraInfo(*item); diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index fc5c8b384..4f2ff8693 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -924,12 +924,29 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) if (coll->Middle.Ceiling > -STEPUP_HEIGHT) return false; - int frontFloor = coll->Front.Floor + LARA_HEIGHT_TREAD; - if (coll->Front.Bridge == NO_VALUE && - (frontFloor <= -CLICK(2) || - frontFloor > CLICK(1.25f) - 4)) + // HACK: Probe at incremetal height steps to account for room stacks. -- Sezz 2024.10.28 + int frontFloor = NO_HEIGHT; + if (coll->Front.Bridge != NO_VALUE) { - return false; + auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, BLOCK(0.5f), -BLOCK(0.5f)); + frontFloor = (pointColl.GetFloorHeight() - item->Pose.Position.y); + } + else + { + int yOffset = CLICK(1.25f); + while (yOffset > -CLICK(2)) + { + auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, BLOCK(0.5f), yOffset); + + frontFloor = pointColl.GetFloorHeight() - item->Pose.Position.y; + if (frontFloor > -CLICK(2) && + frontFloor <= (CLICK(1.25f) - 4)) + { + break; + } + + yOffset -= CLICK(0.5f); + } } // Extra bridge check. From 0a8eb65de35687e957eb51a8a4826d1f96c8a75b Mon Sep 17 00:00:00 2001 From: Adngel Date: Mon, 28 Oct 2024 12:28:16 +0100 Subject: [PATCH 359/410] Fix Collision with no-collidable statics. With this check, statics with Extents 0 in the three axis, will be ignored for the collision checks. --- TombEngine/Game/collision/collide_item.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index bf1140826..012af75e9 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -241,6 +241,13 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, if (customRadius > 0.0f) box1.Extents = Vector3(customRadius); + // Skip if either bounding box has any zero extent (not a collidable volume). + if (box0.Extents.x > 0 || box0.Extents.y > 0 || box0.Extents.z > 0) + continue; + + if (box1.Extents.x > 0 || box1.Extents.y > 0 || box1.Extents.z > 0) + continue; + // Test accurate box intersection. if (box0.Intersects(box1)) collObjects.Statics.push_back(&staticObj); From 0faa11a882cf011f4483a8dd3e1fc430a7f58aa6 Mon Sep 17 00:00:00 2001 From: Adngel Date: Mon, 28 Oct 2024 15:05:50 +0100 Subject: [PATCH 360/410] Update collide_item.cpp Updated non-collidable volumes check. --- TombEngine/Game/collision/collide_item.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 012af75e9..1a3b42c4d 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -234,6 +234,13 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, if (!Geometry::CircleIntersects(circle, collidingCircle)) continue; + // Skip if either bounding box has any zero extent (not a collidable volume). + if (bounds.GetExtents().Length() > 0) + continue; + + if (collidingBounds.GetExtents().Length() > 0) + continue; + auto box0 = bounds.ToBoundingOrientedBox(staticObj.pos.Position); auto box1 = collidingBounds.ToBoundingOrientedBox(collidingItem.Pose); @@ -241,13 +248,6 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, if (customRadius > 0.0f) box1.Extents = Vector3(customRadius); - // Skip if either bounding box has any zero extent (not a collidable volume). - if (box0.Extents.x > 0 || box0.Extents.y > 0 || box0.Extents.z > 0) - continue; - - if (box1.Extents.x > 0 || box1.Extents.y > 0 || box1.Extents.z > 0) - continue; - // Test accurate box intersection. if (box0.Intersects(box1)) collObjects.Statics.push_back(&staticObj); From 5f974935b4bcacae66ae860cb2add024ed62bbc0 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Tue, 29 Oct 2024 06:01:03 +0100 Subject: [PATCH 361/410] Fixed black screen and stretched strings after changing display settings in game. --- .../doc/2 classes/Objects.Moveable.html | 62 ++++++++++++++++--- TombEngine/Game/gui.cpp | 2 + TombEngine/Renderer/Renderer.cpp | 5 ++ TombEngine/Renderer/Renderer.h | 4 ++ TombEngine/Renderer/RendererDraw.cpp | 2 + TombEngine/Renderer/RendererDrawMenu.cpp | 15 +++++ 6 files changed, 80 insertions(+), 10 deletions(-) diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index f4ba70179..f21adbec6 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -122,11 +122,11 @@ pickups, and Lara herself (see also Shatter item. - Moveable:SetEffect(effect, timeout) + Moveable:SetEffect(effect[, timeout]) Set effect to moveable - Moveable:SetCustomEffect(Color1, Color2, timeout) + Moveable:SetCustomEffect(Color1, Color2[, timeout]) Set custom colored burn effect to moveable @@ -227,10 +227,14 @@ pickups, and Lara herself (see also Determine whether the moveable is active or not - Moveable:GetJointPosition(index) + Moveable:GetJointPosition(index[, offset]) Get the object's joint position + Moveable:GetJointRotation(index) + Get the object's joint rotation + + Moveable:GetRotation() Get the moveable's rotation @@ -496,7 +500,7 @@ most can just be ignored (see usage).
    - Moveable:SetEffect(effect, timeout) + Moveable:SetEffect(effect[, timeout])
    Set effect to moveable @@ -511,7 +515,8 @@ most can just be ignored (see usage).
  • timeout float - time (in seconds) after which effect turns off (optional). + time (in seconds) after which effect turns off. + (optional)
  • @@ -522,7 +527,7 @@ most can just be ignored (see usage).
    - Moveable:SetCustomEffect(Color1, Color2, timeout) + Moveable:SetCustomEffect(Color1, Color2[, timeout])
    Set custom colored burn effect to moveable @@ -541,7 +546,8 @@ most can just be ignored (see usage).
  • timeout float - time (in seconds) after which effect turns off (optional). + time (in seconds) after which effect turns off. + (optional)
  • @@ -1098,7 +1104,7 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)
    - Moveable:GetJointPosition(index) + Moveable:GetJointPosition(index[, offset])
    Get the object's joint position @@ -1111,13 +1117,46 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM) int of a joint to get position +
  • offset + Vec3 + a pre-rotation offset to the joint + (optional) +
  • Returns:

      Vec3 - a copy of the moveable's position + a copy of the moveable's joint position +
    + + + + +
    +
    + + Moveable:GetJointRotation(index) +
    +
    + Get the object's joint rotation + + + +

    Parameters:

    +
      +
    • index + int + of a joint to get rotation +
    • +
    + +

    Returns:

    +
      + + Rotation + a calculated copy of the moveable's joint rotation
    @@ -1361,7 +1400,10 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)

    Usage:

      -
      LevelFuncs.objCollided = function(obj1, obj2)
      +        
      -- obj1 is the collision moveable
      +-- obj2 is the collider moveable
      +
      +LevelFuncs.objCollided = function(obj1, obj2)
           print(obj1:GetName() .. " collided with " .. obj2:GetName())
       end
       baddy:SetOnCollidedWithObject(LevelFuncs.objCollided)
      diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index d1a35fa2f..737b4e07f 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -625,6 +625,8 @@ namespace TEN::Gui g_Renderer.ChangeScreenResolution(CurrentSettings.Configuration.ScreenWidth, CurrentSettings.Configuration.ScreenHeight, CurrentSettings.Configuration.EnableWindowedMode); + g_Renderer.SetGraphicsSettingsChanged(); + MenuToDisplay = fromPauseMenu ? Menu::Pause : Menu::Options; SelectedOption = fromPauseMenu ? 1 : 0; } diff --git a/TombEngine/Renderer/Renderer.cpp b/TombEngine/Renderer/Renderer.cpp index 25a220b53..e251bc09e 100644 --- a/TombEngine/Renderer/Renderer.cpp +++ b/TombEngine/Renderer/Renderer.cpp @@ -419,4 +419,9 @@ namespace TEN::Renderer _context->RSSetScissorRects(1, rects); } + + void Renderer::SetGraphicsSettingsChanged() + { + _graphicsSettingsChanged = true; + } } diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h index e38ff2fad..5f2d2ddaa 100644 --- a/TombEngine/Renderer/Renderer.h +++ b/TombEngine/Renderer/Renderer.h @@ -384,6 +384,8 @@ namespace TEN::Renderer // High framerate. float _interpolationFactor = 0.0f; + bool _graphicsSettingsChanged = false; + // Private functions void ApplySMAA(RenderTarget2D* renderTarget, RenderView& view); void ApplyFXAA(RenderTarget2D* renderTarget, RenderView& view); @@ -666,6 +668,8 @@ namespace TEN::Renderer void SetPostProcessStrength(float strength); Vector3 GetPostProcessTint(); void SetPostProcessTint(Vector3 color); + + void SetGraphicsSettingsChanged(); }; extern Renderer g_Renderer; diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index c6e7a945a..f9ee79c6b 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -2156,6 +2156,8 @@ namespace TEN::Renderer void Renderer::DumpGameScene() { RenderScene(&_dumpScreenRenderTarget, false, _gameCamera); + + _graphicsSettingsChanged = false; } void Renderer::DrawItems(RenderView& view, RendererPass rendererPass) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 7c5fbd4f2..f7666d24c 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1138,9 +1138,24 @@ namespace TEN::Renderer void Renderer::RenderInventory() { + if (_graphicsSettingsChanged) + { + _currentGameCamera = RenderView(&Camera, Camera.Roll, Camera.Fov, 32, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView()), g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); + _gameCamera = RenderView(&Camera, Camera.Roll, Camera.Fov, 32, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView()), g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); + + Camera.DisableInterpolation = true; + + DumpGameScene(); + } + _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); + // Reset GPU state. + SetBlendMode(BlendMode::Opaque, true); + SetDepthState(DepthState::Write, true); + SetCullMode(CullMode::CounterClockwise, true); + RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 0.5f); _swapChain->Present(1, 0); From 2c93dad6f0fa5bead2e7845afb21f447c55982cc Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Tue, 29 Oct 2024 08:10:25 +0100 Subject: [PATCH 362/410] Fixed display sprites and display strings rendering in the inventory background --- CHANGELOG.md | 4 ++-- TombEngine/Game/gui.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c97b4be0e..fe066d3bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,9 +17,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed issue with Lara not rotating together with bridges while picking up items. * Fixed ghost collision with moveables with zero bounds. * Fixed several binocular bugs. -* Fixed incorrect climbing out of water on bridge objects. * Fixed faulty death sectors. -* Fixed water climbouts in front of static meshes. +* Fixed incorrect climbing out of water on bridge objects and in front of static meshes. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed AI for TR2 skidoo driver and worker with shotgun. @@ -36,6 +35,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed teeth spikes not triggering the player impale animation. * Fixed TR4 mine crash with OCB 1 when triggered. * Fixed cases where Atlantean mutant's bombs cause the game to crash. +* Fixed display sprites and display strings rendering in the inventory background. * Fixed young Lara hair drawing. https://tombengine.com/docs/level-settings/#young_lara ### Features/Amendments diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index d1a35fa2f..6be9728c3 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -7,6 +7,7 @@ #include "Game/camera.h" #include "Game/control/control.h" #include "Game/control/volume.h" +#include "Game/effects/DisplaySprite.h" #include "Game/items.h" #include "Game/Lara/lara.h" #include "Game/Lara/lara_fire.h" @@ -28,6 +29,7 @@ #include "Specific/trutils.h" #include "Specific/winmain.h" +using namespace TEN::Effects::DisplaySprite; using namespace TEN::Input; using namespace TEN::Renderer; using namespace TEN::Utils; @@ -3127,6 +3129,8 @@ namespace TEN::Gui bool GuiController::CallPause() { + ClearAllDisplaySprites(); + g_Renderer.PrepareScene(); g_Renderer.DumpGameScene(); PauseAllSounds(SoundPauseMode::Pause); SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); @@ -3208,6 +3212,8 @@ namespace TEN::Gui player.Inventory.OldBusy = player.Inventory.IsBusy; + ClearAllDisplaySprites(); + g_Renderer.PrepareScene(); g_Renderer.DumpGameScene(); PauseAllSounds(SoundPauseMode::Inventory); SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always); From 21f42c0a4ce6548434f038063b24fcede2a8a117 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Tue, 29 Oct 2024 08:43:38 +0100 Subject: [PATCH 363/410] Optimize GetCollidedObjects to avoid extra bound conversions --- TombEngine/Game/collision/collide_item.cpp | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 1a3b42c4d..2d5816904 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -109,6 +109,13 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, auto collidingSphere = BoundingSphere(collidingBounds.GetCenter() + collidingItem.Pose.Position.ToVector3(), collidingExtents.Length()); auto collidingCircle = Vector3(collidingSphere.Center.x, collidingSphere.Center.z, (customRadius > 0.0f) ? customRadius : std::hypot(collidingExtents.x, collidingExtents.z)); + // Convert bounding box to DX bounds. + auto convertedBounds = collidingBounds.ToBoundingOrientedBox(collidingItem.Pose); + + // Override extents if specified. + if (customRadius > 0.0f) + convertedBounds.Extents = Vector3(customRadius); + // Quickly discard collision if colliding item bounds are below tolerance threshold. if (collidingSphere.Radius <= EXTENTS_LENGTH_MIN) return collObjects; @@ -185,15 +192,10 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, if (!Geometry::CircleIntersects(circle, collidingCircle)) continue; - auto box0 = bounds.ToBoundingOrientedBox(item.Pose); - auto box1 = collidingBounds.ToBoundingOrientedBox(collidingItem.Pose); - - // Override extents if specified. - if (customRadius > 0.0f) - box1.Extents = Vector3(customRadius); + auto box = bounds.ToBoundingOrientedBox(item.Pose); // Test accurate box intersection. - if (box0.Intersects(box1)) + if (box.Intersects(convertedBounds)) collObjects.Items.push_back(&item); } while (itemNumber != NO_VALUE); @@ -235,21 +237,16 @@ CollidedObjectData GetCollidedObjects(ItemInfo& collidingItem, bool onlyVisible, continue; // Skip if either bounding box has any zero extent (not a collidable volume). - if (bounds.GetExtents().Length() > 0) + if (bounds.GetExtents().Length() <= EXTENTS_LENGTH_MIN) continue; - if (collidingBounds.GetExtents().Length() > 0) + if (collidingBounds.GetExtents().Length() <= EXTENTS_LENGTH_MIN) continue; - auto box0 = bounds.ToBoundingOrientedBox(staticObj.pos.Position); - auto box1 = collidingBounds.ToBoundingOrientedBox(collidingItem.Pose); - - // Override extents if specified. - if (customRadius > 0.0f) - box1.Extents = Vector3(customRadius); + auto box = bounds.ToBoundingOrientedBox(staticObj.pos.Position); // Test accurate box intersection. - if (box0.Intersects(box1)) + if (box.Intersects(convertedBounds)) collObjects.Statics.push_back(&staticObj); } } From eb820fad633ff17f8baee54c6303a7ac0904e0f0 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Tue, 29 Oct 2024 08:44:12 +0100 Subject: [PATCH 364/410] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe066d3bb..c320f1ff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed laserhead teleporting Lara and making her invisible on death. * Fixed sarcophagus pick-ups. * Fixed issue with Lara not rotating together with bridges while picking up items. -* Fixed ghost collision with moveables with zero bounds. +* Fixed ghost collision with objects with zero bounds. * Fixed several binocular bugs. * Fixed faulty death sectors. * Fixed incorrect climbing out of water on bridge objects and in front of static meshes. From 999c6e831450378e57af6ce526a5dae9fc428074 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:16:46 +0100 Subject: [PATCH 365/410] Save camera position in a savegame --- CHANGELOG.md | 1 + TombEngine/Game/control/control.cpp | 8 - TombEngine/Game/savegame.cpp | 21 ++ .../flatbuffers/ten_itemdata_generated.h | 162 ++++--------- .../flatbuffers/ten_savegame_generated.h | 224 +++++++++++++----- .../Specific/savegame/schema/ten_itemdata.fbs | 23 +- .../Specific/savegame/schema/ten_savegame.fbs | 6 + 7 files changed, 251 insertions(+), 194 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c320f1ff8..f07852f04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed incorrect climbing out of water on bridge objects and in front of static meshes. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. +* Fixed camera position after loading a savegame. * Fixed AI for TR2 skidoo driver and worker with shotgun. * Fixed ember emitter crashing when ocb is between -1 and -10. * Fixed electric cleaner and squishy block not detecting collision with certain block heights. diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index de2121aaf..052a9c94a 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -495,14 +495,6 @@ void InitializeOrLoadGame(bool loadGame) { SaveGame::Load(g_GameFlow->SelectedSaveGame); - Camera.pos.x = LaraItem->Pose.Position.x + 256; - Camera.pos.y = LaraItem->Pose.Position.y + 256; - Camera.pos.z = LaraItem->Pose.Position.z + 256; - - Camera.target.x = LaraItem->Pose.Position.x; - Camera.target.y = LaraItem->Pose.Position.y; - Camera.target.z = LaraItem->Pose.Position.z; - InitializeGame = false; g_GameFlow->SelectedSaveGame = 0; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 05e8291f6..c72264798 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -130,6 +130,11 @@ Save::Vector4 FromVector4(const Vector4& vec) return Save::Vector4(vec.x, vec.y, vec.z, vec.w); } +Save::GameVector FromGameVector(const GameVector& vec) +{ + return Save::GameVector(vec.x, vec.y, vec.z, (int)vec.RoomNumber); +} + Pose ToPose(const Save::Pose& pose) { return Pose( @@ -172,6 +177,11 @@ Vector4 ToVector4(const Save::Vector4* vec) return Vector4(vec->x(), vec->y(), vec->z(), vec->w()); } +GameVector ToGameVector(const Save::GameVector* vec) +{ + return GameVector(vec->x(), vec->y(), vec->z(), (short)vec->room_number()); +} + bool SaveGame::IsSaveGameSlotValid(int slot) { if (slot < 0 || slot > SAVEGAME_MAX_SLOT) @@ -495,6 +505,12 @@ const std::vector SaveGame::Build() collision.add_last_bridge_item_pose(&FromPose(LaraCollision.LastBridgeItemPose)); auto collisionOffset = collision.Finish(); + Save::CameraBuilder camera{ fbb }; + camera.add_position(&FromGameVector(Camera.pos)); + camera.add_target(&FromGameVector(Camera.target)); + auto cameraOffset = camera.Finish(); + + std::vector> carriedWeapons; for (int i = 0; i < (int)LaraWeaponType::NumWeapons; i++) { @@ -1410,6 +1426,7 @@ const std::vector SaveGame::Build() sgb.add_header(headerOffset); sgb.add_level(levelStatisticsOffset); sgb.add_game(gameStatisticsOffset); + sgb.add_camera(cameraOffset); sgb.add_lara(laraOffset); sgb.add_rooms(roomOffset); sgb.add_next_item_free(NextItemFree); @@ -1997,6 +2014,10 @@ static void ParsePlayer(const Save::SaveGame* s) LaraCollision.LastBridgeItemNumber = s->lara()->collision()->last_bridge_item_number(); LaraCollision.LastBridgeItemPose = ToPose(*s->lara()->collision()->last_bridge_item_pose()); + // Camera + Camera.pos = ToGameVector(s->camera()->position()); + Camera.target = ToGameVector(s->camera()->target()); + for (auto& item : g_Level.Items) { if (item.ObjectNumber != ID_LARA || item.Index >= g_Level.NumItems) diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h index 9e37eea3b..3f179e2ef 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_itemdata_generated.h @@ -59,10 +59,6 @@ struct Motorboat; struct MotorboatBuilder; struct MotorboatT; -struct GameVector; -struct GameVectorBuilder; -struct GameVectorT; - struct Wraith; struct WraithBuilder; struct WraithT; @@ -111,6 +107,8 @@ struct Vector3; struct Vector4; +struct GameVector; + enum class ItemData : uint8_t { NONE = 0, Int = 1, @@ -130,16 +128,15 @@ enum class ItemData : uint8_t { Skidoo = 15, UPV = 16, Motorboat = 17, - GameVector = 18, - Wraith = 19, - Rubberboat = 20, - Pushable = 21, - Minecart = 22, + Wraith = 18, + Rubberboat = 19, + Pushable = 20, + Minecart = 21, MIN = NONE, MAX = Minecart }; -inline const ItemData (&EnumValuesItemData())[23] { +inline const ItemData (&EnumValuesItemData())[22] { static const ItemData values[] = { ItemData::NONE, ItemData::Int, @@ -159,7 +156,6 @@ inline const ItemData (&EnumValuesItemData())[23] { ItemData::Skidoo, ItemData::UPV, ItemData::Motorboat, - ItemData::GameVector, ItemData::Wraith, ItemData::Rubberboat, ItemData::Pushable, @@ -169,7 +165,7 @@ inline const ItemData (&EnumValuesItemData())[23] { } inline const char * const *EnumNamesItemData() { - static const char * const names[24] = { + static const char * const names[23] = { "NONE", "Int", "Short", @@ -188,7 +184,6 @@ inline const char * const *EnumNamesItemData() { "Skidoo", "UPV", "Motorboat", - "GameVector", "Wraith", "Rubberboat", "Pushable", @@ -276,10 +271,6 @@ template<> struct ItemDataTraits { static const ItemData enum_value = ItemData::Motorboat; }; -template<> struct ItemDataTraits { - static const ItemData enum_value = ItemData::GameVector; -}; - template<> struct ItemDataTraits { static const ItemData enum_value = ItemData::Wraith; }; @@ -464,14 +455,6 @@ struct ItemDataUnion { return type == ItemData::Motorboat ? reinterpret_cast(value) : nullptr; } - TEN::Save::GameVectorT *AsGameVector() { - return type == ItemData::GameVector ? - reinterpret_cast(value) : nullptr; - } - const TEN::Save::GameVectorT *AsGameVector() const { - return type == ItemData::GameVector ? - reinterpret_cast(value) : nullptr; - } TEN::Save::WraithT *AsWraith() { return type == ItemData::Wraith ? reinterpret_cast(value) : nullptr; @@ -697,6 +680,46 @@ struct Vector4::Traits { using type = Vector4; }; +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) GameVector FLATBUFFERS_FINAL_CLASS { + private: + int32_t x_; + int32_t y_; + int32_t z_; + int32_t room_number_; + + public: + struct Traits; + GameVector() + : x_(0), + y_(0), + z_(0), + room_number_(0) { + } + GameVector(int32_t _x, int32_t _y, int32_t _z, int32_t _room_number) + : x_(flatbuffers::EndianScalar(_x)), + y_(flatbuffers::EndianScalar(_y)), + z_(flatbuffers::EndianScalar(_z)), + room_number_(flatbuffers::EndianScalar(_room_number)) { + } + int32_t x() const { + return flatbuffers::EndianScalar(x_); + } + int32_t y() const { + return flatbuffers::EndianScalar(y_); + } + int32_t z() const { + return flatbuffers::EndianScalar(z_); + } + int32_t room_number() const { + return flatbuffers::EndianScalar(room_number_); + } +}; +FLATBUFFERS_STRUCT_END(GameVector, 16); + +struct GameVector::Traits { + using type = GameVector; +}; + struct CreatureTargetT : public flatbuffers::NativeTable { typedef CreatureTarget TableType; int32_t object_number = 0; @@ -2031,51 +2054,6 @@ struct Motorboat::Traits { flatbuffers::Offset CreateMotorboat(flatbuffers::FlatBufferBuilder &_fbb, const MotorboatT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); -struct GameVectorT : public flatbuffers::NativeTable { - typedef GameVector TableType; -}; - -struct GameVector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - typedef GameVectorT NativeTableType; - typedef GameVectorBuilder Builder; - struct Traits; - bool Verify(flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - verifier.EndTable(); - } - GameVectorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; - void UnPackTo(GameVectorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; - static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const GameVectorT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); -}; - -struct GameVectorBuilder { - typedef GameVector Table; - flatbuffers::FlatBufferBuilder &fbb_; - flatbuffers::uoffset_t start_; - explicit GameVectorBuilder(flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = flatbuffers::Offset(end); - return o; - } -}; - -inline flatbuffers::Offset CreateGameVector( - flatbuffers::FlatBufferBuilder &_fbb) { - GameVectorBuilder builder_(_fbb); - return builder_.Finish(); -} - -struct GameVector::Traits { - using type = GameVector; - static auto constexpr Create = CreateGameVector; -}; - -flatbuffers::Offset CreateGameVector(flatbuffers::FlatBufferBuilder &_fbb, const GameVectorT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); - struct WraithT : public flatbuffers::NativeTable { typedef Wraith TableType; }; @@ -3442,29 +3420,6 @@ inline flatbuffers::Offset CreateMotorboat(flatbuffers::FlatBufferBui _fbb); } -inline GameVectorT *GameVector::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = std::make_unique(); - UnPackTo(_o.get(), _resolver); - return _o.release(); -} - -inline void GameVector::UnPackTo(GameVectorT *_o, const flatbuffers::resolver_function_t *_resolver) const { - (void)_o; - (void)_resolver; -} - -inline flatbuffers::Offset GameVector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GameVectorT* _o, const flatbuffers::rehasher_function_t *_rehasher) { - return CreateGameVector(_fbb, _o, _rehasher); -} - -inline flatbuffers::Offset CreateGameVector(flatbuffers::FlatBufferBuilder &_fbb, const GameVectorT *_o, const flatbuffers::rehasher_function_t *_rehasher) { - (void)_rehasher; - (void)_o; - struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const GameVectorT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; - return TEN::Save::CreateGameVector( - _fbb); -} - inline WraithT *Wraith::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); @@ -3882,10 +3837,6 @@ inline bool VerifyItemData(flatbuffers::Verifier &verifier, const void *obj, Ite auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); } - case ItemData::GameVector: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } case ItemData::Wraith: { auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); @@ -3988,10 +3939,6 @@ inline void *ItemDataUnion::UnPack(const void *obj, ItemData type, const flatbuf auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); } - case ItemData::GameVector: { - auto ptr = reinterpret_cast(obj); - return ptr->UnPack(resolver); - } case ItemData::Wraith: { auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); @@ -4082,10 +4029,6 @@ inline flatbuffers::Offset ItemDataUnion::Pack(flatbuffers::FlatBufferBuil auto ptr = reinterpret_cast(value); return CreateMotorboat(_fbb, ptr, _rehasher).Union(); } - case ItemData::GameVector: { - auto ptr = reinterpret_cast(value); - return CreateGameVector(_fbb, ptr, _rehasher).Union(); - } case ItemData::Wraith: { auto ptr = reinterpret_cast(value); return CreateWraith(_fbb, ptr, _rehasher).Union(); @@ -4176,10 +4119,6 @@ inline ItemDataUnion::ItemDataUnion(const ItemDataUnion &u) : type(u.type), valu value = new TEN::Save::MotorboatT(*reinterpret_cast(u.value)); break; } - case ItemData::GameVector: { - value = new TEN::Save::GameVectorT(*reinterpret_cast(u.value)); - break; - } case ItemData::Wraith: { value = new TEN::Save::WraithT(*reinterpret_cast(u.value)); break; @@ -4288,11 +4227,6 @@ inline void ItemDataUnion::Reset() { delete ptr; break; } - case ItemData::GameVector: { - auto ptr = reinterpret_cast(value); - delete ptr; - break; - } case ItemData::Wraith: { auto ptr = reinterpret_cast(value); delete ptr; diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index fde07fd5a..a929d1d63 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -105,6 +105,10 @@ struct Lara; struct LaraBuilder; struct LaraT; +struct Camera; +struct CameraBuilder; +struct CameraT; + struct FixedCamera; struct FixedCameraBuilder; struct FixedCameraT; @@ -867,9 +871,6 @@ struct Item FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const TEN::Save::Motorboat *data_as_Motorboat() const { return data_type() == TEN::Save::ItemData::Motorboat ? static_cast(data()) : nullptr; } - const TEN::Save::GameVector *data_as_GameVector() const { - return data_type() == TEN::Save::ItemData::GameVector ? static_cast(data()) : nullptr; - } const TEN::Save::Wraith *data_as_Wraith() const { return data_type() == TEN::Save::ItemData::Wraith ? static_cast(data()) : nullptr; } @@ -1048,10 +1049,6 @@ template<> inline const TEN::Save::Motorboat *Item::data_as inline const TEN::Save::GameVector *Item::data_as() const { - return data_as_GameVector(); -} - template<> inline const TEN::Save::Wraith *Item::data_as() const { return data_as_Wraith(); } @@ -4461,6 +4458,75 @@ inline flatbuffers::Offset CreateLaraDirect( flatbuffers::Offset CreateLara(flatbuffers::FlatBufferBuilder &_fbb, const LaraT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct CameraT : public flatbuffers::NativeTable { + typedef Camera TableType; + std::unique_ptr position{}; + std::unique_ptr target{}; +}; + +struct Camera FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef CameraT NativeTableType; + typedef CameraBuilder Builder; + struct Traits; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_POSITION = 4, + VT_TARGET = 6 + }; + const TEN::Save::GameVector *position() const { + return GetStruct(VT_POSITION); + } + const TEN::Save::GameVector *target() const { + return GetStruct(VT_TARGET); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_POSITION) && + VerifyField(verifier, VT_TARGET) && + verifier.EndTable(); + } + CameraT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(CameraT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const CameraT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct CameraBuilder { + typedef Camera Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_position(const TEN::Save::GameVector *position) { + fbb_.AddStruct(Camera::VT_POSITION, position); + } + void add_target(const TEN::Save::GameVector *target) { + fbb_.AddStruct(Camera::VT_TARGET, target); + } + explicit CameraBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateCamera( + flatbuffers::FlatBufferBuilder &_fbb, + const TEN::Save::GameVector *position = 0, + const TEN::Save::GameVector *target = 0) { + CameraBuilder builder_(_fbb); + builder_.add_target(target); + builder_.add_position(position); + return builder_.Finish(); +} + +struct Camera::Traits { + using type = Camera; + static auto constexpr Create = CreateCamera; +}; + +flatbuffers::Offset CreateCamera(flatbuffers::FlatBufferBuilder &_fbb, const CameraT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct FixedCameraT : public flatbuffers::NativeTable { typedef FixedCamera TableType; int32_t flags = 0; @@ -7189,6 +7255,7 @@ struct SaveGameT : public flatbuffers::NativeTable { std::unique_ptr header{}; std::unique_ptr game{}; std::unique_ptr level{}; + std::unique_ptr camera{}; std::unique_ptr lara{}; std::vector> rooms{}; std::vector> items{}; @@ -7248,55 +7315,56 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_HEADER = 4, VT_GAME = 6, VT_LEVEL = 8, - VT_LARA = 10, - VT_ROOMS = 12, - VT_ITEMS = 14, - VT_NEXT_ITEM_FREE = 16, - VT_NEXT_ITEM_ACTIVE = 18, - VT_ROOM_ITEMS = 20, - VT_FISH_SWARM = 22, - VT_FXINFOS = 24, - VT_NEXT_FX_FREE = 26, - VT_NEXT_FX_ACTIVE = 28, - VT_FIXED_CAMERAS = 30, - VT_SINKS = 32, - VT_STATIC_MESHES = 34, - VT_FLYBY_CAMERAS = 36, - VT_PARTICLES = 38, - VT_RATS = 40, - VT_SPIDERS = 42, - VT_SCARABS = 44, - VT_BATS = 46, - VT_FLIP_MAPS = 48, - VT_FLIP_STATS = 50, - VT_FLIP_EFFECT = 52, - VT_FLIP_TIMER = 54, - VT_FLIP_STATUS = 56, - VT_CURRENT_FOV = 58, - VT_LAST_INV_ITEM = 60, - VT_ACTION_QUEUE = 62, - VT_SOUNDTRACKS = 64, - VT_CD_FLAGS = 66, - VT_POSTPROCESS_MODE = 68, - VT_POSTPROCESS_STRENGTH = 70, - VT_POSTPROCESS_TINT = 72, - VT_ROPE = 74, - VT_PENDULUM = 76, - VT_ALTERNATE_PENDULUM = 78, - VT_VOLUMES = 80, - VT_GLOBAL_EVENT_SETS = 82, - VT_VOLUME_EVENT_SETS = 84, - VT_SCRIPT_VARS = 86, - VT_CALLBACKS_PRE_START = 88, - VT_CALLBACKS_POST_START = 90, - VT_CALLBACKS_PRE_END = 92, - VT_CALLBACKS_POST_END = 94, - VT_CALLBACKS_PRE_SAVE = 96, - VT_CALLBACKS_POST_SAVE = 98, - VT_CALLBACKS_PRE_LOAD = 100, - VT_CALLBACKS_POST_LOAD = 102, - VT_CALLBACKS_PRE_LOOP = 104, - VT_CALLBACKS_POST_LOOP = 106 + VT_CAMERA = 10, + VT_LARA = 12, + VT_ROOMS = 14, + VT_ITEMS = 16, + VT_NEXT_ITEM_FREE = 18, + VT_NEXT_ITEM_ACTIVE = 20, + VT_ROOM_ITEMS = 22, + VT_FISH_SWARM = 24, + VT_FXINFOS = 26, + VT_NEXT_FX_FREE = 28, + VT_NEXT_FX_ACTIVE = 30, + VT_FIXED_CAMERAS = 32, + VT_SINKS = 34, + VT_STATIC_MESHES = 36, + VT_FLYBY_CAMERAS = 38, + VT_PARTICLES = 40, + VT_RATS = 42, + VT_SPIDERS = 44, + VT_SCARABS = 46, + VT_BATS = 48, + VT_FLIP_MAPS = 50, + VT_FLIP_STATS = 52, + VT_FLIP_EFFECT = 54, + VT_FLIP_TIMER = 56, + VT_FLIP_STATUS = 58, + VT_CURRENT_FOV = 60, + VT_LAST_INV_ITEM = 62, + VT_ACTION_QUEUE = 64, + VT_SOUNDTRACKS = 66, + VT_CD_FLAGS = 68, + VT_POSTPROCESS_MODE = 70, + VT_POSTPROCESS_STRENGTH = 72, + VT_POSTPROCESS_TINT = 74, + VT_ROPE = 76, + VT_PENDULUM = 78, + VT_ALTERNATE_PENDULUM = 80, + VT_VOLUMES = 82, + VT_GLOBAL_EVENT_SETS = 84, + VT_VOLUME_EVENT_SETS = 86, + VT_SCRIPT_VARS = 88, + VT_CALLBACKS_PRE_START = 90, + VT_CALLBACKS_POST_START = 92, + VT_CALLBACKS_PRE_END = 94, + VT_CALLBACKS_POST_END = 96, + VT_CALLBACKS_PRE_SAVE = 98, + VT_CALLBACKS_POST_SAVE = 100, + VT_CALLBACKS_PRE_LOAD = 102, + VT_CALLBACKS_POST_LOAD = 104, + VT_CALLBACKS_PRE_LOOP = 106, + VT_CALLBACKS_POST_LOOP = 108 }; const TEN::Save::SaveGameHeader *header() const { return GetPointer(VT_HEADER); @@ -7307,6 +7375,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const TEN::Save::SaveGameStatistics *level() const { return GetPointer(VT_LEVEL); } + const TEN::Save::Camera *camera() const { + return GetPointer(VT_CAMERA); + } const TEN::Save::Lara *lara() const { return GetPointer(VT_LARA); } @@ -7462,6 +7533,8 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyTable(game()) && VerifyOffset(verifier, VT_LEVEL) && verifier.VerifyTable(level()) && + VerifyOffset(verifier, VT_CAMERA) && + verifier.VerifyTable(camera()) && VerifyOffset(verifier, VT_LARA) && verifier.VerifyTable(lara()) && VerifyOffset(verifier, VT_ROOMS) && @@ -7595,6 +7668,9 @@ struct SaveGameBuilder { void add_level(flatbuffers::Offset level) { fbb_.AddOffset(SaveGame::VT_LEVEL, level); } + void add_camera(flatbuffers::Offset camera) { + fbb_.AddOffset(SaveGame::VT_CAMERA, camera); + } void add_lara(flatbuffers::Offset lara) { fbb_.AddOffset(SaveGame::VT_LARA, lara); } @@ -7758,6 +7834,7 @@ inline flatbuffers::Offset CreateSaveGame( flatbuffers::Offset header = 0, flatbuffers::Offset game = 0, flatbuffers::Offset level = 0, + flatbuffers::Offset camera = 0, flatbuffers::Offset lara = 0, flatbuffers::Offset>> rooms = 0, flatbuffers::Offset>> items = 0, @@ -7856,6 +7933,7 @@ inline flatbuffers::Offset CreateSaveGame( builder_.add_items(items); builder_.add_rooms(rooms); builder_.add_lara(lara); + builder_.add_camera(camera); builder_.add_level(level); builder_.add_game(game); builder_.add_header(header); @@ -7873,6 +7951,7 @@ inline flatbuffers::Offset CreateSaveGameDirect( flatbuffers::Offset header = 0, flatbuffers::Offset game = 0, flatbuffers::Offset level = 0, + flatbuffers::Offset camera = 0, flatbuffers::Offset lara = 0, const std::vector> *rooms = nullptr, const std::vector> *items = nullptr, @@ -7959,6 +8038,7 @@ inline flatbuffers::Offset CreateSaveGameDirect( header, game, level, + camera, lara, rooms__, items__, @@ -9195,6 +9275,35 @@ inline flatbuffers::Offset CreateLara(flatbuffers::FlatBufferBuilder &_fbb _weapons); } +inline CameraT *Camera::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Camera::UnPackTo(CameraT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = position(); if (_e) _o->position = std::unique_ptr(new TEN::Save::GameVector(*_e)); } + { auto _e = target(); if (_e) _o->target = std::unique_ptr(new TEN::Save::GameVector(*_e)); } +} + +inline flatbuffers::Offset Camera::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CameraT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateCamera(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateCamera(flatbuffers::FlatBufferBuilder &_fbb, const CameraT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CameraT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _position = _o->position ? _o->position.get() : 0; + auto _target = _o->target ? _o->target.get() : 0; + return TEN::Save::CreateCamera( + _fbb, + _position, + _target); +} + inline FixedCameraT *FixedCamera::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); @@ -10156,6 +10265,7 @@ inline void SaveGame::UnPackTo(SaveGameT *_o, const flatbuffers::resolver_functi { auto _e = header(); if (_e) _o->header = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = game(); if (_e) _o->game = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = level(); if (_e) _o->level = std::unique_ptr(_e->UnPack(_resolver)); } + { auto _e = camera(); if (_e) _o->camera = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = lara(); if (_e) _o->lara = std::unique_ptr(_e->UnPack(_resolver)); } { auto _e = rooms(); if (_e) { _o->rooms.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->rooms[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = items(); if (_e) { _o->items.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->items[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } @@ -10218,6 +10328,7 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild auto _header = _o->header ? CreateSaveGameHeader(_fbb, _o->header.get(), _rehasher) : 0; auto _game = _o->game ? CreateSaveGameStatistics(_fbb, _o->game.get(), _rehasher) : 0; auto _level = _o->level ? CreateSaveGameStatistics(_fbb, _o->level.get(), _rehasher) : 0; + auto _camera = _o->camera ? CreateCamera(_fbb, _o->camera.get(), _rehasher) : 0; auto _lara = _o->lara ? CreateLara(_fbb, _o->lara.get(), _rehasher) : 0; auto _rooms = _fbb.CreateVector> (_o->rooms.size(), [](size_t i, _VectorArgs *__va) { return CreateRoom(*__va->__fbb, __va->__o->rooms[i].get(), __va->__rehasher); }, &_va ); auto _items = _fbb.CreateVector> (_o->items.size(), [](size_t i, _VectorArgs *__va) { return CreateItem(*__va->__fbb, __va->__o->items[i].get(), __va->__rehasher); }, &_va ); @@ -10272,6 +10383,7 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild _header, _game, _level, + _camera, _lara, _rooms, _items, diff --git a/TombEngine/Specific/savegame/schema/ten_itemdata.fbs b/TombEngine/Specific/savegame/schema/ten_itemdata.fbs index 7e3d8166f..d14c69973 100644 --- a/TombEngine/Specific/savegame/schema/ten_itemdata.fbs +++ b/TombEngine/Specific/savegame/schema/ten_itemdata.fbs @@ -123,10 +123,6 @@ table Motorboat { } -table GameVector { - -} - table Wraith { } @@ -232,18 +228,14 @@ struct Vector4 { w: float; } +struct GameVector { + x: int32; + y: int32; + z: int32; + room_number: int32; +} + union ItemData { - /*byte, - ubyte, - bool, - short, - ushort, - int, - uint, - float, - long, - ulong, - double,*/ Int, Short, Float, @@ -261,7 +253,6 @@ union ItemData { Skidoo, UPV, Motorboat, - GameVector, Wraith, Rubberboat, Pushable, diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index 068d26b50..8e71756a2 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -303,6 +303,11 @@ table Lara { weapons: [CarriedWeaponInfo]; } +table Camera { + position: GameVector; + target: GameVector; +} + table FixedCamera { flags: int32; } @@ -518,6 +523,7 @@ table SaveGame { header: SaveGameHeader; game: SaveGameStatistics; level: SaveGameStatistics; + camera: Camera; lara: Lara; rooms: [Room]; items: [Item]; From 6b35cae8041f24fb20339d30a235b152a4861fd0 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:44:37 +0100 Subject: [PATCH 366/410] Fix garbage frame when switching from/to flyby camera --- TombEngine/Game/camera.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index cdfab3dcf..9232508b6 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1526,6 +1526,15 @@ void PrepareCamera() void UpdateCamera() { + // HACK: Disable interpolation when switching to/from flyby camera. + // When camera structs are converted to a class, this should go to getter/setter. -- Lwmte, 29.10.2024 + static bool spotcamSwitched = false; + if (UseSpotCam != spotcamSwitched) + { + Camera.DisableInterpolation = true; + spotcamSwitched = UseSpotCam; + } + if (UseSpotCam) { // Draw flyby cameras. From b3b835673165d490e81b5054e4bb209ae66b296c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 00:19:42 +0100 Subject: [PATCH 367/410] Fix title flyby interpolation --- TombEngine/Renderer/RendererDrawMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index c407a0fc0..e3558dee9 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1151,12 +1151,12 @@ namespace TEN::Renderer _stringsToDraw.clear(); _isLocked = false; + InterpolateCamera(interpFactor); DumpGameScene(); _context->ClearDepthStencilView(_backBuffer.DepthStencilView.Get(), D3D11_CLEAR_STENCIL | D3D11_CLEAR_DEPTH, 1.0f, 0); _context->ClearRenderTargetView(_backBuffer.RenderTargetView.Get(), Colors::Black); - InterpolateCamera(interpFactor); RenderInventoryScene(&_backBuffer, &_dumpScreenRenderTarget, 1.0f); _swapChain->Present(1, 0); From 29dff9016cfd6ea83562bd593853709dd0cdaae4 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 00:28:35 +0100 Subject: [PATCH 368/410] Rearrange control loop a little more --- TombEngine/Game/control/control.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 052a9c94a..dfebce414 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -217,21 +217,14 @@ GameStatus ControlPhase() DoFlipEffect(FlipEffect, LaraItem); - UpdateCamera(); - PlaySoundSources(); Sound_UpdateScene(); + UpdateCamera(); + // Post-loop script and event handling. g_GameScript->OnLoop(DELTA_TIME, true); - // Clear savegame loaded flag. - JustLoaded = false; - - // Update timers. - GameTimer++; - GlobalCounter++; - // Handle inventory, pause, load, save screens. auto result = HandleMenuCalls(isTitle); if (result != GameStatus::Normal) @@ -242,6 +235,13 @@ GameStatus ControlPhase() if (result != GameStatus::Normal) return result; + // Clear savegame loaded flag. + JustLoaded = false; + + // Update timers. + GameTimer++; + GlobalCounter++; + auto time2 = std::chrono::high_resolution_clock::now(); ControlPhaseTime = (std::chrono::duration_cast(time2 - time1)).count() / 1000000; From f9f727122b741d4a82346664a14b0c104c51b669 Mon Sep 17 00:00:00 2001 From: MontyTRC89 Date: Wed, 30 Oct 2024 06:17:32 +0100 Subject: [PATCH 369/410] Fixed controls settings rendering --- TombEngine/Game/control/control.cpp | 23 ++--- TombEngine/Game/control/control.h | 2 +- TombEngine/Game/gui.cpp | 131 ++++++++++++++++++---------- 3 files changed, 98 insertions(+), 58 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index de2121aaf..4627f9db1 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -127,7 +127,7 @@ void DrawPhase(bool isTitle, float interpolationFactor) g_Renderer.Lock(); } -GameStatus ControlPhase() +GameStatus ControlPhase(bool insideMenu) { auto time1 = std::chrono::high_resolution_clock::now(); bool isTitle = (CurrentLevel == 0); @@ -233,14 +233,17 @@ GameStatus ControlPhase() GlobalCounter++; // Handle inventory, pause, load, save screens. - auto result = HandleMenuCalls(isTitle); - if (result != GameStatus::Normal) - return result; + if (!insideMenu) + { + auto result = HandleMenuCalls(isTitle); + if (result != GameStatus::Normal) + return result; - // Handle global input events. - result = HandleGlobalInputEvents(isTitle); - if (result != GameStatus::Normal) - return result; + // Handle global input events. + result = HandleGlobalInputEvents(isTitle); + if (result != GameStatus::Normal) + return result; + } auto time2 = std::chrono::high_resolution_clock::now(); ControlPhaseTime = (std::chrono::duration_cast(time2 - time1)).count() / 1000000; @@ -542,7 +545,7 @@ GameStatus DoGameLoop(int levelIndex) // Before entering actual game loop, ControlPhase() must be // called once to sort out various runtime shenanigangs (e.g. hair). - status = ControlPhase(); + status = ControlPhase(false); g_Synchronizer.Init(); bool legacy30FpsDoneDraw = false; @@ -553,7 +556,7 @@ GameStatus DoGameLoop(int levelIndex) while (g_Synchronizer.Synced()) { - status = ControlPhase(); + status = ControlPhase(false); g_Synchronizer.Step(); legacy30FpsDoneDraw = false; diff --git a/TombEngine/Game/control/control.h b/TombEngine/Game/control/control.h index a51893e5d..646808f27 100644 --- a/TombEngine/Game/control/control.h +++ b/TombEngine/Game/control/control.h @@ -80,7 +80,7 @@ extern std::vector OutsideRoomTable[OUTSIDE_SIZE][OUTSIDE_SIZE]; void DrawPhase(bool isTitle, float interpolationFactor); -GameStatus ControlPhase(); +GameStatus ControlPhase(bool insideMenu); GameStatus DoLevel(int levelIndex, bool loadGame = false); GameStatus DoGameLoop(int levelIndex); void EndGameLoop(int levelIndex, GameStatus reason); diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index 737b4e07f..3d4c4fef5 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -684,77 +684,114 @@ namespace TEN::Gui { ClearAllActions(); + g_Synchronizer.Init(); + + bool legacy30FpsDoneDraw = false; + bool decreaseCounter = false; + while (CurrentSettings.NewKeyWaitTimer > 0.0f) { - CurrentSettings.NewKeyWaitTimer -= 1.0f; - if (CurrentSettings.NewKeyWaitTimer <= 0.0f) - CurrentSettings.NewKeyWaitTimer = 0.0f; + g_Synchronizer.Sync(); - UpdateInputActions(item); + while (g_Synchronizer.Synced()) + { + CurrentSettings.NewKeyWaitTimer -= 1.0f; + if (CurrentSettings.NewKeyWaitTimer <= 0.0f) + CurrentSettings.NewKeyWaitTimer = 0.0f; - if (CurrentSettings.IgnoreInput) - { - if (NoAction()) - CurrentSettings.IgnoreInput = false; - } - else - { - int selectedKey = 0; - for (selectedKey = 0; selectedKey < MAX_INPUT_SLOTS; selectedKey++) + if (!fromPauseMenu) { - if (KeyMap[selectedKey]) - break; + ControlPhase(true); + } + else + { + // Just for updating blink time + g_Renderer.PrepareScene(); } - if (selectedKey == MAX_INPUT_SLOTS) - selectedKey = 0; + UpdateInputActions(item); - if (selectedKey && !g_KeyNames[selectedKey].empty()) + if (CurrentSettings.IgnoreInput) { - unsigned int baseIndex = 0; - switch (MenuToDisplay) + if (NoAction()) + CurrentSettings.IgnoreInput = false; + } + else + { + int selectedKey = 0; + for (selectedKey = 0; selectedKey < MAX_INPUT_SLOTS; selectedKey++) { - case Menu::VehicleActions: - baseIndex = (unsigned int)GeneralActionStrings.size(); - break; - - case Menu::QuickActions: - baseIndex = unsigned int(GeneralActionStrings.size() + VehicleActionStrings.size()); - break; - - case Menu::MenuActions: - baseIndex = unsigned int(GeneralActionStrings.size() + VehicleActionStrings.size() + QuickActionStrings.size()); - break; - - default: - break; + if (KeyMap[selectedKey]) + break; } - Bindings[1][baseIndex + SelectedOption] = selectedKey; - DefaultConflict(); + if (selectedKey == MAX_INPUT_SLOTS) + selectedKey = 0; - CurrentSettings.NewKeyWaitTimer = 0.0f; - CurrentSettings.IgnoreInput = true; - return; + if (selectedKey && !g_KeyNames[selectedKey].empty()) + { + unsigned int baseIndex = 0; + switch (MenuToDisplay) + { + case Menu::VehicleActions: + baseIndex = (unsigned int)GeneralActionStrings.size(); + break; + + case Menu::QuickActions: + baseIndex = unsigned int(GeneralActionStrings.size() + VehicleActionStrings.size()); + break; + + case Menu::MenuActions: + baseIndex = unsigned int(GeneralActionStrings.size() + VehicleActionStrings.size() + QuickActionStrings.size()); + break; + + default: + break; + } + + Bindings[1][baseIndex + SelectedOption] = selectedKey; + DefaultConflict(); + + CurrentSettings.NewKeyWaitTimer = 0.0f; + CurrentSettings.IgnoreInput = true; + return; + } } + + g_Synchronizer.Step(); + + legacy30FpsDoneDraw = false; } - if (fromPauseMenu) + if (!g_Configuration.EnableHighFramerate) { - g_Renderer.RenderInventory(); - if (!g_Configuration.EnableHighFramerate) + if (!legacy30FpsDoneDraw) { - g_Renderer.Synchronize(); + if (fromPauseMenu) + { + g_Renderer.RenderInventory(); + } + else + { + g_Renderer.RenderTitle(0); + } + g_Renderer.Lock(); + legacy30FpsDoneDraw = true; } } else { - g_Renderer.RenderTitle(0); - if (!g_Configuration.EnableHighFramerate) + //g_Renderer.PrepareScene(); + + if (fromPauseMenu) { - g_Renderer.Synchronize(); + g_Renderer.RenderInventory(); } - ControlPhase(); + else + { + g_Renderer.RenderTitle(0); + } + g_Renderer.Lock(); } } } From f7f347986b8e534f72341f7a617182213c226e39 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 09:21:24 +0100 Subject: [PATCH 370/410] Decopypaste cam matrix update --- TombEngine/Renderer/RendererDrawMenu.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index ef0a538a8..11e5a6ebe 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1140,11 +1140,8 @@ namespace TEN::Renderer { if (_graphicsSettingsChanged) { - _currentGameCamera = RenderView(&Camera, Camera.Roll, Camera.Fov, 32, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView()), g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); - _gameCamera = RenderView(&Camera, Camera.Roll, Camera.Fov, 32, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView()), g_Configuration.ScreenWidth, g_Configuration.ScreenHeight); - + UpdateCameraMatrices(&Camera, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView())); Camera.DisableInterpolation = true; - DumpGameScene(); } From 9d31f26dd891475c01bfde45766f605e8b676259 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 10:42:55 +0100 Subject: [PATCH 371/410] Update CHANGELOG.md --- CHANGELOG.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f07852f04..bdb41890e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,8 +12,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed leveljump vehicle transfer. * Fixed weapons not properly hitting enemies. * Fixed falling through dynamic bridges that are moving upwards. -* Fixed laserhead teleporting Lara and making her invisible on death. -* Fixed sarcophagus pick-ups. +* Fixed Laserhead teleporting Lara and making her invisible on death. +* Fixed pick-ups from Sarcophagus objects. * Fixed issue with Lara not rotating together with bridges while picking up items. * Fixed ghost collision with objects with zero bounds. * Fixed several binocular bugs. @@ -22,20 +22,20 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed camera position after loading a savegame. -* Fixed AI for TR2 skidoo driver and worker with shotgun. -* Fixed ember emitter crashing when ocb is between -1 and -10. -* Fixed electric cleaner and squishy block not detecting collision with certain block heights. -* Fixed squishy blocks crashing the level. +* Fixed AI for TR2 Skidoo driver and Worker with shotgun. +* Fixed Ember Emitter crashing when ocb is between -1 and -10. +* Fixed Electric Cleaner and Squishy Block not detecting collision with certain block heights. +* Fixed Squishy Blocks crashing the level. * Fixed Larson and Pierre pathfinding. +* Fixed Dart Emitters failing with antitrigger. +* Fixed Homing Dart Emitter spawning darts continously when player is on its trigger. +* Fixed Four Blade Trap floor and ceiling collision. +* Fixed Joby Spikes collision and deformation. +* Fixed Sentry Gun joint rotation. +* Fixed Teeth Spikes not triggering the player impale animation. +* Fixed TR4 Mine crash with OCB 1 when triggered. +* Fixed cases where Atlantean Mutant's bombs cause the game to crash. * Fixed torch flame delay when the player throws or drops a torch. -* Fixed dart emitters failing with antitrigger. -* Fixed homing dart emitter spawning darts continously when player is on its trigger. -* Fixed four blade trap floor and ceiling collision. -* Fixed Joby spikes collision and deformation. -* Fixed sentry gun joint rotation. -* Fixed teeth spikes not triggering the player impale animation. -* Fixed TR4 mine crash with OCB 1 when triggered. -* Fixed cases where Atlantean mutant's bombs cause the game to crash. * Fixed display sprites and display strings rendering in the inventory background. * Fixed young Lara hair drawing. https://tombengine.com/docs/level-settings/#young_lara @@ -43,7 +43,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added high framerate mode (also known as 60 FPS mode). * Added a customisable global lensflare effect. https://tombengine.com/docs/level-settings/#lensflare -* Added a customisable starry sky and meteor effect (based on TR5). https://tombengine.com/docs/level-settings/#stars +* Added a customisable starry sky and meteor effect. https://tombengine.com/docs/level-settings/#stars * Added the ability to display "Lara's Home" entry in the main menu. * Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. From e936507b529e5f0276206d92f2163a3c6ec27911 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:04:06 +0200 Subject: [PATCH 372/410] Update README.md --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fd3834ff5..a18ba1833 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,12 @@ ![Logo](https://github.com/MontyTRC89/TombEngine/assets/80340234/f22c9ca9-7159-467f-b8ad-7bb32274a278) -In the year 2000, Core Design granted us a great gift: their TR4-based Level Editor, which allowed people to create custom levels. It was, unfortunately, quite limited, hence why over the decades it was upgraded massively with fan patcher projects such as Tomb Raider Engine Patcher (TREP) and Tomb Raider Next Generation (TRNG). - -TombEngine (TEN) is a new, open-source engine which aims to abolish all limits, fix bugs from the original games, introduce new features while refining old ones, and provide for a refined, user-friendly level creation process. Current support includes: +TombEngine (TEN) is an open-source, custom level engine which aims to abolish limits and fix bugs of the classic Tomb Raider games, introduce new features while refining old ones, and provide user-friendly level creation process. Current support includes: - Lua (as the native scripting language) -- All objects from the classic series (1-5) -- Many more exciting gameplay functionalities such as diagonal shimmying and expanded crawlspace flexibility -- An enlarged 2D map, allowing for the creation of massive levels (imagine one big level may previously have been split into five!) +- Many objects from the original series (1-5) +- Support for high framerate, antialiasing, mipmapping and SSAO +- Full diagonal geometry support +- Uncapped 2D map - A streamlined player control scheme. If you would like to participate in TEN discussion with other TEN devs whether it is contributing, bugs or general discussion, then join this discord server: https://discord.gg/h5tUYFmres From 5b4b60fcda547ccd848cb4ea8f9ee22c743bb3cc Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:06:38 +0200 Subject: [PATCH 373/410] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a18ba1833..980f0aff7 100644 --- a/README.md +++ b/README.md @@ -35,5 +35,5 @@ Visual Studio may also warn about NuGet packages. To fix: 4) Compile again and once done, you should be able to compile a level with TombEditor and run it in TEN. # Disclaimer -We do not and have never worked for Core Design, Eidos Interactive, or Square Enix. This is a hobby project. Tomb Raider is a registered trademark of Square Enix; TombEngine is not be sold. The code is open-source to encourage contributions and to be used for study purposes. We are not responsible for illegal uses of this source code. This source code is released as-is and continues to be maintained by non-paid contributors in their free time. +This is a community project which is not affiliated with Core Design, Eidos Interactive, or Square Enix. Tomb Raider is a registered trademark of Square Enix; TombEngine is not be sold. The code is open-source to encourage contributions and to be used for study purposes. We are not responsible for illegal uses of this source code. This source code is released as-is and continues to be maintained by non-paid contributors in their free time. From 7f584c76aad9f3154450987883de2406b3d51023 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:30:06 +0200 Subject: [PATCH 374/410] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 980f0aff7..f08d7c4be 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ TombEngine (TEN) is an open-source, custom level engine which aims to abolish li - Many objects from the original series (1-5) - Support for high framerate, antialiasing, mipmapping and SSAO - Full diagonal geometry support -- Uncapped 2D map +- Uncapped map size - A streamlined player control scheme. If you would like to participate in TEN discussion with other TEN devs whether it is contributing, bugs or general discussion, then join this discord server: https://discord.gg/h5tUYFmres From 8afb19cdd072edf851dc44dfd11661fec5dd5e49 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Wed, 30 Oct 2024 16:14:47 +0200 Subject: [PATCH 375/410] Update pull_request_template.md --- pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pull_request_template.md b/pull_request_template.md index b4eb2e74e..9be755808 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,4 +1,4 @@ -## todo +## Checklist - [ ] I have added a changelog entry to CHANGELOG.md file on the branch/fork (if it is an internal change then it is not needed) - [ ] Pull request meets the Coding Conventions standards: https://github.com/MontyTRC89/TombEngine/blob/master/CONTRIBUTING.md#coding-conventions From cbcbde8e6d010b164f11480f371bc28b2826bdaa Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:36:37 +0100 Subject: [PATCH 376/410] Update post-build events and automatically copy scripts --- TombEngine/TombEngine.vcxproj | 116 +++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 30 deletions(-) diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 67b70dfb3..5d709b98c 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -139,20 +139,34 @@ - CD $(ProjectDir)..\Documentation\ + CD "$(ProjectDir)..\Documentation\" CALL compile.bat . -CD $(ProjectDir)Specific\savegame\schema\ +CD "$(ProjectDir)Specific\savegame\schema\" CALL gen.bat -md "$(SolutionDir)Build\$(Configuration)\Shaders" -xcopy /Y /D "$(ProjectDir)Shaders\*.*" "$(SolutionDir)Build\$(Configuration)\Shaders\" -xcopy /Y /D "$(ProjectDir)Shaders\HUD\*.hlsl" "$(SolutionDir)Build\$(Configuration)\Shaders\HUD\" +SET BuildDir=$(SolutionDir)Build\$(Configuration) +SET ShaderDir=%BuildDir%\Shaders +SET ScriptsDir=%BuildDir%\Scripts +SET EngineDir=%ScriptsDir%\Engine -xcopy /Y "$(SolutionDir)Libs\bass\x86\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\lua\x86\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\ois\x86\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" +if not exist %ShaderDir% mkdir %ShaderDir% +if not exist %ScriptsDir% mkdir %ScriptsDir% +if not exist %EngineDir% mkdir %EngineDir% + +xcopy /D /Y /I /E "$(ProjectDir)Shaders\*.*" %ShaderDir% + +xcopy /Y "$(SolutionDir)Libs\bass\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\lua\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\ois\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + +xcopy /D /Y /I /E "$(SolutionDir)Scripts\Engine\*.*" %EngineDir% +xcopy /D /Y "$(SolutionDir)Scripts\SystemStrings.lua" %ScriptsDir% + +if not exist "%ScriptsDir%\Gameflow.lua" xcopy /Y "$(SolutionDir)Scripts\Gameflow.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Settings.lua" xcopy /Y "$(SolutionDir)Scripts\Settings.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.lua" %ScriptsDir% Generating documentation, savegame flatbuffer and copying needed files... @@ -190,20 +204,34 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" - CD $(ProjectDir)..\Documentation\ + CD "$(ProjectDir)..\Documentation\" CALL compile.bat . -CD $(ProjectDir)Specific\savegame\schema\ +CD "$(ProjectDir)Specific\savegame\schema\" CALL gen.bat -md "$(SolutionDir)Build\$(Configuration)\Shaders" -xcopy /Y /D "$(ProjectDir)Shaders\*.*" "$(SolutionDir)Build\$(Configuration)\Shaders\" -xcopy /Y /D "$(ProjectDir)Shaders\HUD\*.hlsl" "$(SolutionDir)Build\$(Configuration)\Shaders\HUD\" +SET BuildDir=$(SolutionDir)Build\$(Configuration) +SET ShaderDir=%BuildDir%\Shaders +SET ScriptsDir=%BuildDir%\Scripts +SET EngineDir=%ScriptsDir%\Engine + +if not exist %ShaderDir% mkdir %ShaderDir% +if not exist %ScriptsDir% mkdir %ScriptsDir% +if not exist %EngineDir% mkdir %EngineDir% + +xcopy /D /Y /I /E "$(ProjectDir)Shaders\*.*" %ShaderDir% xcopy /Y "$(SolutionDir)Libs\bass\x64\*.dll" "$(TargetDir)" xcopy /Y "$(SolutionDir)Libs\lua\x64\*.dll" "$(TargetDir)" xcopy /Y "$(SolutionDir)Libs\ois\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + +xcopy /D /Y /I /E "$(SolutionDir)Scripts\Engine\*.*" %EngineDir% +xcopy /D /Y "$(SolutionDir)Scripts\SystemStrings.lua" %ScriptsDir% + +if not exist "%ScriptsDir%\Gameflow.lua" xcopy /Y "$(SolutionDir)Scripts\Gameflow.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Settings.lua" xcopy /Y "$(SolutionDir)Scripts\Settings.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.lua" %ScriptsDir% Generating documentation, savegame flatbuffer and copying needed files... @@ -254,20 +282,34 @@ del "$(TargetDir)*.exp" /q del "$(TargetDir)OIS_d.dll" /q - CD $(ProjectDir)..\Documentation\ + CD "$(ProjectDir)..\Documentation\" CALL compile.bat . -CD $(ProjectDir)Specific\savegame\schema\ +CD "$(ProjectDir)Specific\savegame\schema\" CALL gen.bat -md "$(SolutionDir)Build\$(Configuration)\Shaders" -xcopy /Y /D "$(ProjectDir)Shaders\*.*" "$(SolutionDir)Build\$(Configuration)\Shaders\" -xcopy /Y /D "$(ProjectDir)Shaders\HUD\*.hlsl" "$(SolutionDir)Build\$(Configuration)\Shaders\HUD\" +SET BuildDir=$(SolutionDir)Build\$(Configuration) +SET ShaderDir=%BuildDir%\Shaders +SET ScriptsDir=%BuildDir%\Scripts +SET EngineDir=%ScriptsDir%\Engine -xcopy /Y "$(SolutionDir)Libs\bass\x86\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\lua\x86\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\ois\x86\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" +if not exist %ShaderDir% mkdir %ShaderDir% +if not exist %ScriptsDir% mkdir %ScriptsDir% +if not exist %EngineDir% mkdir %EngineDir% + +xcopy /D /Y /I /E "$(ProjectDir)Shaders\*.*" %ShaderDir% + +xcopy /Y "$(SolutionDir)Libs\bass\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\lua\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\ois\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + +xcopy /D /Y /I /E "$(SolutionDir)Scripts\Engine\*.*" %EngineDir% +xcopy /D /Y "$(SolutionDir)Scripts\SystemStrings.lua" %ScriptsDir% + +if not exist "%ScriptsDir%\Gameflow.lua" xcopy /Y "$(SolutionDir)Scripts\Gameflow.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Settings.lua" xcopy /Y "$(SolutionDir)Scripts\Settings.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.lua" %ScriptsDir% Generating documentation, savegame flatbuffer and copying needed files... @@ -319,20 +361,34 @@ del "$(TargetDir)*.exp" /q del "$(TargetDir)OIS_d.dll" /q - CD $(ProjectDir)..\Documentation\ + CD "$(ProjectDir)..\Documentation\" CALL compile.bat . -CD $(ProjectDir)Specific\savegame\schema\ +CD "$(ProjectDir)Specific\savegame\schema\" CALL gen.bat -md "$(SolutionDir)Build\$(Configuration)\Shaders" -xcopy /Y /D "$(ProjectDir)Shaders\*.*" "$(SolutionDir)Build\$(Configuration)\Shaders\" -xcopy /Y /D "$(ProjectDir)Shaders\HUD\*.hlsl" "$(SolutionDir)Build\$(Configuration)\Shaders\HUD\" +SET BuildDir=$(SolutionDir)Build\$(Configuration) +SET ShaderDir=%BuildDir%\Shaders +SET ScriptsDir=%BuildDir%\Scripts +SET EngineDir=%ScriptsDir%\Engine + +if not exist %ShaderDir% mkdir %ShaderDir% +if not exist %ScriptsDir% mkdir %ScriptsDir% +if not exist %EngineDir% mkdir %EngineDir% + +xcopy /D /Y /I /E "$(ProjectDir)Shaders\*.*" %ShaderDir% xcopy /Y "$(SolutionDir)Libs\bass\x64\*.dll" "$(TargetDir)" xcopy /Y "$(SolutionDir)Libs\lua\x64\*.dll" "$(TargetDir)" xcopy /Y "$(SolutionDir)Libs\ois\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" + +xcopy /D /Y /I /E "$(SolutionDir)Scripts\Engine\*.*" %EngineDir% +xcopy /D /Y "$(SolutionDir)Scripts\SystemStrings.lua" %ScriptsDir% + +if not exist "%ScriptsDir%\Gameflow.lua" xcopy /Y "$(SolutionDir)Scripts\Gameflow.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Settings.lua" xcopy /Y "$(SolutionDir)Scripts\Settings.lua" %ScriptsDir% +if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.lua" %ScriptsDir% Generating documentation, savegame flatbuffer and copying needed files... From 20c6c6f95cef6b0c0c1c11a791abfc4682f75b81 Mon Sep 17 00:00:00 2001 From: Sezz Date: Thu, 31 Oct 2024 21:09:26 +1100 Subject: [PATCH 377/410] Reduce distance for water tread climb out check --- TombEngine/Game/Lara/lara_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 4f2ff8693..a909c1aba 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -928,7 +928,7 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) int frontFloor = NO_HEIGHT; if (coll->Front.Bridge != NO_VALUE) { - auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, BLOCK(0.5f), -BLOCK(0.5f)); + auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, BLOCK(0.2f), -BLOCK(0.5f)); frontFloor = (pointColl.GetFloorHeight() - item->Pose.Position.y); } else @@ -936,7 +936,7 @@ bool TestLaraWaterClimbOut(ItemInfo* item, CollisionInfo* coll) int yOffset = CLICK(1.25f); while (yOffset > -CLICK(2)) { - auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, BLOCK(0.5f), yOffset); + auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, BLOCK(0.2f), yOffset); frontFloor = pointColl.GetFloorHeight() - item->Pose.Position.y; if (frontFloor > -CLICK(2) && From 3a928a99a9ea885dc8881a649ed5b6f0ec1c74ef Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:45:07 +0100 Subject: [PATCH 378/410] Fix build action paths --- TombEngine/TombEngine.vcxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 5d709b98c..0ff6b4b44 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -156,10 +156,10 @@ if not exist %EngineDir% mkdir %EngineDir% xcopy /D /Y /I /E "$(ProjectDir)Shaders\*.*" %ShaderDir% -xcopy /Y "$(SolutionDir)Libs\bass\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\lua\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\ois\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\bass\x86\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\lua\x86\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\ois\x86\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" xcopy /D /Y /I /E "$(SolutionDir)Scripts\Engine\*.*" %EngineDir% xcopy /D /Y "$(SolutionDir)Scripts\SystemStrings.lua" %ScriptsDir% @@ -299,10 +299,10 @@ if not exist %EngineDir% mkdir %EngineDir% xcopy /D /Y /I /E "$(ProjectDir)Shaders\*.*" %ShaderDir% -xcopy /Y "$(SolutionDir)Libs\bass\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\lua\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\ois\x64\*.dll" "$(TargetDir)" -xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\bass\x86\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\lua\x86\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\ois\x86\*.dll" "$(TargetDir)" +xcopy /Y "$(SolutionDir)Libs\zlib\x86\*.dll" "$(TargetDir)" xcopy /D /Y /I /E "$(SolutionDir)Scripts\Engine\*.*" %EngineDir% xcopy /D /Y "$(SolutionDir)Scripts\SystemStrings.lua" %ScriptsDir% From 61e82c00333630a9e235ccb663594d3e2551847b Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:46:23 +0100 Subject: [PATCH 379/410] Throw warning instead of error if level script was not found --- TombEngine/Game/control/control.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index a843c9567..727b7ab2f 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -2,6 +2,7 @@ #include "Game/control/control.h" #include +#include #include "Game/camera.h" #include "Game/collision/collide_room.h" @@ -458,7 +459,13 @@ void InitializeScripting(int levelIndex, LevelLoadType type) // Run level script if it exists. if (!level.ScriptFileName.empty()) { - g_GameScript->ExecuteScriptFile(g_GameFlow->GetGameDir() + level.ScriptFileName); + const std::string levelScriptName = g_GameFlow->GetGameDir() + level.ScriptFileName; + + if (std::filesystem::is_regular_file(levelScriptName)) + g_GameScript->ExecuteScriptFile(levelScriptName); + else + TENLog("Level script not found: " + levelScriptName, LogLevel::Warning); + g_GameScript->InitCallbacks(); g_GameStringsHandler->SetCallbackDrawString([](const std::string& key, D3DCOLOR color, const Vec2& pos, float scale, int flags) { From dbe1a596506815c26c0d90bbaf7e9a01f800b468 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:17:23 +0100 Subject: [PATCH 380/410] Debug portals --- TombEngine/Game/camera.cpp | 28 ++++++++++++++++++++++++ TombEngine/Game/camera.h | 1 + TombEngine/Renderer/RendererDrawMenu.cpp | 4 ++++ TombEngine/Renderer/RendererEnums.h | 1 + 4 files changed, 34 insertions(+) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 9232508b6..24f6f7d9f 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -5,6 +5,7 @@ #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" #include "Game/control/los.h" +#include "Game/Debug/Debug.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" #include "Game/effects/weather.h" @@ -21,6 +22,7 @@ #include "Sound/sound.h" #include "Specific/Input/Input.h" #include "Specific/level.h" +#include "Specific/winmain.h" using namespace TEN::Collision::Point; @@ -1549,6 +1551,32 @@ void UpdateCamera() // Update cameras matrices there, after having done all the possible camera logic. g_Renderer.UpdateCameraMatrices(&Camera, BLOCK(g_GameFlow->GetLevel(CurrentLevel)->GetFarView())); + + DrawPortals(); +} + +void DrawPortals() +{ + if (!DebugMode) + return; + + for (auto& number : g_Level.Rooms[Camera.pos.RoomNumber].NeighborRoomNumbers) + { + auto& room = g_Level.Rooms[number]; + + auto p = room.Position.ToVector3(); + + for (auto& door : room.doors) + { + DrawDebugTriangle(door.vertices[0] + p, door.vertices[1] + p, door.vertices[2] + p, Color(1.0f, 1.0f, 0.0f, 0.2f), RendererDebugPage::PortalDebug); + DrawDebugTriangle(door.vertices[2] + p, door.vertices[3] + p, door.vertices[0] + p, Color(1.0f, 1.0f, 0.0f, 0.2f), RendererDebugPage::PortalDebug); + + auto center = p + (door.vertices[0] + door.vertices[1] + door.vertices[2] + door.vertices[3]) * 0.25f; + auto target = center + door.normal * 128.0f; + + DrawDebugLine(center, target, Color(1.0f, 1.0f, 0.0f, 1.0f), RendererDebugPage::PortalDebug); + } + } } void UpdateMikePos(const ItemInfo& item) diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 961c00ae9..59db6e4f8 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -120,6 +120,7 @@ void SetCinematicBars(float height, float speed); void ClearCinematicBars(); void PrepareCamera(); void UpdateCamera(); +void DrawPortals(); void UpdateFadeScreenAndCinematicBars(); void UpdateMikePos(const ItemInfo& item); diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 11e5a6ebe..7741c23b7 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1351,6 +1351,10 @@ namespace TEN::Renderer PrintDebugMessage("WIREFRAME MODE"); break; + case RendererDebugPage::PortalDebug: + PrintDebugMessage("PORTAL DEBUG"); + break; + default: break; } diff --git a/TombEngine/Renderer/RendererEnums.h b/TombEngine/Renderer/RendererEnums.h index 69fa97d1e..38c044480 100644 --- a/TombEngine/Renderer/RendererEnums.h +++ b/TombEngine/Renderer/RendererEnums.h @@ -149,6 +149,7 @@ enum class RendererDebugPage CollisionStats, PathfindingStats, WireframeMode, + PortalDebug, Count }; From 55c50704532ab9aae711ce2991e3928171accfd3 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:31:10 +0100 Subject: [PATCH 381/410] Update camera.cpp --- TombEngine/Game/camera.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 24f6f7d9f..c4633f30d 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1557,6 +1557,9 @@ void UpdateCamera() void DrawPortals() { + static constexpr auto extColor = Color(1.0f, 1.0f, 0.0f, 0.15f); + static constexpr auto intColor = Color(1.0f, 0.0f, 0.0f, 0.15f); + if (!DebugMode) return; @@ -1565,16 +1568,17 @@ void DrawPortals() auto& room = g_Level.Rooms[number]; auto p = room.Position.ToVector3(); + auto color = number == Camera.pos.RoomNumber ? intColor : extColor; for (auto& door : room.doors) { - DrawDebugTriangle(door.vertices[0] + p, door.vertices[1] + p, door.vertices[2] + p, Color(1.0f, 1.0f, 0.0f, 0.2f), RendererDebugPage::PortalDebug); - DrawDebugTriangle(door.vertices[2] + p, door.vertices[3] + p, door.vertices[0] + p, Color(1.0f, 1.0f, 0.0f, 0.2f), RendererDebugPage::PortalDebug); + DrawDebugTriangle(door.vertices[0] + p, door.vertices[1] + p, door.vertices[2] + p, color, RendererDebugPage::PortalDebug); + DrawDebugTriangle(door.vertices[2] + p, door.vertices[3] + p, door.vertices[0] + p, color, RendererDebugPage::PortalDebug); auto center = p + (door.vertices[0] + door.vertices[1] + door.vertices[2] + door.vertices[3]) * 0.25f; auto target = center + door.normal * 128.0f; - DrawDebugLine(center, target, Color(1.0f, 1.0f, 0.0f, 1.0f), RendererDebugPage::PortalDebug); + DrawDebugLine(center, target, color, RendererDebugPage::PortalDebug); } } } From 00cc4b93a90a2ee8aa29311fd87cf678b453154f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:46:26 +0100 Subject: [PATCH 382/410] Move some text stats to portal debug page --- TombEngine/Renderer/RendererDraw.cpp | 5 ++--- TombEngine/Renderer/RendererDrawMenu.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp index 48357b4b9..f0e73c32a 100644 --- a/TombEngine/Renderer/RendererDraw.cpp +++ b/TombEngine/Renderer/RendererDraw.cpp @@ -10,6 +10,7 @@ #include "Game/camera.h" #include "Game/control/control.h" #include "Game/control/volume.h" +#include "Game/effects/DisplaySprite.h" #include "Game/effects/Hair.h" #include "Game/effects/tomb4fx.h" #include "Game/effects/weather.h" @@ -27,12 +28,10 @@ #include "Objects/TR5/Emitter/tr5_rats_emitter.h" #include "Renderer/RenderView.h" #include "Renderer/Renderer.h" +#include "Renderer/Structures/RendererSortableObject.h" #include "Specific/configuration.h" #include "Specific/level.h" #include "Specific/winmain.h" -#include "Renderer/Structures/RendererSortableObject.h" -#include "Game/effects/weather.h" -#include "Game/effects/DisplaySprite.h" using namespace std::chrono; using namespace TEN::Effects::Hair; diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index 7741c23b7..d21e63fc3 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1178,7 +1178,7 @@ namespace TEN::Renderer void Renderer::DrawDebugInfo(RenderView& view) { - if (CurrentLevel == 0) + if (!DebugMode || CurrentLevel == 0) return; _currentLineHeight = DISPLAY_SPACE_RES.y / 30; @@ -1203,7 +1203,6 @@ namespace TEN::Renderer PrintDebugMessage("Update time: %d", _timeUpdate); PrintDebugMessage("Frame time: %d", _timeFrame); PrintDebugMessage("ControlPhase() time: %d", ControlPhaseTime); - PrintDebugMessage("Room collector time: %d", _timeRoomsCollector); PrintDebugMessage("TOTAL draw calls: %d", _numDrawCalls); PrintDebugMessage(" Rooms: %d", _numRoomsDrawCalls); PrintDebugMessage(" Movables: %d", _numMoveablesDrawCalls); @@ -1220,10 +1219,6 @@ namespace TEN::Renderer PrintDebugMessage(" Sprites: %d", _numSortedSpritesDrawCalls); PrintDebugMessage("SHADOW MAP draw calls: %d", _numShadowMapDrawCalls); PrintDebugMessage("DEBRIS draw calls: %d", _numDebrisDrawCalls); - PrintDebugMessage("Rooms: %d", view.RoomsToDraw.size()); - PrintDebugMessage(" CheckPortal() calls: %d", _numCheckPortalCalls); - PrintDebugMessage(" GetVisibleRooms() calls: %d", _numGetVisibleRoomsCalls); - PrintDebugMessage(" Dot products: %d", _numDotProducts); _spriteBatch->Begin(SpriteSortMode_Deferred, _renderStates->Opaque()); @@ -1353,6 +1348,11 @@ namespace TEN::Renderer case RendererDebugPage::PortalDebug: PrintDebugMessage("PORTAL DEBUG"); + PrintDebugMessage("Room collector time: %d", _timeRoomsCollector); + PrintDebugMessage("Rooms: %d", view.RoomsToDraw.size()); + PrintDebugMessage(" CheckPortal() calls: %d", _numCheckPortalCalls); + PrintDebugMessage(" GetVisibleRooms() calls: %d", _numGetVisibleRoomsCalls); + PrintDebugMessage(" Dot products: %d", _numDotProducts); break; default: @@ -1369,7 +1369,7 @@ namespace TEN::Renderer { page = (int)RendererDebugPage::Count - 1; } - else if (page > (int)RendererDebugPage::WireframeMode) + else if (page >= (int)RendererDebugPage::Count) { page = (int)RendererDebugPage::None; } From f00576340af7b8a28bfdbf6b65ac101e9eba2774 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 08:47:02 +0100 Subject: [PATCH 383/410] Always treat static meshes as solid when Lara is in the shimmy mode --- CHANGELOG.md | 1 + TombEngine/Game/Lara/lara.cpp | 3 +++ TombEngine/Game/Lara/lara_hang.cpp | 4 ++-- TombEngine/Game/Lara/lara_tests.cpp | 1 + TombEngine/Game/collision/collide_item.cpp | 9 +++++++-- TombEngine/Game/collision/collide_room.h | 5 +++-- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb41890e..8aad736a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed ghost collision with objects with zero bounds. * Fixed several binocular bugs. * Fixed faulty death sectors. +* Fixed shimmy softlocks around static meshes with soft collision. * Fixed incorrect climbing out of water on bridge objects and in front of static meshes. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. diff --git a/TombEngine/Game/Lara/lara.cpp b/TombEngine/Game/Lara/lara.cpp index 957c96890..46b34aec8 100644 --- a/TombEngine/Game/Lara/lara.cpp +++ b/TombEngine/Game/Lara/lara.cpp @@ -356,6 +356,7 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll) coll->Setup.BlockMonkeySwingEdge = false; coll->Setup.EnableObjectPush = true; coll->Setup.EnableSpasm = true; + coll->Setup.ForceSolidStatics = false; coll->Setup.PrevPosition = item->Pose.Position; coll->Setup.PrevAnimObjectID = item->Animation.AnimObjectID; coll->Setup.PrevAnimNumber = item->Animation.AnimNumber; @@ -426,6 +427,7 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll) coll->Setup.BlockMonkeySwingEdge = false; coll->Setup.EnableObjectPush = true; coll->Setup.EnableSpasm = false; + coll->Setup.ForceSolidStatics = false; coll->Setup.PrevPosition = item->Pose.Position; // Handle look-around. @@ -498,6 +500,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll) coll->Setup.BlockMonkeySwingEdge = false; coll->Setup.EnableObjectPush = true; coll->Setup.EnableSpasm = false; + coll->Setup.ForceSolidStatics = false; coll->Setup.PrevPosition = item->Pose.Position; // Handle look-around. diff --git a/TombEngine/Game/Lara/lara_hang.cpp b/TombEngine/Game/Lara/lara_hang.cpp index f9dc87d44..432b1e1ba 100644 --- a/TombEngine/Game/Lara/lara_hang.cpp +++ b/TombEngine/Game/Lara/lara_hang.cpp @@ -146,10 +146,10 @@ void lara_col_hang(ItemInfo* item, CollisionInfo* coll) if (item->Animation.AnimNumber == LA_REACH_TO_HANG || item->Animation.AnimNumber == LA_HANG_IDLE) { - TestForObjectOnLedge(item, coll); - if (IsHeld(In::Forward)) { + TestForObjectOnLedge(item, coll); + if (coll->Front.Floor > -(CLICK(3.5f) - 46) && TestValidLedge(item, coll) && !coll->HitStatic) { diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index a909c1aba..484f70aba 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -141,6 +141,7 @@ bool TestLaraHang(ItemInfo* item, CollisionInfo* coll) coll->Setup.UpperFloorBound = -STEPUP_HEIGHT; coll->Setup.LowerCeilingBound = 0; coll->Setup.ForwardAngle = lara->Control.MoveAngle; + coll->Setup.ForceSolidStatics = true; // When Lara is about to move, use larger embed offset for stabilizing diagonal shimmying) int embedOffset = 4; diff --git a/TombEngine/Game/collision/collide_item.cpp b/TombEngine/Game/collision/collide_item.cpp index 2d5816904..eaaa9263b 100644 --- a/TombEngine/Game/collision/collide_item.cpp +++ b/TombEngine/Game/collision/collide_item.cpp @@ -939,6 +939,7 @@ void CollideBridgeItems(ItemInfo& item, CollisionInfo& coll, PointCollisionData& void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll) { + coll->HitStatic = false; coll->HitTallObject = false; for (auto i : g_Level.Rooms[item->RoomNumber].NeighborRoomNumbers) @@ -948,8 +949,12 @@ void CollideSolidStatics(ItemInfo* item, CollisionInfo* coll) for (auto& mesh : g_Level.Rooms[i].mesh) { - // Only process meshes which are visible and solid. - if (!(mesh.flags & StaticMeshFlags::SM_VISIBLE) || !(mesh.flags & StaticMeshFlags::SM_SOLID)) + // Only process meshes which are visible. + if (!(mesh.flags & StaticMeshFlags::SM_VISIBLE)) + continue; + + // Only process meshes which are solid, or if solid mode is set by the setup. + if (!coll->Setup.ForceSolidStatics && !(mesh.flags & StaticMeshFlags::SM_SOLID)) continue; float distance = Vector3i::Distance(item->Pose.Position, mesh.pos.Position); diff --git a/TombEngine/Game/collision/collide_room.h b/TombEngine/Game/collision/collide_room.h index 41af7775f..16ae61831 100644 --- a/TombEngine/Game/collision/collide_room.h +++ b/TombEngine/Game/collision/collide_room.h @@ -80,8 +80,9 @@ struct CollisionSetupData bool BlockMonkeySwingEdge = false; // Inquirers - bool EnableObjectPush = false; - bool EnableSpasm = false; + bool EnableObjectPush = false; + bool EnableSpasm = false; + bool ForceSolidStatics = false; // Previous parameters Vector3i PrevPosition = Vector3i::Zero; From c6e7fae88f6c79ce693e799ab02ba97fe6ed25f9 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 09:03:06 +0100 Subject: [PATCH 384/410] Display portal corners and camera room number in portal debug mode, reduce depth to 1 --- CHANGELOG.md | 1 + TombEngine/Game/camera.cpp | 10 ++++++++-- TombEngine/Game/room.cpp | 2 +- TombEngine/Game/room.h | 1 + TombEngine/Renderer/RendererDrawMenu.cpp | 1 + 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aad736a2..5e2455fe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. * Added visible mouse pointer in windowed mode. +* Added portal debug mode. * Added new sound conditions: Quicksand and Underwater. - Quicksand - sound effect plays when a moveable is in quicksand. - Underwater - sound plays when the camera is submerged. diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index c4633f30d..3046c22cc 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1563,7 +1563,10 @@ void DrawPortals() if (!DebugMode) return; - for (auto& number : g_Level.Rooms[Camera.pos.RoomNumber].NeighborRoomNumbers) + auto neighborRooms = GetNeighborRoomNumbers(Camera.pos.RoomNumber, 1); + neighborRooms.push_back(camera.pos.RoomNumber); + + for (auto& number : neighborRooms) { auto& room = g_Level.Rooms[number]; @@ -1575,8 +1578,11 @@ void DrawPortals() DrawDebugTriangle(door.vertices[0] + p, door.vertices[1] + p, door.vertices[2] + p, color, RendererDebugPage::PortalDebug); DrawDebugTriangle(door.vertices[2] + p, door.vertices[3] + p, door.vertices[0] + p, color, RendererDebugPage::PortalDebug); + DrawDebugLine(door.vertices[0] + p, door.vertices[2] + p, color, RendererDebugPage::PortalDebug); + DrawDebugLine(door.vertices[1] + p, door.vertices[3] + p, color, RendererDebugPage::PortalDebug); + auto center = p + (door.vertices[0] + door.vertices[1] + door.vertices[2] + door.vertices[3]) * 0.25f; - auto target = center + door.normal * 128.0f; + auto target = center + door.normal * CLICK(1); DrawDebugLine(center, target, color, RendererDebugPage::PortalDebug); } diff --git a/TombEngine/Game/room.cpp b/TombEngine/Game/room.cpp index 405a46c2d..ddeb7a57b 100644 --- a/TombEngine/Game/room.cpp +++ b/TombEngine/Game/room.cpp @@ -269,7 +269,7 @@ Vector3i GetRoomCenter(int roomNumber) room.Position.z + halfDepth); } -static std::vector GetNeighborRoomNumbers(int roomNumber, unsigned int searchDepth, std::vector& visitedRoomNumbers = std::vector{}) +std::vector GetNeighborRoomNumbers(int roomNumber, unsigned int searchDepth, std::vector& visitedRoomNumbers) { // Invalid room; return empty vector. if (g_Level.Rooms.size() <= roomNumber) diff --git a/TombEngine/Game/room.h b/TombEngine/Game/room.h index 4a111e3fa..8bf665efe 100644 --- a/TombEngine/Game/room.h +++ b/TombEngine/Game/room.h @@ -133,6 +133,7 @@ int IsRoomOutside(int x, int y, int z); void InitializeNeighborRoomList(); GameBoundingBox& GetBoundsAccurate(const MESH_INFO& mesh, bool getVisibilityBox); +std::vector GetNeighborRoomNumbers(int roomNumber, unsigned int searchDepth, std::vector& visitedRoomNumbers = std::vector{}); namespace TEN::Collision::Room { diff --git a/TombEngine/Renderer/RendererDrawMenu.cpp b/TombEngine/Renderer/RendererDrawMenu.cpp index d21e63fc3..c9fb4888b 100644 --- a/TombEngine/Renderer/RendererDrawMenu.cpp +++ b/TombEngine/Renderer/RendererDrawMenu.cpp @@ -1348,6 +1348,7 @@ namespace TEN::Renderer case RendererDebugPage::PortalDebug: PrintDebugMessage("PORTAL DEBUG"); + PrintDebugMessage("Camera RoomNumber: %d", Camera.pos.RoomNumber); PrintDebugMessage("Room collector time: %d", _timeRoomsCollector); PrintDebugMessage("Rooms: %d", view.RoomsToDraw.size()); PrintDebugMessage(" CheckPortal() calls: %d", _numCheckPortalCalls); From c6165da100a8bc70500956ef30d1a76bb3ab36d1 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 09:19:31 +0100 Subject: [PATCH 385/410] Update camera.cpp --- TombEngine/Game/camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 3046c22cc..1b9f49dac 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1564,7 +1564,7 @@ void DrawPortals() return; auto neighborRooms = GetNeighborRoomNumbers(Camera.pos.RoomNumber, 1); - neighborRooms.push_back(camera.pos.RoomNumber); + neighborRooms.push_back(Camera.pos.RoomNumber); for (auto& number : neighborRooms) { From b82054f1ad516e2ae8a676a17c5e2282a89042d9 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 21:45:51 +0100 Subject: [PATCH 386/410] Skip recompiling savegame.cpp, if flatbuffers schema files weren't changed --- TombEngine/TombEngine.vcxproj | 64 ++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 8 deletions(-) diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj index 0ff6b4b44..455bf7851 100644 --- a/TombEngine/TombEngine.vcxproj +++ b/TombEngine/TombEngine.vcxproj @@ -139,11 +139,35 @@ - CD "$(ProjectDir)..\Documentation\" -CALL compile.bat . + SETLOCAL EnableDelayedExpansion -CD "$(ProjectDir)Specific\savegame\schema\" -CALL gen.bat +SET SchemaDir=$(ProjectDir)Specific\savegame\schema +SET TimestampFile=$(TargetDir)flatbuffers.timestamp + +FOR %%F IN ("%SchemaDir%\ten_itemdata.fbs" "%SchemaDir%\ten_savegame.fbs") DO ( + SET "CurrentTimestamp=!CurrentTimestamp! %%~tF" +) + +IF EXIST "%TimestampFile%" ( + SET /P LastTimestamp=<"%TimestampFile%" +) + +SET CurrentTimestamp=%CurrentTimestamp: =% +SET LastTimestamp=%LastTimestamp: =% + +IF "%CurrentTimestamp%" == "%LastTimestamp%" ( + ECHO Skipping gen.bat, schema files are unchanged +) ELSE ( + ECHO Generating savegame code from flatbuffer schema... + CD "%SchemaDir%" + CALL gen.bat + ECHO !CurrentTimestamp! > "%TimestampFile%" +) + +ENDLOCAL + +CD "$(ProjectDir)..\Documentation\" +CALL compile.bat . SET BuildDir=$(SolutionDir)Build\$(Configuration) SET ShaderDir=%BuildDir%\Shaders @@ -204,11 +228,35 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings. - CD "$(ProjectDir)..\Documentation\" -CALL compile.bat . + SETLOCAL EnableDelayedExpansion -CD "$(ProjectDir)Specific\savegame\schema\" -CALL gen.bat +SET SchemaDir=$(ProjectDir)Specific\savegame\schema +SET TimestampFile=$(TargetDir)flatbuffers.timestamp + +FOR %%F IN ("%SchemaDir%\ten_itemdata.fbs" "%SchemaDir%\ten_savegame.fbs") DO ( + SET "CurrentTimestamp=!CurrentTimestamp! %%~tF" +) + +IF EXIST "%TimestampFile%" ( + SET /P LastTimestamp=<"%TimestampFile%" +) + +SET CurrentTimestamp=%CurrentTimestamp: =% +SET LastTimestamp=%LastTimestamp: =% + +IF "%CurrentTimestamp%" == "%LastTimestamp%" ( + ECHO Skipping gen.bat, schema files are unchanged +) ELSE ( + ECHO Generating savegame code from flatbuffer schema... + CD "%SchemaDir%" + CALL gen.bat + ECHO !CurrentTimestamp! > "%TimestampFile%" +) + +ENDLOCAL + +CD "$(ProjectDir)..\Documentation\" +CALL compile.bat . SET BuildDir=$(SolutionDir)Build\$(Configuration) SET ShaderDir=%BuildDir%\Shaders From 8060cc87069f7a0401293891492ed977476bdc13 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Fri, 1 Nov 2024 23:37:00 +0200 Subject: [PATCH 387/410] Update README.md --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f08d7c4be..52dab0c1e 100644 --- a/README.md +++ b/README.md @@ -21,18 +21,20 @@ To compile TEN, ensure you have installed: Steps: 1) Clone the repository to your GitHub Desktop -2) Launch TombEngine.sln and compile -3) Once compiled, create a separate folder to serve as your main TEN directory -4) Copy everything inside the Build folder to the main TEN directory -5) Copy the Scripts folder to your main TEN directory -6) Ensure you have the necessary level data and texture files as well -7) In the case Windows warns about missing DLLs, (bass.dll, etc.) copy the missing DLL files found inside the Libs folder to your main TEN directory. +2) Open TombEngine.sln +4) Compile the solution +5) Once compiled, create a separate folder to serve as your main TEN directory (or create test TEN project using TombIDE) +6) Copy everything inside the Build folder to the main TEN directory +7) Ensure you have the necessary level data and texture files as well +8) In the case Windows warns about missing DLLs, (bass.dll, etc.) copy the missing DLL files found inside the Libs folder to your main TEN directory. Visual Studio may also warn about NuGet packages. To fix: 1) Delete the Packages folder 2) Go back to Microsoft Visual Studio 3) Right-click on the TombEngine solution in the Solution Explorer tab and select "Restore NuGet Packages" -4) Compile again and once done, you should be able to compile a level with TombEditor and run it in TEN. +4) If it doesn't help, manually install `directxtk_desktop_2019` and `Microsoft.XAudio2.Redist` packages via NuGet Package Manager + +Once done, you should be able to build a level with TombEditor and run it in TEN. # Disclaimer This is a community project which is not affiliated with Core Design, Eidos Interactive, or Square Enix. Tomb Raider is a registered trademark of Square Enix; TombEngine is not be sold. The code is open-source to encourage contributions and to be used for study purposes. We are not responsible for illegal uses of this source code. This source code is released as-is and continues to be maintained by non-paid contributors in their free time. From e186f48b3faa9e19b981965777ad6f41cea36c24 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 2 Nov 2024 16:25:00 +1100 Subject: [PATCH 388/410] Conventions --- TombEngine/Game/camera.cpp | 68 ++++++++++++++--------------- TombEngine/Game/control/control.cpp | 7 ++- 2 files changed, 37 insertions(+), 38 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 1b9f49dac..67d375074 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -5,7 +5,6 @@ #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" #include "Game/control/los.h" -#include "Game/Debug/Debug.h" #include "Game/effects/debris.h" #include "Game/effects/effects.h" #include "Game/effects/weather.h" @@ -24,7 +23,6 @@ #include "Specific/level.h" #include "Specific/winmain.h" - using namespace TEN::Collision::Point; using namespace TEN::Effects::Environment; using namespace TEN::Entities::Generic; @@ -1526,6 +1524,38 @@ void PrepareCamera() } } +static void DrawPortals() +{ + constexpr auto EXT_COLOR = Color(1.0f, 1.0f, 0.0f, 0.15f); + constexpr auto INT_COLOR = Color(1.0f, 0.0f, 0.0f, 0.15f); + + if (!DebugMode) + return; + + auto neighborRoomNumbers = GetNeighborRoomNumbers(Camera.pos.RoomNumber, 1); + for (auto& roomNumber : neighborRoomNumbers) + { + const auto& room = g_Level.Rooms[roomNumber]; + + auto pos = room.Position.ToVector3(); + auto color = (roomNumber == Camera.pos.RoomNumber) ? INT_COLOR : EXT_COLOR; + + for (const auto& door : room.doors) + { + DrawDebugTriangle(door.vertices[0] + pos, door.vertices[1] + pos, door.vertices[2] + pos, color, RendererDebugPage::PortalDebug); + DrawDebugTriangle(door.vertices[2] + pos, door.vertices[3] + pos, door.vertices[0] + pos, color, RendererDebugPage::PortalDebug); + + DrawDebugLine(door.vertices[0] + pos, door.vertices[2] + pos, color, RendererDebugPage::PortalDebug); + DrawDebugLine(door.vertices[1] + pos, door.vertices[3] + pos, color, RendererDebugPage::PortalDebug); + + auto center = pos + ((door.vertices[0] + door.vertices[1] + door.vertices[2] + door.vertices[3]) / 4); + auto target = Geometry::TranslatePoint(center, door.normal, CLICK(1)); + + DrawDebugLine(center, target, color, RendererDebugPage::PortalDebug); + } + } +} + void UpdateCamera() { // HACK: Disable interpolation when switching to/from flyby camera. @@ -1555,40 +1585,6 @@ void UpdateCamera() DrawPortals(); } -void DrawPortals() -{ - static constexpr auto extColor = Color(1.0f, 1.0f, 0.0f, 0.15f); - static constexpr auto intColor = Color(1.0f, 0.0f, 0.0f, 0.15f); - - if (!DebugMode) - return; - - auto neighborRooms = GetNeighborRoomNumbers(Camera.pos.RoomNumber, 1); - neighborRooms.push_back(Camera.pos.RoomNumber); - - for (auto& number : neighborRooms) - { - auto& room = g_Level.Rooms[number]; - - auto p = room.Position.ToVector3(); - auto color = number == Camera.pos.RoomNumber ? intColor : extColor; - - for (auto& door : room.doors) - { - DrawDebugTriangle(door.vertices[0] + p, door.vertices[1] + p, door.vertices[2] + p, color, RendererDebugPage::PortalDebug); - DrawDebugTriangle(door.vertices[2] + p, door.vertices[3] + p, door.vertices[0] + p, color, RendererDebugPage::PortalDebug); - - DrawDebugLine(door.vertices[0] + p, door.vertices[2] + p, color, RendererDebugPage::PortalDebug); - DrawDebugLine(door.vertices[1] + p, door.vertices[3] + p, color, RendererDebugPage::PortalDebug); - - auto center = p + (door.vertices[0] + door.vertices[1] + door.vertices[2] + door.vertices[3]) * 0.25f; - auto target = center + door.normal * CLICK(1); - - DrawDebugLine(center, target, color, RendererDebugPage::PortalDebug); - } - } -} - void UpdateMikePos(const ItemInfo& item) { if (Camera.mikeAtLara) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 727b7ab2f..7f0fa21ca 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -459,12 +459,15 @@ void InitializeScripting(int levelIndex, LevelLoadType type) // Run level script if it exists. if (!level.ScriptFileName.empty()) { - const std::string levelScriptName = g_GameFlow->GetGameDir() + level.ScriptFileName; - + auto levelScriptName = g_GameFlow->GetGameDir() + level.ScriptFileName; if (std::filesystem::is_regular_file(levelScriptName)) + { g_GameScript->ExecuteScriptFile(levelScriptName); + } else + { TENLog("Level script not found: " + levelScriptName, LogLevel::Warning); + } g_GameScript->InitCallbacks(); g_GameStringsHandler->SetCallbackDrawString([](const std::string& key, D3DCOLOR color, const Vec2& pos, float scale, int flags) From d49d3227661167df5052e37a0fbaaa558a52400f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 07:24:52 +0100 Subject: [PATCH 389/410] Fix incorrect bridge thickness calculation --- TombEngine/Game/collision/floordata.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TombEngine/Game/collision/floordata.cpp b/TombEngine/Game/collision/floordata.cpp index cf34916e3..e59d89ae3 100644 --- a/TombEngine/Game/collision/floordata.cpp +++ b/TombEngine/Game/collision/floordata.cpp @@ -202,6 +202,9 @@ int FloorInfo::GetSurfaceHeight(const Vector3i& pos, bool isFloor) const const auto& bridgeItem = g_Level.Items[itemNumber]; const auto& bridge = GetBridgeObject(bridgeItem); + auto bridgeFloorHeight = bridge.GetFloorHeight(bridgeItem, pos); + auto bridgeCeilingHeight = bridge.GetCeilingHeight(bridgeItem, pos); + // 2.1) Get bridge surface height. auto bridgeSurfaceHeight = isFloor ? bridge.GetFloorHeight(bridgeItem, pos) : bridge.GetCeilingHeight(bridgeItem, pos); @@ -210,7 +213,8 @@ int FloorInfo::GetSurfaceHeight(const Vector3i& pos, bool isFloor) const // Use bridge midpoint to decide whether to return bridge height or room height, in case probe point // is located within the bridge. Without it, dynamic bridges may fail while Lara is standing on them. - int midpoint = (bridge.GetFloorBorder(bridgeItem) + bridge.GetCeilingBorder(bridgeItem)) / 2; + int thickness = bridge.GetCeilingBorder(bridgeItem) - bridge.GetFloorBorder(bridgeItem); + int midpoint = bridgeItem.Pose.Position.y + thickness / 2; // 2.2) Track closest floor or ceiling height. if (isFloor) From aac4316e71d79c2f88c3cd3da380609bece32cf1 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 08:31:28 +0100 Subject: [PATCH 390/410] Fixed incorrect swing ledge grabs with steep grab angles --- CHANGELOG.md | 1 + TombEngine/Game/Lara/lara_tests.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e2455fe9..bf71f85e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed several binocular bugs. * Fixed faulty death sectors. * Fixed shimmy softlocks around static meshes with soft collision. +* Fixed incorrect swing ledge grabs with steep grab angles. * Fixed incorrect climbing out of water on bridge objects and in front of static meshes. * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 484f70aba..416694185 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -747,11 +747,12 @@ bool TestHangSwingIn(ItemInfo* item, CollisionInfo* coll) auto* lara = GetLaraInfo(item); int y = item->Pose.Position.y; - auto probe = GetPointCollision(*item, item->Pose.Orientation.y, OFFSET_RADIUS(coll->Setup.Radius)); + auto probe = GetPointCollision(*item, item->Pose.Orientation.y, CLICK(1.5f)); - if ((probe.GetFloorHeight() - y) > 0 && - (probe.GetCeilingHeight() - y) < -CLICK(1.6f) && - probe.GetFloorHeight() != NO_HEIGHT) + if (probe.GetFloorHeight() != NO_HEIGHT && + probe.GetFloorHeight() - y > 0 && + probe.GetCeilingHeight() - y < -CLICK(1.6f) && + y - probe.GetCeilingHeight() - coll->Setup.Height > -CLICK(0.3f)) // Check if there is enough space above the ledge for Lara's hands / head { return true; } From 132517993b907f65dec78cea390205b4b1d5219d Mon Sep 17 00:00:00 2001 From: Sezz Date: Sat, 2 Nov 2024 18:55:41 +1100 Subject: [PATCH 391/410] Update hang swing in check --- TombEngine/Game/Lara/lara_tests.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/TombEngine/Game/Lara/lara_tests.cpp b/TombEngine/Game/Lara/lara_tests.cpp index 416694185..5748ca575 100644 --- a/TombEngine/Game/Lara/lara_tests.cpp +++ b/TombEngine/Game/Lara/lara_tests.cpp @@ -744,15 +744,16 @@ CornerTestResult TestItemAtNextCornerPosition(ItemInfo* item, CollisionInfo* col bool TestHangSwingIn(ItemInfo* item, CollisionInfo* coll) { - auto* lara = GetLaraInfo(item); + int vPos = item->Pose.Position.y; + auto pointColl = GetPointCollision(*item, item->Pose.Orientation.y, OFFSET_RADIUS(coll->Setup.Radius) + item->Animation.Velocity.z); - int y = item->Pose.Position.y; - auto probe = GetPointCollision(*item, item->Pose.Orientation.y, CLICK(1.5f)); + // 1) Test for wall. + if (pointColl.GetFloorHeight() == NO_HEIGHT) + return false; - if (probe.GetFloorHeight() != NO_HEIGHT && - probe.GetFloorHeight() - y > 0 && - probe.GetCeilingHeight() - y < -CLICK(1.6f) && - y - probe.GetCeilingHeight() - coll->Setup.Height > -CLICK(0.3f)) // Check if there is enough space above the ledge for Lara's hands / head + // 2) Test leg space. + if ((pointColl.GetFloorHeight() - vPos) > 0 && + (pointColl.GetCeilingHeight() - vPos) < -CLICK(1.6f)) { return true; } From 35319cc811d709b42e9c0978f05f60cbfe448866 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 14:30:24 +0300 Subject: [PATCH 392/410] Load after death (#1442) * Initial commit * Don't open load game dialog if no savegames are present * Block empty load menu only only on death events * Update CHANGELOG.md * Add braces and define constant --------- Co-authored-by: Sezz --- CHANGELOG.md | 1 + TombEngine/Game/control/control.cpp | 29 ++++++++++++++++------------- TombEngine/Game/gui.cpp | 7 +++++++ TombEngine/Game/savegame.cpp | 11 +++++++++++ TombEngine/Game/savegame.h | 1 + 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf71f85e6..8e4ce0504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added the ability to display "Lara's Home" entry in the main menu. * Added the ability to change pickup item count by modifying item hit points. * Added F12 as alternative to PrtSc for screenshots. +* Added ability to invoke load game dialog after death by pressing any key. * Added visible mouse pointer in windowed mode. * Added portal debug mode. * Added new sound conditions: Quicksand and Underwater. diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 7f0fa21ca..d41762444 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -90,6 +90,9 @@ using namespace TEN::Renderer; using namespace TEN::Entities::Creatures::TR3; using namespace TEN::Entities::Effects; +constexpr auto DEATH_NO_INPUT_TIMEOUT = 10 * FPS; +constexpr auto DEATH_INPUT_TIMEOUT = 3 * FPS; + int GameTimer = 0; int GlobalCounter = 0; @@ -639,33 +642,36 @@ GameStatus HandleMenuCalls(bool isTitle) return gameStatus; } + bool playerAlive = LaraItem->HitPoints > 0; + + bool doLoad = IsClicked(In::Load) || + (!IsClicked(In::Inventory) && !NoAction() && SaveGame::IsLoadGamePossible() && Lara.Control.Count.Death > DEATH_INPUT_TIMEOUT); + bool doSave = IsClicked(In::Save) && playerAlive; + bool doPause = IsClicked(In::Pause) && playerAlive; + bool doInventory = (IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_VALUE) && playerAlive; + // Handle inventory. - if (IsClicked(In::Save) && LaraItem->HitPoints > 0 && - g_Gui.GetInventoryMode() != InventoryMode::Save && - g_GameFlow->IsLoadSaveEnabled()) + if (doSave && g_GameFlow->IsLoadSaveEnabled() && g_Gui.GetInventoryMode() != InventoryMode::Save) { SaveGame::LoadHeaders(); g_Gui.SetInventoryMode(InventoryMode::Save); g_Gui.CallInventory(LaraItem, false); } - else if (IsClicked(In::Load) && - g_Gui.GetInventoryMode() != InventoryMode::Load && - g_GameFlow->IsLoadSaveEnabled()) + else if (doLoad && g_GameFlow->IsLoadSaveEnabled() && g_Gui.GetInventoryMode() != InventoryMode::Load) { SaveGame::LoadHeaders(); + g_Gui.SetInventoryMode(InventoryMode::Load); if (g_Gui.CallInventory(LaraItem, false)) gameStatus = GameStatus::LoadGame; } - else if (IsClicked(In::Pause) && LaraItem->HitPoints > 0 && - g_Gui.GetInventoryMode() != InventoryMode::Pause) + else if (doPause && g_Gui.GetInventoryMode() != InventoryMode::Pause) { if (g_Gui.CallPause()) gameStatus = GameStatus::ExitToTitle; } - else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_VALUE) && - LaraItem->HitPoints > 0 && !Lara.Control.Look.IsUsingBinoculars) + else if (doInventory && LaraItem->HitPoints > 0 && !Lara.Control.Look.IsUsingBinoculars) { if (g_Gui.CallInventory(LaraItem, true)) gameStatus = GameStatus::LoadGame; @@ -682,9 +688,6 @@ GameStatus HandleMenuCalls(bool isTitle) GameStatus HandleGlobalInputEvents(bool isTitle) { - constexpr auto DEATH_NO_INPUT_TIMEOUT = 10 * FPS; - constexpr auto DEATH_INPUT_TIMEOUT = 3 * FPS; - if (isTitle) return GameStatus::Normal; diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp index a6f2e7438..949634a88 100644 --- a/TombEngine/Game/gui.cpp +++ b/TombEngine/Game/gui.cpp @@ -3506,8 +3506,15 @@ namespace TEN::Gui LoadResult GuiController::DoLoad() { + constexpr auto DEATH_NO_INPUT_LOAD_TIMEOUT = 1 * FPS; + bool canLoop = g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::SaveLoadOnly || g_Configuration.MenuOptionLoopingMode == MenuOptionLoopingMode::AllMenus; + + // If load menu is accessed after death, delay input polling to allow player to stop spamming input. + if (GetLaraInfo(*LaraItem).Control.Count.Death > 0 && TimeInMenu < DEATH_NO_INPUT_LOAD_TIMEOUT) + return LoadResult::None; + SelectedSaveSlot = GetLoopedSelectedOption(SelectedSaveSlot, SAVEGAME_MAX - 1, canLoop); if (GuiIsSelected()) diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index c72264798..4fc74e8be 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -206,6 +206,17 @@ bool SaveGame::DoesSaveGameExist(int slot, bool silent) return true; } +bool SaveGame::IsLoadGamePossible() +{ + for (int i = 0; i < SAVEGAME_MAX; i++) + { + if (Infos[i].Present) + return true; + } + + return false; +} + std::string SaveGame::GetSavegameFilename(int slot) { return (FullSaveDirectory + SAVEGAME_FILE_MASK + std::to_string(slot)); diff --git a/TombEngine/Game/savegame.h b/TombEngine/Game/savegame.h index 0d31db314..61a8d922e 100644 --- a/TombEngine/Game/savegame.h +++ b/TombEngine/Game/savegame.h @@ -64,6 +64,7 @@ public: static void Delete(int slot); static bool DoesSaveGameExist(int slot, bool silent = false); + static bool IsLoadGamePossible(); static void SaveHub(int index); static void LoadHub(int index); From c20cfffabda4d1f960c3cf39c826e9324fdf9f92 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 12:36:39 +0100 Subject: [PATCH 393/410] Bump version --- TombEngine/Resources.rc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TombEngine/Resources.rc b/TombEngine/Resources.rc index c475bfd5e..f315a574a 100644 --- a/TombEngine/Resources.rc +++ b/TombEngine/Resources.rc @@ -26,8 +26,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,0,0 - PRODUCTVERSION 1,7,1,0 + FILEVERSION 1,5,0,0 + PRODUCTVERSION 1,7,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BLOCK "000904b0" BEGIN VALUE "CompanyName", "Tomb Engine Development Community" - VALUE "FileVersion", "1.4.0.0" + VALUE "FileVersion", "1.5.0.0" VALUE "InternalName", "TombEngine.exe" VALUE "LegalCopyright", "Copyright (c) 2024" VALUE "OriginalFilename", "TombEngine.exe" VALUE "ProductName", "Tomb Engine" - VALUE "ProductVersion", "1.7.1.0" + VALUE "ProductVersion", "1.7.2.0" END END BLOCK "VarFileInfo" From 840b32fb7145b3d61daaaef98d4b0f325e9a30c7 Mon Sep 17 00:00:00 2001 From: Joey Quint Date: Sat, 2 Nov 2024 13:44:27 +0100 Subject: [PATCH 394/410] Expose moveable's target state to Lua API (#1436) --- CHANGELOG.md | 1 + .../doc/2 classes/Objects.Moveable.html | 26 +++++++++++++++++++ .../Scripting/Internal/ReservedScriptNames.h | 1 + .../TEN/Objects/Moveable/MoveableObject.cpp | 11 ++++++++ .../TEN/Objects/Moveable/MoveableObject.h | 1 + 5 files changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e4ce0504..e3b1b3d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Added Inventory.GetUsedItem(), Inventory.SetUsedItem() and Inventory.ClearUsedItem() functions. * Added Input.KeyClearAll() function. * Added Moveable.GetJointRotation() and optional 'offset' parameter for Moveable.GetJointPosition(). +* Added Moveable.GetTargetState() function. * Added Room:GetRoomNumber() function. * Removed anims.monkeyAutoJump. It is now a player menu configuration. * Fixed Volume:GetActive() method. diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index f21adbec6..06a82df82 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -154,6 +154,10 @@ pickups, and Lara herself (see also Retrieve the index of the current state. + Moveable:GetTargetState() + Retrieve the index of the target state. + + Moveable:SetState(index) Set the object's state to the one specified by the given index. @@ -689,6 +693,28 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)
      +
    +
    + + Moveable:GetTargetState() +
    +
    + Retrieve the index of the target state. + This corresponds to the state the object is trying to get into, which is sometimes different from the active state. + + + + +

    Returns:

    +
      + + int + the index of the target state +
    + + + +
    diff --git a/TombEngine/Scripting/Internal/ReservedScriptNames.h b/TombEngine/Scripting/Internal/ReservedScriptNames.h index 26f762c52..42022655e 100644 --- a/TombEngine/Scripting/Internal/ReservedScriptNames.h +++ b/TombEngine/Scripting/Internal/ReservedScriptNames.h @@ -149,6 +149,7 @@ static constexpr char ScriptReserved_SetFrameNumber[] = "SetFrame"; static constexpr char ScriptReserved_GetAnimNumber[] = "GetAnim"; static constexpr char ScriptReserved_SetAnimNumber[] = "SetAnim"; static constexpr char ScriptReserved_GetStateNumber[] = "GetState"; +static constexpr char ScriptReserved_GetTargetStateNumber[] = "GetTargetState"; static constexpr char ScriptReserved_SetStateNumber[] = "SetState"; static constexpr char ScriptReserved_GetOCB[] = "GetOCB"; static constexpr char ScriptReserved_SetOCB[] = "SetOCB"; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp index 4dfbcf4e4..fa72ce12c 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp @@ -223,6 +223,12 @@ void Moveable::Register(sol::state& state, sol::table& parent) // @treturn int the index of the active state ScriptReserved_GetStateNumber, &Moveable::GetStateNumber, +/// Retrieve the index of the target state. +// This corresponds to the state the object is trying to get into, which is sometimes different from the active state. +// @function Moveable:GetTargetState +// @treturn int the index of the target state + ScriptReserved_GetTargetStateNumber, &Moveable::GetTargetStateNumber, + /// Set the object's state to the one specified by the given index. // Performs no bounds checking. *Ensure the number given is correct, else // object may end up in corrupted animation state.* @@ -846,6 +852,11 @@ int Moveable::GetStateNumber() const return m_item->Animation.ActiveState; } +int Moveable::GetTargetStateNumber() const +{ + return m_item->Animation.TargetState; +} + void Moveable::SetStateNumber(int stateNumber) { m_item->Animation.TargetState = stateNumber; diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h index d3c0867fd..dfb795f31 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h @@ -56,6 +56,7 @@ public: void SetRot(const Rotation& rot); [[nodiscard]] int GetStateNumber() const; + [[nodiscard]] int GetTargetStateNumber() const; void SetStateNumber(int stateNumber); [[nodiscard]] int GetAnimNumber() const; From 7196210da90cd4ad82649bbb8bed4a048c7ac9d1 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sat, 2 Nov 2024 12:46:02 +0000 Subject: [PATCH 395/410] Custom bars (#1432) * Add Custom Bar Graphic slot * Add ID_CUSTOM_AMMO_GRAPHIC slot Used for nodes in Tomb Editor --- TombEngine/Objects/game_object_ids.h | 2 ++ TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h index 9307fa3bf..5bf09dace 100644 --- a/TombEngine/Objects/game_object_ids.h +++ b/TombEngine/Objects/game_object_ids.h @@ -1001,6 +1001,8 @@ enum GAME_OBJECT_ID : short // NOTE: 1378 - 1379 reserved for blood effects. -- Sezz 2023.05.29 ID_CROSSHAIR = 1380, ID_SPEEDOMETER, + ID_CUSTOM_BAR_GRAPHIC, + ID_CUSTOM_AMMO_GRAPHIC, ID_PANEL_BORDER = 1400, ID_PANEL_MIDDLE, diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index 6409f2f92..3dee49b74 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -988,6 +988,9 @@ The following constants are inside ObjID. AIR_BAR_TEXTURE DASH_BAR_TEXTURE SFX_BAR_TEXTURE + SPEEDOMETER + CUSTOM_BAR_GRAPHIC + PANEL_BORDER PANEL_MIDDLE PANEL_CORNER @@ -2166,6 +2169,9 @@ static const std::unordered_map kObjIDs { { "DASH_BAR_TEXTURE", ID_DASH_BAR_TEXTURE }, { "SFX_BAR_TEXTURE", ID_SFX_BAR_TEXTURE }, { "CROSSHAIR", ID_CROSSHAIR }, + { "SPEEDOMETER", ID_SPEEDOMETER }, + { "CUSTOM_BAR_GRAPHIC", ID_CUSTOM_BAR_GRAPHIC }, + { "CUSTOM_AMMO_GRAPHIC",ID_CUSTOM_AMMO_GRAPHIC }, { "PANEL_BORDER", ID_PANEL_BORDER }, { "PANEL_MIDDLE", ID_PANEL_MIDDLE }, { "PANEL_CORNER", ID_PANEL_CORNER }, From 78cefae27bd14603b7783a5898bb894fdba8a15c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 19:26:22 +0100 Subject: [PATCH 396/410] Fixed broken ropes after loading a savegame --- CHANGELOG.md | 1 + TombEngine/Game/savegame.cpp | 51 ++-- .../flatbuffers/ten_savegame_generated.h | 243 ++++++++++++------ .../Specific/savegame/schema/ten_savegame.fbs | 14 +- 4 files changed, 187 insertions(+), 122 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3b1b3d88..41d3f8903 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed incorrect diving animation when swandiving from a high place. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed camera position after loading a savegame. +* Fixed broken ropes after loading a savegame. * Fixed AI for TR2 Skidoo driver and Worker with shotgun. * Fixed Ember Emitter crashing when ocb is between -1 and -10. * Fixed Electric Cleaner and Squishy Block not detecting collision with certain block heights. diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 4fc74e8be..42a877e0e 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -1237,38 +1237,24 @@ const std::vector SaveGame::Build() { ROPE_STRUCT* rope = &Ropes[Lara.Control.Rope.Ptr]; - std::vector segments; + std::vector> segments; for (int i = 0; i < ROPE_SEGMENTS; i++) - segments.push_back(&FromVector3i(rope->segment[i])); - auto segmentsOffset = fbb.CreateVector(segments); + { + Save::RopeSegmentBuilder segment{ fbb }; - std::vector velocities; - for (int i = 0; i < ROPE_SEGMENTS; i++) - velocities.push_back(&FromVector3i(rope->velocity[i])); - auto velocitiesOffset = fbb.CreateVector(velocities); + segment.add_segment(&FromVector3i(rope->segment[i])); + segment.add_velocity(&FromVector3i(rope->velocity[i])); + segment.add_normalised_segment(&FromVector3i(rope->normalisedSegment[i])); + segment.add_mesh_segment(&FromVector3i(rope->meshSegment[i])); + segment.add_coord(&FromVector3i(rope->coords[i])); - std::vector normalisedSegments; - for (int i = 0; i < ROPE_SEGMENTS; i++) - normalisedSegments.push_back(&FromVector3i(rope->normalisedSegment[i])); - auto normalisedSegmentsOffset = fbb.CreateVector(normalisedSegments); - - std::vector meshSegments; - for (int i = 0; i < ROPE_SEGMENTS; i++) - meshSegments.push_back(&FromVector3i(rope->meshSegment[i])); - auto meshSegmentsOffset = fbb.CreateVector(meshSegments); - - std::vector coords; - for (int i = 0; i < ROPE_SEGMENTS; i++) - coords.push_back(&FromVector3i(rope->coords[i])); - auto coordsOffset = fbb.CreateVector(coords); + segments.push_back(segment.Finish()); + } + auto ropeSegmentsOffset = fbb.CreateVector(segments); Save::RopeBuilder ropeInfo{ fbb }; - ropeInfo.add_segments(segmentsOffset); - ropeInfo.add_velocities(velocitiesOffset); - ropeInfo.add_mesh_segments(meshSegmentsOffset); - ropeInfo.add_normalised_segments(normalisedSegmentsOffset); - ropeInfo.add_coords(coordsOffset); + ropeInfo.add_segments(ropeSegmentsOffset); ropeInfo.add_coiled(rope->coiled); ropeInfo.add_position(&FromVector3i(rope->position)); ropeInfo.add_segment_length(rope->segmentLength); @@ -1995,13 +1981,14 @@ static void ParsePlayer(const Save::SaveGame* s) { auto* rope = &Ropes[Lara.Control.Rope.Ptr]; - for (int i = 0; i < ROPE_SEGMENTS; i++) + for (int i = 0; i < s->rope()->segments()->size(); i++) { - rope->segment[i] = ToVector3i(s->rope()->segments()->Get(i)); - rope->normalisedSegment[i] = ToVector3i(s->rope()->normalised_segments()->Get(i)); - rope->meshSegment[i] = ToVector3i(s->rope()->mesh_segments()->Get(i)); - rope->coords[i] = ToVector3i(s->rope()->coords()->Get(i)); - rope->velocity[i] = ToVector3i(s->rope()->velocities()->Get(i)); + auto ropeSegment = s->rope()->segments()->Get(i); + rope->segment[i] = ToVector3i(ropeSegment->segment()); + rope->normalisedSegment[i] = ToVector3i(ropeSegment->normalised_segment()); + rope->meshSegment[i] = ToVector3i(ropeSegment->mesh_segment()); + rope->coords[i] = ToVector3i(ropeSegment->coord()); + rope->velocity[i] = ToVector3i(ropeSegment->velocity()); } rope->coiled = s->rope()->coiled(); diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h index a929d1d63..3bbe2dae6 100644 --- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h +++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h @@ -137,6 +137,10 @@ struct SwarmObjectInfo; struct SwarmObjectInfoBuilder; struct SwarmObjectInfoT; +struct RopeSegment; +struct RopeSegmentBuilder; +struct RopeSegmentT; + struct Rope; struct RopeBuilder; struct RopeT; @@ -5451,14 +5455,112 @@ struct SwarmObjectInfo::Traits { flatbuffers::Offset CreateSwarmObjectInfo(flatbuffers::FlatBufferBuilder &_fbb, const SwarmObjectInfoT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct RopeSegmentT : public flatbuffers::NativeTable { + typedef RopeSegment TableType; + std::unique_ptr segment{}; + std::unique_ptr velocity{}; + std::unique_ptr normalised_segment{}; + std::unique_ptr mesh_segment{}; + std::unique_ptr coord{}; +}; + +struct RopeSegment FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef RopeSegmentT NativeTableType; + typedef RopeSegmentBuilder Builder; + struct Traits; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SEGMENT = 4, + VT_VELOCITY = 6, + VT_NORMALISED_SEGMENT = 8, + VT_MESH_SEGMENT = 10, + VT_COORD = 12 + }; + const TEN::Save::Vector3 *segment() const { + return GetStruct(VT_SEGMENT); + } + const TEN::Save::Vector3 *velocity() const { + return GetStruct(VT_VELOCITY); + } + const TEN::Save::Vector3 *normalised_segment() const { + return GetStruct(VT_NORMALISED_SEGMENT); + } + const TEN::Save::Vector3 *mesh_segment() const { + return GetStruct(VT_MESH_SEGMENT); + } + const TEN::Save::Vector3 *coord() const { + return GetStruct(VT_COORD); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SEGMENT) && + VerifyField(verifier, VT_VELOCITY) && + VerifyField(verifier, VT_NORMALISED_SEGMENT) && + VerifyField(verifier, VT_MESH_SEGMENT) && + VerifyField(verifier, VT_COORD) && + verifier.EndTable(); + } + RopeSegmentT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(RopeSegmentT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const RopeSegmentT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct RopeSegmentBuilder { + typedef RopeSegment Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_segment(const TEN::Save::Vector3 *segment) { + fbb_.AddStruct(RopeSegment::VT_SEGMENT, segment); + } + void add_velocity(const TEN::Save::Vector3 *velocity) { + fbb_.AddStruct(RopeSegment::VT_VELOCITY, velocity); + } + void add_normalised_segment(const TEN::Save::Vector3 *normalised_segment) { + fbb_.AddStruct(RopeSegment::VT_NORMALISED_SEGMENT, normalised_segment); + } + void add_mesh_segment(const TEN::Save::Vector3 *mesh_segment) { + fbb_.AddStruct(RopeSegment::VT_MESH_SEGMENT, mesh_segment); + } + void add_coord(const TEN::Save::Vector3 *coord) { + fbb_.AddStruct(RopeSegment::VT_COORD, coord); + } + explicit RopeSegmentBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRopeSegment( + flatbuffers::FlatBufferBuilder &_fbb, + const TEN::Save::Vector3 *segment = 0, + const TEN::Save::Vector3 *velocity = 0, + const TEN::Save::Vector3 *normalised_segment = 0, + const TEN::Save::Vector3 *mesh_segment = 0, + const TEN::Save::Vector3 *coord = 0) { + RopeSegmentBuilder builder_(_fbb); + builder_.add_coord(coord); + builder_.add_mesh_segment(mesh_segment); + builder_.add_normalised_segment(normalised_segment); + builder_.add_velocity(velocity); + builder_.add_segment(segment); + return builder_.Finish(); +} + +struct RopeSegment::Traits { + using type = RopeSegment; + static auto constexpr Create = CreateRopeSegment; +}; + +flatbuffers::Offset CreateRopeSegment(flatbuffers::FlatBufferBuilder &_fbb, const RopeSegmentT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct RopeT : public flatbuffers::NativeTable { typedef Rope TableType; - std::vector segments{}; - std::vector velocities{}; - std::vector normalised_segments{}; - std::vector mesh_segments{}; + std::vector> segments{}; std::unique_ptr position{}; - std::vector coords{}; int32_t segment_length = 0; int32_t active = 0; int32_t coiled = 0; @@ -5470,33 +5572,17 @@ struct Rope FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Traits; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_SEGMENTS = 4, - VT_VELOCITIES = 6, - VT_NORMALISED_SEGMENTS = 8, - VT_MESH_SEGMENTS = 10, - VT_POSITION = 12, - VT_COORDS = 14, - VT_SEGMENT_LENGTH = 16, - VT_ACTIVE = 18, - VT_COILED = 20 + VT_POSITION = 6, + VT_SEGMENT_LENGTH = 8, + VT_ACTIVE = 10, + VT_COILED = 12 }; - const flatbuffers::Vector *segments() const { - return GetPointer *>(VT_SEGMENTS); - } - const flatbuffers::Vector *velocities() const { - return GetPointer *>(VT_VELOCITIES); - } - const flatbuffers::Vector *normalised_segments() const { - return GetPointer *>(VT_NORMALISED_SEGMENTS); - } - const flatbuffers::Vector *mesh_segments() const { - return GetPointer *>(VT_MESH_SEGMENTS); + const flatbuffers::Vector> *segments() const { + return GetPointer> *>(VT_SEGMENTS); } const TEN::Save::Vector3 *position() const { return GetStruct(VT_POSITION); } - const flatbuffers::Vector *coords() const { - return GetPointer *>(VT_COORDS); - } int32_t segment_length() const { return GetField(VT_SEGMENT_LENGTH, 0); } @@ -5510,15 +5596,8 @@ struct Rope FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SEGMENTS) && verifier.VerifyVector(segments()) && - VerifyOffset(verifier, VT_VELOCITIES) && - verifier.VerifyVector(velocities()) && - VerifyOffset(verifier, VT_NORMALISED_SEGMENTS) && - verifier.VerifyVector(normalised_segments()) && - VerifyOffset(verifier, VT_MESH_SEGMENTS) && - verifier.VerifyVector(mesh_segments()) && + verifier.VerifyVectorOfTables(segments()) && VerifyField(verifier, VT_POSITION) && - VerifyOffset(verifier, VT_COORDS) && - verifier.VerifyVector(coords()) && VerifyField(verifier, VT_SEGMENT_LENGTH) && VerifyField(verifier, VT_ACTIVE) && VerifyField(verifier, VT_COILED) && @@ -5533,24 +5612,12 @@ struct RopeBuilder { typedef Rope Table; flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_segments(flatbuffers::Offset> segments) { + void add_segments(flatbuffers::Offset>> segments) { fbb_.AddOffset(Rope::VT_SEGMENTS, segments); } - void add_velocities(flatbuffers::Offset> velocities) { - fbb_.AddOffset(Rope::VT_VELOCITIES, velocities); - } - void add_normalised_segments(flatbuffers::Offset> normalised_segments) { - fbb_.AddOffset(Rope::VT_NORMALISED_SEGMENTS, normalised_segments); - } - void add_mesh_segments(flatbuffers::Offset> mesh_segments) { - fbb_.AddOffset(Rope::VT_MESH_SEGMENTS, mesh_segments); - } void add_position(const TEN::Save::Vector3 *position) { fbb_.AddStruct(Rope::VT_POSITION, position); } - void add_coords(flatbuffers::Offset> coords) { - fbb_.AddOffset(Rope::VT_COORDS, coords); - } void add_segment_length(int32_t segment_length) { fbb_.AddElement(Rope::VT_SEGMENT_LENGTH, segment_length, 0); } @@ -5573,12 +5640,8 @@ struct RopeBuilder { inline flatbuffers::Offset CreateRope( flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset> segments = 0, - flatbuffers::Offset> velocities = 0, - flatbuffers::Offset> normalised_segments = 0, - flatbuffers::Offset> mesh_segments = 0, + flatbuffers::Offset>> segments = 0, const TEN::Save::Vector3 *position = 0, - flatbuffers::Offset> coords = 0, int32_t segment_length = 0, int32_t active = 0, int32_t coiled = 0) { @@ -5586,11 +5649,7 @@ inline flatbuffers::Offset CreateRope( builder_.add_coiled(coiled); builder_.add_active(active); builder_.add_segment_length(segment_length); - builder_.add_coords(coords); builder_.add_position(position); - builder_.add_mesh_segments(mesh_segments); - builder_.add_normalised_segments(normalised_segments); - builder_.add_velocities(velocities); builder_.add_segments(segments); return builder_.Finish(); } @@ -5602,28 +5661,16 @@ struct Rope::Traits { inline flatbuffers::Offset CreateRopeDirect( flatbuffers::FlatBufferBuilder &_fbb, - const std::vector *segments = nullptr, - const std::vector *velocities = nullptr, - const std::vector *normalised_segments = nullptr, - const std::vector *mesh_segments = nullptr, + const std::vector> *segments = nullptr, const TEN::Save::Vector3 *position = 0, - const std::vector *coords = nullptr, int32_t segment_length = 0, int32_t active = 0, int32_t coiled = 0) { - auto segments__ = segments ? _fbb.CreateVectorOfStructs(*segments) : 0; - auto velocities__ = velocities ? _fbb.CreateVectorOfStructs(*velocities) : 0; - auto normalised_segments__ = normalised_segments ? _fbb.CreateVectorOfStructs(*normalised_segments) : 0; - auto mesh_segments__ = mesh_segments ? _fbb.CreateVectorOfStructs(*mesh_segments) : 0; - auto coords__ = coords ? _fbb.CreateVectorOfStructs(*coords) : 0; + auto segments__ = segments ? _fbb.CreateVector>(*segments) : 0; return TEN::Save::CreateRope( _fbb, segments__, - velocities__, - normalised_segments__, - mesh_segments__, position, - coords__, segment_length, active, coiled); @@ -9624,6 +9671,44 @@ inline flatbuffers::Offset CreateSwarmObjectInfo(flatbuffers::F _flags); } +inline RopeSegmentT *RopeSegment::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void RopeSegment::UnPackTo(RopeSegmentT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = segment(); if (_e) _o->segment = std::unique_ptr(new TEN::Save::Vector3(*_e)); } + { auto _e = velocity(); if (_e) _o->velocity = std::unique_ptr(new TEN::Save::Vector3(*_e)); } + { auto _e = normalised_segment(); if (_e) _o->normalised_segment = std::unique_ptr(new TEN::Save::Vector3(*_e)); } + { auto _e = mesh_segment(); if (_e) _o->mesh_segment = std::unique_ptr(new TEN::Save::Vector3(*_e)); } + { auto _e = coord(); if (_e) _o->coord = std::unique_ptr(new TEN::Save::Vector3(*_e)); } +} + +inline flatbuffers::Offset RopeSegment::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RopeSegmentT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateRopeSegment(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateRopeSegment(flatbuffers::FlatBufferBuilder &_fbb, const RopeSegmentT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const RopeSegmentT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _segment = _o->segment ? _o->segment.get() : 0; + auto _velocity = _o->velocity ? _o->velocity.get() : 0; + auto _normalised_segment = _o->normalised_segment ? _o->normalised_segment.get() : 0; + auto _mesh_segment = _o->mesh_segment ? _o->mesh_segment.get() : 0; + auto _coord = _o->coord ? _o->coord.get() : 0; + return TEN::Save::CreateRopeSegment( + _fbb, + _segment, + _velocity, + _normalised_segment, + _mesh_segment, + _coord); +} + inline RopeT *Rope::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); @@ -9633,12 +9718,8 @@ inline RopeT *Rope::UnPack(const flatbuffers::resolver_function_t *_resolver) co inline void Rope::UnPackTo(RopeT *_o, const flatbuffers::resolver_function_t *_resolver) const { (void)_o; (void)_resolver; - { auto _e = segments(); if (_e) { _o->segments.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->segments[_i] = *_e->Get(_i); } } } - { auto _e = velocities(); if (_e) { _o->velocities.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->velocities[_i] = *_e->Get(_i); } } } - { auto _e = normalised_segments(); if (_e) { _o->normalised_segments.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->normalised_segments[_i] = *_e->Get(_i); } } } - { auto _e = mesh_segments(); if (_e) { _o->mesh_segments.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->mesh_segments[_i] = *_e->Get(_i); } } } + { auto _e = segments(); if (_e) { _o->segments.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->segments[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = position(); if (_e) _o->position = std::unique_ptr(new TEN::Save::Vector3(*_e)); } - { auto _e = coords(); if (_e) { _o->coords.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->coords[_i] = *_e->Get(_i); } } } { auto _e = segment_length(); _o->segment_length = _e; } { auto _e = active(); _o->active = _e; } { auto _e = coiled(); _o->coiled = _e; } @@ -9652,23 +9733,15 @@ inline flatbuffers::Offset CreateRope(flatbuffers::FlatBufferBuilder &_fbb (void)_rehasher; (void)_o; struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const RopeT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; - auto _segments = _fbb.CreateVectorOfStructs(_o->segments); - auto _velocities = _fbb.CreateVectorOfStructs(_o->velocities); - auto _normalised_segments = _fbb.CreateVectorOfStructs(_o->normalised_segments); - auto _mesh_segments = _fbb.CreateVectorOfStructs(_o->mesh_segments); + auto _segments = _fbb.CreateVector> (_o->segments.size(), [](size_t i, _VectorArgs *__va) { return CreateRopeSegment(*__va->__fbb, __va->__o->segments[i].get(), __va->__rehasher); }, &_va ); auto _position = _o->position ? _o->position.get() : 0; - auto _coords = _fbb.CreateVectorOfStructs(_o->coords); auto _segment_length = _o->segment_length; auto _active = _o->active; auto _coiled = _o->coiled; return TEN::Save::CreateRope( _fbb, _segments, - _velocities, - _normalised_segments, - _mesh_segments, _position, - _coords, _segment_length, _active, _coiled); diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs index 8e71756a2..d7089ad40 100644 --- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs +++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs @@ -382,13 +382,17 @@ table SwarmObjectInfo { flags: int32; } +table RopeSegment { + segment: Vector3; + velocity: Vector3; + normalised_segment: Vector3; + mesh_segment: Vector3; + coord: Vector3; +} + table Rope { - segments: [Vector3]; - velocities: [Vector3]; - normalised_segments: [Vector3]; - mesh_segments: [Vector3]; + segments: [RopeSegment]; position: Vector3; - coords: [Vector3]; segment_length: int32; active: int32; coiled: int32; From 45fca953854f9d96228364d81f20ca5ff82a2c94 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 19:26:40 +0100 Subject: [PATCH 397/410] Added recompiled doc files --- Documentation/doc/4 enums/Objects.ObjID.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 5324243e9..84f5e8d80 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -1108,6 +1108,9 @@ HEALTH_BAR_TEXTURE AIR_BAR_TEXTURE DASH_BAR_TEXTURE SFX_BAR_TEXTURE +SPEEDOMETER +CUSTOM_BAR_GRAPHIC + PANEL_BORDER PANEL_MIDDLE PANEL_CORNER From 7d4e29ee07a51ee1ded6c0a8621021d1e57877f0 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 19:51:40 +0100 Subject: [PATCH 398/410] Fixed room clipping when flyby path goes out of room bounds --- CHANGELOG.md | 1 + TombEngine/Game/spotcam.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41d3f8903..1f10c521a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed incorrect swing ledge grabs with steep grab angles. * Fixed incorrect climbing out of water on bridge objects and in front of static meshes. * Fixed incorrect diving animation when swandiving from a high place. +* Fixed room clipping when flyby path goes out of room bounds. * Fixed camera rotating with the player's hips when climbing out of water. * Fixed camera position after loading a savegame. * Fixed broken ropes after loading a savegame. diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index e66343a87..7477dfb0d 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -5,6 +5,7 @@ #include "Game/camera.h" #include "Game/control/control.h" #include "Game/control/volume.h" +#include "Game/collision/Point.h" #include "Game/effects/tomb4fx.h" #include "Game/items.h" #include "Game/Lara/lara.h" @@ -14,6 +15,7 @@ using namespace TEN::Input; using namespace TEN::Renderer; using namespace TEN::Control::Volumes; +using namespace TEN::Collision::Point; constexpr auto MAX_CAMERA = 18; @@ -493,8 +495,13 @@ void CalculateSpotCameras() if (Camera.pos.RoomNumber != SpotCam[CurrentSplineCamera].roomNumber) Camera.DisableInterpolation = true; - Camera.pos.RoomNumber = SpotCam[CurrentSplineCamera].roomNumber; - GetFloor(Camera.pos.x, Camera.pos.y, Camera.pos.z, &Camera.pos.RoomNumber); + auto position = Vector3i(Camera.pos.x, Camera.pos.y, Camera.pos.z); + int collRoomNumber = GetPointCollision(position, SpotCam[CurrentSplineCamera].roomNumber).GetRoomNumber(); + + if (collRoomNumber != Camera.pos.RoomNumber) + collRoomNumber = FindRoomNumber(position, SpotCam[CurrentSplineCamera].roomNumber); + + Camera.pos.RoomNumber = collRoomNumber; } else { From eec17d9f30ef9399c9ae87f7145433e4987fbe29 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sat, 2 Nov 2024 20:03:51 +0100 Subject: [PATCH 399/410] Add comment --- TombEngine/Game/spotcam.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index 7477dfb0d..69e51dfb4 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -494,6 +494,10 @@ void CalculateSpotCameras() { if (Camera.pos.RoomNumber != SpotCam[CurrentSplineCamera].roomNumber) Camera.DisableInterpolation = true; + + // HACK: Sometimes actual camera room number desyncs from room number derived using floordata functions. + // If such case is identified, we do a brute-force search for coherrent room number. + // This issue is only present in sub-click floor height setups after TE 1.7.0. -- Lwmte, 02.11.2024 auto position = Vector3i(Camera.pos.x, Camera.pos.y, Camera.pos.z); int collRoomNumber = GetPointCollision(position, SpotCam[CurrentSplineCamera].roomNumber).GetRoomNumber(); From 2b020b664dd8e7b7720c186a8b81fc1eb5b2ad43 Mon Sep 17 00:00:00 2001 From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Date: Sat, 2 Nov 2024 22:12:35 +0000 Subject: [PATCH 400/410] Fixed the CUSTOM_AMMO_GRAPHIC not appearing in the Lua API --- TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h index 3dee49b74..2f1e2e899 100644 --- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h +++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h @@ -990,6 +990,7 @@ The following constants are inside ObjID. SFX_BAR_TEXTURE SPEEDOMETER CUSTOM_BAR_GRAPHIC + CUSTOM_AMMO_GRAPHIC PANEL_BORDER PANEL_MIDDLE From bc5df6af98dceab5b88e20d8fac026e6b4b64525 Mon Sep 17 00:00:00 2001 From: Sezz Date: Sun, 3 Nov 2024 18:23:48 +1100 Subject: [PATCH 401/410] Format recent merges --- TombEngine/Game/Hud/PickupSummary.cpp | 15 ++++++++------- TombEngine/Game/Hud/PickupSummary.h | 2 +- TombEngine/Game/control/los.cpp | 1 - TombEngine/Game/pickup/pickup_ammo.cpp | 2 +- TombEngine/Game/pickup/pickup_ammo.h | 2 +- TombEngine/Game/pickup/pickup_consumable.cpp | 2 +- TombEngine/Objects/TR2/Entity/tr2_skidman.cpp | 4 ++++ 7 files changed, 16 insertions(+), 12 deletions(-) diff --git a/TombEngine/Game/Hud/PickupSummary.cpp b/TombEngine/Game/Hud/PickupSummary.cpp index dcbd8fe30..4376cf80b 100644 --- a/TombEngine/Game/Hud/PickupSummary.cpp +++ b/TombEngine/Game/Hud/PickupSummary.cpp @@ -126,18 +126,19 @@ namespace TEN::Hud pickup.StringScalar = 0.0f; } - void PickupSummaryController::AddDisplayPickup(ItemInfo& item) + void PickupSummaryController::AddDisplayPickup(const ItemInfo& item) { - // Ammo and consumables are a special case, as internal amount differs from pickup amount. - - int ammoCount = GetDefaultAmmoCount(item.ObjectNumber); + // NOTE: Ammo and consumables are a special case, as internal amount differs from pickup amount. + int ammoCount = GetDefaultAmmoCount(item.ObjectNumber); int consumableCount = GetDefaultConsumableCount(item.ObjectNumber); int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT; - if (ammoCount != NO_VALUE) count = ammoCount; - if (consumableCount != NO_VALUE) count = consumableCount; + if (ammoCount != NO_VALUE) + count = ammoCount; + if (consumableCount != NO_VALUE) + count = consumableCount; - AddDisplayPickup(item.ObjectNumber, item.Pose.Position.ToVector3(), item.HitPoints > 0 ? item.HitPoints : count); + AddDisplayPickup(item.ObjectNumber, item.Pose.Position.ToVector3(), (item.HitPoints > 0) ? item.HitPoints : count); } void PickupSummaryController::AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector3& pos, unsigned int count) diff --git a/TombEngine/Game/Hud/PickupSummary.h b/TombEngine/Game/Hud/PickupSummary.h index d653bf490..b79898a8d 100644 --- a/TombEngine/Game/Hud/PickupSummary.h +++ b/TombEngine/Game/Hud/PickupSummary.h @@ -59,7 +59,7 @@ namespace TEN::Hud void AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector2& origin, unsigned int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT); void AddDisplayPickup(GAME_OBJECT_ID objectID, const Vector3& pos, unsigned int count = DISPLAY_PICKUP_COUNT_ARG_DEFAULT); - void AddDisplayPickup(ItemInfo& item); + void AddDisplayPickup(const ItemInfo& item); void Update(); void Draw() const; diff --git a/TombEngine/Game/control/los.cpp b/TombEngine/Game/control/los.cpp index 7cd0b2c5f..003d04b30 100644 --- a/TombEngine/Game/control/los.cpp +++ b/TombEngine/Game/control/los.cpp @@ -518,7 +518,6 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G if (sphere.Intersects(rayOrigin, rayDir, distance)) { // Test for minimum distance. - if (distance < minDist) { minDist = distance; diff --git a/TombEngine/Game/pickup/pickup_ammo.cpp b/TombEngine/Game/pickup/pickup_ammo.cpp index 4aa2fa097..bd6d957da 100644 --- a/TombEngine/Game/pickup/pickup_ammo.cpp +++ b/TombEngine/Game/pickup/pickup_ammo.cpp @@ -102,4 +102,4 @@ int GetDefaultAmmoCount(GAME_OBJECT_ID objectID) return NO_VALUE; return kAmmo[arrayPos].Amount; -} \ No newline at end of file +} diff --git a/TombEngine/Game/pickup/pickup_ammo.h b/TombEngine/Game/pickup/pickup_ammo.h index fb5b2e4bf..3d7565c7f 100644 --- a/TombEngine/Game/pickup/pickup_ammo.h +++ b/TombEngine/Game/pickup/pickup_ammo.h @@ -8,4 +8,4 @@ bool TryAddingAmmo(LaraInfo&, GAME_OBJECT_ID objectID, std::optional amount bool TryRemovingAmmo(LaraInfo&, GAME_OBJECT_ID objectID, std::optional amount = std::nullopt); bool TryModifyingAmmo(LaraInfo& lara, GAME_OBJECT_ID objectID, std::optional amount, ModificationType modType); std::optional GetAmmoCount(LaraInfo&, GAME_OBJECT_ID objectID); -int GetDefaultAmmoCount(GAME_OBJECT_ID objectID); \ No newline at end of file +int GetDefaultAmmoCount(GAME_OBJECT_ID objectID); diff --git a/TombEngine/Game/pickup/pickup_consumable.cpp b/TombEngine/Game/pickup/pickup_consumable.cpp index d681b0d45..0bdeccc35 100644 --- a/TombEngine/Game/pickup/pickup_consumable.cpp +++ b/TombEngine/Game/pickup/pickup_consumable.cpp @@ -85,4 +85,4 @@ int GetDefaultConsumableCount(GAME_OBJECT_ID objectID) return NO_VALUE; return kConsumables[arrayPos].Amount; -} \ No newline at end of file +} diff --git a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp index da284a3e4..94fb34145 100644 --- a/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp +++ b/TombEngine/Objects/TR2/Entity/tr2_skidman.cpp @@ -81,9 +81,13 @@ namespace TEN::Entities::Creatures::TR2 auto& item = g_Level.Items[itemNumber]; if (item.Flags & IFLAG_REVERSE) + { item.Status = ITEM_NOT_ACTIVE; + } else + { item.Status = ITEM_INVISIBLE; + } } void SkidooManCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) From f1f2d165c5ee1655e5e0cb25477de414543e848b Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 09:29:52 +0100 Subject: [PATCH 402/410] Fixed camera behaviour on sloped surfaces after player's death --- CHANGELOG.md | 1 + TombEngine/Game/camera.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f10c521a..ee74d0abb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed incorrect diving animation when swandiving from a high place. * Fixed room clipping when flyby path goes out of room bounds. * Fixed camera rotating with the player's hips when climbing out of water. +* Fixed camera behaviour on sloped surfaces after player's death. * Fixed camera position after loading a savegame. * Fixed broken ropes after loading a savegame. * Fixed AI for TR2 Skidoo driver and Worker with shotgun. diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 67d375074..d03d35f7f 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1289,8 +1289,7 @@ void CalculateCamera(const CollisionInfo& coll) Camera.DisableInterpolation = (Camera.DisableInterpolation || Camera.lastType != Camera.type); Camera.lastType = Camera.type; - if ((Camera.type != CameraType::Heavy || Camera.timer == -1) && - LaraItem->HitPoints > 0) + if (Camera.type != CameraType::Heavy || Camera.timer == -1) { Camera.type = CameraType::Chase; Camera.speed = 10; From 856dccad1f491c485528475aec46307ca5332b10 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 09:30:01 +0100 Subject: [PATCH 403/410] Swap debug pages --- TombEngine/Renderer/RendererEnums.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TombEngine/Renderer/RendererEnums.h b/TombEngine/Renderer/RendererEnums.h index 38c044480..c159c1c42 100644 --- a/TombEngine/Renderer/RendererEnums.h +++ b/TombEngine/Renderer/RendererEnums.h @@ -148,8 +148,8 @@ enum class RendererDebugPage InputStats, CollisionStats, PathfindingStats, - WireframeMode, PortalDebug, + WireframeMode, Count }; From 83981b369eea5c32cf1a3fa24c28208a5760dd2f Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 09:30:17 +0100 Subject: [PATCH 404/410] Bump version to reflect release state --- TombEngine/Resources.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TombEngine/Resources.rc b/TombEngine/Resources.rc index f315a574a..7984b7c19 100644 --- a/TombEngine/Resources.rc +++ b/TombEngine/Resources.rc @@ -26,7 +26,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,5,0,0 + FILEVERSION 1,5,0,1 PRODUCTVERSION 1,7,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG @@ -43,7 +43,7 @@ BEGIN BLOCK "000904b0" BEGIN VALUE "CompanyName", "Tomb Engine Development Community" - VALUE "FileVersion", "1.5.0.0" + VALUE "FileVersion", "1.5.0.1" VALUE "InternalName", "TombEngine.exe" VALUE "LegalCopyright", "Copyright (c) 2024" VALUE "OriginalFilename", "TombEngine.exe" From 8a809877c4de182c4c9f2eae33a9d2f5c5b933d9 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:50:46 +0100 Subject: [PATCH 405/410] Disable flyby camera interpolation in cases when it travels too far --- TombEngine/Game/spotcam.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index 6fdb06963..1f3b906d1 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -391,7 +391,6 @@ void CalculateSpotCameras() { SetScreenFadeIn(FADE_SCREEN_SPEED); CameraFade = CurrentSplineCamera; - Camera.DisableInterpolation = true; } if ((SpotCam[CurrentSplineCamera].flags & SCF_SCREEN_FADE_OUT) && @@ -399,7 +398,6 @@ void CalculateSpotCameras() { SetScreenFadeOut(FADE_SCREEN_SPEED); CameraFade = CurrentSplineCamera; - Camera.DisableInterpolation = true; } sp = 0; @@ -472,6 +470,14 @@ void CalculateSpotCameras() if ((s->flags & SCF_DISABLE_BREAKOUT) || !lookPressed) { + // Disable interpolation if camera traveled too far. + auto p1 = Vector3(Camera.pos.x, Camera.pos.y, Camera.pos.z); + auto p2 = Vector3(cpx, cpy, cpz); + auto dist = Vector3::Distance(p1, p2); + + if (dist > CLICK(1)) + Camera.DisableInterpolation = true; + Camera.pos.x = cpx; Camera.pos.y = cpy; Camera.pos.z = cpz; @@ -492,9 +498,6 @@ void CalculateSpotCameras() auto outsideRoom = IsRoomOutside(cpx, cpy, cpz); if (outsideRoom == NO_VALUE) { - if (Camera.pos.RoomNumber != SpotCam[CurrentSplineCamera].roomNumber) - Camera.DisableInterpolation = true; - // HACK: Sometimes actual camera room number desyncs from room number derived using floordata functions. // If such case is identified, we do a brute-force search for coherrent room number. // This issue is only present in sub-click floor height setups after TE 1.7.0. -- Lwmte, 02.11.2024 @@ -705,10 +708,10 @@ void CalculateSpotCameras() Camera.pos.x = InitialCameraPosition.x; Camera.pos.y = InitialCameraPosition.y; Camera.pos.z = InitialCameraPosition.z; + Camera.pos.RoomNumber = InitialCameraRoom; Camera.target.x = InitialCameraTarget.x; Camera.target.y = InitialCameraTarget.y; Camera.target.z = InitialCameraTarget.z; - Camera.pos.RoomNumber = InitialCameraRoom; } SpotcamOverlay = false; From 4a8d66d077c8825a2071f52d197d1018dc1e7255 Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:54:23 +0100 Subject: [PATCH 406/410] Update Objects.ObjID.html --- Documentation/doc/4 enums/Objects.ObjID.html | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 84f5e8d80..8ceefa220 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -1110,6 +1110,7 @@ DASH_BAR_TEXTURE SFX_BAR_TEXTURE SPEEDOMETER CUSTOM_BAR_GRAPHIC +CUSTOM_AMMO_GRAPHIC PANEL_BORDER PANEL_MIDDLE From d72208cfb3f8344e0962ae0651b4f83247e2249a Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:56:52 +0100 Subject: [PATCH 407/410] Remove another unnecessary flag assignment --- TombEngine/Game/spotcam.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index 1f3b906d1..bc8a91065 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -512,9 +512,6 @@ void CalculateSpotCameras() } else { - if (Camera.pos.RoomNumber != outsideRoom) - Camera.DisableInterpolation = true; - Camera.pos.RoomNumber = outsideRoom; } From f51d499e68a07f53713bd6c361eb4073a1d79a4c Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 11:39:16 +0100 Subject: [PATCH 408/410] Regenerate documentation --- Documentation/config.ld | 2 +- Documentation/doc/1 modules/Effects.html | 2 +- Documentation/doc/1 modules/Flow.html | 2 +- Documentation/doc/1 modules/Input.html | 2 +- Documentation/doc/1 modules/Inventory.html | 2 +- Documentation/doc/1 modules/Logic.html | 2 +- Documentation/doc/1 modules/Objects.html | 2 +- Documentation/doc/1 modules/Sound.html | 2 +- Documentation/doc/1 modules/Strings.html | 2 +- Documentation/doc/1 modules/Util.html | 2 +- Documentation/doc/1 modules/View.html | 2 +- Documentation/doc/2 classes/Flow.Animations.html | 2 +- Documentation/doc/2 classes/Flow.Fog.html | 2 +- Documentation/doc/2 classes/Flow.InventoryItem.html | 2 +- Documentation/doc/2 classes/Flow.LensFlare.html | 2 +- Documentation/doc/2 classes/Flow.Level.html | 2 +- Documentation/doc/2 classes/Flow.Mirror.html | 2 +- Documentation/doc/2 classes/Flow.Settings.html | 2 +- Documentation/doc/2 classes/Flow.SkyLayer.html | 2 +- Documentation/doc/2 classes/Flow.Starfield.html | 2 +- Documentation/doc/2 classes/Objects.AIObject.html | 2 +- Documentation/doc/2 classes/Objects.Camera.html | 2 +- Documentation/doc/2 classes/Objects.LaraObject.html | 2 +- Documentation/doc/2 classes/Objects.Moveable.html | 2 +- Documentation/doc/2 classes/Objects.Room.html | 2 +- Documentation/doc/2 classes/Objects.Sink.html | 2 +- Documentation/doc/2 classes/Objects.SoundSource.html | 2 +- Documentation/doc/2 classes/Objects.Static.html | 2 +- Documentation/doc/2 classes/Objects.Volume.html | 2 +- Documentation/doc/2 classes/Strings.DisplayString.html | 2 +- Documentation/doc/2 classes/View.DisplaySprite.html | 2 +- Documentation/doc/3 primitive classes/Color.html | 2 +- Documentation/doc/3 primitive classes/Rotation.html | 2 +- Documentation/doc/3 primitive classes/Vec2.html | 2 +- Documentation/doc/3 primitive classes/Vec3.html | 2 +- Documentation/doc/4 enums/Effects.BlendID.html | 2 +- Documentation/doc/4 enums/Effects.EffectID.html | 2 +- Documentation/doc/4 enums/Flow.GameStatus.html | 2 +- Documentation/doc/4 enums/Input.ActionID.html | 2 +- Documentation/doc/4 enums/Objects.AmmoType.html | 2 +- Documentation/doc/4 enums/Objects.MoveableStatus.html | 2 +- Documentation/doc/4 enums/Objects.ObjID.html | 2 +- Documentation/doc/4 enums/Objects.RoomFlagID.html | 2 +- Documentation/doc/4 enums/Objects.RoomReverb.html | 2 +- Documentation/doc/4 enums/Sound.SoundTrackType.html | 2 +- Documentation/doc/4 enums/Util.LogLevel.html | 2 +- Documentation/doc/4 enums/View.AlignMode.html | 2 +- Documentation/doc/4 enums/View.CameraType.html | 2 +- Documentation/doc/4 enums/View.PostProcessMode.html | 2 +- Documentation/doc/4 enums/View.ScaleMode.html | 2 +- Documentation/doc/5 lua utility modules/EventSequence.html | 2 +- Documentation/doc/5 lua utility modules/Timer.html | 2 +- Documentation/doc/index.html | 4 ++-- 53 files changed, 54 insertions(+), 54 deletions(-) diff --git a/Documentation/config.ld b/Documentation/config.ld index 6220159cc..bd40d633c 100644 --- a/Documentation/config.ld +++ b/Documentation/config.ld @@ -12,7 +12,7 @@ new_type("luautil", "5 Lua utility modules", true) not_luadoc = true -local version = "1.4" +local version = "1.5" project = "TombEngine" title = "TombEngine " .. version .. " Lua API" description = "TombEngine " .. version .. " scripting interface" diff --git a/Documentation/doc/1 modules/Effects.html b/Documentation/doc/1 modules/Effects.html index fbdd34565..ad3ca0b7d 100644 --- a/Documentation/doc/1 modules/Effects.html +++ b/Documentation/doc/1 modules/Effects.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html index 1a38ee19a..4b028009d 100644 --- a/Documentation/doc/1 modules/Flow.html +++ b/Documentation/doc/1 modules/Flow.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Input.html b/Documentation/doc/1 modules/Input.html index 844cdb7c5..bf7b07fec 100644 --- a/Documentation/doc/1 modules/Input.html +++ b/Documentation/doc/1 modules/Input.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Inventory.html b/Documentation/doc/1 modules/Inventory.html index 7eabf50dc..32be88d47 100644 --- a/Documentation/doc/1 modules/Inventory.html +++ b/Documentation/doc/1 modules/Inventory.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Logic.html b/Documentation/doc/1 modules/Logic.html index 641535284..500e3d67e 100644 --- a/Documentation/doc/1 modules/Logic.html +++ b/Documentation/doc/1 modules/Logic.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Objects.html b/Documentation/doc/1 modules/Objects.html index e2254f3e5..e616c0ac0 100644 --- a/Documentation/doc/1 modules/Objects.html +++ b/Documentation/doc/1 modules/Objects.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Sound.html b/Documentation/doc/1 modules/Sound.html index ef08ef33e..cc291c4eb 100644 --- a/Documentation/doc/1 modules/Sound.html +++ b/Documentation/doc/1 modules/Sound.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Strings.html b/Documentation/doc/1 modules/Strings.html index f851e0e07..e570b6358 100644 --- a/Documentation/doc/1 modules/Strings.html +++ b/Documentation/doc/1 modules/Strings.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/Util.html b/Documentation/doc/1 modules/Util.html index 967e94298..319360268 100644 --- a/Documentation/doc/1 modules/Util.html +++ b/Documentation/doc/1 modules/Util.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/1 modules/View.html b/Documentation/doc/1 modules/View.html index fb8ac12f0..b201316aa 100644 --- a/Documentation/doc/1 modules/View.html +++ b/Documentation/doc/1 modules/View.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.Animations.html b/Documentation/doc/2 classes/Flow.Animations.html index 138c78dee..b48bf5fc2 100644 --- a/Documentation/doc/2 classes/Flow.Animations.html +++ b/Documentation/doc/2 classes/Flow.Animations.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.Fog.html b/Documentation/doc/2 classes/Flow.Fog.html index e90cb08d9..11a25b76a 100644 --- a/Documentation/doc/2 classes/Flow.Fog.html +++ b/Documentation/doc/2 classes/Flow.Fog.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.InventoryItem.html b/Documentation/doc/2 classes/Flow.InventoryItem.html index d8eba55a3..a6677c716 100644 --- a/Documentation/doc/2 classes/Flow.InventoryItem.html +++ b/Documentation/doc/2 classes/Flow.InventoryItem.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.LensFlare.html b/Documentation/doc/2 classes/Flow.LensFlare.html index 4f972ab32..0af9dd01b 100644 --- a/Documentation/doc/2 classes/Flow.LensFlare.html +++ b/Documentation/doc/2 classes/Flow.LensFlare.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.Level.html b/Documentation/doc/2 classes/Flow.Level.html index 942ae6163..eaffdc6fb 100644 --- a/Documentation/doc/2 classes/Flow.Level.html +++ b/Documentation/doc/2 classes/Flow.Level.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.Mirror.html b/Documentation/doc/2 classes/Flow.Mirror.html index 26e8fbfb4..b100c6f4b 100644 --- a/Documentation/doc/2 classes/Flow.Mirror.html +++ b/Documentation/doc/2 classes/Flow.Mirror.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.Settings.html b/Documentation/doc/2 classes/Flow.Settings.html index a29324f2e..007e40a45 100644 --- a/Documentation/doc/2 classes/Flow.Settings.html +++ b/Documentation/doc/2 classes/Flow.Settings.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.SkyLayer.html b/Documentation/doc/2 classes/Flow.SkyLayer.html index f3863417a..69565445a 100644 --- a/Documentation/doc/2 classes/Flow.SkyLayer.html +++ b/Documentation/doc/2 classes/Flow.SkyLayer.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Flow.Starfield.html b/Documentation/doc/2 classes/Flow.Starfield.html index a0d3880c4..199aa62ed 100644 --- a/Documentation/doc/2 classes/Flow.Starfield.html +++ b/Documentation/doc/2 classes/Flow.Starfield.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.AIObject.html b/Documentation/doc/2 classes/Objects.AIObject.html index 8b8095d28..308b5c37a 100644 --- a/Documentation/doc/2 classes/Objects.AIObject.html +++ b/Documentation/doc/2 classes/Objects.AIObject.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.Camera.html b/Documentation/doc/2 classes/Objects.Camera.html index 5729dcefa..a7ec64c6b 100644 --- a/Documentation/doc/2 classes/Objects.Camera.html +++ b/Documentation/doc/2 classes/Objects.Camera.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.LaraObject.html b/Documentation/doc/2 classes/Objects.LaraObject.html index eaf8bc408..f153396da 100644 --- a/Documentation/doc/2 classes/Objects.LaraObject.html +++ b/Documentation/doc/2 classes/Objects.LaraObject.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html index 06a82df82..fdd8a2559 100644 --- a/Documentation/doc/2 classes/Objects.Moveable.html +++ b/Documentation/doc/2 classes/Objects.Moveable.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.Room.html b/Documentation/doc/2 classes/Objects.Room.html index 306cb447b..191bdc97d 100644 --- a/Documentation/doc/2 classes/Objects.Room.html +++ b/Documentation/doc/2 classes/Objects.Room.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.Sink.html b/Documentation/doc/2 classes/Objects.Sink.html index f88a0f3f6..ceb1904e5 100644 --- a/Documentation/doc/2 classes/Objects.Sink.html +++ b/Documentation/doc/2 classes/Objects.Sink.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.SoundSource.html b/Documentation/doc/2 classes/Objects.SoundSource.html index 6221a947d..78ca5f16c 100644 --- a/Documentation/doc/2 classes/Objects.SoundSource.html +++ b/Documentation/doc/2 classes/Objects.SoundSource.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.Static.html b/Documentation/doc/2 classes/Objects.Static.html index 9b23623cc..362584c3a 100644 --- a/Documentation/doc/2 classes/Objects.Static.html +++ b/Documentation/doc/2 classes/Objects.Static.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Objects.Volume.html b/Documentation/doc/2 classes/Objects.Volume.html index 575b2cbbf..3970c11bf 100644 --- a/Documentation/doc/2 classes/Objects.Volume.html +++ b/Documentation/doc/2 classes/Objects.Volume.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/Strings.DisplayString.html b/Documentation/doc/2 classes/Strings.DisplayString.html index 9a7d4ae31..c32acc85d 100644 --- a/Documentation/doc/2 classes/Strings.DisplayString.html +++ b/Documentation/doc/2 classes/Strings.DisplayString.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/2 classes/View.DisplaySprite.html b/Documentation/doc/2 classes/View.DisplaySprite.html index 376e1fc4f..97256f8a6 100644 --- a/Documentation/doc/2 classes/View.DisplaySprite.html +++ b/Documentation/doc/2 classes/View.DisplaySprite.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/3 primitive classes/Color.html b/Documentation/doc/3 primitive classes/Color.html index 73ace19b3..7021129ac 100644 --- a/Documentation/doc/3 primitive classes/Color.html +++ b/Documentation/doc/3 primitive classes/Color.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/3 primitive classes/Rotation.html b/Documentation/doc/3 primitive classes/Rotation.html index b163bc9de..79ee6746c 100644 --- a/Documentation/doc/3 primitive classes/Rotation.html +++ b/Documentation/doc/3 primitive classes/Rotation.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/3 primitive classes/Vec2.html b/Documentation/doc/3 primitive classes/Vec2.html index 1968ad094..e42f03304 100644 --- a/Documentation/doc/3 primitive classes/Vec2.html +++ b/Documentation/doc/3 primitive classes/Vec2.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/3 primitive classes/Vec3.html b/Documentation/doc/3 primitive classes/Vec3.html index ce6afe46f..9aeb59a86 100644 --- a/Documentation/doc/3 primitive classes/Vec3.html +++ b/Documentation/doc/3 primitive classes/Vec3.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Effects.BlendID.html b/Documentation/doc/4 enums/Effects.BlendID.html index 176648f3d..d3f8f0c97 100644 --- a/Documentation/doc/4 enums/Effects.BlendID.html +++ b/Documentation/doc/4 enums/Effects.BlendID.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Effects.EffectID.html b/Documentation/doc/4 enums/Effects.EffectID.html index a4f375d07..9ad52e5b6 100644 --- a/Documentation/doc/4 enums/Effects.EffectID.html +++ b/Documentation/doc/4 enums/Effects.EffectID.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Flow.GameStatus.html b/Documentation/doc/4 enums/Flow.GameStatus.html index 913f32956..1575981e4 100644 --- a/Documentation/doc/4 enums/Flow.GameStatus.html +++ b/Documentation/doc/4 enums/Flow.GameStatus.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Input.ActionID.html b/Documentation/doc/4 enums/Input.ActionID.html index f6baf89fd..1838d08c1 100644 --- a/Documentation/doc/4 enums/Input.ActionID.html +++ b/Documentation/doc/4 enums/Input.ActionID.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Objects.AmmoType.html b/Documentation/doc/4 enums/Objects.AmmoType.html index 1d0acd788..ab6edf13e 100644 --- a/Documentation/doc/4 enums/Objects.AmmoType.html +++ b/Documentation/doc/4 enums/Objects.AmmoType.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Objects.MoveableStatus.html b/Documentation/doc/4 enums/Objects.MoveableStatus.html index d72b97b7a..51fef38ca 100644 --- a/Documentation/doc/4 enums/Objects.MoveableStatus.html +++ b/Documentation/doc/4 enums/Objects.MoveableStatus.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html index 8ceefa220..eef909dc7 100644 --- a/Documentation/doc/4 enums/Objects.ObjID.html +++ b/Documentation/doc/4 enums/Objects.ObjID.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Objects.RoomFlagID.html b/Documentation/doc/4 enums/Objects.RoomFlagID.html index 99800c4a7..f5aec2102 100644 --- a/Documentation/doc/4 enums/Objects.RoomFlagID.html +++ b/Documentation/doc/4 enums/Objects.RoomFlagID.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Objects.RoomReverb.html b/Documentation/doc/4 enums/Objects.RoomReverb.html index 2602f78a7..8af2f63c1 100644 --- a/Documentation/doc/4 enums/Objects.RoomReverb.html +++ b/Documentation/doc/4 enums/Objects.RoomReverb.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Sound.SoundTrackType.html b/Documentation/doc/4 enums/Sound.SoundTrackType.html index a940321bc..71391280e 100644 --- a/Documentation/doc/4 enums/Sound.SoundTrackType.html +++ b/Documentation/doc/4 enums/Sound.SoundTrackType.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/Util.LogLevel.html b/Documentation/doc/4 enums/Util.LogLevel.html index 6b21b58ee..9a558d2f2 100644 --- a/Documentation/doc/4 enums/Util.LogLevel.html +++ b/Documentation/doc/4 enums/Util.LogLevel.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/View.AlignMode.html b/Documentation/doc/4 enums/View.AlignMode.html index 568016c03..067a9b16a 100644 --- a/Documentation/doc/4 enums/View.AlignMode.html +++ b/Documentation/doc/4 enums/View.AlignMode.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/View.CameraType.html b/Documentation/doc/4 enums/View.CameraType.html index ffd8a8402..f46afe46e 100644 --- a/Documentation/doc/4 enums/View.CameraType.html +++ b/Documentation/doc/4 enums/View.CameraType.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/View.PostProcessMode.html b/Documentation/doc/4 enums/View.PostProcessMode.html index 37ddb7709..ae2a247f1 100644 --- a/Documentation/doc/4 enums/View.PostProcessMode.html +++ b/Documentation/doc/4 enums/View.PostProcessMode.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/4 enums/View.ScaleMode.html b/Documentation/doc/4 enums/View.ScaleMode.html index 1460c4610..e51125c98 100644 --- a/Documentation/doc/4 enums/View.ScaleMode.html +++ b/Documentation/doc/4 enums/View.ScaleMode.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/5 lua utility modules/EventSequence.html b/Documentation/doc/5 lua utility modules/EventSequence.html index c1f7495c3..81b60a585 100644 --- a/Documentation/doc/5 lua utility modules/EventSequence.html +++ b/Documentation/doc/5 lua utility modules/EventSequence.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/5 lua utility modules/Timer.html b/Documentation/doc/5 lua utility modules/Timer.html index 542dce9e2..482ccacce 100644 --- a/Documentation/doc/5 lua utility modules/Timer.html +++ b/Documentation/doc/5 lua utility modules/Timer.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html index 4d237a75b..814a66e4a 100644 --- a/Documentation/doc/index.html +++ b/Documentation/doc/index.html @@ -3,7 +3,7 @@ - TombEngine 1.4 Lua API + TombEngine 1.5 Lua API @@ -102,7 +102,7 @@
    -

    TombEngine 1.4 scripting interface

    +

    TombEngine 1.5 scripting interface

    Welcome to the TombEngine scripting API. This is a work in progress and some information might be wrong or outdated. Please also note that this is primarily a reference document, not a tutorial, so expect descriptions to be fairly sparse.

    At the time of writing, there is a tutorial describing the basics of Lua, as well as a number of example scripts, on the TombEngine website.

    From 4aac07c0c4e1b0f883a838296db668a62ce313ab Mon Sep 17 00:00:00 2001 From: Lwmte <3331699+Lwmte@users.noreply.github.com> Date: Sun, 3 Nov 2024 12:11:49 +0100 Subject: [PATCH 409/410] Fixed binocular bugs --- TombEngine/Game/control/control.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index d41762444..43c3bd150 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -224,11 +224,6 @@ GameStatus ControlPhase(bool insideMenu) PlaySoundSources(); Sound_UpdateScene(); - UpdateCamera(); - - // Post-loop script and event handling. - g_GameScript->OnLoop(DELTA_TIME, true); - // Handle inventory, pause, load, save screens. if (!insideMenu) { @@ -242,6 +237,11 @@ GameStatus ControlPhase(bool insideMenu) return result; } + UpdateCamera(); + + // Post-loop script and event handling. + g_GameScript->OnLoop(DELTA_TIME, true); + // Clear savegame loaded flag. JustLoaded = false; From a962a17f66db3372869044c79294255353b7ef83 Mon Sep 17 00:00:00 2001 From: Adngel <60930991+Adngel@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:08:59 +0100 Subject: [PATCH 410/410] Adngel fix death camera (#1449) * Update function * Adding comments. * Function renamed Function renamed and conditionals separated for clarity. * Extracted Camera data modifications Extracted commands that changes camera data, from the camera code, and moved them into the objects coded to follow similar logic with other cases (like enemies that change these values from their control code). Leaving a simplified CalculateDeathCamera() function. * Update tr5_rollingball.cpp Not really needed, so I removed it to keep consistency with the other calls. Also edited values adding the .0f for same reasons. --- TombEngine/Game/camera.cpp | 24 +++++++++++++++++++ TombEngine/Game/camera.h | 1 + .../Objects/TR4/Trap/tr4_teethspike.cpp | 6 +++++ .../Objects/TR5/Object/tr5_rollingball.cpp | 10 ++++++-- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index d03d35f7f..49414d5ff 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -1289,6 +1289,9 @@ void CalculateCamera(const CollisionInfo& coll) Camera.DisableInterpolation = (Camera.DisableInterpolation || Camera.lastType != Camera.type); Camera.lastType = Camera.type; + if (CalculateDeathCamera()) + return; + if (Camera.type != CameraType::Heavy || Camera.timer == -1) { Camera.type = CameraType::Chase; @@ -1304,6 +1307,27 @@ void CalculateCamera(const CollisionInfo& coll) } } +bool CalculateDeathCamera() +{ + // If player is alive, it's not a death camera. + if (LaraItem->HitPoints > 0) + return false; + + // If Lara is in a special death animation (from extra_anims) triggered by enemies. + if (LaraItem->Animation.AnimObjectID == ID_LARA_EXTRA_ANIMS) + return true; + + // Special death animations + if (LaraItem->Animation.AnimNumber == LA_SPIKE_DEATH || + LaraItem->Animation.AnimNumber == LA_BOULDER_DEATH || + LaraItem->Animation.AnimNumber == LA_TRAIN_OVERBOARD_DEATH) + { + return true; + } + + return false; +} + bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius) { auto sphere = BoundingSphere(Camera.pos.ToVector3(), radius); diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 59db6e4f8..5bf9429cb 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -105,6 +105,7 @@ void BinocularCamera(ItemInfo* item); void ConfirmCameraTargetPos(); void CalculateCamera(const CollisionInfo& coll); void RumbleScreen(); +bool CalculateDeathCamera(); bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius); void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius); void ItemsCollideCamera(); diff --git a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp index 0774e0666..a07bcac0d 100644 --- a/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp +++ b/TombEngine/Objects/TR4/Trap/tr4_teethspike.cpp @@ -1,6 +1,7 @@ #include "framework.h" #include "Objects/TR4/Trap/tr4_teethspike.h" +#include "Game/camera.h" #include "Game/collision/collide_item.h" #include "Game/collision/collide_room.h" #include "Game/collision/Point.h" @@ -161,6 +162,11 @@ namespace TEN::Entities::Traps { SetAnimation(LaraItem, LA_SPIKE_DEATH); LaraItem->Animation.IsAirborne = false; + + Camera.flags = CF_FOLLOW_CENTER; + Camera.targetAngle = ANGLE(-150.0f); + Camera.targetElevation = ANGLE(-25.0f); + Camera.targetDistance = BLOCK(2); } } } diff --git a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp index 5c77a6512..fe7088ff1 100644 --- a/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp +++ b/TombEngine/Objects/TR5/Object/tr5_rollingball.cpp @@ -41,6 +41,11 @@ void RollingBallCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* c !TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, laraItem)) { SetAnimation(laraItem, LA_BOULDER_DEATH); + + Camera.flags = CF_FOLLOW_CENTER; + Camera.targetAngle = ANGLE(170.0f); + Camera.targetElevation = ANGLE(-25.0f); + Camera.targetDistance = BLOCK(2); } } else @@ -364,8 +369,9 @@ void ClassicRollingBallCollision(short itemNum, ItemInfo* lara, CollisionInfo* c SetAnimation(lara, LA_BOULDER_DEATH); Camera.flags = CF_FOLLOW_CENTER; - Camera.targetAngle = ANGLE(170); - Camera.targetElevation = -ANGLE(25); + Camera.targetAngle = ANGLE(170.0f); + Camera.targetElevation = -ANGLE(-25.0f); + Camera.targetDistance = BLOCK(2); for (int i = 0; i < 15; i++) {