diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cea2b24c..aa07bf0f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): * Fixed Lara's Home entry not working. * Fixed exploding TR3 bosses. * Fixed original issue with deactivation of Dart Emitter. +* Fixed original issue with weapon hotkeys available in binoculars or lasersight mode. * Fixed Lens Flare object not functioning properly. * Fixed lens flares not being occluded by static meshes and moveables. * Fixed spotlight shadows. @@ -39,6 +40,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor): ### New Features * Added fast savegame reloading. * Added ricochet sounds and make the effect more prominent. +* Allow camera shake during flybys. * Allow to run the engine without title level. * Allow more than 1024 objects in a level. * Allow more than 1000 static mesh slots in a level. diff --git a/Scripts/Engine/Timer.lua b/Scripts/Engine/Timer.lua index 59ce2f3a3..a47bdc0f7 100644 --- a/Scripts/Engine/Timer.lua +++ b/Scripts/Engine/Timer.lua @@ -202,7 +202,7 @@ Timer = { str:SetColor(pausedColor) end - TEN.Strings.ShowString(str, 1) + TEN.Strings.ShowString(str, 1, false) end end diff --git a/TombEngine/Game/Lara/lara_helpers.cpp b/TombEngine/Game/Lara/lara_helpers.cpp index 48fee7e30..35bc49722 100644 --- a/TombEngine/Game/Lara/lara_helpers.cpp +++ b/TombEngine/Game/Lara/lara_helpers.cpp @@ -342,6 +342,10 @@ void HandlePlayerQuickActions(ItemInfo& item) g_Gui.UseItem(item, GAME_OBJECT_ID::ID_BIGMEDI_ITEM); } + // Don't process weapon hotkeys in optics mode. + if (player.Control.Look.IsUsingBinoculars) + return; + // Handle weapon scroll request. if (IsClicked(In::PreviousWeapon) || IsClicked(In::NextWeapon)) { diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp index 1a79ecfc8..f1007e352 100644 --- a/TombEngine/Game/camera.cpp +++ b/TombEngine/Game/camera.cpp @@ -215,6 +215,38 @@ inline void RumbleFromBounce() Rumble(std::clamp((float)abs(Camera.bounce) / 70.0f, 0.0f, 0.8f), 0.2f); } +void CalculateBounce(bool binocularMode) +{ + if (Camera.bounce == 0) + return; + + if (Camera.bounce <= 0) + { + if (binocularMode) + { + Camera.target.x += (CLICK(0.25f) / 4) * (GetRandomControl() % (-Camera.bounce) - (-Camera.bounce / 2)); + Camera.target.y += (CLICK(0.25f) / 4) * (GetRandomControl() % (-Camera.bounce) - (-Camera.bounce / 2)); + Camera.target.z += (CLICK(0.25f) / 4) * (GetRandomControl() % (-Camera.bounce) - (-Camera.bounce / 2)); + } + else + { + int bounce = -Camera.bounce; + int bounce2 = bounce / 2; + Camera.target.x += GetRandomControl() % bounce - bounce2; + Camera.target.y += GetRandomControl() % bounce - bounce2; + Camera.target.z += GetRandomControl() % bounce - bounce2; + } + + Camera.bounce += 5; + RumbleFromBounce(); + } + else + { + Camera.pos.y += Camera.bounce; + Camera.target.y += Camera.bounce; + Camera.bounce = 0; + } +} void InitializeCamera() { @@ -313,25 +345,7 @@ void MoveCamera(GameVector* ideal, int speed) Camera.pos.z += (ideal->z - Camera.pos.z) / speed; Camera.pos.RoomNumber = ideal->RoomNumber; - if (Camera.bounce) - { - if (Camera.bounce <= 0) - { - int bounce = -Camera.bounce; - int bounce2 = bounce / 2; - Camera.target.x += GetRandomControl() % bounce - bounce2; - Camera.target.y += GetRandomControl() % bounce - bounce2; - Camera.target.z += GetRandomControl() % bounce - bounce2; - Camera.bounce += 5; - RumbleFromBounce(); - } - else - { - Camera.pos.y += Camera.bounce; - Camera.target.y += Camera.bounce; - Camera.bounce = 0; - } - } + CalculateBounce(false); int y = Camera.pos.y; if (TestEnvironment(ENV_FLAG_SWAMP, Camera.pos.RoomNumber)) @@ -1000,23 +1014,8 @@ void BinocularCamera(ItemInfo* item) Camera.target.RoomNumber = item->RoomNumber; } - if (Camera.bounce && - Camera.type == Camera.oldType) - { - if (Camera.bounce <= 0) - { - Camera.target.x += (CLICK(0.25f) / 4) * (GetRandomControl() % (-Camera.bounce) - (-Camera.bounce / 2)); - Camera.target.y += (CLICK(0.25f) / 4) * (GetRandomControl() % (-Camera.bounce) - (-Camera.bounce / 2)); - Camera.target.z += (CLICK(0.25f) / 4) * (GetRandomControl() % (-Camera.bounce) - (-Camera.bounce / 2)); - Camera.bounce += 5; - RumbleFromBounce(); - } - else - { - Camera.bounce = 0; - Camera.target.y += Camera.bounce; - } - } + if (Camera.type == Camera.oldType) + CalculateBounce(true); Camera.target.RoomNumber = GetPointCollision(Camera.pos.ToVector3i(), Camera.target.RoomNumber).GetRoomNumber(); LookAt(&Camera, 0); diff --git a/TombEngine/Game/camera.h b/TombEngine/Game/camera.h index 6a6939c94..f92703ec7 100644 --- a/TombEngine/Game/camera.h +++ b/TombEngine/Game/camera.h @@ -99,6 +99,7 @@ void BounceCamera(ItemInfo* item, short bounce, short maxDistance); void BinocularCamera(ItemInfo* item); void ConfirmCameraTargetPos(); void CalculateCamera(const CollisionInfo& coll); +void CalculateBounce(bool binocularMode); void RumbleScreen(); bool TestBoundsCollideCamera(const GameBoundingBox& bounds, const Pose& pose, short radius); void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius); diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp index 548df849c..0941e0682 100644 --- a/TombEngine/Game/control/control.cpp +++ b/TombEngine/Game/control/control.cpp @@ -594,8 +594,14 @@ void InitializeOrLoadGame(bool loadGame) g_Gui.SetEnterInventory(NO_VALUE); // Restore game? - if (loadGame && SaveGame::Load(g_GameFlow->SelectedSaveGame)) + if (loadGame) { + if (!SaveGame::Load(g_GameFlow->SelectedSaveGame)) + { + NextLevel = g_GameFlow->GetNumLevels(); + return; + } + InitializeGame = false; g_GameFlow->SelectedSaveGame = 0; diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp index 968867ccd..fe1962878 100644 --- a/TombEngine/Game/savegame.cpp +++ b/TombEngine/Game/savegame.cpp @@ -206,6 +206,19 @@ bool SaveGame::DoesSaveGameExist(int slot, bool silent) return true; } +bool SaveGame::IsSaveGameValid(int slot) +{ + SaveGameHeader header; + if (!LoadHeader(slot, &header)) + return false; + + // Hash mismatch between savegame and level file means that level version has changed. + if (header.LevelHash != LastLevelHash) + return false; + + return true; +} + bool SaveGame::IsLoadGamePossible() { for (int i = 0; i < SAVEGAME_MAX; i++) @@ -1614,15 +1627,9 @@ bool SaveGame::Save(int slot) bool SaveGame::Load(int slot) { - if (!IsSaveGameSlotValid(slot)) + if (!IsSaveGameValid(slot)) { - TENLog("Savegame slot " + std::to_string(slot) + " is invalid, load is impossible.", LogLevel::Error); - return false; - } - - if (!DoesSaveGameExist(slot)) - { - TENLog("Savegame in slot " + std::to_string(slot) + " does not exist.", LogLevel::Error); + TENLog("Loading from savegame in slot " + std::to_string(slot) + " is impossible, data is missing or level has changed.", LogLevel::Error); return false; } diff --git a/TombEngine/Game/savegame.h b/TombEngine/Game/savegame.h index 3b09ac92d..067391a93 100644 --- a/TombEngine/Game/savegame.h +++ b/TombEngine/Game/savegame.h @@ -66,6 +66,7 @@ public: static bool DoesSaveGameExist(int slot, bool silent = false); static bool IsLoadGamePossible(); + static bool IsSaveGameValid(int slot); static void SaveHub(int index); static void LoadHub(int index); diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp index e39ba51a0..2d2b3bc54 100644 --- a/TombEngine/Game/spotcam.cpp +++ b/TombEngine/Game/spotcam.cpp @@ -494,6 +494,7 @@ void CalculateSpotCameras() Camera.target.x = ctx; Camera.target.y = cty; Camera.target.z = ctz; + CalculateBounce(false); } int outsideRoom = IsRoomOutside(cpx, cpy, cpz);