From 64a2d60d2f9a9cbed525d9e30881f90bae361e3d Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 00:29:33 +0100
Subject: [PATCH 01/53] Added safeguards for problems surfaced in #1618
---
TombEngine/Game/animation.cpp | 4 ++++
TombEngine/Renderer/RendererDraw.cpp | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp
index 53d0a6d46..04eb59905 100644
--- a/TombEngine/Game/animation.cpp
+++ b/TombEngine/Game/animation.cpp
@@ -711,6 +711,10 @@ Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite)
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex)
{
const auto& object = Objects[objectID];
+ int boneIndex = object.boneIndex + (jointIndex * 4);
+
+ if (g_Level.Bones.size() <= boneIndex)
+ return Vector3::Zero;
int* bonePtr = &g_Level.Bones[object.boneIndex + (jointIndex * 4)];
return Vector3(*(bonePtr + 1), *(bonePtr + 2), *(bonePtr + 3));
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 98e29e66f..a79e06298 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -2571,6 +2571,12 @@ namespace TEN::Renderer
if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p))
continue;
+ if (_staticTextures.size() <= bucket.Texture)
+ {
+ TENLog("Attempted to set incorrect static mesh texture atlas", LogLevel::Warning);
+ continue;
+ }
+
BindTexture(TextureRegister::ColorMap,
&std::get<0>(_staticTextures[bucket.Texture]),
SamplerStateRegister::AnisotropicClamp);
From c608e6dec5d76ee2453486b6405173cf14079e77 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 00:30:52 +0100
Subject: [PATCH 02/53] Update CHANGELOG.md
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index edf146d46..78bf16d1c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Bug fixes
* Fixed particles remaining in the level after reloading from the savegame.
* Fixed particles being canceled by fog bulbs.
+* Fixed crash in case hair object is the last object in a level.
+* Fixed crash with incorrectly applied animated textures on static meshes.
### Lua API changes
* Added missing constructor for `Collision.Probe` without room number.
From 8c26702678cd4c167a26c87ef5e89cce9aa76365 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 08:31:05 +0100
Subject: [PATCH 03/53] Always warn about different game version
---
TombEngine/Specific/level.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp
index 3addd27f9..4935ecb0a 100644
--- a/TombEngine/Specific/level.cpp
+++ b/TombEngine/Specific/level.cpp
@@ -1317,7 +1317,7 @@ bool LoadLevel(const std::string& path, bool partial)
auto assemblyVersion = TEN::Utils::GetProductOrFileVersion(true);
for (int i = 0; i < assemblyVersion.size(); i++)
{
- if (assemblyVersion[i] < version[i])
+ if (assemblyVersion[i] != version[i])
{
TENLog("Level version is different from TEN version.", LogLevel::Warning);
break;
From b1ee6a190eb1a4fdf5af76406a2bb18492b5986e Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 09:42:01 +0100
Subject: [PATCH 04/53] Added ability to perform Lua commands in the console
window in realtime
---
CHANGELOG.md | 37 +++++++++++++++++---------------
TombEngine/Specific/winmain.cpp | 38 +++++++++++++++++++++++++++++++--
2 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 78bf16d1c..30710e1f3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,9 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.8.1](link to release) - yyyy-mm-dd
+### New features
+* Added ability to perform Lua commands in the console window in realtime.
+
### Bug fixes
* Fixed particles remaining in the level after reloading from the savegame.
* Fixed particles being canceled by fog bulbs.
@@ -35,7 +38,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed custom shatter sounds with custom sound IDs not playing correctly.
* Fixed crashes with sound samples larger than 2 megabytes.
-### New Features
+### New features
* Added multithreading and an option for it to flow system settings.
* Added ability to use floor trapdoors, keys and puzzle items underwater.
- You must update your Lara object: https://github.com/TombEngine/Resources/raw/main/Wad2%20Objects/Lara/TEN_Lara.wad2
@@ -84,7 +87,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed gravity being applied underwater when exiting the fly cheat.
* Fixed gravity being applied when vaulting on the same frame as the player lands.
-### New Features
+### New features
* Added realtime shader reloading in debug mode by pressing F9 key.
* Added load, save, stopwatch and compass as a functional pick-up items with ability to add or remove them from inventory.
* Increased particle limit from 1024 to 4096.
@@ -134,7 +137,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed spotlight shadows.
* Fixed Skeleton and Mummy not reacting to shotgun hits.
-### New Features
+### New features
* Added classic mirror effect with ability to reflect moveables and static meshes.
* Added ability to customize many hardcoded parameters, such as flare, weapon, and hair settings.
* Added dynamic shadow casting on objects and static meshes.
@@ -210,7 +213,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed display sprites and display strings rendering in the inventory background.
* Fixed young Lara hair drawing. https://tombengine.com/docs/level-settings/#young_lara
-### New Features
+### New features
* 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. https://tombengine.com/docs/level-settings/#stars
@@ -270,7 +273,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed bottom collision for solid static meshes.
* Fixed T-Rex's head rotation.
-### New Features
+### New features
* 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:
@@ -317,7 +320,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed incorrect light collection in some cases.
* Fixed normal mapping for rooms, items, and statics.'
-### New Features
+### New features
* Added ambient occlusion (SSAO).
* Added new post-process workflow (monochrome, negative, exclusion) with tinting.
* Added SMAA antialiasing instead of MSAA.
@@ -376,7 +379,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fix camera snap when disengaging the look-around mode.
* Fix TR4 mapper not being visible.
-### New Features
+### New features
* Improve head-on wall collision.
* Overhaul pushables:
- Separate climbable and non-climbable pushable object slots.
@@ -459,7 +462,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fix incorrect culling for scaled static meshes.
* Fix normal mapping.
-### New Features
+### New features
* 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.
@@ -507,7 +510,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fix rendering for static meshes with custom blending modes and alpha transparency.
* Fix inconsistent multiline string spacing on different display modes.
-### New Features
+### New features
* Remove search object 4 hardcoded meshswap activated with a flipmap.
* Add TR1 cowboy.
* Add TR3 wall mounted blade.
@@ -565,7 +568,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
- 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.
-### New Features/Amedments
+### New features/Amedments
* Add dedicated WRAITH_TRAP object with enhanced effects.
- OCB 0: Effect disabled.
- OCB 1: Effect enabled.
@@ -614,7 +617,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fix TR3 big gun spawning rocket with 0 life which caused an immediate explosion.
* Fix TR3 Tony and add boss effect for him.
-### New Features
+### New features
* Add TR3 civvy.
* Add TR3 electric cleaner.
* Add TR3 Sophia Leigh with following OCBs:
@@ -666,7 +669,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fix grenade and rocket launcher lighting.
* Fix ceiling trapdoor and floor trapdoor that Lara couldn't open manually.
-### New Features
+### New features
* Make enemies drop pickups at first available bounding box corner point, not centerpoint.
* Restore original volumetric explosion effects.
* Add TR3 lizard and Puna.
@@ -718,7 +721,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fix bone rotations of some entities.
* Fix Lara's animation for cog switch release.
-### New Features
+### New features
* 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.
@@ -732,7 +735,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.0.4](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.6.2) - 2022-12-16
-### New Features
+### New features
* 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).
@@ -804,7 +807,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.0.3](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.6.1) - 2022-11-18
-### New Features
+### New features
* 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.
@@ -872,7 +875,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.0.2](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.6) - 2022-09-16
-### New Features
+### New features
* Fix removing Pistols with TakeItem and SetItemCount.
* Allow saving and loading of Vec3s in LevelVars and GameVars.
* Support volume triggers made with node editor.
@@ -927,7 +930,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.0.1](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.5.2) - 2022-08-16
-### New Features
+### New features
* Added antialiasing support.
* Added static mesh scaling support.
* Added free rotation for teeth spikes instead of using OCB codes.
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index bd7b2cefa..d120636c4 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -30,8 +30,8 @@ using std::cout;
using std::endl;
WINAPP App;
-unsigned int ThreadID;
-uintptr_t ThreadHandle;
+unsigned int ThreadID, ConsoleThreadID;
+uintptr_t ThreadHandle, ConsoleThreadHandle;
HACCEL hAccTable;
bool DebugMode = false;
HWND WindowsHandle;
@@ -242,6 +242,37 @@ bool GenerateDummyLevel(const std::string& levelPath)
return true;
}
+unsigned CALLBACK ConsoleInput(void*)
+{
+ std::string input;
+
+ while (!ThreadEnded)
+ {
+ if (!std::getline(std::cin, input))
+ break;
+
+ if (g_GameScript == nullptr)
+ {
+ TENLog("Scripting engine not initialized.", LogLevel::Error);
+ continue;
+ }
+ else
+ {
+ try
+ {
+ g_GameScript->ExecuteString(input);
+ }
+ catch (const exception& ex)
+ {
+ std::string error = ex.what();
+ TENLog("Error executing " + input + ": " + error.substr(error.find(":1: ") + 4), LogLevel::Error);
+ }
+ }
+ }
+
+ return true;
+}
+
void WinProcMsg()
{
MSG msg;
@@ -406,7 +437,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
#ifndef _DEBUG
if (!DebugMode)
ShowWindow(GetConsoleWindow(), 0);
+ else
#endif
+ ConsoleThreadHandle = BeginThread(ConsoleInput, ConsoleThreadID);
// Clear application structure.
memset(&App, 0, sizeof(WINAPP));
@@ -615,6 +648,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
void WinClose()
{
+ CloseHandle((HANDLE)ConsoleThreadHandle);
WaitForSingleObject((HANDLE)ThreadHandle, 5000);
DestroyAcceleratorTable(hAccTable);
From 075c438b5d4c76e30c623941a61bbc55ca27114a Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 09:49:03 +0100
Subject: [PATCH 05/53] Update CHANGELOG.md
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30710e1f3..622cb7839 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.8.1](link to release) - yyyy-mm-dd
### New features
-* Added ability to perform Lua commands in the console window in realtime.
+* Added live console input to perform Lua commands in realtime.
### Bug fixes
* Fixed particles remaining in the level after reloading from the savegame.
From d47e8d0e6989d5461be7f281005f33989b3818a1 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 09:57:25 +0100
Subject: [PATCH 06/53] Don't try to execute empty lines
---
TombEngine/Specific/winmain.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index d120636c4..5a68753bc 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -251,6 +251,9 @@ unsigned CALLBACK ConsoleInput(void*)
if (!std::getline(std::cin, input))
break;
+ if (std::regex_match(input, std::regex("^\\s*$")))
+ continue;
+
if (g_GameScript == nullptr)
{
TENLog("Scripting engine not initialized.", LogLevel::Error);
From f0f733519fbdc465804cc09abe32371e939908c2 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 10:01:51 +0100
Subject: [PATCH 07/53] Simplify error message
---
TombEngine/Specific/winmain.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index 5a68753bc..01d13bf8c 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -267,8 +267,7 @@ unsigned CALLBACK ConsoleInput(void*)
}
catch (const exception& ex)
{
- std::string error = ex.what();
- TENLog("Error executing " + input + ": " + error.substr(error.find(":1: ") + 4), LogLevel::Error);
+ TENLog("Error executing " + input + ": " + ex.what(), LogLevel::Error);
}
}
}
From e27ec86e853ad0f24c524e8fc8a5139e8f86f908 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 10:28:12 +0100
Subject: [PATCH 08/53] Allow to run console input in freeze modes as well
---
.../Scripting/Include/ScriptInterfaceGame.h | 1 +
.../Internal/TEN/Logic/LogicHandler.cpp | 26 +++++++++++++++++++
.../Internal/TEN/Logic/LogicHandler.h | 5 +++-
TombEngine/Specific/winmain.cpp | 13 +---------
4 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/TombEngine/Scripting/Include/ScriptInterfaceGame.h b/TombEngine/Scripting/Include/ScriptInterfaceGame.h
index 73b0be0ee..121cbe2f2 100644
--- a/TombEngine/Scripting/Include/ScriptInterfaceGame.h
+++ b/TombEngine/Scripting/Include/ScriptInterfaceGame.h
@@ -62,6 +62,7 @@ public:
virtual void OnUseItem(GAME_OBJECT_ID objectNumber) = 0;
virtual void OnFreeze() = 0;
+ virtual void AddConsoleInput(const std::string& input) = 0;
virtual void ShortenTENCalls() = 0;
virtual void FreeLevelScripts() = 0;
virtual void ResetScripts(bool clearGameVars) = 0;
diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp
index e85c98ce5..e1cf4ed6b 100644
--- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp
+++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.cpp
@@ -620,6 +620,28 @@ int Handle(TypeFrom& var, MapType& varsMap, size_t& numVars, std::vectorsecond;
}
+void LogicHandler::AddConsoleInput(const std::string& input)
+{
+ _consoleInput = input;
+}
+
+void LogicHandler::PerformConsoleInput()
+{
+ if (!_consoleInput.empty())
+ {
+ try
+ {
+ ExecuteString(_consoleInput);
+ }
+ catch (const std::exception& ex)
+ {
+ TENLog("Error executing " + _consoleInput + ": " + ex.what(), LogLevel::Error);
+ }
+
+ _consoleInput.clear();
+ }
+}
+
std::string LogicHandler::GetRequestedPath() const
{
auto path = std::string();
@@ -1027,6 +1049,8 @@ void LogicHandler::OnLoop(float deltaTime, bool postLoop)
for (const auto& name : _callbacksPreLoop)
CallLevelFuncByName(name, deltaTime);
+ PerformConsoleInput();
+
lua_gc(_handler.GetState()->lua_state(), LUA_GCCOLLECT, 0);
if (_onLoop.valid())
CallLevelFunc(_onLoop, deltaTime);
@@ -1099,6 +1123,8 @@ void LogicHandler::OnFreeze()
for (const auto& name : _callbacksPreFreeze)
CallLevelFuncByName(name);
+ PerformConsoleInput();
+
if (_onFreeze.valid())
CallLevelFunc(_onFreeze);
diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h
index f4f7ff481..8ff7be4e2 100644
--- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h
+++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h
@@ -75,11 +75,13 @@ private:
sol::protected_function _onFreeze = {};
std::unordered_map*> _callbacks;
-
std::vector> _savedVarPath;
bool _shortenedCalls = false;
+ std::string _consoleInput = "";
+ void PerformConsoleInput();
+
std::string GetRequestedPath() const;
void ResetLevelTables();
@@ -132,6 +134,7 @@ public:
void HandleEvent(const std::string& name, EventType type, sol::optional activator);
void EnableEvent(const std::string& name, EventType type);
void DisableEvent(const std::string& name, EventType type);
+ void AddConsoleInput(const std::string& input);
void ResetScripts(bool clearGameVars) override;
void ShortenTENCalls() override;
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index 01d13bf8c..f4cf4d9da 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -24,10 +24,6 @@ using namespace TEN::Renderer;
using namespace TEN::Input;
using namespace TEN::Utils;
-using std::exception;
-using std::string;
-using std::cout;
-using std::endl;
WINAPP App;
unsigned int ThreadID, ConsoleThreadID;
@@ -261,14 +257,7 @@ unsigned CALLBACK ConsoleInput(void*)
}
else
{
- try
- {
- g_GameScript->ExecuteString(input);
- }
- catch (const exception& ex)
- {
- TENLog("Error executing " + input + ": " + ex.what(), LogLevel::Error);
- }
+ g_GameScript->AddConsoleInput(input);
}
}
From 8427ae770621d2cd3f195378d31a4190472b7948 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 10:37:36 +0100
Subject: [PATCH 09/53] Update winmain.cpp
---
TombEngine/Specific/winmain.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index f4cf4d9da..3efdd8b20 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -639,7 +639,9 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
void WinClose()
{
- CloseHandle((HANDLE)ConsoleThreadHandle);
+ if (ConsoleThreadHandle)
+ CloseHandle((HANDLE)ConsoleThreadHandle);
+
WaitForSingleObject((HANDLE)ThreadHandle, 5000);
DestroyAcceleratorTable(hAccTable);
From 382b9d1ef59425fb9c43272b400f11dab9b47031 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 22 Mar 2025 10:56:17 +0100
Subject: [PATCH 10/53] Fixed incorrect debug line
---
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 87de33b5c..e38f1e440 100644
--- a/TombEngine/Renderer/RendererDrawMenu.cpp
+++ b/TombEngine/Renderer/RendererDrawMenu.cpp
@@ -1331,7 +1331,7 @@ namespace TEN::Renderer
PrintDebugMessage("RoomNumber: %d", LaraItem->RoomNumber);
PrintDebugMessage("PathfindingBoxID: %d", LaraItem->BoxNumber);
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 Bounds: (%d, %d), (%d, %d)", room.Position.x, room.Position.z, room.Position.x + 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);
From ac77c5f9ad007944fa89c1bda5b716cac4325088 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sun, 23 Mar 2025 08:24:36 +0100
Subject: [PATCH 11/53] Rollback MovingLaserFlags rename, bump version number
---
TombEngine/Objects/TR5/Trap/MovingLaser.cpp | 34 ++++++++++-----------
TombEngine/version.h | 4 +--
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/TombEngine/Objects/TR5/Trap/MovingLaser.cpp b/TombEngine/Objects/TR5/Trap/MovingLaser.cpp
index bb07f8c19..830d14746 100644
--- a/TombEngine/Objects/TR5/Trap/MovingLaser.cpp
+++ b/TombEngine/Objects/TR5/Trap/MovingLaser.cpp
@@ -23,7 +23,7 @@ namespace TEN::Entities::Traps
constexpr auto MOVING_LASER_ACCEL = 1.0f;
constexpr auto MOVING_LASER_PAUSE_FRAME_COUNT = 30;
- enum class MovingLaserProperty
+ enum class MovingLaserFlags
{
Velocity,
PauseTimer,
@@ -35,8 +35,8 @@ namespace TEN::Entities::Traps
void InitializeMovingLaser(short itemNumber)
{
auto& item = g_Level.Items[itemNumber];
- item.ItemFlags[(int)MovingLaserProperty::DirectionSign] = 1;
- item.ItemFlags[(int)MovingLaserProperty::Velocity] = 10;
+ item.ItemFlags[(int)MovingLaserFlags::DirectionSign] = 1;
+ item.ItemFlags[(int)MovingLaserFlags::Velocity] = 10;
// Offset by 1/4 block to make it dangerous at sector edges.
item.Pose.Translate(item.Pose.Orientation, -BLOCK(0.25f));
@@ -51,7 +51,7 @@ namespace TEN::Entities::Traps
// Calculate distances.
float moveDist = BLOCK(item.TriggerFlags) + BLOCK(0.5f);
- float distPerFrame = (BLOCK(item.ItemFlags[(int)MovingLaserProperty::Velocity]) * 0.25f) / (float)FPS;
+ float distPerFrame = (BLOCK(item.ItemFlags[(int)MovingLaserFlags::Velocity]) * 0.25f) / (float)FPS;
item.Animation.ActiveState = 0;
@@ -74,38 +74,38 @@ namespace TEN::Entities::Traps
return;
}
- if (item.ItemFlags[(int)MovingLaserProperty::PauseTimer] > 0)
+ if (item.ItemFlags[(int)MovingLaserFlags::PauseTimer] > 0)
{
- item.ItemFlags[(int)MovingLaserProperty::PauseTimer]--;
- if (item.ItemFlags[(int)MovingLaserProperty::PauseTimer] == 0)
+ item.ItemFlags[(int)MovingLaserFlags::PauseTimer]--;
+ if (item.ItemFlags[(int)MovingLaserFlags::PauseTimer] == 0)
{
- item.ItemFlags[(int)MovingLaserProperty::DirectionSign] *= -1;
- item.ItemFlags[(int)MovingLaserProperty::DistanceTraveled] = 0;
+ item.ItemFlags[(int)MovingLaserFlags::DirectionSign] *= -1;
+ item.ItemFlags[(int)MovingLaserFlags::DistanceTraveled] = 0;
}
AnimateItem(&item);
return;
}
- item.Pose.Translate(item.Pose.Orientation, (item.ItemFlags[(int)MovingLaserProperty::DirectionSign] * item.ItemFlags[(int)MovingLaserProperty::VelocityCalc]));
+ item.Pose.Translate(item.Pose.Orientation, (item.ItemFlags[(int)MovingLaserFlags::DirectionSign] * item.ItemFlags[(int)MovingLaserFlags::VelocityCalc]));
- item.ItemFlags[(int)MovingLaserProperty::DistanceTraveled] += item.ItemFlags[(int)MovingLaserProperty::VelocityCalc];
+ item.ItemFlags[(int)MovingLaserFlags::DistanceTraveled] += item.ItemFlags[(int)MovingLaserFlags::VelocityCalc];
- if (item.ItemFlags[(int)MovingLaserProperty::DistanceTraveled] < (moveDist - BLOCK(0.5f)))
+ if (item.ItemFlags[(int)MovingLaserFlags::DistanceTraveled] < (moveDist - BLOCK(0.5f)))
{
- item.ItemFlags[(int)MovingLaserProperty::VelocityCalc] = std::min(distPerFrame, item.ItemFlags[(int)MovingLaserProperty::VelocityCalc] + MOVING_LASER_ACCEL);
+ item.ItemFlags[(int)MovingLaserFlags::VelocityCalc] = std::min(distPerFrame, item.ItemFlags[(int)MovingLaserFlags::VelocityCalc] + MOVING_LASER_ACCEL);
}
else
{
- item.ItemFlags[(int)MovingLaserProperty::VelocityCalc] = std::max(MOVING_LASER_VELOCITY_MIN, item.ItemFlags[(int)MovingLaserProperty::VelocityCalc] - MOVING_LASER_ACCEL);
+ item.ItemFlags[(int)MovingLaserFlags::VelocityCalc] = std::max(MOVING_LASER_VELOCITY_MIN, item.ItemFlags[(int)MovingLaserFlags::VelocityCalc] - MOVING_LASER_ACCEL);
}
- if (item.ItemFlags[(int)MovingLaserProperty::DistanceTraveled] >= moveDist)
+ if (item.ItemFlags[(int)MovingLaserFlags::DistanceTraveled] >= moveDist)
{
- item.ItemFlags[(int)MovingLaserProperty::PauseTimer] = MOVING_LASER_PAUSE_FRAME_COUNT;
+ item.ItemFlags[(int)MovingLaserFlags::PauseTimer] = MOVING_LASER_PAUSE_FRAME_COUNT;
}
- if (item.ItemFlags[(int)MovingLaserProperty::PauseTimer] == 0)
+ if (item.ItemFlags[(int)MovingLaserFlags::PauseTimer] == 0)
{
SoundEffect(SFX_TR5_MOVING_LASER_LOOP, &item.Pose, SoundEnvironment::Always);
}
diff --git a/TombEngine/version.h b/TombEngine/version.h
index 464c2b659..654ddf744 100644
--- a/TombEngine/version.h
+++ b/TombEngine/version.h
@@ -2,12 +2,12 @@
#define TE_MAJOR_VERSION 1
#define TE_MINOR_VERSION 8
-#define TE_BUILD_NUMBER 0
+#define TE_BUILD_NUMBER 1
#define TE_REVISION_NUMBER 0
#define TEN_MAJOR_VERSION 1
#define TEN_MINOR_VERSION 8
-#define TEN_BUILD_NUMBER 0
+#define TEN_BUILD_NUMBER 1
#define TEN_REVISION_NUMBER 0
#define TEST_BUILD 1
From 78e8d34c005f80497840cb6bc0e6dab16963ac00 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Mon, 24 Mar 2025 22:03:52 +0100
Subject: [PATCH 12/53] Fixed console on Win11 and monkey pathfinding
---
CHANGELOG.md | 2 ++
TombEngine/Game/control/box.cpp | 10 +++++++---
TombEngine/Specific/winmain.cpp | 2 +-
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 622cb7839..9dab845db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,10 +9,12 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Added live console input to perform Lua commands in realtime.
### Bug fixes
+* Fixed pathfinding for friendly NPCs, such as monkeys.
* Fixed particles remaining in the level after reloading from the savegame.
* Fixed particles being canceled by fog bulbs.
* Fixed crash in case hair object is the last object in a level.
* Fixed crash with incorrectly applied animated textures on static meshes.
+* Fixed console window not hiding in non-debug mode on Windows 11.
### Lua API changes
* Added missing constructor for `Collision.Probe` without room number.
diff --git a/TombEngine/Game/control/box.cpp b/TombEngine/Game/control/box.cpp
index b60256557..763dfec8b 100644
--- a/TombEngine/Game/control/box.cpp
+++ b/TombEngine/Game/control/box.cpp
@@ -1150,6 +1150,7 @@ bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber)
{
if (enemy == nullptr || boxNumber == NO_VALUE)
return false;
+
auto* box = &g_Level.PathfindingBoxes[boxNumber];
int xRange = STALK_DIST + ((box->bottom - box->top) * BLOCK(1));
@@ -1635,8 +1636,11 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent)
auto* LOT = &creature->LOT;
auto* enemy = creature->Enemy;
- if (enemy == nullptr)
- return;
+
+ // HACK: Fallback to bored mood from attack mood if enemy was cleared.
+ // Replaces previous "fix" with early exit, because it was breaking friendly NPC pathfinding. -- Lwmte, 24.03.25
+ if (enemy == nullptr && creature->Mood == MoodType::Attack)
+ creature->Mood = MoodType::Bored;
int boxNumber;
switch (creature->Mood)
@@ -1645,7 +1649,7 @@ void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent)
boxNumber = LOT->Node[GetRandomControl() * LOT->ZoneCount >> 15].boxNumber;
if (ValidBox(item, AI->zoneNumber, boxNumber))
{
- if (StalkBox(item, enemy, boxNumber) && enemy->HitPoints > 0 && creature->Enemy)
+ if (StalkBox(item, enemy, boxNumber) && creature->Enemy && enemy->HitPoints > 0)
{
TargetBox(LOT, boxNumber);
creature->Mood = MoodType::Bored;
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index 3efdd8b20..6384e29b4 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -427,7 +427,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// Hide console window if mode isn't debug.
#ifndef _DEBUG
if (!DebugMode)
- ShowWindow(GetConsoleWindow(), 0);
+ FreeConsole();
else
#endif
ConsoleThreadHandle = BeginThread(ConsoleInput, ConsoleThreadID);
From c2c6b5f0726eebbb0e745691e5651ece67b18dd5 Mon Sep 17 00:00:00 2001
From: Sezz
Date: Tue, 25 Mar 2025 15:05:07 +1100
Subject: [PATCH 13/53] Minor changes
---
TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h | 3 ++-
TombEngine/Specific/winmain.cpp | 7 +++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h
index 8ff7be4e2..cbc659d14 100644
--- a/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h
+++ b/TombEngine/Scripting/Internal/TEN/Logic/LogicHandler.h
@@ -79,7 +79,8 @@ private:
bool _shortenedCalls = false;
- std::string _consoleInput = "";
+ std::string _consoleInput = {};
+
void PerformConsoleInput();
std::string GetRequestedPath() const;
diff --git a/TombEngine/Specific/winmain.cpp b/TombEngine/Specific/winmain.cpp
index 6384e29b4..560073115 100644
--- a/TombEngine/Specific/winmain.cpp
+++ b/TombEngine/Specific/winmain.cpp
@@ -240,8 +240,7 @@ bool GenerateDummyLevel(const std::string& levelPath)
unsigned CALLBACK ConsoleInput(void*)
{
- std::string input;
-
+ auto input = std::string();
while (!ThreadEnded)
{
if (!std::getline(std::cin, input))
@@ -427,10 +426,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// Hide console window if mode isn't debug.
#ifndef _DEBUG
if (!DebugMode)
+ {
FreeConsole();
+ }
else
#endif
+ {
ConsoleThreadHandle = BeginThread(ConsoleInput, ConsoleThreadID);
+ }
// Clear application structure.
memset(&App, 0, sizeof(WINAPP));
From 22195b32675b0729f4a89abf02f8d380f3bda03e Mon Sep 17 00:00:00 2001
From: Sezz
Date: Wed, 26 Mar 2025 23:26:00 +1100
Subject: [PATCH 14/53] Fix key binding settings saving for current session
after hitting Esc to cancel
---
CHANGELOG.md | 3 ++-
TombEngine/Game/gui.cpp | 19 +++++++++++++------
TombEngine/Game/gui.h | 6 +++---
3 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9dab845db..4e17ee3ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,12 +9,13 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Added live console input to perform Lua commands in realtime.
### Bug fixes
-* Fixed pathfinding for friendly NPCs, such as monkeys.
+* Fixed pathfinding for friendly NPCs such as monkeys.
* Fixed particles remaining in the level after reloading from the savegame.
* Fixed particles being canceled by fog bulbs.
* Fixed crash in case hair object is the last object in a level.
* Fixed crash with incorrectly applied animated textures on static meshes.
* Fixed console window not hiding in non-debug mode on Windows 11.
+* Fixed key binding settings saving for the current play session after hitting Esc to cancel.
### Lua API changes
* Added missing constructor for `Collision.Probe` without room number.
diff --git a/TombEngine/Game/gui.cpp b/TombEngine/Game/gui.cpp
index a024419a2..46558185d 100644
--- a/TombEngine/Game/gui.cpp
+++ b/TombEngine/Game/gui.cpp
@@ -690,7 +690,7 @@ namespace TEN::Gui
CurrentSettings.IgnoreInput = true;
}
- if (CurrentSettings.NewKeyWaitTimer > 0.0f)
+ if (CurrentSettings.NewKeyWaitTimer > 0)
{
ClearAllActions();
@@ -699,15 +699,15 @@ namespace TEN::Gui
bool legacy30FpsDoneDraw = false;
bool decreaseCounter = false;
- while (CurrentSettings.NewKeyWaitTimer > 0.0f)
+ while (CurrentSettings.NewKeyWaitTimer > 0)
{
g_Synchronizer.Sync();
while (g_Synchronizer.Synced())
{
- CurrentSettings.NewKeyWaitTimer -= 1.0f;
- if (CurrentSettings.NewKeyWaitTimer <= 0.0f)
- CurrentSettings.NewKeyWaitTimer = 0.0f;
+ CurrentSettings.NewKeyWaitTimer--;
+ if (CurrentSettings.NewKeyWaitTimer <= 0)
+ CurrentSettings.NewKeyWaitTimer = 0;
if (!fromPauseMenu)
{
@@ -760,7 +760,7 @@ namespace TEN::Gui
g_Bindings.SetKeyBinding(InputDeviceID::Custom, InputActionID(baseIndex + SelectedOption), selectedKeyID);
DefaultConflict();
- CurrentSettings.NewKeyWaitTimer = 0.0f;
+ CurrentSettings.NewKeyWaitTimer = 0;
CurrentSettings.IgnoreInput = true;
return;
}
@@ -850,6 +850,7 @@ namespace TEN::Gui
if (SelectedOption == (OptionCount - 2))
{
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
+
ApplyDefaultBindings();
return;
}
@@ -858,9 +859,11 @@ namespace TEN::Gui
if (SelectedOption == (OptionCount - 1))
{
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
+
CurrentSettings.Configuration.Bindings = g_Bindings.GetBindingProfile(InputDeviceID::Custom);
g_Configuration.Bindings = g_Bindings.GetBindingProfile(InputDeviceID::Custom);
SaveConfiguration();
+
MenuToDisplay = fromPauseMenu ? Menu::Pause : Menu::Options;
SelectedOption = 2;
return;
@@ -870,7 +873,9 @@ namespace TEN::Gui
if (SelectedOption == OptionCount)
{
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
+
g_Bindings.SetBindingProfile(InputDeviceID::Custom, CurrentSettings.Configuration.Bindings);
+
MenuToDisplay = fromPauseMenu ? Menu::Pause : Menu::Options;
SelectedOption = 2;
return;
@@ -881,6 +886,8 @@ namespace TEN::Gui
{
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
+ g_Bindings.SetBindingProfile(InputDeviceID::Custom, CurrentSettings.Configuration.Bindings);
+
MenuToDisplay = Menu::Options;
SelectedOption = 2;
}
diff --git a/TombEngine/Game/gui.h b/TombEngine/Game/gui.h
index bca6f8b3a..8a04f1e9c 100644
--- a/TombEngine/Game/gui.h
+++ b/TombEngine/Game/gui.h
@@ -111,9 +111,9 @@ namespace TEN::Gui
GameConfiguration Configuration = {};
- int SelectedScreenResolution = 0;
- bool IgnoreInput = false; // Ignore input until all actions are inactive.
- float NewKeyWaitTimer = 0.0f;
+ int SelectedScreenResolution = 0;
+ bool IgnoreInput = false; // Ignore input until all actions are inactive.
+ int NewKeyWaitTimer = 0;
};
class GuiController
From 539c19bdee440763adf332ab6301d057e5155824 Mon Sep 17 00:00:00 2001
From: Sezz
Date: Thu, 27 Mar 2025 03:43:10 +1100
Subject: [PATCH 15/53] Update README.md
---
README.md | 56 +++++++++++++++++++++++++++----------------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/README.md b/README.md
index 5ad28cfa3..557b222d6 100644
--- a/README.md
+++ b/README.md
@@ -1,41 +1,41 @@
-# TombEngine
+# Tomb Engine

-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)
-- Many objects from the original series (1-5)
-- Support for high framerate, antialiasing, mipmapping and SSAO
-- Full diagonal geometry support
-- Uncapped map size
-- A streamlined player control scheme.
+*Tomb Engine* (*TEN*) is an open-source custom level engine which aims to abolish limits and fix bugs of the classic Tomb Raider games. It aims to introduce new features, refine old ones, and provide a user-friendly level creation process. Current support includes:
+- *Lua* as the native scripting language.
+- Many objects from the original series (1-5).
+- Support for high framerate, antialiasing, mipmapping, and SSAO.
+- Full diagonal geometry support.
+- 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
+Contributions are welcome. If you would like to participate in development to any degree, whether that be through suggestions, bug reports, or code, join our [Discord server](https://discord.gg/h5tUYFmres).
-Tomb Engine should be used in conjuction with Tomb Editor. Tomb Editor is also open source written in C#, you can find the repository here: https://github.com/MontyTRC89/Tomb-Editor
+*Tomb Engine* is used in conjunction with *Tomb Editor*. The repository can be found [here](https://github.com/MontyTRC89/Tomb-Editor).
-# Compiling TombEngine
-To compile TEN, ensure you have installed:
-- Microsoft Visual Studio
-- Tomb Editor (if you would like to create and test levels)
+# Compiling *Tomb Engine*
+To compile *TEN*, ensure you have installed:
+- *Microsoft Visual Studio*
+- *Tomb Editor* (for level creation and testing)
Steps:
-1) Clone the repository to your GitHub Desktop
-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.
+1) Clone the repository to your GitHub Desktop.
+2) Open `TombEngine.sln`.
+4) Compile the solution.
+5) Once compiled, create a separate folder to serve as your main *TEN* directory (or create a 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.
+8) In 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) If it doesn't help, manually install `directxtk_desktop_2019` and `Microsoft.XAudio2.Redist` packages via NuGet Package Manager
+*Visual Studio* may warn about NuGet packages. To fix:
+1) Delete the `Packages` folder.
+2) Go back to *Microsoft Visual Studio*.
+3) Right-click on the *TEN* solution in the *Solution Explorer* tab and select "Restore NuGet Packages".
+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.
+Once done, you should be able to build a level with *Tomb Editor* and run it in *TEN*.
# Disclaimer
-This is a community project which is not affiliated with Core Design, Eidos Interactive, or Embracer Group AB. Tomb Raider is a registered trademark of Embracer Group AB. 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 community project is unaffiliated with Core Design, Eidos Interactive, or Embracer Group AB. *Tomb Raider* is a registered trademark of Embracer Group AB. *Tomb Engine* is not for sale. The code is open-source to encourage contributions and 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 917a86863eb55a3561a4bc7f01f765c2f9e3d169 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 26 Mar 2025 19:41:53 +0100
Subject: [PATCH 16/53] Changed lensflare formula
---
TombEngine/Shaders/PostProcess.fx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx
index 79c3ebef2..0c7c232ea 100644
--- a/TombEngine/Shaders/PostProcess.fx
+++ b/TombEngine/Shaders/PostProcess.fx
@@ -185,7 +185,7 @@ float4 PSLensFlare(PixelShaderInput input) : SV_Target
totalLensFlareColor += lensFlareColor;
}
- color.xyz += totalLensFlareColor;
+ color.xyz = lerp(color.xyz, color.xyz + totalLensFlareColor, saturate(dot(totalLensFlareColor, float3(0.5f, 0.5f, 0.5f))));
return color;
}
\ No newline at end of file
From 8e5f045d022716d2ef3d7d6a1055bb93727d8c67 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 26 Mar 2025 22:58:32 +0100
Subject: [PATCH 17/53] Update PostProcess.fx
---
TombEngine/Shaders/PostProcess.fx | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx
index 0c7c232ea..10d717245 100644
--- a/TombEngine/Shaders/PostProcess.fx
+++ b/TombEngine/Shaders/PostProcess.fx
@@ -114,27 +114,27 @@ float3 LensFlare(float2 uv, float2 pos)
f0 += f0 * (sin((ang + rotationOffset + 1.0f / 18.0f) * 8.0f) * 0.2f + dist * 0.1f + 0.2f);
// Lensflare glow components
- float f2 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.8f * pos), 2.0f)), 0.0f) * 0.25f;
- float f22 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.85f * pos), 2.0f)), 0.0f) * 0.23f;
- float f23 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.9f * pos), 2.0f)), 0.0f) * 0.21f;
+ float f2 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.8f * pos), 1.0f)), 0.0f) * 0.25f;
+ float f22 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.85f * pos), 1.0f)), 0.0f) * 0.23f;
+ float f23 = max(1.0f / (1.0f + 32.0f * pow(length(uvd + 0.9f * pos), 1.0f)), 0.0f) * 0.21f;
// Circular lens artifacts
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;
+ float f4 = max(0.01f - pow(length(uvx + 0.4f * pos), 2.4f), 0.0f) * 9.0f;
+ float f42 = max(0.01f - pow(length(uvx + 0.45f * pos), 2.4f), 0.0f) * 7.0f;
+ float f43 = max(0.01f - pow(length(uvx + 0.5f * pos), 2.4f), 0.0f) * 6.0f;
// Smaller lens artifacts
uvx = lerp(uv, uvd, -0.4f);
- float f5 = max(0.01f - pow(length(uvx + 0.2f * pos), 5.5f), 0.0f) * 2.0f;
+ 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;
// Symmetric artifacts
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;
+ float f6 = max(0.01f - pow(length(uvx - 0.3f * pos), 1.6f), 0.0f) * 9.0f;
+ float f62 = max(0.01f - pow(length(uvx - 0.325f * pos), 1.6f), 0.0f) * 6.0f;
+ float f63 = max(0.01f - pow(length(uvx - 0.35f * pos), 1.6f), 0.0f) * 7.0f;
// Sunflare and lensflare outputs
float3 sunflare = float3(f0, f0, f0);
From 9469a0e63a311da5b96918dda46c33d7c0e58e48 Mon Sep 17 00:00:00 2001
From: Nemoel-Tomo
Date: Fri, 28 Mar 2025 06:44:07 +0100
Subject: [PATCH 18/53] Tomo - fireflies (#1597)
* tests only - nothing to see
* update
* update
* update
* update corpse
* update savegame, formatting
* import develop
* formatting
* fix broken streamer vertex
* update firefly streamer spawn
* update effect
* Add in objects for fireflies
* fixed all reviews, formatting, changing on-off cycle
* formatting
* reduced the emitted light to two lights per cluster
* adding antitrigger
* formatting
* fixed corpse
* fixed a bug with corpse
* fixed corpse fall bug
* formatting
* Small refactors
* Fix merge
---------
Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com>
Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com>
---
Documentation/doc/4 enums/Objects.ObjID.html | 3 +
TombEngine/Game/Setup.cpp | 2 +
TombEngine/Game/control/control.cpp | 3 +
TombEngine/Game/control/flipeffect.cpp | 3 +
TombEngine/Game/savegame.cpp | 69 ++-
TombEngine/Objects/Effects/Fireflies.cpp | 445 ++++++++++++++++
TombEngine/Objects/Effects/Fireflies.h | 76 +++
TombEngine/Objects/TR3/Object/corpse.cpp | 100 +++-
TombEngine/Objects/TR5/tr5_objects.cpp | 10 +
TombEngine/Objects/game_object_ids.h | 5 +-
TombEngine/Renderer/Renderer.h | 1 +
TombEngine/Renderer/RendererDraw.cpp | 1 +
TombEngine/Renderer/RendererDrawEffect.cpp | 45 ++
.../Internal/TEN/Objects/ObjectIDs.h | 7 +-
.../flatbuffers/ten_savegame_generated.h | 493 ++++++++++++++++--
.../Specific/savegame/schema/ten_savegame.fbs | 26 +
TombEngine/TombEngine.vcxproj | 2 +
17 files changed, 1220 insertions(+), 71 deletions(-)
create mode 100644 TombEngine/Objects/Effects/Fireflies.cpp
create mode 100644 TombEngine/Objects/Effects/Fireflies.h
diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html
index 7fa0d1ba0..b10a91473 100644
--- a/Documentation/doc/4 enums/Objects.ObjID.html
+++ b/Documentation/doc/4 enums/Objects.ObjID.html
@@ -952,6 +952,7 @@ DOPPELGANGER_ORIGIN
CORPSE
WRAITH_TRAP
WATERFALL_EMITTER
+FIREFLY_EMITTER
MESHSWAP1
MESHSWAP2
MESHSWAP3
@@ -1132,6 +1133,7 @@ AIR_BAR_TEXTURE
DASH_BAR_TEXTURE
SFX_BAR_TEXTURE
WATERFALL_SPRITES
+FIREFLY_SPRITES
CROSSHAIR_GRAPHICS
SPEEDOMETER_GRAPHICS
CUSTOM_BAR_GRAPHICS
@@ -1410,6 +1412,7 @@ AIR_BAR_TEXTURE
DASH_BAR_TEXTURE
SFX_BAR_TEXTURE
WATERFALL_SPRITES
+FIREFLY_SPRITES
CROSSHAIR_GRAPHICS
SPEEDOMETER_GRAPHICS
CUSTOM_BAR_GRAPHICS
diff --git a/TombEngine/Game/Setup.cpp b/TombEngine/Game/Setup.cpp
index 42bfb08df..22ab28749 100644
--- a/TombEngine/Game/Setup.cpp
+++ b/TombEngine/Game/Setup.cpp
@@ -27,6 +27,7 @@
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
#include "Objects/Utils/object_helper.h"
#include "Specific/level.h"
+#include "Objects/Effects/Fireflies.h"
using namespace TEN::Effects::Hair;
using namespace TEN::Entities;
@@ -200,6 +201,7 @@ void InitializeSpecialEffects()
TEN::Entities::TR4::ClearBeetleSwarm();
TEN::Entities::Creatures::TR3::ClearFishSwarm();
+ TEN::Effects::Fireflies::ClearFireflySwarm();
}
void CustomObjects()
diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp
index 412c974dd..d5171cbae 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 "Objects/Effects/Fireflies.h"
using namespace std::chrono;
using namespace TEN::Effects;
@@ -89,6 +90,7 @@ using namespace TEN::Math;
using namespace TEN::Renderer;
using namespace TEN::Entities::Creatures::TR3;
using namespace TEN::Entities::Effects;
+using namespace TEN::Effects::Fireflies;
constexpr auto DEATH_NO_INPUT_TIMEOUT = 10 * FPS;
constexpr auto DEATH_INPUT_TIMEOUT = 3 * FPS;
@@ -211,6 +213,7 @@ GameStatus GamePhase(bool insideMenu)
UpdateLocusts();
UpdateUnderwaterBloodParticles();
UpdateFishSwarm();
+ UpdateFireflySwarm();
UpdateGlobalLensFlare();
// Update HUD.
diff --git a/TombEngine/Game/control/flipeffect.cpp b/TombEngine/Game/control/flipeffect.cpp
index e1b3af5d4..c473386d0 100644
--- a/TombEngine/Game/control/flipeffect.cpp
+++ b/TombEngine/Game/control/flipeffect.cpp
@@ -17,6 +17,7 @@
#include "Game/Setup.h"
#include "Sound/sound.h"
#include "Specific/level.h"
+#include "Objects/Effects/Fireflies.h"
#include "Objects/Generic/puzzles_keys.h"
#include "Objects/TR3/Entity/FishSwarm.h"
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
@@ -29,6 +30,7 @@ using namespace TEN::Effects::Environment;
using namespace TEN::Effects::Footprint;
using namespace TEN::Effects::Hair;
using namespace TEN::Entities::Creatures::TR3;
+using namespace TEN::Effects::Fireflies;
int FlipEffect;
@@ -90,6 +92,7 @@ void ClearSwarmEnemies(ItemInfo* item)
ClearBeetleSwarm();
ClearLocusts();
ClearFishSwarm();
+ ClearFireflySwarm();
}
void FlashOrange(ItemInfo* item)
diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp
index b2ae7ec0c..8f3f1394c 100644
--- a/TombEngine/Game/savegame.cpp
+++ b/TombEngine/Game/savegame.cpp
@@ -10,6 +10,7 @@
#include "Game/control/flipeffect.h"
#include "Game/control/lot.h"
#include "Game/control/volume.h"
+#include "Objects/Effects/Fireflies.h"
#include "Game/effects/item_fx.h"
#include "Game/effects/effects.h"
#include "Game/effects/weather.h"
@@ -43,8 +44,9 @@
using namespace flatbuffers;
using namespace TEN::Collision::Floordata;
using namespace TEN::Control::Volumes;
-using namespace TEN::Effects::Items;
using namespace TEN::Effects::Environment;
+using namespace TEN::Effects::Fireflies;
+using namespace TEN::Effects::Items;
using namespace TEN::Entities::Creatures::TR3;
using namespace TEN::Entities::Generic;
using namespace TEN::Entities::Switches;
@@ -924,6 +926,38 @@ const std::vector SaveGame::Build()
}
auto fishSwarmOffset = fbb.CreateVector(fishSwarm);
+ std::vector> fireflySwarm;
+ for (const auto& firefly : FireflySwarm)
+ {
+ Save::FireflyDataBuilder fireflySave{ fbb };
+ fireflySave.add_sprite_index(firefly.SpriteSeqID);
+ fireflySave.add_sprite_id(firefly.SpriteID);
+ fireflySave.add_blend_mode((int)firefly.blendMode);
+ fireflySave.add_scalar(firefly.scalar);
+ fireflySave.add_position(&FromVector3(firefly.Position));
+ fireflySave.add_room_number(firefly.RoomNumber);
+ fireflySave.add_position_target(&FromVector3(firefly.PositionTarget));
+ fireflySave.add_orientation(&FromEulerAngles(firefly.Orientation));
+ fireflySave.add_velocity(firefly.Velocity);
+ fireflySave.add_target_item_number((firefly.TargetItemPtr == nullptr) ? -1 : firefly.TargetItemPtr->Index);
+ fireflySave.add_z_vel(firefly.zVel);
+ fireflySave.add_life(firefly.Life);
+ fireflySave.add_number(firefly.Number);
+ fireflySave.add_d_r(firefly.rB);
+ fireflySave.add_d_g(firefly.gB);
+ fireflySave.add_d_b(firefly.bB);
+ fireflySave.add_r(firefly.r);
+ fireflySave.add_g(firefly.g);
+ fireflySave.add_b(firefly.b);
+ fireflySave.add_on(firefly.on);
+ fireflySave.add_size(firefly.size);
+ fireflySave.add_rot_Ang(firefly.rotAng);
+
+ auto fireflySaveOffset = fireflySave.Finish();
+ fireflySwarm.push_back(fireflySaveOffset);
+ }
+ auto fireflySwarmOffset = fbb.CreateVector(fireflySwarm);
+
// 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
@@ -1545,6 +1579,7 @@ const std::vector SaveGame::Build()
sgb.add_next_item_active(NextItemActive);
sgb.add_items(serializedItemsOffset);
sgb.add_fish_swarm(fishSwarmOffset);
+ sgb.add_firefly_swarm(fireflySwarmOffset);
sgb.add_fxinfos(serializedEffectsOffset);
sgb.add_next_fx_free(NextFxFree);
sgb.add_next_fx_active(NextFxActive);
@@ -2289,6 +2324,38 @@ static void ParseEffects(const Save::SaveGame* s)
FishSwarm.push_back(fish);
}
+ // Load firefly swarm.
+ for (int i = 0; i < s->firefly_swarm()->size(); i++)
+ {
+ const auto& fireflySave = s->firefly_swarm()->Get(i);
+ auto firefly = FireflyData{};
+
+ firefly.SpriteSeqID = fireflySave->sprite_index();
+ firefly.SpriteID = fireflySave->sprite_id();
+ firefly.blendMode = (BlendMode)fireflySave->blend_mode();
+ firefly.scalar = fireflySave->scalar();
+ firefly.Position = ToVector3(fireflySave->position());
+ firefly.RoomNumber = fireflySave->room_number();
+ firefly.PositionTarget = ToVector3(fireflySave->position_target());
+ firefly.Orientation = ToEulerAngles(fireflySave->orientation());
+ firefly.Velocity = fireflySave->velocity();
+ firefly.TargetItemPtr = (fireflySave->target_item_number() == -1) ? nullptr : &g_Level.Items[fireflySave->target_item_number()];
+ firefly.zVel = fireflySave->z_vel();
+ firefly.Life = fireflySave->life();
+ firefly.Number = fireflySave->number();
+ firefly.rB = fireflySave->d_r();
+ firefly.gB = fireflySave->d_g();
+ firefly.bB = fireflySave->d_b();
+ firefly.r = fireflySave->r();
+ firefly.g = fireflySave->g();
+ firefly.b = fireflySave->b();
+ firefly.on = fireflySave->on();
+ firefly.size = fireflySave->size();
+ firefly.rotAng = fireflySave->rot_Ang();
+
+ FireflySwarm.push_back(firefly);
+ }
+
// Load particles.
for (int i = 0; i < s->particles()->size(); i++)
{
diff --git a/TombEngine/Objects/Effects/Fireflies.cpp b/TombEngine/Objects/Effects/Fireflies.cpp
new file mode 100644
index 000000000..0510283f9
--- /dev/null
+++ b/TombEngine/Objects/Effects/Fireflies.cpp
@@ -0,0 +1,445 @@
+#include "framework.h"
+#include "Objects/Effects/Fireflies.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/Streamer.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 "Renderer/Renderer.h"
+#include "Specific/clock.h"
+#include "Specific/level.h"
+
+using namespace TEN::Collision::Point;
+using namespace TEN::Math;
+using namespace TEN::Renderer;
+using namespace TEN::Effects::Streamer;
+
+namespace TEN::Effects::Fireflies
+{
+ constexpr auto FIREFLY_COHESION_FACTOR = 600.1f;
+ constexpr auto FIREFLY_SPACING_FACTOR = 600.0f;
+ constexpr auto FIREFLY_CATCH_UP_FACTOR = 0.2f;
+ constexpr auto FIREFLY_TARGET_DISTANCE_MAX = SQUARE(BLOCK(1.0f));
+ constexpr auto FIREFLY_BASE_SEPARATION_DISTANCE = 10.0f;
+ constexpr auto FIREFLY_FLEE_DISTANCE = BLOCK(0.7);
+ constexpr auto MAX_FIREFLIES = 92;
+ constexpr auto DEFAULT_FIREFLY_COUNT = 20;
+ constexpr auto FIREFLY_RISE_UP_FACTOR = 200;
+ constexpr auto MAX_AREA_RANGE = 8;
+ constexpr auto LIGHT_ALPHA_CYCLE_DURATION = 120.0f;
+
+ std::vector FireflySwarm = {};
+ std::unordered_map nextFireflyNumberMap; // Numbering the Fireflies for Streamer effect.
+
+ void InitializeFireflySwarm(short itemNumber)
+ {
+ auto& item = g_Level.Items[itemNumber];
+
+ item.Animation.Velocity.z = Random::GenerateFloat(32.0f, 160.0f);
+
+ item.HitPoints = DEFAULT_FIREFLY_COUNT;
+ item.ItemFlags[FirefliesItemFlags::TargetItemPtr] = item.Index;
+ item.ItemFlags[FirefliesItemFlags::Light] = 1; // 0 = Turn off light effect, 1 = turn on light (DEFAULT).
+
+ item.ItemFlags[FirefliesItemFlags::TriggerFlags] = std::clamp((int)item.TriggerFlags, -MAX_AREA_RANGE, MAX_AREA_RANGE);
+
+ item.ItemFlags[FirefliesItemFlags::Spawncounter] = 0;
+ item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] = 0;
+
+ // Firefly numbers that has the light.
+ item.ItemFlags[FirefliesItemFlags::LightIndex1] = NO_VALUE;
+ item.ItemFlags[FirefliesItemFlags::LightIndex2] = NO_VALUE;
+ }
+
+ void SpawnFireflySwarm(ItemInfo& item, int triggerFlags)
+ {
+ constexpr auto VEL_MAX = 34.0f;
+ constexpr auto VEL_MIN = 6.0f;
+
+ // Create new firefly.
+ auto& firefly = GetNewEffect(FireflySwarm, MAX_FIREFLIES);
+
+ unsigned char r = 255;
+ unsigned char g = 255;
+ unsigned char b = 255;
+
+ if (triggerFlags >= 0)
+ {
+ float brightnessShift = Random::GenerateFloat(-0.1f, 0.1f);
+ r = std::clamp(item.Model.Color.x / 2.0f + brightnessShift, 0.0f, 1.0f) * UCHAR_MAX;
+ g = std::clamp(item.Model.Color.y / 2.0f + brightnessShift, 0.0f, 1.0f) * UCHAR_MAX;
+ b = std::clamp(item.Model.Color.z / 2.0f + brightnessShift, 0.0f, 1.0f) * UCHAR_MAX;
+
+ firefly.SpriteSeqID = ID_FIREFLY_SPRITES;
+ firefly.SpriteID = 0;
+ firefly.blendMode = BlendMode::Additive;
+ firefly.scalar = 3.0f;
+ firefly.size = 1.0f;
+ }
+ else
+ {
+ firefly.SpriteSeqID = ID_FIREFLY_SPRITES;
+ firefly.SpriteID = 1;
+ firefly.blendMode = BlendMode::Subtractive;
+ firefly.scalar = 1.2f;
+ firefly.size = 1.2f;
+ }
+
+ firefly.r = firefly.rB = r;
+ firefly.g = firefly.gB = g;
+ firefly.b = firefly.bB = b;
+
+ firefly.rotAng = ANGLE(0.0f);
+
+ if (item.TriggerFlags > 8)
+ firefly.rotAng = ANGLE(90.0f);
+
+ firefly.on = true;
+
+ firefly.Position = item.Pose.Position.ToVector3();
+ firefly.RoomNumber = item.RoomNumber;
+ firefly.Orientation = item.Pose.Orientation;
+ firefly.Velocity = Random::GenerateFloat(VEL_MIN, VEL_MAX);
+ firefly.zVel = 0.3f;
+
+ firefly.Life = Random::GenerateInt(1, 400);
+ firefly.TargetItemPtr = &g_Level.Items[item.ItemFlags[FirefliesItemFlags::TargetItemPtr]];
+
+ int& nextFireflyNumber = nextFireflyNumberMap[item.Index];
+ firefly.Number = nextFireflyNumber++;
+ }
+
+ void ControlFireflySwarm(short itemNumber)
+ {
+ auto& item = g_Level.Items[itemNumber];
+
+ if (!TriggerActive(&item))
+ {
+ // Remove all fireflies associated with this item.
+ RemoveFireflies(item);
+
+ // Reset ItemFlags.
+ if (item.HitPoints == NOT_TARGETABLE)
+ item.HitPoints = item.ItemFlags[FirefliesItemFlags::Spawncounter];
+
+ item.ItemFlags[FirefliesItemFlags::Spawncounter] = 0;
+ item.ItemFlags[FirefliesItemFlags::LightIndex1] = NO_VALUE;
+ item.ItemFlags[FirefliesItemFlags::LightIndex2] = NO_VALUE;
+
+ return;
+ }
+
+ constexpr auto ALPHA_PAUSE_DURATION = 2.0f;
+ static float frameCounter = 0.0f;
+
+ // Increment the counter variable in each frame.
+ frameCounter += 1.0f;
+
+ if (item.HitPoints != NOT_TARGETABLE)
+ {
+ int fireflyCount = item.HitPoints - item.ItemFlags[FirefliesItemFlags::Spawncounter];
+
+ if (fireflyCount < 0)
+ {
+ int firefliesToTurnOff = -fireflyCount;
+ for (auto& firefly : FireflySwarm)
+ {
+ if (firefly.TargetItemPtr == &item && firefly.Life > 0.0f)
+ {
+ firefly.Life = 0.0f;
+ firefly.on = false;
+ firefliesToTurnOff--;
+
+ if (firefliesToTurnOff == 0)
+ break;
+ }
+ }
+ }
+ else if (fireflyCount > 0)
+ {
+ for (int i = 0; i < fireflyCount; i++)
+ {
+ SpawnFireflySwarm(item, item.TriggerFlags);
+ }
+ }
+
+ item.ItemFlags[FirefliesItemFlags::Spawncounter] = item.HitPoints;
+ item.HitPoints = NOT_TARGETABLE;
+ }
+
+ // Update color values for blinking effect.
+ float alphaFactor;
+
+ for (auto& firefly : FireflySwarm)
+ {
+ auto targetItem = firefly.TargetItemPtr;
+
+ if (targetItem == &item)
+ {
+ // Choose one of the available firefly number that has the light.
+ if (targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] == NO_VALUE && targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
+ {
+ targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] = Random::GenerateInt(0, targetItem->TriggerFlags);
+ }
+ // Two lights max for each cluster.
+ if (targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] == NO_VALUE && targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
+ {
+ targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] = Random::GenerateInt(0, targetItem->TriggerFlags);
+ }
+
+ auto posBase = firefly.Position;
+ auto rotMatrix = firefly.Orientation.ToRotationMatrix();
+ auto pos = posBase + Vector3::Transform(Vector3(0, 0, 30), rotMatrix);
+ auto direction0 = Geometry::RotatePoint(posBase, EulerAngles::Identity);
+ short orient2D = firefly.Orientation.z;
+
+ if (targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
+ {
+ StreamerEffect.Spawn(targetItem->Index, firefly.Number, pos, direction0, orient2D,
+ Vector4(firefly.r / (float)UCHAR_MAX, firefly.g / (float)UCHAR_MAX, firefly.b / (float)UCHAR_MAX, 1.0f),
+ Vector4::Zero,
+ 6.3f - (firefly.zVel / 12), ((firefly.Velocity / 8) + firefly.zVel * 3) / (float)UCHAR_MAX, 0.0f, -0.1f, 90.0f, StreamerFeatherMode::None, BlendMode::Additive);
+ }
+ else if (targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] < 0)
+ {
+ StreamerEffect.Spawn(targetItem->Index, firefly.Number, pos, direction0, orient2D,
+ Vector4((firefly.r / 2) / (float)UCHAR_MAX, (firefly.g / 2) / (float)UCHAR_MAX, (firefly.b / 2) / (float)UCHAR_MAX, 0.2f),
+ Vector4((firefly.r / 3) / (float)UCHAR_MAX, (firefly.g / 3) / (float)UCHAR_MAX, (firefly.b / 3) / (float)UCHAR_MAX, 0.2f),
+ 0.0f, 0.4f, 0.0f, 0.2f, 0.0f, StreamerFeatherMode::None, BlendMode::Subtractive);
+ }
+
+ if ((targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] == firefly.Number || targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] == firefly.Number) &&
+ targetItem->ItemFlags[FirefliesItemFlags::Light] == 1)
+ {
+ float totalCycleDuration = 2 * (LIGHT_ALPHA_CYCLE_DURATION + ALPHA_PAUSE_DURATION);
+ float alphaTime = fmod(frameCounter, totalCycleDuration);
+
+ if (alphaTime < ALPHA_PAUSE_DURATION)
+ {
+ alphaFactor = 1.0f; // Pause on Alpha 1.
+ }
+ else if (alphaTime < ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
+ {
+ alphaFactor = 1.0f - ((alphaTime - ALPHA_PAUSE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION);
+ }
+ else if (alphaTime < 2 * ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
+ {
+ alphaFactor = 0.0f; // Pause on Alpha 0.
+ targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] = NO_VALUE;
+ targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] = NO_VALUE;
+ }
+ else
+ {
+ alphaFactor = (alphaTime - 2 * ALPHA_PAUSE_DURATION - LIGHT_ALPHA_CYCLE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION;
+ }
+
+ SpawnDynamicLight(firefly.Position.x, firefly.Position.y, firefly.Position.z, 3,
+ static_cast(std::clamp(firefly.r * alphaFactor, 0.0f, (float)firefly.r)),
+ static_cast(std::clamp(firefly.g * alphaFactor, 0.0f, (float)firefly.g)),
+ static_cast(std::clamp(firefly.b * alphaFactor, 0.0f, (float)firefly.b)));
+ }
+ }
+ }
+ }
+
+ void UpdateFireflySwarm()
+ {
+ constexpr auto FLEE_VEL = 1.5f;
+ constexpr auto ALPHA_PAUSE_DURATION = 100.0f;
+
+ static const auto SPHERE = BoundingSphere(Vector3::Zero, BLOCK(1 / 8.0f));
+
+ if (FireflySwarm.empty())
+ return;
+
+ const auto& playerItem = *LaraItem;
+ static float frameCounter = 0.0f;
+
+ // Increment the counter variable in each frame.
+ frameCounter += 1.0f;
+
+ for (auto& firefly : FireflySwarm)
+ {
+ if (firefly.Life <= 0.0f || !firefly.on)
+ continue;
+
+ auto targetItem = firefly.TargetItemPtr;
+
+ if (targetItem->ItemFlags[FirefliesItemFlags::RemoveFliesEffect])
+ {
+ firefly.r = 0;
+ firefly.g = 0;
+ firefly.b = 0;
+ continue;
+ }
+
+ firefly.StoreInterpolationData();
+
+ firefly.PositionTarget = Random::GeneratePointInSphere(SPHERE);
+
+ int multiplierX = CLICK(targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] * 2);
+ int multiplierY = CLICK(targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] * 4);
+ int multiplierZ = CLICK(targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] * 2);
+
+ auto spheroidAxis = Vector3(multiplierX, multiplierY, multiplierZ);
+ auto itemPos = Vector3i(targetItem->Pose.Position.x, targetItem->Pose.Position.y - FIREFLY_RISE_UP_FACTOR, targetItem->Pose.Position.z);
+
+ // Calculate desired position based on target object and random offsets.
+ auto desiredPos = itemPos + Random::GeneratePointInSpheroid(firefly.PositionTarget, EulerAngles::Identity, spheroidAxis);
+ auto dir = desiredPos - firefly.Position;
+
+ auto dirs = dir.ToVector3();
+ dirs.Normalize();
+ auto dirNorm = dirs;
+
+ // Define cohesion factor to keep fireflies close together.
+ float distToTarget = dirs.Length();
+
+ float targetVel = (distToTarget * FIREFLY_COHESION_FACTOR) + Random::GenerateFloat(3.0f, 5.0f);
+ firefly.Velocity = std::min(targetVel, targetItem->Animation.Velocity.z - 21.0f);
+
+ // If firefly is too far from target, increase velocity to catch up.
+ if (distToTarget > FIREFLY_TARGET_DISTANCE_MAX)
+ firefly.Velocity += FIREFLY_CATCH_UP_FACTOR;
+
+ // Translate.
+ auto moveDir = firefly.Orientation.ToDirection();
+ moveDir.Normalize();
+ firefly.Position += (moveDir * firefly.Velocity) / 26.0f;
+ firefly.Position += (moveDir * FIREFLY_SPACING_FACTOR) / 26.0f;
+
+ auto orientTo = Geometry::GetOrientToPoint(firefly.Position, desiredPos.ToVector3());
+ firefly.Orientation.Lerp(orientTo, 0.1f);
+
+ // Update color values for blinking effect.
+ float totalCycleDuration = 2 * (LIGHT_ALPHA_CYCLE_DURATION + ALPHA_PAUSE_DURATION);
+ float alphaTime = fmod(frameCounter + firefly.Life, totalCycleDuration);
+ float alphaFactor;
+
+ if (alphaTime < ALPHA_PAUSE_DURATION)
+ {
+ alphaFactor = 1.0f;
+ }
+ else if (alphaTime < ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
+ {
+ alphaFactor = 1.0f - ((alphaTime - ALPHA_PAUSE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION);
+ }
+ else if (alphaTime < 2 * ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
+ {
+ alphaFactor = 0.0f;
+ }
+ else
+ {
+ alphaFactor = (alphaTime - 2 * ALPHA_PAUSE_DURATION - LIGHT_ALPHA_CYCLE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION;
+ }
+
+ firefly.r = static_cast(firefly.rB * alphaFactor);
+ firefly.g = static_cast(firefly.gB * alphaFactor);
+ firefly.b = static_cast(firefly.bB * alphaFactor);
+
+ for (const auto& otherFirefly : FireflySwarm)
+ {
+ if (&firefly == &otherFirefly)
+ continue;
+
+ float distToOtherFirefly = Vector3i::Distance(firefly.Position, otherFirefly.Position);
+ float distToPlayer = Vector3i::Distance(firefly.Position, playerItem.Pose.Position);
+
+ // If player is too close, flee.
+ if (distToPlayer < FIREFLY_FLEE_DISTANCE && playerItem.Animation.ActiveState != 2)
+ {
+ auto separationDir = firefly.Position - playerItem.Pose.Position.ToVector3();
+ separationDir.Normalize();
+
+ // Reduce the Y component of the escape direction.
+ separationDir.y *= Random::GenerateFloat(0.0f, 0.4f);
+
+ // Normalize the direction again to get the length of the vector.
+ separationDir.Normalize();
+
+ firefly.Position += separationDir * FLEE_VEL;
+
+ auto orientTo = Geometry::GetOrientToPoint(firefly.Position, separationDir);
+ firefly.Orientation.Lerp(orientTo, 0.05f);
+
+ firefly.Velocity -= std::min(FLEE_VEL, firefly.TargetItemPtr->Animation.Velocity.z - 1.0f);
+
+ if (Random::TestProbability(1.0f / 700.0f) &&
+ targetItem->ItemFlags[FirefliesItemFlags::Light] == 1 &&
+ targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
+ {
+ if (firefly.zVel == 0.3f)
+ {
+ firefly.zVel = 50.0f;
+ }
+ }
+
+ if (firefly.zVel > 50.0f)
+ firefly.zVel = 0.3f;
+ }
+
+ if (distToOtherFirefly < FIREFLY_BASE_SEPARATION_DISTANCE)
+ {
+ auto separationDir = firefly.Position - otherFirefly.Position;
+ separationDir.Normalize();
+
+ firefly.Position += separationDir * (FIREFLY_BASE_SEPARATION_DISTANCE - distToOtherFirefly);
+ }
+ }
+
+ auto pointColl = GetPointCollision(firefly.Position, firefly.RoomNumber);
+
+ // Update firefly room number.
+ if (pointColl.GetRoomNumber() != firefly.RoomNumber &&
+ pointColl.GetRoomNumber() != NO_VALUE)
+ {
+ firefly.RoomNumber = pointColl.GetRoomNumber();
+ }
+
+ if (targetItem->ItemFlags[FirefliesItemFlags::Light] == 1 && targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
+ {
+ if (Random::TestProbability(1.0f / (700.0f - (float)(targetItem->ItemFlags[FirefliesItemFlags::Spawncounter] * 2))))
+ firefly.zVel = 100.0f;
+
+ if (firefly.zVel > 1.0f)
+ firefly.zVel -= 2.0f;
+ if (firefly.zVel <= 1.0f)
+ firefly.zVel = 0.3f;
+ }
+ }
+ }
+
+ void RemoveFireflies(ItemInfo& item)
+ {
+ FireflySwarm.erase(std::remove_if(FireflySwarm.begin(), FireflySwarm.end(),
+ [&item](FireflyData& firefly)
+ {
+ if (firefly.TargetItemPtr == &item)
+ {
+ firefly.Life = 0.0f;
+ firefly.on = false;
+ return true;
+ }
+ return false;
+ }), FireflySwarm.end());
+ nextFireflyNumberMap.erase(item.Index);
+ }
+
+ void ClearFireflySwarm()
+ {
+ FireflySwarm.clear();
+ nextFireflyNumberMap.clear();
+ }
+}
+
+
diff --git a/TombEngine/Objects/Effects/Fireflies.h b/TombEngine/Objects/Effects/Fireflies.h
new file mode 100644
index 000000000..807869b81
--- /dev/null
+++ b/TombEngine/Objects/Effects/Fireflies.h
@@ -0,0 +1,76 @@
+#pragma once
+#include "Game/items.h"
+#include "Math/Math.h"
+
+using namespace TEN::Math;
+
+namespace TEN::Effects::Fireflies
+{
+ enum FirefliesItemFlags
+ {
+ TargetItemPtr,
+ Light,
+ TriggerFlags,
+ Spawncounter,
+ RemoveFliesEffect,
+ LightIndex1,
+ LightIndex2
+ };
+
+ struct FireflyData
+ {
+ int SpriteSeqID = ID_DEFAULT_SPRITES;
+ int SpriteID = SPR_UNDERWATERDUST;
+ BlendMode blendMode;
+ unsigned int scalar;
+
+ Vector3 Position = Vector3::Zero;
+ int RoomNumber = 0;
+ Vector3 PositionTarget = Vector3::Zero;
+ EulerAngles Orientation = EulerAngles::Identity;
+ float Velocity = 0.0f;
+
+ ItemInfo* TargetItemPtr = nullptr;
+
+ float zVel;
+ float Life = 0.0f;
+ int Number = 0;
+
+ unsigned char rB;
+ unsigned char gB;
+ unsigned char bB;
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+
+ bool on;
+ float size;
+ short rotAng;
+
+ int PrevX;
+ int PrevY;
+ int PrevZ;
+ byte PrevR;
+ byte PrevG;
+ byte PrevB;
+
+ void StoreInterpolationData()
+ {
+ PrevX = Position.x;
+ PrevY = Position.y;
+ PrevZ = Position.z;
+ PrevR = r;
+ PrevG = g;
+ PrevB = b;
+ }
+ };
+
+ extern std::vector FireflySwarm;
+
+ void InitializeFireflySwarm(short itemNumber);
+ void ControlFireflySwarm(short itemNumber);
+ void UpdateFireflySwarm();
+ void ClearFireflySwarm();
+ void SpawnFireflySwarm(ItemInfo& item, int triggerFlags);
+ void RemoveFireflies(ItemInfo& item);
+}
diff --git a/TombEngine/Objects/TR3/Object/corpse.cpp b/TombEngine/Objects/TR3/Object/corpse.cpp
index 527f12f1c..3b3da8a3b 100644
--- a/TombEngine/Objects/TR3/Object/corpse.cpp
+++ b/TombEngine/Objects/TR3/Object/corpse.cpp
@@ -17,6 +17,7 @@
#include "Game/Lara/lara_helpers.h"
#include "Game/Setup.h"
#include "Math/Math.h"
+#include "Objects/Effects/Fireflies.h"
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
#include "Sound/sound.h"
#include "Specific/level.h"
@@ -25,9 +26,13 @@ using namespace TEN::Collision::Point;
using namespace TEN::Effects::Ripple;
using namespace TEN::Effects::Splash;
using namespace TEN::Math;
+using namespace TEN::Effects::Fireflies;
namespace TEN::Entities::TR3
{
+ constexpr auto FLY_EFFECT_MAX_WIDTH = -1;
+ constexpr auto FLY_AMOUNT = 16;
+
enum CorpseState
{
CORPSE_STATE_GROUNDED = 0,
@@ -51,19 +56,25 @@ namespace TEN::Entities::TR3
if (item.TriggerFlags == 1)
{
- item.ItemFlags[1] = (int)CorpseFlag::Hang;
+ item.ItemFlags[7] = (int)CorpseFlag::Hang;
item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_HANG;
item.Animation.ActiveState = CORPSE_STATE_HANG;
}
else
{
- item.ItemFlags[1] = (int)CorpseFlag::Grounded;
+ item.ItemFlags[7] = (int)CorpseFlag::Grounded;
item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_GROUNDED;
item.Animation.ActiveState = CORPSE_STATE_GROUNDED;
}
+ item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] = 0;
+
AddActiveItem(itemNumber);
item.Status = ITEM_ACTIVE;
+
+ item.ItemFlags[FirefliesItemFlags::TargetItemPtr] = item.Index;
+ item.ItemFlags[FirefliesItemFlags::TriggerFlags] = -1;
+ item.HitPoints = FLY_AMOUNT;
}
void ControlCorpse(short itemNumber)
@@ -71,9 +82,11 @@ namespace TEN::Entities::TR3
auto& item = g_Level.Items[itemNumber];
const auto& object = Objects[item.ObjectNumber];
- if (item.ItemFlags[1] == (int)CorpseFlag::Fall)
+ if (item.ItemFlags[7] == (int)CorpseFlag::Fall)
{
bool isWater = TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber);
+ bool isSwamp = TestEnvironment(RoomEnvFlags::ENV_FLAG_SWAMP, item.RoomNumber);
+
float verticalVelCoeff = isWater ? 81.0f : 1.0f;
auto pointColl = GetPointCollision(item);
@@ -94,31 +107,37 @@ namespace TEN::Entities::TR3
ItemNewRoom(itemNumber, pointColl.GetRoomNumber());
}
- pointColl = GetPointCollision(item);
+ // Remove fly effect when in water.
+ if (isWater || isSwamp)
+ {
+ item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] = 1;
+ }
+
+ auto bounds = GameBoundingBox(&item);
+
item.Animation.IsAirborne = true;
- if (pointColl.GetFloorHeight() < item.Pose.Position.y)
+ if (pointColl.GetFloorHeight() <= item.Pose.Position.y - bounds.Y2)
{
if (!isWater)
{
- item.Pose.Position.y = item.Pose.Position.y - item.Animation.Velocity.y;
+ item.Pose.Position.y = pointColl.GetFloorHeight();
SoundEffect(SFX_TR4_CROCGOD_LAND, &item.Pose);
}
- else
+ else
{
- item.Pose.Position.y = item.Pose.Position.y;
+ item.Pose.Position.y = pointColl.GetFloorHeight();
}
item.Animation.IsAirborne = false;
item.Animation.Velocity = Vector3::Zero;
item.Animation.TargetState = CORPSE_STATE_LAND;
item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_LAND;
- AlignEntityToSurface(&item, Vector2(object.radius));
- item.ItemFlags[1] = (int)CorpseFlag::Grounded;
+ item.ItemFlags[7] = (int)CorpseFlag::Grounded;
return;
}
- else
+ else if (item.Animation.ActiveState == CORPSE_STATE_FALL)
{
if (isWater)
{
@@ -133,17 +152,56 @@ namespace TEN::Entities::TR3
AnimateItem(&item);
- if (!TriggerActive(&item))
- return;
-
- int meshCount = object.nmeshes;
- for (int i = 0; i < meshCount; i++)
+ if (!TriggerActive(&item) || item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] == 1)
{
- if (Random::TestProbability(1 / 72.0f))
+ // Remove all fireflies associated with this item.
+ RemoveFireflies(item);
+
+ // Reset ItemFlags.
+ if (item.HitPoints == NOT_TARGETABLE)
+ item.HitPoints = FLY_AMOUNT;
+
+ item.ItemFlags[FirefliesItemFlags::Spawncounter] = 0;
+
+ return;
+ }
+ else
+ {
+ AddActiveItem(itemNumber);
+ item.Status = ITEM_ACTIVE;
+ }
+
+ // Spawn fly effect.
+ if (item.HitPoints != NOT_TARGETABLE)
+ {
+ int fireflyCount = item.HitPoints - item.ItemFlags[FirefliesItemFlags::Spawncounter];
+
+ if (fireflyCount < 0)
{
- auto pos = GetJointPosition(&item, i).ToVector3();
- SpawnCorpseEffect(pos);
+ int firefliesToTurnOff = -fireflyCount;
+ for (auto& firefly : FireflySwarm)
+ {
+ if (firefly.TargetItemPtr == &item && firefly.Life > 0.0f)
+ {
+ firefly.Life = 0.0f;
+ firefly.on = false;
+ firefliesToTurnOff--;
+
+ if (firefliesToTurnOff == 0)
+ break;
+ }
+ }
}
+ else if (fireflyCount > 0)
+ {
+ for (int i = 0; i < fireflyCount; i++)
+ {
+ SpawnFireflySwarm(item, FLY_EFFECT_MAX_WIDTH);
+ }
+ }
+
+ item.ItemFlags[FirefliesItemFlags::Spawncounter] = item.HitPoints;
+ item.HitPoints = NOT_TARGETABLE;
}
}
@@ -160,9 +218,9 @@ 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)CorpseFlag::Hang)
+ if (target.ItemFlags[7] == (int)CorpseFlag::Hang)
{
- target.ItemFlags[1] = (int)CorpseFlag::Fall;
+ target.ItemFlags[7] = (int)CorpseFlag::Fall;
target.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_FALL;
target.Animation.ActiveState = CORPSE_STATE_FALL;
}
diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp
index 9b5b878b6..130d7405f 100644
--- a/TombEngine/Objects/TR5/tr5_objects.cpp
+++ b/TombEngine/Objects/TR5/tr5_objects.cpp
@@ -42,6 +42,7 @@
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
#include "Objects/TR5/Emitter/tr5_smoke_emitter.h"
#include "Objects/TR5/Emitter/Waterfall.h"
+#include "Objects/Effects/Fireflies.h"
// Objects
#include "Objects/TR5/Light/tr5_light.h"
@@ -81,6 +82,7 @@ using namespace TEN::Effects::WaterfallEmitter;
using namespace TEN::Entities::Creatures::TR5;
using namespace TEN::Entities::Switches;
using namespace TEN::Entities::Traps;
+using namespace TEN::Effects::Fireflies;
static void StartEntity(ObjectInfo *obj)
{
@@ -796,6 +798,14 @@ static void StartObject(ObjectInfo *obj)
obj->control = ControlEmberEmitter;
}
+ obj = &Objects[ID_FIREFLY_EMITTER];
+ if (obj->loaded)
+ {
+ obj->Initialize = InitializeFireflySwarm;
+ obj->control = ControlFireflySwarm;
+ obj->drawRoutine = NULL;
+ }
+
obj = &Objects[ID_GEN_SLOT1];
if (obj->loaded)
{
diff --git a/TombEngine/Objects/game_object_ids.h b/TombEngine/Objects/game_object_ids.h
index 26138ce91..18c64a25b 100644
--- a/TombEngine/Objects/game_object_ids.h
+++ b/TombEngine/Objects/game_object_ids.h
@@ -817,6 +817,7 @@ enum GAME_OBJECT_ID : short
ID_CORPSE,
ID_WRAITH_TRAP,
ID_WATERFALL_EMITTER,
+ ID_FIREFLY_EMITTER,
ID_MESHSWAP1 = 1100,
ID_MESHSWAP2,
@@ -1006,8 +1007,8 @@ enum GAME_OBJECT_ID : short
ID_DASH_BAR_TEXTURE,
ID_SFX_BAR_TEXTURE,
ID_WATERFALL_SPRITES,
- // 1379
- ID_CROSSHAIR_GRAPHICS = 1380,
+ ID_FIREFLY_SPRITES,
+ ID_CROSSHAIR_GRAPHICS,
ID_SPEEDOMETER_GRAPHICS,
ID_CUSTOM_BAR_GRAPHICS,
ID_CUSTOM_AMMO_GRAPHICS,
diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h
index cfe315b4c..4e643388d 100644
--- a/TombEngine/Renderer/Renderer.h
+++ b/TombEngine/Renderer/Renderer.h
@@ -409,6 +409,7 @@ namespace TEN::Renderer
void PrepareFires(RenderView& view);
void PrepareParticles(RenderView& view);
void PrepareSmokes(RenderView& view);
+ void PrepareFireflies(RenderView& view);
void PrepareElectricity(RenderView& view);
void PrepareHelicalLasers(RenderView& view);
void PrepareBlood(RenderView& view);
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index a79e06298..1c63b24d8 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -1759,6 +1759,7 @@ namespace TEN::Renderer
PrepareStreamers(view);
PrepareLaserBarriers(view);
PrepareSingleLaserBeam(view);
+ PrepareFireflies(view);
// Sprites grouped in buckets for instancing. Non-commutative sprites are collected at a later stage.
SortAndPrepareSprites(view);
diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp
index 3b00f6c5f..e647f86b1 100644
--- a/TombEngine/Renderer/RendererDrawEffect.cpp
+++ b/TombEngine/Renderer/RendererDrawEffect.cpp
@@ -35,6 +35,7 @@
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
#include "Specific/level.h"
#include "Structures/RendererSpriteBucket.h"
+#include "Objects/Effects/Fireflies.h"
using namespace TEN::Effects::Blood;
using namespace TEN::Effects::Bubble;
@@ -48,6 +49,7 @@ using namespace TEN::Effects::Streamer;
using namespace TEN::Entities::Creatures::TR5;
using namespace TEN::Entities::Traps;
using namespace TEN::Math;
+using namespace TEN::Effects::Fireflies;
extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD];
extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE];
@@ -330,6 +332,49 @@ namespace TEN::Renderer
}
}
+ void Renderer::PrepareFireflies(RenderView& view)
+ {
+ if (!Objects[ID_FIREFLY_EMITTER].loaded)
+ return;
+
+ for (auto& firefly : FireflySwarm)
+ {
+ if (!firefly.on)
+ continue;
+
+
+ if (!CheckIfSlotExists(ID_SPARK_SPRITE, "Particle rendering"))
+ continue;
+
+ auto axis = Vector3(0,0,0);
+ axis.Normalize();
+
+
+ firefly.scalar = 3;
+ firefly.size = 3;
+
+ auto pos = Vector3::Lerp(
+ Vector3(firefly.PrevX, firefly.PrevY, firefly.PrevZ),
+ Vector3(firefly.Position.x, firefly.Position.y, firefly.Position.z),
+ GetInterpolationFactor());
+
+ pos = Vector3(firefly.Position.x, firefly.Position.y, firefly.Position.z);
+
+ // Disallow sprites out of bounds.
+ int spriteIndex = Objects[firefly.SpriteSeqID].meshIndex + firefly.SpriteID;
+ spriteIndex = std::clamp(spriteIndex, 0, (int)_sprites.size());
+
+ AddSpriteBillboard(
+ &_sprites[spriteIndex],
+ pos,
+ Color(firefly.r / (float)UCHAR_MAX, firefly.g / (float)UCHAR_MAX, firefly.b / (float)UCHAR_MAX, 1.0f),
+ TO_RAD(firefly.rotAng << 4), firefly.scalar,
+ Vector2(firefly.size, firefly.size),
+ firefly.blendMode, true, view);
+
+ }
+ }
+
void Renderer::PrepareSmokes(RenderView& view)
{
for (const auto& smoke : SmokeSparks)
diff --git a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h
index 41dba67cb..04e5732a8 100644
--- a/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h
+++ b/TombEngine/Scripting/Internal/TEN/Objects/ObjectIDs.h
@@ -1,7 +1,7 @@
#pragma once
// This file is generated automatically, do not edit it.
-// Last generated on 13/03/2025.
+// Last generated on 17/03/2025.
#include
#include
@@ -815,6 +815,7 @@ The following constants are inside ObjID.
CORPSE
WRAITH_TRAP
WATERFALL_EMITTER
+ FIREFLY_EMITTER
MESHSWAP1
MESHSWAP2
MESHSWAP3
@@ -995,6 +996,7 @@ The following constants are inside ObjID.
DASH_BAR_TEXTURE
SFX_BAR_TEXTURE
WATERFALL_SPRITES
+ FIREFLY_SPRITES
CROSSHAIR_GRAPHICS
SPEEDOMETER_GRAPHICS
CUSTOM_BAR_GRAPHICS
@@ -1245,6 +1247,7 @@ The following ObjID members refer to sprites.
DASH_BAR_TEXTURE
SFX_BAR_TEXTURE
WATERFALL_SPRITES
+ FIREFLY_SPRITES
CROSSHAIR_GRAPHICS
SPEEDOMETER_GRAPHICS
CUSTOM_BAR_GRAPHICS
@@ -2052,6 +2055,7 @@ static const std::unordered_map GAME_OBJECT_IDS {
{ "CORPSE", ID_CORPSE },
{ "WRAITH_TRAP", ID_WRAITH_TRAP },
{ "WATERFALL_EMITTER", ID_WATERFALL_EMITTER },
+ { "FIREFLY_EMITTER", ID_FIREFLY_EMITTER },
{ "MESHSWAP1", ID_MESHSWAP1 },
{ "MESHSWAP2", ID_MESHSWAP2 },
{ "MESHSWAP3", ID_MESHSWAP3 },
@@ -2232,6 +2236,7 @@ static const std::unordered_map GAME_OBJECT_IDS {
{ "DASH_BAR_TEXTURE", ID_DASH_BAR_TEXTURE },
{ "SFX_BAR_TEXTURE", ID_SFX_BAR_TEXTURE },
{ "WATERFALL_SPRITES", ID_WATERFALL_SPRITES },
+ { "FIREFLY_SPRITES", ID_FIREFLY_SPRITES },
{ "CROSSHAIR_GRAPHICS", ID_CROSSHAIR_GRAPHICS },
{ "SPEEDOMETER_GRAPHICS", ID_SPEEDOMETER_GRAPHICS },
{ "CUSTOM_BAR_GRAPHICS", ID_CUSTOM_BAR_GRAPHICS },
diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h
index 5c8333d07..a99d79882 100644
--- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h
+++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h
@@ -169,6 +169,10 @@ struct FishData;
struct FishDataBuilder;
struct FishDataT;
+struct FireflyData;
+struct FireflyDataBuilder;
+struct FireflyDataT;
+
struct KeyValPair;
struct ScriptTable;
@@ -6861,6 +6865,295 @@ struct FishData::Traits {
flatbuffers::Offset CreateFishData(flatbuffers::FlatBufferBuilder &_fbb, const FishDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+struct FireflyDataT : public flatbuffers::NativeTable {
+ typedef FireflyData TableType;
+ int32_t sprite_index = 0;
+ int32_t sprite_id = 0;
+ int32_t blend_mode = 0;
+ int32_t scalar = 0;
+ std::unique_ptr position{};
+ int32_t room_number = 0;
+ std::unique_ptr position_target{};
+ std::unique_ptr orientation{};
+ float velocity = 0.0f;
+ int32_t target_item_number = 0;
+ float z_vel = 0.0f;
+ float life = 0.0f;
+ int32_t number = 0;
+ int32_t d_r = 0;
+ int32_t d_g = 0;
+ int32_t d_b = 0;
+ int32_t r = 0;
+ int32_t g = 0;
+ int32_t b = 0;
+ bool on = false;
+ float size = 0.0f;
+ int32_t rot_Ang = 0;
+};
+
+struct FireflyData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef FireflyDataT NativeTableType;
+ typedef FireflyDataBuilder Builder;
+ struct Traits;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_SPRITE_INDEX = 4,
+ VT_SPRITE_ID = 6,
+ VT_BLEND_MODE = 8,
+ VT_SCALAR = 10,
+ VT_POSITION = 12,
+ VT_ROOM_NUMBER = 14,
+ VT_POSITION_TARGET = 16,
+ VT_ORIENTATION = 18,
+ VT_VELOCITY = 20,
+ VT_TARGET_ITEM_NUMBER = 22,
+ VT_Z_VEL = 24,
+ VT_LIFE = 26,
+ VT_NUMBER = 28,
+ VT_D_R = 30,
+ VT_D_G = 32,
+ VT_D_B = 34,
+ VT_R = 36,
+ VT_G = 38,
+ VT_B = 40,
+ VT_ON = 42,
+ VT_SIZE = 44,
+ VT_ROT_ANG = 46
+ };
+ int32_t sprite_index() const {
+ return GetField(VT_SPRITE_INDEX, 0);
+ }
+ int32_t sprite_id() const {
+ return GetField(VT_SPRITE_ID, 0);
+ }
+ int32_t blend_mode() const {
+ return GetField(VT_BLEND_MODE, 0);
+ }
+ int32_t scalar() const {
+ return GetField(VT_SCALAR, 0);
+ }
+ const TEN::Save::Vector3 *position() const {
+ return GetStruct(VT_POSITION);
+ }
+ int32_t room_number() const {
+ return GetField(VT_ROOM_NUMBER, 0);
+ }
+ const TEN::Save::Vector3 *position_target() const {
+ return GetStruct(VT_POSITION_TARGET);
+ }
+ const TEN::Save::EulerAngles *orientation() const {
+ return GetStruct(VT_ORIENTATION);
+ }
+ float velocity() const {
+ return GetField(VT_VELOCITY, 0.0f);
+ }
+ int32_t target_item_number() const {
+ return GetField(VT_TARGET_ITEM_NUMBER, 0);
+ }
+ float z_vel() const {
+ return GetField(VT_Z_VEL, 0.0f);
+ }
+ float life() const {
+ return GetField(VT_LIFE, 0.0f);
+ }
+ int32_t number() const {
+ return GetField(VT_NUMBER, 0);
+ }
+ int32_t d_r() const {
+ return GetField(VT_D_R, 0);
+ }
+ int32_t d_g() const {
+ return GetField(VT_D_G, 0);
+ }
+ int32_t d_b() const {
+ return GetField(VT_D_B, 0);
+ }
+ int32_t r() const {
+ return GetField(VT_R, 0);
+ }
+ int32_t g() const {
+ return GetField(VT_G, 0);
+ }
+ int32_t b() const {
+ return GetField(VT_B, 0);
+ }
+ bool on() const {
+ return GetField(VT_ON, 0) != 0;
+ }
+ float size() const {
+ return GetField(VT_SIZE, 0.0f);
+ }
+ int32_t rot_Ang() const {
+ return GetField(VT_ROT_ANG, 0);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyField(verifier, VT_SPRITE_INDEX) &&
+ VerifyField(verifier, VT_SPRITE_ID) &&
+ VerifyField(verifier, VT_BLEND_MODE) &&
+ VerifyField(verifier, VT_SCALAR) &&
+ VerifyField(verifier, VT_POSITION) &&
+ VerifyField(verifier, VT_ROOM_NUMBER) &&
+ VerifyField(verifier, VT_POSITION_TARGET) &&
+ VerifyField(verifier, VT_ORIENTATION) &&
+ VerifyField(verifier, VT_VELOCITY) &&
+ VerifyField(verifier, VT_TARGET_ITEM_NUMBER) &&
+ VerifyField(verifier, VT_Z_VEL) &&
+ VerifyField(verifier, VT_LIFE) &&
+ VerifyField(verifier, VT_NUMBER) &&
+ VerifyField(verifier, VT_D_R) &&
+ VerifyField(verifier, VT_D_G) &&
+ VerifyField(verifier, VT_D_B) &&
+ VerifyField(verifier, VT_R) &&
+ VerifyField(verifier, VT_G) &&
+ VerifyField(verifier, VT_B) &&
+ VerifyField(verifier, VT_ON) &&
+ VerifyField(verifier, VT_SIZE) &&
+ VerifyField(verifier, VT_ROT_ANG) &&
+ verifier.EndTable();
+ }
+ FireflyDataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ void UnPackTo(FireflyDataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+ static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct FireflyDataBuilder {
+ typedef FireflyData Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_sprite_index(int32_t sprite_index) {
+ fbb_.AddElement(FireflyData::VT_SPRITE_INDEX, sprite_index, 0);
+ }
+ void add_sprite_id(int32_t sprite_id) {
+ fbb_.AddElement(FireflyData::VT_SPRITE_ID, sprite_id, 0);
+ }
+ void add_blend_mode(int32_t blend_mode) {
+ fbb_.AddElement(FireflyData::VT_BLEND_MODE, blend_mode, 0);
+ }
+ void add_scalar(int32_t scalar) {
+ fbb_.AddElement(FireflyData::VT_SCALAR, scalar, 0);
+ }
+ void add_position(const TEN::Save::Vector3 *position) {
+ fbb_.AddStruct(FireflyData::VT_POSITION, position);
+ }
+ void add_room_number(int32_t room_number) {
+ fbb_.AddElement(FireflyData::VT_ROOM_NUMBER, room_number, 0);
+ }
+ void add_position_target(const TEN::Save::Vector3 *position_target) {
+ fbb_.AddStruct(FireflyData::VT_POSITION_TARGET, position_target);
+ }
+ void add_orientation(const TEN::Save::EulerAngles *orientation) {
+ fbb_.AddStruct(FireflyData::VT_ORIENTATION, orientation);
+ }
+ void add_velocity(float velocity) {
+ fbb_.AddElement(FireflyData::VT_VELOCITY, velocity, 0.0f);
+ }
+ void add_target_item_number(int32_t target_item_number) {
+ fbb_.AddElement(FireflyData::VT_TARGET_ITEM_NUMBER, target_item_number, 0);
+ }
+ void add_z_vel(float z_vel) {
+ fbb_.AddElement(FireflyData::VT_Z_VEL, z_vel, 0.0f);
+ }
+ void add_life(float life) {
+ fbb_.AddElement(FireflyData::VT_LIFE, life, 0.0f);
+ }
+ void add_number(int32_t number) {
+ fbb_.AddElement(FireflyData::VT_NUMBER, number, 0);
+ }
+ void add_d_r(int32_t d_r) {
+ fbb_.AddElement(FireflyData::VT_D_R, d_r, 0);
+ }
+ void add_d_g(int32_t d_g) {
+ fbb_.AddElement(FireflyData::VT_D_G, d_g, 0);
+ }
+ void add_d_b(int32_t d_b) {
+ fbb_.AddElement(FireflyData::VT_D_B, d_b, 0);
+ }
+ void add_r(int32_t r) {
+ fbb_.AddElement(FireflyData::VT_R, r, 0);
+ }
+ void add_g(int32_t g) {
+ fbb_.AddElement(FireflyData::VT_G, g, 0);
+ }
+ void add_b(int32_t b) {
+ fbb_.AddElement(FireflyData::VT_B, b, 0);
+ }
+ void add_on(bool on) {
+ fbb_.AddElement(FireflyData::VT_ON, static_cast(on), 0);
+ }
+ void add_size(float size) {
+ fbb_.AddElement(FireflyData::VT_SIZE, size, 0.0f);
+ }
+ void add_rot_Ang(int32_t rot_Ang) {
+ fbb_.AddElement(FireflyData::VT_ROT_ANG, rot_Ang, 0);
+ }
+ explicit FireflyDataBuilder(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 CreateFireflyData(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ int32_t sprite_index = 0,
+ int32_t sprite_id = 0,
+ int32_t blend_mode = 0,
+ int32_t scalar = 0,
+ const TEN::Save::Vector3 *position = 0,
+ int32_t room_number = 0,
+ const TEN::Save::Vector3 *position_target = 0,
+ const TEN::Save::EulerAngles *orientation = 0,
+ float velocity = 0.0f,
+ int32_t target_item_number = 0,
+ float z_vel = 0.0f,
+ float life = 0.0f,
+ int32_t number = 0,
+ int32_t d_r = 0,
+ int32_t d_g = 0,
+ int32_t d_b = 0,
+ int32_t r = 0,
+ int32_t g = 0,
+ int32_t b = 0,
+ bool on = false,
+ float size = 0.0f,
+ int32_t rot_Ang = 0) {
+ FireflyDataBuilder builder_(_fbb);
+ builder_.add_rot_Ang(rot_Ang);
+ builder_.add_size(size);
+ builder_.add_b(b);
+ builder_.add_g(g);
+ builder_.add_r(r);
+ builder_.add_d_b(d_b);
+ builder_.add_d_g(d_g);
+ builder_.add_d_r(d_r);
+ builder_.add_number(number);
+ builder_.add_life(life);
+ builder_.add_z_vel(z_vel);
+ builder_.add_target_item_number(target_item_number);
+ builder_.add_velocity(velocity);
+ builder_.add_orientation(orientation);
+ builder_.add_position_target(position_target);
+ builder_.add_room_number(room_number);
+ builder_.add_position(position);
+ builder_.add_scalar(scalar);
+ builder_.add_blend_mode(blend_mode);
+ builder_.add_sprite_id(sprite_id);
+ builder_.add_sprite_index(sprite_index);
+ builder_.add_on(on);
+ return builder_.Finish();
+}
+
+struct FireflyData::Traits {
+ using type = FireflyData;
+ static auto constexpr Create = CreateFireflyData;
+};
+
+flatbuffers::Offset CreateFireflyData(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
struct ScriptTableT : public flatbuffers::NativeTable {
typedef ScriptTable TableType;
std::vector keys_vals{};
@@ -8000,6 +8293,7 @@ struct SaveGameT : public flatbuffers::NativeTable {
int32_t next_item_active = 0;
std::vector room_items{};
std::vector> fish_swarm{};
+ std::vector> firefly_swarm{};
std::vector> fxinfos{};
int32_t next_fx_free = 0;
int32_t next_fx_active = 0;
@@ -8066,52 +8360,53 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_NEXT_ITEM_ACTIVE = 24,
VT_ROOM_ITEMS = 26,
VT_FISH_SWARM = 28,
- VT_FXINFOS = 30,
- VT_NEXT_FX_FREE = 32,
- VT_NEXT_FX_ACTIVE = 34,
- VT_FIXED_CAMERAS = 36,
- VT_SINKS = 38,
- VT_STATIC_MESHES = 40,
- VT_FLYBY_CAMERAS = 42,
- VT_PARTICLES = 44,
- VT_RATS = 46,
- VT_SPIDERS = 48,
- VT_SCARABS = 50,
- VT_BATS = 52,
- VT_FLIP_MAPS = 54,
- VT_FLIP_STATS = 56,
- VT_FLIP_EFFECT = 58,
- VT_FLIP_TIMER = 60,
- VT_FLIP_STATUS = 62,
- VT_CURRENT_FOV = 64,
- VT_LAST_INV_ITEM = 66,
- VT_ACTION_QUEUE = 68,
- VT_SOUNDTRACKS = 70,
- VT_CD_FLAGS = 72,
- VT_POSTPROCESS_MODE = 74,
- VT_POSTPROCESS_STRENGTH = 76,
- VT_POSTPROCESS_TINT = 78,
- VT_ROPE = 80,
- VT_PENDULUM = 82,
- VT_ALTERNATE_PENDULUM = 84,
- VT_VOLUMES = 86,
- VT_GLOBAL_EVENT_SETS = 88,
- VT_VOLUME_EVENT_SETS = 90,
- VT_SCRIPT_VARS = 92,
- VT_CALLBACKS_PRE_START = 94,
- VT_CALLBACKS_POST_START = 96,
- VT_CALLBACKS_PRE_END = 98,
- VT_CALLBACKS_POST_END = 100,
- VT_CALLBACKS_PRE_SAVE = 102,
- VT_CALLBACKS_POST_SAVE = 104,
- VT_CALLBACKS_PRE_LOAD = 106,
- VT_CALLBACKS_POST_LOAD = 108,
- VT_CALLBACKS_PRE_LOOP = 110,
- VT_CALLBACKS_POST_LOOP = 112,
- VT_CALLBACKS_PRE_USEITEM = 114,
- VT_CALLBACKS_POST_USEITEM = 116,
- VT_CALLBACKS_PRE_FREEZE = 118,
- VT_CALLBACKS_POST_FREEZE = 120
+ VT_FIREFLY_SWARM = 30,
+ VT_FXINFOS = 32,
+ VT_NEXT_FX_FREE = 34,
+ VT_NEXT_FX_ACTIVE = 36,
+ VT_FIXED_CAMERAS = 38,
+ VT_SINKS = 40,
+ VT_STATIC_MESHES = 42,
+ VT_FLYBY_CAMERAS = 44,
+ VT_PARTICLES = 46,
+ VT_RATS = 48,
+ VT_SPIDERS = 50,
+ VT_SCARABS = 52,
+ VT_BATS = 54,
+ VT_FLIP_MAPS = 56,
+ VT_FLIP_STATS = 58,
+ VT_FLIP_EFFECT = 60,
+ VT_FLIP_TIMER = 62,
+ VT_FLIP_STATUS = 64,
+ VT_CURRENT_FOV = 66,
+ VT_LAST_INV_ITEM = 68,
+ VT_ACTION_QUEUE = 70,
+ VT_SOUNDTRACKS = 72,
+ VT_CD_FLAGS = 74,
+ VT_POSTPROCESS_MODE = 76,
+ VT_POSTPROCESS_STRENGTH = 78,
+ VT_POSTPROCESS_TINT = 80,
+ VT_ROPE = 82,
+ VT_PENDULUM = 84,
+ VT_ALTERNATE_PENDULUM = 86,
+ VT_VOLUMES = 88,
+ VT_GLOBAL_EVENT_SETS = 90,
+ VT_VOLUME_EVENT_SETS = 92,
+ VT_SCRIPT_VARS = 94,
+ VT_CALLBACKS_PRE_START = 96,
+ VT_CALLBACKS_POST_START = 98,
+ VT_CALLBACKS_PRE_END = 100,
+ VT_CALLBACKS_POST_END = 102,
+ VT_CALLBACKS_PRE_SAVE = 104,
+ VT_CALLBACKS_POST_SAVE = 106,
+ VT_CALLBACKS_PRE_LOAD = 108,
+ VT_CALLBACKS_POST_LOAD = 110,
+ VT_CALLBACKS_PRE_LOOP = 112,
+ VT_CALLBACKS_POST_LOOP = 114,
+ VT_CALLBACKS_PRE_USEITEM = 116,
+ VT_CALLBACKS_POST_USEITEM = 118,
+ VT_CALLBACKS_PRE_FREEZE = 120,
+ VT_CALLBACKS_POST_FREEZE = 122
};
const TEN::Save::SaveGameHeader *header() const {
return GetPointer(VT_HEADER);
@@ -8152,6 +8447,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const flatbuffers::Vector> *fish_swarm() const {
return GetPointer> *>(VT_FISH_SWARM);
}
+ const flatbuffers::Vector> *firefly_swarm() const {
+ return GetPointer> *>(VT_FIREFLY_SWARM);
+ }
const flatbuffers::Vector> *fxinfos() const {
return GetPointer> *>(VT_FXINFOS);
}
@@ -8318,6 +8616,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyOffset(verifier, VT_FISH_SWARM) &&
verifier.VerifyVector(fish_swarm()) &&
verifier.VerifyVectorOfTables(fish_swarm()) &&
+ VerifyOffset(verifier, VT_FIREFLY_SWARM) &&
+ verifier.VerifyVector(firefly_swarm()) &&
+ verifier.VerifyVectorOfTables(firefly_swarm()) &&
VerifyOffset(verifier, VT_FXINFOS) &&
verifier.VerifyVector(fxinfos()) &&
verifier.VerifyVectorOfTables(fxinfos()) &&
@@ -8478,6 +8779,9 @@ struct SaveGameBuilder {
void add_fish_swarm(flatbuffers::Offset>> fish_swarm) {
fbb_.AddOffset(SaveGame::VT_FISH_SWARM, fish_swarm);
}
+ void add_firefly_swarm(flatbuffers::Offset>> firefly_swarm) {
+ fbb_.AddOffset(SaveGame::VT_FIREFLY_SWARM, firefly_swarm);
+ }
void add_fxinfos(flatbuffers::Offset>> fxinfos) {
fbb_.AddOffset(SaveGame::VT_FXINFOS, fxinfos);
}
@@ -8642,6 +8946,7 @@ inline flatbuffers::Offset CreateSaveGame(
int32_t next_item_active = 0,
flatbuffers::Offset> room_items = 0,
flatbuffers::Offset>> fish_swarm = 0,
+ flatbuffers::Offset>> firefly_swarm = 0,
flatbuffers::Offset>> fxinfos = 0,
int32_t next_fx_free = 0,
int32_t next_fx_active = 0,
@@ -8734,6 +9039,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_firefly_swarm(firefly_swarm);
builder_.add_fish_swarm(fish_swarm);
builder_.add_room_items(room_items);
builder_.add_next_item_active(next_item_active);
@@ -8771,6 +9077,7 @@ inline flatbuffers::Offset CreateSaveGameDirect(
int32_t next_item_active = 0,
const std::vector *room_items = nullptr,
const std::vector> *fish_swarm = nullptr,
+ const std::vector> *firefly_swarm = nullptr,
const std::vector> *fxinfos = nullptr,
int32_t next_fx_free = 0,
int32_t next_fx_active = 0,
@@ -8821,6 +9128,7 @@ inline flatbuffers::Offset CreateSaveGameDirect(
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 firefly_swarm__ = firefly_swarm ? _fbb.CreateVector>(*firefly_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;
@@ -8868,6 +9176,7 @@ inline flatbuffers::Offset CreateSaveGameDirect(
next_item_active,
room_items__,
fish_swarm__,
+ firefly_swarm__,
fxinfos__,
next_fx_free,
next_fx_active,
@@ -10889,6 +11198,95 @@ inline flatbuffers::Offset CreateFishData(flatbuffers::FlatBufferBuild
_velocity);
}
+inline FireflyDataT *FireflyData::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+ auto _o = std::make_unique();
+ UnPackTo(_o.get(), _resolver);
+ return _o.release();
+}
+
+inline void FireflyData::UnPackTo(FireflyDataT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+ (void)_o;
+ (void)_resolver;
+ { auto _e = sprite_index(); _o->sprite_index = _e; }
+ { auto _e = sprite_id(); _o->sprite_id = _e; }
+ { auto _e = blend_mode(); _o->blend_mode = _e; }
+ { auto _e = scalar(); _o->scalar = _e; }
+ { auto _e = position(); if (_e) _o->position = std::unique_ptr(new TEN::Save::Vector3(*_e)); }
+ { auto _e = room_number(); _o->room_number = _e; }
+ { auto _e = position_target(); if (_e) _o->position_target = std::unique_ptr(new TEN::Save::Vector3(*_e)); }
+ { auto _e = orientation(); if (_e) _o->orientation = std::unique_ptr(new TEN::Save::EulerAngles(*_e)); }
+ { auto _e = velocity(); _o->velocity = _e; }
+ { auto _e = target_item_number(); _o->target_item_number = _e; }
+ { auto _e = z_vel(); _o->z_vel = _e; }
+ { auto _e = life(); _o->life = _e; }
+ { auto _e = number(); _o->number = _e; }
+ { auto _e = d_r(); _o->d_r = _e; }
+ { auto _e = d_g(); _o->d_g = _e; }
+ { auto _e = d_b(); _o->d_b = _e; }
+ { auto _e = r(); _o->r = _e; }
+ { auto _e = g(); _o->g = _e; }
+ { auto _e = b(); _o->b = _e; }
+ { auto _e = on(); _o->on = _e; }
+ { auto _e = size(); _o->size = _e; }
+ { auto _e = rot_Ang(); _o->rot_Ang = _e; }
+}
+
+inline flatbuffers::Offset FireflyData::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+ return CreateFireflyData(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset CreateFireflyData(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+ (void)_rehasher;
+ (void)_o;
+ struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FireflyDataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+ auto _sprite_index = _o->sprite_index;
+ auto _sprite_id = _o->sprite_id;
+ auto _blend_mode = _o->blend_mode;
+ auto _scalar = _o->scalar;
+ auto _position = _o->position ? _o->position.get() : 0;
+ auto _room_number = _o->room_number;
+ auto _position_target = _o->position_target ? _o->position_target.get() : 0;
+ auto _orientation = _o->orientation ? _o->orientation.get() : 0;
+ auto _velocity = _o->velocity;
+ auto _target_item_number = _o->target_item_number;
+ auto _z_vel = _o->z_vel;
+ auto _life = _o->life;
+ auto _number = _o->number;
+ auto _d_r = _o->d_r;
+ auto _d_g = _o->d_g;
+ auto _d_b = _o->d_b;
+ auto _r = _o->r;
+ auto _g = _o->g;
+ auto _b = _o->b;
+ auto _on = _o->on;
+ auto _size = _o->size;
+ auto _rot_Ang = _o->rot_Ang;
+ return TEN::Save::CreateFireflyData(
+ _fbb,
+ _sprite_index,
+ _sprite_id,
+ _blend_mode,
+ _scalar,
+ _position,
+ _room_number,
+ _position_target,
+ _orientation,
+ _velocity,
+ _target_item_number,
+ _z_vel,
+ _life,
+ _number,
+ _d_r,
+ _d_g,
+ _d_b,
+ _r,
+ _g,
+ _b,
+ _on,
+ _size,
+ _rot_Ang);
+}
+
inline ScriptTableT *ScriptTable::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = std::make_unique();
UnPackTo(_o.get(), _resolver);
@@ -11323,6 +11721,7 @@ inline void SaveGame::UnPackTo(SaveGameT *_o, const flatbuffers::resolver_functi
{ 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 = firefly_swarm(); if (_e) { _o->firefly_swarm.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->firefly_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; }
@@ -11392,6 +11791,7 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild
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 _firefly_swarm = _fbb.CreateVector> (_o->firefly_swarm.size(), [](size_t i, _VectorArgs *__va) { return CreateFireflyData(*__va->__fbb, __va->__o->firefly_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;
@@ -11453,6 +11853,7 @@ inline flatbuffers::Offset CreateSaveGame(flatbuffers::FlatBufferBuild
_next_item_active,
_room_items,
_fish_swarm,
+ _firefly_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 b4e852148..bc41d27be 100644
--- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs
+++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs
@@ -499,6 +499,31 @@ table FishData {
velocity: float;
}
+table FireflyData {
+ sprite_index: int32;
+ sprite_id: int32;
+ blend_mode: int32;
+ scalar: int32;
+ position: Vector3;
+ room_number: int32;
+ position_target: Vector3;
+ orientation: EulerAngles;
+ velocity: float;
+ target_item_number: int32;
+ z_vel: float;
+ life: float;
+ number: int32;
+ d_r: int32;
+ d_g: int32;
+ d_b: int32;
+ r: int32;
+ g: int32;
+ b: int32;
+ on: bool;
+ size: float;
+ rot_Ang: int32;
+}
+
struct KeyValPair {
key: uint32;
val: uint32;
@@ -602,6 +627,7 @@ table SaveGame {
next_item_active: int32;
room_items: [int32];
fish_swarm: [FishData];
+ firefly_swarm: [FireflyData];
fxinfos: [FXInfo];
next_fx_free: int32;
next_fx_active: int32;
diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj
index 19ff7ecfb..64841e2e1 100644
--- a/TombEngine/TombEngine.vcxproj
+++ b/TombEngine/TombEngine.vcxproj
@@ -506,6 +506,7 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.
+
@@ -1044,6 +1045,7 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.
+
From 7ba93702818ebb86abd94271326b499de7a79075 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 28 Mar 2025 07:11:04 +0100
Subject: [PATCH 19/53] Update CHANGELOG.md
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e17ee3ae..7f1ceec64 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.8.1](link to release) - yyyy-mm-dd
### New features
+* Added Firefly Emitter object (ID 1099) with corresponding sprite slot (ID 1379).
* Added live console input to perform Lua commands in realtime.
### Bug fixes
From 9fc370833bf3c43127fa250bb86413853123b715 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 28 Mar 2025 21:36:37 +0100
Subject: [PATCH 20/53] Implement flyby spline looping in lua API
---
CHANGELOG.md | 1 +
Documentation/doc/1 modules/View.html | 18 ++++++--
TombEngine/Game/spotcam.cpp | 44 +++++++++++++++----
TombEngine/Game/spotcam.h | 2 +-
.../Internal/TEN/View/ViewHandler.cpp | 10 +++--
5 files changed, 58 insertions(+), 17 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f1ceec64..3d47c249b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Lua API changes
* Added missing constructor for `Collision.Probe` without room number.
+* Added optional looping argument for `View.GetFlybyPosition` and `View.GetFlybyRotation` functions.
## [Version 1.8](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8) - 2025-03-16
diff --git a/Documentation/doc/1 modules/View.html b/Documentation/doc/1 modules/View.html
index f1725ceb1..40f491a7b 100644
--- a/Documentation/doc/1 modules/View.html
+++ b/Documentation/doc/1 modules/View.html
@@ -176,11 +176,11 @@
Play a flyby sequence.
- GetFlybyPosition(seqID, progress)
+ GetFlybyPosition(seqID, progress[, loop])
Get a flyby sequence's position at a specified progress point in percent.
- GetFlybyRotation(seqID, progress)
+ GetFlybyRotation(seqID, progress[, loop])
Get a flyby sequence's rotation at a specified progress point in percent.
@@ -499,7 +499,7 @@
- GetFlybyPosition(seqID, progress)
+ GetFlybyPosition(seqID, progress[, loop])
Get a flyby sequence's position at a specified progress point in percent.
@@ -516,6 +516,11 @@
float
Progress point in percent. Clamped to [0, 100].
+ loop
+ bool
+ Smooth the position near start and end points, as if the sequence is looped.
+ (optional )
+
Returns:
@@ -531,7 +536,7 @@
- GetFlybyRotation(seqID, progress)
+ GetFlybyRotation(seqID, progress[, loop])
Get a flyby sequence's rotation at a specified progress point in percent.
@@ -548,6 +553,11 @@
float
Progress point in percent. Clamped to [0, 100].
+ loop
+ bool
+ Smooth the position near start and end points, as if the sequence is looped.
+ (optional )
+
Returns:
diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp
index ffa8be942..2b6ea8d10 100644
--- a/TombEngine/Game/spotcam.cpp
+++ b/TombEngine/Game/spotcam.cpp
@@ -839,7 +839,7 @@ int Spline(int x, int* knots, int nk)
return ((__int64)x * (((__int64)x * (((__int64)x * c1 >> 16) + c2) >> 16) + (k[2] >> 1) + ((-k[0] - 1) >> 1)) >> 16) + k[1];
}
-Pose GetCameraTransform(int sequence, float alpha)
+Pose GetCameraTransform(int sequence, float alpha, bool loop)
{
alpha = std::clamp(alpha, 0.0f, 1.0f);
@@ -873,15 +873,43 @@ Pose GetCameraTransform(int sequence, float alpha)
}
// Compute spline interpolation of main flyby camera parameters.
- auto origin = Vector3(Spline(splineAlpha, xOrigins.data(), splinePoints),
- Spline(splineAlpha, yOrigins.data(), splinePoints),
- Spline(splineAlpha, zOrigins.data(), splinePoints));
+ auto getInterpolatedPoint = [&](float t, std::vector& x, std::vector& y, std::vector& z)
+ {
+ int tAlpha = int(t * (float)USHRT_MAX);
+ return Vector3(Spline(tAlpha, x.data(), splinePoints),
+ Spline(tAlpha, y.data(), splinePoints),
+ Spline(tAlpha, z.data(), splinePoints));
+ };
- auto target = Vector3(Spline(splineAlpha, xTargets.data(), splinePoints),
- Spline(splineAlpha, yTargets.data(), splinePoints),
- Spline(splineAlpha, zTargets.data(), splinePoints));
+ auto getInterpolatedRoll = [&](float t)
+ {
+ int tAlpha = int(t * (float)USHRT_MAX);
+ return Spline(tAlpha, rolls.data(), splinePoints);
+ };
- short orientZ = Spline(splineAlpha, rolls.data(), splinePoints);
+ Vector3 origin = {};
+ Vector3 target = {};
+ short orientZ = 0;
+
+ constexpr float BLEND_RANGE = 0.1f;
+ constexpr float BLEND_START = BLEND_RANGE;
+ constexpr float BLEND_END = 1.0f - BLEND_RANGE;
+
+ // If loop is enabled and we are at the start or end of the sequence, blend between the last and first cameras.
+ if (loop && (alpha < BLEND_START || alpha >= BLEND_END))
+ {
+ float blendFactor = (alpha < BLEND_START) ? 0.5f + (alpha / BLEND_RANGE) * 0.5f : (alpha - BLEND_END) / BLEND_START * 0.5f;
+
+ origin = Vector3::Lerp(getInterpolatedPoint(BLEND_END, xOrigins, yOrigins, zOrigins), getInterpolatedPoint(BLEND_START, xOrigins, yOrigins, zOrigins), blendFactor);
+ target = Vector3::Lerp(getInterpolatedPoint(BLEND_END, xTargets, yTargets, zTargets), getInterpolatedPoint(BLEND_START, xTargets, yTargets, zTargets), blendFactor);
+ orientZ = Lerp(getInterpolatedRoll(BLEND_END), getInterpolatedRoll(BLEND_START), blendFactor);
+ }
+ else
+ {
+ origin = getInterpolatedPoint(alpha, xOrigins, yOrigins, zOrigins);
+ target = getInterpolatedPoint(alpha, xTargets, yTargets, zTargets);
+ orientZ = getInterpolatedRoll(alpha);
+ }
auto pose = Pose(origin, EulerAngles(target - origin));
pose.Orientation.z = orientZ;
diff --git a/TombEngine/Game/spotcam.h b/TombEngine/Game/spotcam.h
index 035929e93..07917c26d 100644
--- a/TombEngine/Game/spotcam.h
+++ b/TombEngine/Game/spotcam.h
@@ -64,4 +64,4 @@ void InitializeSpotCam(short sequence);
void CalculateSpotCameras();
int Spline(int x, int* knots, int nk);
-Pose GetCameraTransform(int sequence, float alpha);
+Pose GetCameraTransform(int sequence, float alpha, bool loop);
diff --git a/TombEngine/Scripting/Internal/TEN/View/ViewHandler.cpp b/TombEngine/Scripting/Internal/TEN/View/ViewHandler.cpp
index 501784af1..8076215b2 100644
--- a/TombEngine/Scripting/Internal/TEN/View/ViewHandler.cpp
+++ b/TombEngine/Scripting/Internal/TEN/View/ViewHandler.cpp
@@ -111,18 +111,18 @@ namespace TEN::Scripting::View
InitializeSpotCam(seqID);
}
- static Vec3 GetFlybyPosition(int seqID, float progress)
+ static Vec3 GetFlybyPosition(int seqID, float progress, TypeOrNil loop)
{
constexpr auto PROGRESS_MAX = 100.0f;
- return Vec3(GetCameraTransform(seqID, progress / PROGRESS_MAX).Position);
+ return Vec3(GetCameraTransform(seqID, progress / PROGRESS_MAX, ValueOr(loop, false)).Position);
}
- static Rotation GetFlybyRotation(int seqID, float progress)
+ static Rotation GetFlybyRotation(int seqID, float progress, TypeOrNil loop)
{
constexpr auto PROGRESS_MAX = 100.0f;
- return Rotation(GetCameraTransform(seqID, progress / PROGRESS_MAX).Orientation);
+ return Rotation(GetCameraTransform(seqID, progress / PROGRESS_MAX, ValueOr(loop, false)).Orientation);
}
static void FlashScreen(TypeOrNil col, TypeOrNil speed)
@@ -244,6 +244,7 @@ namespace TEN::Scripting::View
// @function GetFlybyPosition
// @tparam int seqID Flyby sequence ID.
// @tparam float progress Progress point in percent. Clamped to [0, 100].
+ // @tparam[opt] bool loop Smooth the position near start and end points, as if the sequence is looped.
// @treturn Vec3 Position at the given progress point.
tableView.set_function(ScriptReserved_GetFlybyPosition, &GetFlybyPosition);
@@ -251,6 +252,7 @@ namespace TEN::Scripting::View
// @function GetFlybyRotation
// @tparam int seqID Flyby sequence ID.
// @tparam float progress Progress point in percent. Clamped to [0, 100].
+ // @tparam[opt] bool loop Smooth the position near start and end points, as if the sequence is looped.
// @treturn Rotation Rotation at the given progress point.
tableView.set_function(ScriptReserved_GetFlybyRotation, &GetFlybyRotation);
From d4c8b72bbe0a31bbe6dd238fedfc7fd5ecfa88a5 Mon Sep 17 00:00:00 2001
From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com>
Date: Fri, 28 Mar 2025 21:37:07 +0000
Subject: [PATCH 21/53] Test commit for Discord
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d47c249b..0a92d6d75 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.8.1](link to release) - yyyy-mm-dd
### New features
-* Added Firefly Emitter object (ID 1099) with corresponding sprite slot (ID 1379).
+* Added Firefly Emitter object (ID 1099) with corresponding sprite slots (ID 1379).
* Added live console input to perform Lua commands in realtime.
### Bug fixes
From 83f71eaf3bb471d3b7f733b211c5d99a5a1f0159 Mon Sep 17 00:00:00 2001
From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com>
Date: Fri, 28 Mar 2025 21:39:40 +0000
Subject: [PATCH 22/53] Revert "Test commit for Discord"
This reverts commit d4c8b72bbe0a31bbe6dd238fedfc7fd5ecfa88a5.
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a92d6d75..3d47c249b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
## [Version 1.8.1](link to release) - yyyy-mm-dd
### New features
-* Added Firefly Emitter object (ID 1099) with corresponding sprite slots (ID 1379).
+* Added Firefly Emitter object (ID 1099) with corresponding sprite slot (ID 1379).
* Added live console input to perform Lua commands in realtime.
### Bug fixes
From 74b7688c7b777bb742c7c21b78aa804a3b0647e2 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 28 Mar 2025 23:23:43 +0100
Subject: [PATCH 23/53] Update Settings.lua
---
Scripts/Settings.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Scripts/Settings.lua b/Scripts/Settings.lua
index 75981eaf7..989c44f8e 100644
--- a/Scripts/Settings.lua
+++ b/Scripts/Settings.lua
@@ -19,7 +19,7 @@ local settings = Flow.Settings.new()
settings.Flare.offset = Vec3(0, 0, 41)
settings.Flare.range = 9
settings.Flare.timeout = 60
- settings.Flare.lensflareBrightness = 0.5
+ settings.Flare.lensflareBrightness = 1.0
settings.Flare.sparks = true
settings.Flare.smoke = true
settings.Flare.flicker = true
@@ -35,6 +35,7 @@ local settings = Flow.Settings.new()
settings.System.errorMode = Flow.ErrorMode.WARN
settings.System.fastReload = true
+ settings.System.multithreaded = true
-- Hair[1] is normal player hair. Types [2] and [3] are for left and right young Lara hair.
From 3e2a1ccf379f6ff16352d25687424ed2e13db4a4 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 28 Mar 2025 23:39:49 +0100
Subject: [PATCH 24/53] Update 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/Collision.Probe.html | 2 +-
Documentation/doc/2 classes/Flow.Level.html | 2 +-
Documentation/doc/2 classes/Flow.Settings.html | 2 +-
Documentation/doc/2 classes/Flow.Statistics.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/Flow.Fog.html | 2 +-
Documentation/doc/3 primitive classes/Flow.Horizon.html | 2 +-
Documentation/doc/3 primitive classes/Flow.InventoryItem.html | 2 +-
Documentation/doc/3 primitive classes/Flow.LensFlare.html | 2 +-
Documentation/doc/3 primitive classes/Flow.SkyLayer.html | 2 +-
Documentation/doc/3 primitive classes/Flow.Starfield.html | 2 +-
Documentation/doc/3 primitive classes/Rotation.html | 2 +-
Documentation/doc/3 primitive classes/Time.html | 2 +-
Documentation/doc/3 primitive classes/Vec2.html | 2 +-
Documentation/doc/3 primitive classes/Vec3.html | 2 +-
Documentation/doc/4 enums/Collision.MaterialType.html | 2 +-
Documentation/doc/4 enums/Effects.BlendID.html | 2 +-
Documentation/doc/4 enums/Effects.EffectID.html | 2 +-
Documentation/doc/4 enums/Effects.ParticleAnimationType.html | 2 +-
Documentation/doc/4 enums/Effects.StreamerFeatherMode.html | 2 +-
Documentation/doc/4 enums/Flow.ErrorMode.html | 2 +-
Documentation/doc/4 enums/Flow.FreezeMode.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.HandStatus.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/Objects.WeaponType.html | 2 +-
Documentation/doc/4 enums/Sound.SoundTrackType.html | 2 +-
Documentation/doc/4 enums/Strings.DisplayStringOption.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/CustomBar.html | 2 +-
Documentation/doc/5 lua utility modules/Diary.html | 2 +-
Documentation/doc/5 lua utility modules/EventSequence.html | 2 +-
Documentation/doc/5 lua utility modules/Timer.html | 2 +-
Documentation/doc/5 lua utility modules/Type.html | 2 +-
Documentation/doc/index.html | 4 ++--
66 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/Documentation/config.ld b/Documentation/config.ld
index abc23eb0c..6a3876d25 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.8"
+local version = "1.8.1"
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 1ba87f3f0..d8d58667e 100644
--- a/Documentation/doc/1 modules/Effects.html
+++ b/Documentation/doc/1 modules/Effects.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html
index 9ca9202e8..a8ae0a9b0 100644
--- a/Documentation/doc/1 modules/Flow.html
+++ b/Documentation/doc/1 modules/Flow.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Input.html b/Documentation/doc/1 modules/Input.html
index 789bad1c6..c3439c75c 100644
--- a/Documentation/doc/1 modules/Input.html
+++ b/Documentation/doc/1 modules/Input.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Inventory.html b/Documentation/doc/1 modules/Inventory.html
index 14f4f6be5..45a377928 100644
--- a/Documentation/doc/1 modules/Inventory.html
+++ b/Documentation/doc/1 modules/Inventory.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Logic.html b/Documentation/doc/1 modules/Logic.html
index 83b919387..dff8277a1 100644
--- a/Documentation/doc/1 modules/Logic.html
+++ b/Documentation/doc/1 modules/Logic.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Objects.html b/Documentation/doc/1 modules/Objects.html
index 1e77c2f79..06d84e7c1 100644
--- a/Documentation/doc/1 modules/Objects.html
+++ b/Documentation/doc/1 modules/Objects.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Sound.html b/Documentation/doc/1 modules/Sound.html
index d7c87bb04..6f1305b02 100644
--- a/Documentation/doc/1 modules/Sound.html
+++ b/Documentation/doc/1 modules/Sound.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Strings.html b/Documentation/doc/1 modules/Strings.html
index d5aaeda4a..16b10bee4 100644
--- a/Documentation/doc/1 modules/Strings.html
+++ b/Documentation/doc/1 modules/Strings.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/Util.html b/Documentation/doc/1 modules/Util.html
index cc0443c3d..a9b7c3972 100644
--- a/Documentation/doc/1 modules/Util.html
+++ b/Documentation/doc/1 modules/Util.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/1 modules/View.html b/Documentation/doc/1 modules/View.html
index 40f491a7b..557e35756 100644
--- a/Documentation/doc/1 modules/View.html
+++ b/Documentation/doc/1 modules/View.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Collision.Probe.html b/Documentation/doc/2 classes/Collision.Probe.html
index 4ff672202..19c7f4ec2 100644
--- a/Documentation/doc/2 classes/Collision.Probe.html
+++ b/Documentation/doc/2 classes/Collision.Probe.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Flow.Level.html b/Documentation/doc/2 classes/Flow.Level.html
index 0060d532e..c7c23ab6b 100644
--- a/Documentation/doc/2 classes/Flow.Level.html
+++ b/Documentation/doc/2 classes/Flow.Level.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Flow.Settings.html b/Documentation/doc/2 classes/Flow.Settings.html
index 326b6b4ce..6003f5cdc 100644
--- a/Documentation/doc/2 classes/Flow.Settings.html
+++ b/Documentation/doc/2 classes/Flow.Settings.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Flow.Statistics.html b/Documentation/doc/2 classes/Flow.Statistics.html
index 0c3663c4b..9cc173115 100644
--- a/Documentation/doc/2 classes/Flow.Statistics.html
+++ b/Documentation/doc/2 classes/Flow.Statistics.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.AIObject.html b/Documentation/doc/2 classes/Objects.AIObject.html
index 951d0e4d3..0122971a9 100644
--- a/Documentation/doc/2 classes/Objects.AIObject.html
+++ b/Documentation/doc/2 classes/Objects.AIObject.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.Camera.html b/Documentation/doc/2 classes/Objects.Camera.html
index 4899f78e0..630d1a44f 100644
--- a/Documentation/doc/2 classes/Objects.Camera.html
+++ b/Documentation/doc/2 classes/Objects.Camera.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.LaraObject.html b/Documentation/doc/2 classes/Objects.LaraObject.html
index 2b43e2d46..41fefa5bc 100644
--- a/Documentation/doc/2 classes/Objects.LaraObject.html
+++ b/Documentation/doc/2 classes/Objects.LaraObject.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html
index e4152b181..cddc5ebb0 100644
--- a/Documentation/doc/2 classes/Objects.Moveable.html
+++ b/Documentation/doc/2 classes/Objects.Moveable.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.Room.html b/Documentation/doc/2 classes/Objects.Room.html
index 04cd67ef3..acc0de38b 100644
--- a/Documentation/doc/2 classes/Objects.Room.html
+++ b/Documentation/doc/2 classes/Objects.Room.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.Sink.html b/Documentation/doc/2 classes/Objects.Sink.html
index 322a09400..54ee6f9de 100644
--- a/Documentation/doc/2 classes/Objects.Sink.html
+++ b/Documentation/doc/2 classes/Objects.Sink.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.SoundSource.html b/Documentation/doc/2 classes/Objects.SoundSource.html
index 19e05dff7..6daf287f2 100644
--- a/Documentation/doc/2 classes/Objects.SoundSource.html
+++ b/Documentation/doc/2 classes/Objects.SoundSource.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.Static.html b/Documentation/doc/2 classes/Objects.Static.html
index cddabdcf2..faa84c20f 100644
--- a/Documentation/doc/2 classes/Objects.Static.html
+++ b/Documentation/doc/2 classes/Objects.Static.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Objects.Volume.html b/Documentation/doc/2 classes/Objects.Volume.html
index af6e4b1ed..77e6b626a 100644
--- a/Documentation/doc/2 classes/Objects.Volume.html
+++ b/Documentation/doc/2 classes/Objects.Volume.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/Strings.DisplayString.html b/Documentation/doc/2 classes/Strings.DisplayString.html
index 005c134f0..d4b209327 100644
--- a/Documentation/doc/2 classes/Strings.DisplayString.html
+++ b/Documentation/doc/2 classes/Strings.DisplayString.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/2 classes/View.DisplaySprite.html b/Documentation/doc/2 classes/View.DisplaySprite.html
index 1dbe32283..f6f4917b7 100644
--- a/Documentation/doc/2 classes/View.DisplaySprite.html
+++ b/Documentation/doc/2 classes/View.DisplaySprite.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Color.html b/Documentation/doc/3 primitive classes/Color.html
index 9ccc6e9d6..e10a2c8ec 100644
--- a/Documentation/doc/3 primitive classes/Color.html
+++ b/Documentation/doc/3 primitive classes/Color.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Flow.Fog.html b/Documentation/doc/3 primitive classes/Flow.Fog.html
index 49d245efb..dbf35a6b5 100644
--- a/Documentation/doc/3 primitive classes/Flow.Fog.html
+++ b/Documentation/doc/3 primitive classes/Flow.Fog.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Flow.Horizon.html b/Documentation/doc/3 primitive classes/Flow.Horizon.html
index c8097d43b..891539543 100644
--- a/Documentation/doc/3 primitive classes/Flow.Horizon.html
+++ b/Documentation/doc/3 primitive classes/Flow.Horizon.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Flow.InventoryItem.html b/Documentation/doc/3 primitive classes/Flow.InventoryItem.html
index 4daff8cd5..ac66af1ac 100644
--- a/Documentation/doc/3 primitive classes/Flow.InventoryItem.html
+++ b/Documentation/doc/3 primitive classes/Flow.InventoryItem.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Flow.LensFlare.html b/Documentation/doc/3 primitive classes/Flow.LensFlare.html
index 5f7538fba..493f9432b 100644
--- a/Documentation/doc/3 primitive classes/Flow.LensFlare.html
+++ b/Documentation/doc/3 primitive classes/Flow.LensFlare.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Flow.SkyLayer.html b/Documentation/doc/3 primitive classes/Flow.SkyLayer.html
index 1289afc53..dc92bbb1d 100644
--- a/Documentation/doc/3 primitive classes/Flow.SkyLayer.html
+++ b/Documentation/doc/3 primitive classes/Flow.SkyLayer.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Flow.Starfield.html b/Documentation/doc/3 primitive classes/Flow.Starfield.html
index f4aa48998..9182b0b89 100644
--- a/Documentation/doc/3 primitive classes/Flow.Starfield.html
+++ b/Documentation/doc/3 primitive classes/Flow.Starfield.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Rotation.html b/Documentation/doc/3 primitive classes/Rotation.html
index 728815250..08d1dedf6 100644
--- a/Documentation/doc/3 primitive classes/Rotation.html
+++ b/Documentation/doc/3 primitive classes/Rotation.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Time.html b/Documentation/doc/3 primitive classes/Time.html
index c1b159661..1edf989a5 100644
--- a/Documentation/doc/3 primitive classes/Time.html
+++ b/Documentation/doc/3 primitive classes/Time.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Vec2.html b/Documentation/doc/3 primitive classes/Vec2.html
index 825d7fa48..eb65b2271 100644
--- a/Documentation/doc/3 primitive classes/Vec2.html
+++ b/Documentation/doc/3 primitive classes/Vec2.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/3 primitive classes/Vec3.html b/Documentation/doc/3 primitive classes/Vec3.html
index 696df8778..5ff74ce81 100644
--- a/Documentation/doc/3 primitive classes/Vec3.html
+++ b/Documentation/doc/3 primitive classes/Vec3.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Collision.MaterialType.html b/Documentation/doc/4 enums/Collision.MaterialType.html
index 69c90fa69..564b8ca1f 100644
--- a/Documentation/doc/4 enums/Collision.MaterialType.html
+++ b/Documentation/doc/4 enums/Collision.MaterialType.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Effects.BlendID.html b/Documentation/doc/4 enums/Effects.BlendID.html
index 738be8a6b..bd2f1aca9 100644
--- a/Documentation/doc/4 enums/Effects.BlendID.html
+++ b/Documentation/doc/4 enums/Effects.BlendID.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Effects.EffectID.html b/Documentation/doc/4 enums/Effects.EffectID.html
index 9b33780a8..32b783f43 100644
--- a/Documentation/doc/4 enums/Effects.EffectID.html
+++ b/Documentation/doc/4 enums/Effects.EffectID.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Effects.ParticleAnimationType.html b/Documentation/doc/4 enums/Effects.ParticleAnimationType.html
index 82bc18a38..f1351b9af 100644
--- a/Documentation/doc/4 enums/Effects.ParticleAnimationType.html
+++ b/Documentation/doc/4 enums/Effects.ParticleAnimationType.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Effects.StreamerFeatherMode.html b/Documentation/doc/4 enums/Effects.StreamerFeatherMode.html
index 7415e2354..47692e9c5 100644
--- a/Documentation/doc/4 enums/Effects.StreamerFeatherMode.html
+++ b/Documentation/doc/4 enums/Effects.StreamerFeatherMode.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Flow.ErrorMode.html b/Documentation/doc/4 enums/Flow.ErrorMode.html
index 5bab3199b..4bf7d6fab 100644
--- a/Documentation/doc/4 enums/Flow.ErrorMode.html
+++ b/Documentation/doc/4 enums/Flow.ErrorMode.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Flow.FreezeMode.html b/Documentation/doc/4 enums/Flow.FreezeMode.html
index d3144922d..d01a30a1a 100644
--- a/Documentation/doc/4 enums/Flow.FreezeMode.html
+++ b/Documentation/doc/4 enums/Flow.FreezeMode.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Flow.GameStatus.html b/Documentation/doc/4 enums/Flow.GameStatus.html
index b3ec60f29..0e9262274 100644
--- a/Documentation/doc/4 enums/Flow.GameStatus.html
+++ b/Documentation/doc/4 enums/Flow.GameStatus.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Input.ActionID.html b/Documentation/doc/4 enums/Input.ActionID.html
index 0d3e1c9ba..b0c16ee50 100644
--- a/Documentation/doc/4 enums/Input.ActionID.html
+++ b/Documentation/doc/4 enums/Input.ActionID.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.AmmoType.html b/Documentation/doc/4 enums/Objects.AmmoType.html
index 812f506e8..cf02b25c1 100644
--- a/Documentation/doc/4 enums/Objects.AmmoType.html
+++ b/Documentation/doc/4 enums/Objects.AmmoType.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.HandStatus.html b/Documentation/doc/4 enums/Objects.HandStatus.html
index 06cc70974..5e6f31be9 100644
--- a/Documentation/doc/4 enums/Objects.HandStatus.html
+++ b/Documentation/doc/4 enums/Objects.HandStatus.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.MoveableStatus.html b/Documentation/doc/4 enums/Objects.MoveableStatus.html
index 9ce6251e0..21ceb56ef 100644
--- a/Documentation/doc/4 enums/Objects.MoveableStatus.html
+++ b/Documentation/doc/4 enums/Objects.MoveableStatus.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.ObjID.html b/Documentation/doc/4 enums/Objects.ObjID.html
index b10a91473..87fb56147 100644
--- a/Documentation/doc/4 enums/Objects.ObjID.html
+++ b/Documentation/doc/4 enums/Objects.ObjID.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.RoomFlagID.html b/Documentation/doc/4 enums/Objects.RoomFlagID.html
index 517ed6b71..3edc7b5ce 100644
--- a/Documentation/doc/4 enums/Objects.RoomFlagID.html
+++ b/Documentation/doc/4 enums/Objects.RoomFlagID.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.RoomReverb.html b/Documentation/doc/4 enums/Objects.RoomReverb.html
index e8282b8dc..420e1731c 100644
--- a/Documentation/doc/4 enums/Objects.RoomReverb.html
+++ b/Documentation/doc/4 enums/Objects.RoomReverb.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Objects.WeaponType.html b/Documentation/doc/4 enums/Objects.WeaponType.html
index 219c79085..c45efc459 100644
--- a/Documentation/doc/4 enums/Objects.WeaponType.html
+++ b/Documentation/doc/4 enums/Objects.WeaponType.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Sound.SoundTrackType.html b/Documentation/doc/4 enums/Sound.SoundTrackType.html
index 359b78984..ad9eb5e39 100644
--- a/Documentation/doc/4 enums/Sound.SoundTrackType.html
+++ b/Documentation/doc/4 enums/Sound.SoundTrackType.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Strings.DisplayStringOption.html b/Documentation/doc/4 enums/Strings.DisplayStringOption.html
index d561e2684..e43f3200b 100644
--- a/Documentation/doc/4 enums/Strings.DisplayStringOption.html
+++ b/Documentation/doc/4 enums/Strings.DisplayStringOption.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/Util.LogLevel.html b/Documentation/doc/4 enums/Util.LogLevel.html
index d00c53ea6..3e463cf45 100644
--- a/Documentation/doc/4 enums/Util.LogLevel.html
+++ b/Documentation/doc/4 enums/Util.LogLevel.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/View.AlignMode.html b/Documentation/doc/4 enums/View.AlignMode.html
index 1f95d4bf0..479a64e04 100644
--- a/Documentation/doc/4 enums/View.AlignMode.html
+++ b/Documentation/doc/4 enums/View.AlignMode.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/View.CameraType.html b/Documentation/doc/4 enums/View.CameraType.html
index 255946261..8059b3c65 100644
--- a/Documentation/doc/4 enums/View.CameraType.html
+++ b/Documentation/doc/4 enums/View.CameraType.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/View.PostProcessMode.html b/Documentation/doc/4 enums/View.PostProcessMode.html
index 825aa6742..03b0419d6 100644
--- a/Documentation/doc/4 enums/View.PostProcessMode.html
+++ b/Documentation/doc/4 enums/View.PostProcessMode.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/4 enums/View.ScaleMode.html b/Documentation/doc/4 enums/View.ScaleMode.html
index 868e2f41e..d00970ef0 100644
--- a/Documentation/doc/4 enums/View.ScaleMode.html
+++ b/Documentation/doc/4 enums/View.ScaleMode.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/5 lua utility modules/CustomBar.html b/Documentation/doc/5 lua utility modules/CustomBar.html
index 940e0b6bd..2940474c8 100644
--- a/Documentation/doc/5 lua utility modules/CustomBar.html
+++ b/Documentation/doc/5 lua utility modules/CustomBar.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/5 lua utility modules/Diary.html b/Documentation/doc/5 lua utility modules/Diary.html
index 27e48878c..58d81a722 100644
--- a/Documentation/doc/5 lua utility modules/Diary.html
+++ b/Documentation/doc/5 lua utility modules/Diary.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/5 lua utility modules/EventSequence.html b/Documentation/doc/5 lua utility modules/EventSequence.html
index 9f68608b1..cea188d4f 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.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/5 lua utility modules/Timer.html b/Documentation/doc/5 lua utility modules/Timer.html
index fead185e8..5cff92477 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.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/5 lua utility modules/Type.html b/Documentation/doc/5 lua utility modules/Type.html
index 290e73067..dad15e9ec 100644
--- a/Documentation/doc/5 lua utility modules/Type.html
+++ b/Documentation/doc/5 lua utility modules/Type.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
diff --git a/Documentation/doc/index.html b/Documentation/doc/index.html
index e934b8f98..780a8b9e5 100644
--- a/Documentation/doc/index.html
+++ b/Documentation/doc/index.html
@@ -3,7 +3,7 @@
- TombEngine 1.8 Lua API
+ TombEngine 1.8.1 Lua API
@@ -115,7 +115,7 @@
-
TombEngine 1.8 scripting interface
+
TombEngine 1.8.1 scripting interface
Welcome to the TombEngine scripting API.
Note that this is primarily a reference document, not a tutorial, so expect descriptions to be fairly sparse.
From 410250bf2d900810e520c8091ccbe0a1ee92e933 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 29 Mar 2025 09:55:09 +0100
Subject: [PATCH 25/53] Update CHANGELOG.md
---
CHANGELOG.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d47c249b..6c8243091 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed crash with incorrectly applied animated textures on static meshes.
* Fixed console window not hiding in non-debug mode on Windows 11.
* Fixed key binding settings saving for the current play session after hitting Esc to cancel.
+* Fixed lensflare blending formula to avoid screen overbright.
### Lua API changes
* Added missing constructor for `Collision.Probe` without room number.
From 5c83574a0e1d253cab1bee8a071e0ef07c6f2164 Mon Sep 17 00:00:00 2001
From: Stranger1992 <84292688+Stranger1992@users.noreply.github.com>
Date: Sat, 29 Mar 2025 14:16:09 +0000
Subject: [PATCH 26/53] Updated changelog for release version
Bug Fixes moved to top (as per other version entries)
---
CHANGELOG.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6c8243091..a1be08042 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,11 +3,7 @@
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.8.1](link to release) - yyyy-mm-dd
-
-### New features
-* Added Firefly Emitter object (ID 1099) with corresponding sprite slot (ID 1379).
-* Added live console input to perform Lua commands in realtime.
+## [Version 1.8.1](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8.1) - 2025-03-29
### Bug fixes
* Fixed pathfinding for friendly NPCs such as monkeys.
@@ -19,6 +15,10 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed key binding settings saving for the current play session after hitting Esc to cancel.
* Fixed lensflare blending formula to avoid screen overbright.
+### New features
+* Added Firefly Emitter object (ID 1099) with corresponding sprite slot (ID 1379).
+* Added live console input to perform Lua commands in realtime.
+
### Lua API changes
* Added missing constructor for `Collision.Probe` without room number.
* Added optional looping argument for `View.GetFlybyPosition` and `View.GetFlybyRotation` functions.
From ed596ba07be092529ba5077d120e71fa5ddb7f32 Mon Sep 17 00:00:00 2001
From: Sezz
Date: Sun, 30 Mar 2025 14:26:36 +1100
Subject: [PATCH 27/53] Update spotcam.cpp
---
TombEngine/Game/spotcam.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp
index 2b6ea8d10..3225d38d9 100644
--- a/TombEngine/Game/spotcam.cpp
+++ b/TombEngine/Game/spotcam.cpp
@@ -841,6 +841,10 @@ int Spline(int x, int* knots, int nk)
Pose GetCameraTransform(int sequence, float alpha, bool loop)
{
+ constexpr auto BLEND_RANGE = 0.1f;
+ constexpr auto BLEND_START = BLEND_RANGE;
+ constexpr auto BLEND_END = 1.0f - BLEND_RANGE;
+
alpha = std::clamp(alpha, 0.0f, 1.0f);
// Retrieve camera count in sequence.
@@ -887,18 +891,14 @@ Pose GetCameraTransform(int sequence, float alpha, bool loop)
return Spline(tAlpha, rolls.data(), splinePoints);
};
- Vector3 origin = {};
- Vector3 target = {};
+ auto origin = Vector3::Zero;
+ auto target = Vector3::Zero;
short orientZ = 0;
- constexpr float BLEND_RANGE = 0.1f;
- constexpr float BLEND_START = BLEND_RANGE;
- constexpr float BLEND_END = 1.0f - BLEND_RANGE;
-
- // If loop is enabled and we are at the start or end of the sequence, blend between the last and first cameras.
+ // If loop is enabled and alpha is at sequence start or end, blend between last and first cameras.
if (loop && (alpha < BLEND_START || alpha >= BLEND_END))
{
- float blendFactor = (alpha < BLEND_START) ? 0.5f + (alpha / BLEND_RANGE) * 0.5f : (alpha - BLEND_END) / BLEND_START * 0.5f;
+ float blendFactor = (alpha < BLEND_START) ? (0.5f + ((alpha / BLEND_RANGE) * 0.5f)) : (((alpha - BLEND_END) / BLEND_START) * 0.5f);
origin = Vector3::Lerp(getInterpolatedPoint(BLEND_END, xOrigins, yOrigins, zOrigins), getInterpolatedPoint(BLEND_START, xOrigins, yOrigins, zOrigins), blendFactor);
target = Vector3::Lerp(getInterpolatedPoint(BLEND_END, xTargets, yTargets, zTargets), getInterpolatedPoint(BLEND_START, xTargets, yTargets, zTargets), blendFactor);
From 8bc15b32006b868571dc5610bfbecb6be77d996b Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sun, 30 Mar 2025 11:29:17 +0200
Subject: [PATCH 28/53] Update spotcam.cpp
---
TombEngine/Game/spotcam.cpp | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/TombEngine/Game/spotcam.cpp b/TombEngine/Game/spotcam.cpp
index 3225d38d9..e58df71d2 100644
--- a/TombEngine/Game/spotcam.cpp
+++ b/TombEngine/Game/spotcam.cpp
@@ -847,10 +847,19 @@ Pose GetCameraTransform(int sequence, float alpha, bool loop)
alpha = std::clamp(alpha, 0.0f, 1.0f);
+ if (sequence < 0 || sequence >= MAX_SPOTCAMS)
+ {
+ TENLog("Wrong flyby sequence number provided for getting camera coordinates.", LogLevel::Warning);
+ return Pose::Zero;
+ }
+
// Retrieve camera count in sequence.
int cameraCount = CameraCnt[SpotCamRemap[sequence]];
if (cameraCount < 2)
- return Pose::Zero; // Not enough cameras to interpolate.
+ {
+ TENLog("Not enough cameras in flyby sequence to calculate the coordinates.", LogLevel::Warning);
+ return Pose::Zero;
+ }
// Find first ID for sequence.
int firstSeqID = 0;
From 7c8b67d2bb10db9c42b418a5da2dde0f00d8e83d Mon Sep 17 00:00:00 2001
From: Jakub <80340234+Jakub768@users.noreply.github.com>
Date: Sun, 30 Mar 2025 23:56:01 +0100
Subject: [PATCH 29/53] Update AUTHORS.md
---
AUTHORS.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/AUTHORS.md b/AUTHORS.md
index 096d4944c..7bff5eeb4 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -49,5 +49,4 @@ This is the credit list of **all** the people who contributed to TombEngine in a
- JoeyQuint (Standing 180° turn, monkey swing 180° turn)
### TombEngine Marketing
-- Kubsy (Twitter and forum posts)
-- Stranger1992 (This website, Facebook, Instagram, Youtube and Twitch.
+- Stranger1992 (This website, Facebook, Instagram, Youtube, Twitter, and Twitch.
From 5a71239d7b9a9247b95e81bb1b399a5623a46a99 Mon Sep 17 00:00:00 2001
From: MontyTRC89
Date: Tue, 1 Apr 2025 10:01:57 +0200
Subject: [PATCH 30/53] SSAO fixes for alpha blended surfaces and possibly
performance improvements;
---
TombEngine/Renderer/RendererDraw.cpp | 8 ++++++--
TombEngine/Shaders/CBCamera.hlsli | 4 ++--
TombEngine/Shaders/SSAO.fx | 14 ++++++++------
3 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 1c63b24d8..391f07fc6 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -3229,13 +3229,17 @@ namespace TEN::Renderer
case RendererPass::GBuffer:
if (blendMode != BlendMode::Opaque &&
blendMode != BlendMode::AlphaTest &&
- blendMode != BlendMode::FastAlphaBlend)
+ blendMode != BlendMode::FastAlphaBlend &&
+ // WARNING: For G-Buffer step we consider alpha blend like alpha test
+ // assuming that most of the geometry used in rooms, items and statics
+ // are fences, foliages, trees... But it could fail with translucent surfaces!
+ blendMode != BlendMode::AlphaBlend)
{
return false;
}
if (blendMode == BlendMode::Opaque)
- {
+ {
SetBlendMode(BlendMode::Opaque);
SetAlphaTest(AlphaTestMode::None, 1.0f);
}
diff --git a/TombEngine/Shaders/CBCamera.hlsli b/TombEngine/Shaders/CBCamera.hlsli
index 34a7709c0..457b89526 100644
--- a/TombEngine/Shaders/CBCamera.hlsli
+++ b/TombEngine/Shaders/CBCamera.hlsli
@@ -7,8 +7,8 @@ cbuffer CBCamera : register(b0)
{
float4x4 ViewProjection;
float4x4 View;
- float4x4 Projection;
- float4x4 InverseProjection;
+ float4x4 Projection;
+ float4x4 InverseProjection;
float4x4 DualParaboloidView;
float4 CamPositionWS;
float4 CamDirectionWS;
diff --git a/TombEngine/Shaders/SSAO.fx b/TombEngine/Shaders/SSAO.fx
index b5a9c5dba..844419b7e 100644
--- a/TombEngine/Shaders/SSAO.fx
+++ b/TombEngine/Shaders/SSAO.fx
@@ -50,11 +50,12 @@ float PS(PixelShaderInput input) : SV_Target
float3 position = ReconstructPositionFromDepth(input.UV);
float3 encodedNormal = NormalsTexture.Sample(NormalsSampler, input.UV).xyz;
- // Let's avoid SSAO on the skybox and on surfaces with no normals
- if (length(encodedNormal) <= 0.0001f)
- {
- return float4(1.0f, 1.0f, 1.0f, 1.0f);
- }
+ float farMask = step(40960.0f, length(position)); // 1 if too far
+ float noNormalMask = step(length(encodedNormal), 0.0001f); // 1 if normal is too small
+ float earlyExit = saturate(farMask + noNormalMask); // 0 if both are fine
+
+ if (earlyExit > 0.0f)
+ return float4(1.0f, 1.0f, 1.0f, 1.0f);
float3 normal = DecodeNormal(encodedNormal);
float3 randomVec = NoiseTexture.Sample(NoiseSampler, input.UV * noiseScale).xyz;
@@ -82,7 +83,8 @@ float PS(PixelShaderInput input) : SV_Target
float sampleDepth = ReconstructPositionFromDepth(offset.xy).z;
float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth));
- occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck;
+ occlusion += lerp(0.0f, rangeCheck, step(0.0, sampleDepth - samplePos.z - bias));
+ //occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck;
}
occlusion = 1.0 - (occlusion / kernelSize);
From 2fb0a609a3e2aa46d4540df4598550099ceef6d5 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 2 Apr 2025 05:01:51 +0200
Subject: [PATCH 31/53] Remove duplicate log entry
---
TombEngine/Renderer/RendererCompatibility.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp
index 7ae2ef7d5..ef561320b 100644
--- a/TombEngine/Renderer/RendererCompatibility.cpp
+++ b/TombEngine/Renderer/RendererCompatibility.cpp
@@ -68,9 +68,6 @@ namespace TEN::Renderer
_animatedTextures[i] = tex;
}
- if (_animatedTextures.size() > 0)
- TENLog("Generated " + std::to_string(_animatedTextures.size()) + " animated textures.", LogLevel::Info);
-
std::transform(g_Level.AnimatedTexturesSequences.begin(), g_Level.AnimatedTexturesSequences.end(), std::back_inserter(_animatedTextureSets), [](ANIMATED_TEXTURES_SEQUENCE& sequence) {
RendererAnimatedTextureSet set{};
set.NumTextures = sequence.numFrames;
From 4e523957a5940339b034af520384089eb695eb88 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 2 Apr 2025 05:42:18 +0200
Subject: [PATCH 32/53] Fixed #1603 and gunshell/flash renderer crashes
---
CHANGELOG.md | 6 +
.../Objects/TR5/Object/tr5_teleporter.cpp | 170 +-----------------
.../Objects/TR5/Object/tr5_teleporter.h | 1 -
TombEngine/Objects/TR5/tr5_objects.cpp | 1 -
TombEngine/Renderer/RendererDraw.cpp | 3 +
TombEngine/Renderer/RendererDrawEffect.cpp | 45 ++---
6 files changed, 42 insertions(+), 184 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1be08042..a74dc0ee6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@
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.8.2]
+
+### Bug fixes
+* Fixed crashes when shooting, if gunflash or gunshell objects are not present in a level.
+* Fixed Teleporter object.
+
## [Version 1.8.1](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8.1) - 2025-03-29
### Bug fixes
diff --git a/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp b/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
index 6ebb9961a..a3166f832 100644
--- a/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
+++ b/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
@@ -7,22 +7,11 @@
#include "Game/effects/weather.h"
#include "Game/Lara/lara.h"
#include "Game/camera.h"
+#include "Game/collision/Point.h"
+using namespace TEN::Collision::Point;
using namespace TEN::Effects::Environment;
-void InitializeTeleporter(short itemNumber)
-{
- /*ItemInfo* item = &g_Level.Items[itemNumber];
-
- if (item->triggerFlags == 512)
- {
- ItemInfo* puzzleHoleItem = FindItem(ID_PUZZLE_HOLE2);
- v4 = (signed int)((unsigned __int64)(391146079i64 * ((char*)v3 - (char*)items)) >> 32) >> 9;
- result = (unsigned int)((unsigned __int64)(391146079i64 * ((char*)v3 - (char*)items)) >> 32) >> 31;
- item->itemFlags[1] = result + v4;
- }*/
-}
-
void ControlTeleporter(short itemNumber)
{
ItemInfo* item = &g_Level.Items[itemNumber];
@@ -30,149 +19,6 @@ void ControlTeleporter(short itemNumber)
if (!TriggerActive(item))
return;
- /*if (item->triggerFlags == 512)
- {
- if (item->itemFlags[2])
- {
- Lara.Puzzles[1] = 1;
- RemoveActiveItem(itemNumber);
- item->flags &= 0xC1FF;
- }
- else
- {
- item->itemFlags[0] += 2;
-
- if (item->itemFlags[0] <= 255)
- {
- int flags = item->itemFlags[0] >> 3;
- if (flags >= 4)
- {
- if (flags > 31)
- flags = 31;
- }
- else
- {
- flags = 4;
- }
-
- ItemInfo* targetItem = &g_Level.Items[item->itemFlags[1]];
- SoundEffect(SFX_TR5_TELEPORT, &targetItem->pos, SoundEnvironment::Land);
-
- if (GlobalCounter & 1)
- {
- Vector3i src;
- pos.x = targetItem->pos.Position.x;
- pos.y = targetItem->pos.Position.y - 496;
- pos.z = targetItem->pos.Position.z + 472;
-
- int dl = 4 * item->itemFlags[0] + 256;
-
- Vector3i dest;
- dest.x = src.x + GetRandomControl() % dl - (dl >> 1);
- dest.y = src.y + GetRandomControl() % dl - (dl >> 1);
- dest.z = src.z + GetRandomControl() % dl - (dl >> 1);
-
- int color = (item->itemFlags[0] >> 2) | (((item->itemFlags[0] - (GetRandomControl() % (item->itemFlags[0] >> 1))) | (item->itemFlags[0] << 8)) << 8);
- color |= 0x18; // BYTE1
-
- //TriggerEnergyArc(&src, &dest, (GetRandomControl() & 0x1F) + 16, color, 15, 40, 5);
-
- v20 = v16;
- v21 = v12 & 0xFFFFFFFE;
- LOBYTE(v20) = v16 & 0xFE;
- BYTE1(v21) |= 0x80u;
- TriggerLightningGlow(src.x, src.y, src.z, (item->itemFlags[0] >> 3) | ((v20 | (v21 << 8)) << 7));
- v22 = GetRandomControl();
- SpawnDynamicLight(src.x, src.y, src.z, (v22 & 3) + (item->itemFlags[0] >> 5) + 8, v12, v16, v13);
- }
- LOBYTE(v3) = GetRandomControl();
- if (v3 & 1)
- {
- v23 = item->itemFlags[0];
- v24 = item->itemFlags[0];
- v25 = GetRandomControl();
-
- auto R = v23;
- auto G = v24 - v25 % (v24 >> 1);
- auto B = v24 >> 2;
- Weather.Flash(R, G, B, 0.03f);
-
- LOBYTE(v3) = SoundEffect(SFX_TR5_TELEPORT_CRACKLES, nullptr);
- }
- if (!(GlobalCounter & 3))
- {
- v26 = GetRandomControl();
- v27 = 0;
- v28 = v26 & 3;
- v29 = 0;
- if (v28)
- {
- if (v28 == 1)
- v29 = 512;
- else
- v27 = v28 != 2 ? 512 : -512;
- }
- else
- {
- v29 = -512;
- }
- v30 = item->itemFlags[0];
- v31 = &g_Level.Items[item->itemFlags[1]];
- src.Position.x = v29 + v31->pos.Position.x;
- src.Position.y = v31->pos.Position.y - 2328;
- src.zPos = v27 + v31->pos.Position.z;
- *(_DWORD*)& src.xRot = v31->pos.Position.x;
- v32 = item->itemFlags[0];
- *(_DWORD*)& src.zRot = v31->pos.Position.y - 496;
- v45 = v31->pos.Position.z + 472;
- v33 = (v30 >> 2) | (((v30 - GetRandomControl() % (v30 >> 1)) | ((v32 | 0x2400) << 8)) << 8);
- v34 = GetRandomControl();
- TriggerEnergyArc((Vector3i*)& src, (Vector3i*)& src.xRot, (v34 & 0xF) + 16, v33, 13, 56, 5);
- v35* = GetFreeParticle();
- v35->On = 1;
- v36 = item->itemFlags[0];
- v35->dR = v36;
- v35->sR = v36;
- v37 = item->itemFlags[0] >> 1;
- v35->dG = v37;
- v35->sG = v37;
- v38 = item->itemFlags[0];
- v35->ColFadeSpeed = 20;
- v38 >>= 2;
- v35->dB = v38;
- v35->sB = v38;
- v35->FadeToBlack = 4;
- v35->Life = 24;
- v35->sLife = 24;
- v35->blendMode = BlendMode::Additive;
- v35->x = src.Position.x;
- v35->y = src.Position.y;
- v35->z = src.zPos;
- v35->Zvel = 0;
- v35->Yvel = 0;
- v35->Xvel = 0;
- v35->Flags = 10;
- v39 = objects[458].mesh_index;
- v35->Scalar = 3;
- v35->MaxYvel = 0;
- v35->Def = v39 + 11;
- v35->Gravity = 0;
- v3 = (GetRandomControl() & 3) + 24;
- v35->dSize = v3;
- v35->sSize = v3;
- v35->Size = v3;
- }
- return v3;
- }
- FlashFadeR = 255;
- FlashFadeG = 255;
- FlashFadeB = 64;
- FlashFader = 32;
- item->itemFlags[2] = 1;
- SoundEffect(SFX_TR5_TELEPORT_FLASH, nullptr, SoundEnvironment::Land);
- }
- }*/
-
Lara.Control.IsLocked = false;
if (item->TriggerFlags == 666)
@@ -196,12 +42,14 @@ void ControlTeleporter(short itemNumber)
LaraItem->Pose.Position.z = item->Pose.Position.z;
LaraItem->Pose.Orientation.y = item->Pose.Orientation.y - ANGLE(180.0f);
- short roomNumber = item->RoomNumber;
- FloorInfo* floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber);
- LaraItem->Pose.Position.y = GetFloorHeight(floor, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z);
+ auto& pointColl = GetPointCollision(*item);
+ LaraItem->Pose.Position.y = pointColl.GetPosition().y;
- if (LaraItem->RoomNumber != roomNumber)
- ItemNewRoom(LaraItem->Index, roomNumber);
+ if (LaraItem->RoomNumber != pointColl.GetRoomNumber())
+ {
+ ItemNewRoom(LaraItem->Index, pointColl.GetRoomNumber());
+ LaraItem->Location.RoomNumber = pointColl.GetRoomNumber();
+ }
if (item->Flags & IFLAG_INVISIBLE)
{
diff --git a/TombEngine/Objects/TR5/Object/tr5_teleporter.h b/TombEngine/Objects/TR5/Object/tr5_teleporter.h
index 547ddcaba..dde7fc827 100644
--- a/TombEngine/Objects/TR5/Object/tr5_teleporter.h
+++ b/TombEngine/Objects/TR5/Object/tr5_teleporter.h
@@ -1,4 +1,3 @@
#pragma once
-void InitializeTeleporter(short itemNumber);
void ControlTeleporter(short itemNumber);
diff --git a/TombEngine/Objects/TR5/tr5_objects.cpp b/TombEngine/Objects/TR5/tr5_objects.cpp
index 130d7405f..76c70133f 100644
--- a/TombEngine/Objects/TR5/tr5_objects.cpp
+++ b/TombEngine/Objects/TR5/tr5_objects.cpp
@@ -774,7 +774,6 @@ static void StartObject(ObjectInfo *obj)
obj = &Objects[ID_TELEPORTER];
if (obj->loaded)
{
- obj->Initialize = InitializeTeleporter;
obj->control = ControlTeleporter;
obj->drawRoutine = nullptr;
}
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 391f07fc6..e22c9357c 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -263,6 +263,9 @@ namespace TEN::Renderer
objectID = gunshell->objectNumber;
+ if (!_moveableObjects[objectID].has_value())
+ continue;
+
auto translation = Matrix::CreateTranslation(gunshell->pos.Position.ToVector3());
auto rotMatrix = gunshell->pos.Orientation.ToRotationMatrix();
auto worldMatrix = rotMatrix * translation;
diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp
index e647f86b1..cb903c2f6 100644
--- a/TombEngine/Renderer/RendererDrawEffect.cpp
+++ b/TombEngine/Renderer/RendererDrawEffect.cpp
@@ -1085,31 +1085,10 @@ namespace TEN::Renderer
if (!settings.MuzzleFlash)
return false;
- _shaders.Bind(Shader::Statics);
-
- 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->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0);
-
- const auto& room = _rooms[LaraItem->RoomNumber];
- auto* itemPtr = &_items[LaraItem->Index];
-
- // Divide gunflash tint by 2 because tinting uses multiplication and additive color which doesn't look good with overbright color values.
- _stStatic.Color = settings.ColorizeMuzzleFlash ? ((Vector4)settings.FlashColor / 2) : Vector4::One;
- _stStatic.AmbientLight = room.AmbientLight;
- _stStatic.LightMode = (int)LightMode::Static;
- BindStaticLights(itemPtr->LightsToDraw);
-
short length = 0;
short zOffset = 0;
short rotationX = 0;
- SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD);
- SetBlendMode(BlendMode::Additive);
-
if (Lara.Control.Weapon.GunType != LaraWeaponType::Flare &&
Lara.Control.Weapon.GunType != LaraWeaponType::Crossbow)
{
@@ -1151,9 +1130,33 @@ namespace TEN::Renderer
zOffset += 10;
}
+ if (!_moveableObjects[gunflash].has_value())
+ return false;
+
const auto& flashMoveable = *_moveableObjects[gunflash];
const auto& flashMesh = *flashMoveable.ObjectMeshes[0];
+ _shaders.Bind(Shader::Statics);
+
+ 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->IASetIndexBuffer(_moveablesIndexBuffer.Buffer.Get(), DXGI_FORMAT_R32_UINT, 0);
+
+ const auto& room = _rooms[LaraItem->RoomNumber];
+ auto* itemPtr = &_items[LaraItem->Index];
+
+ // Divide gunflash tint by 2 because tinting uses multiplication and additive color which doesn't look good with overbright color values.
+ _stStatic.Color = settings.ColorizeMuzzleFlash ? ((Vector4)settings.FlashColor / 2) : Vector4::One;
+ _stStatic.AmbientLight = room.AmbientLight;
+ _stStatic.LightMode = (int)LightMode::Static;
+ BindStaticLights(itemPtr->LightsToDraw);
+
+ SetAlphaTest(AlphaTestMode::GreatherThan, ALPHA_TEST_THRESHOLD);
+ SetBlendMode(BlendMode::Additive);
+
for (const auto& flashBucket : flashMesh.Buckets)
{
if (flashBucket.BlendMode == BlendMode::Opaque)
From 144a93dfe8ee9c290dc146405175faa4ecda0566 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 2 Apr 2025 06:02:03 +0200
Subject: [PATCH 33/53] Fixed #1616
---
CHANGELOG.md | 1 +
TombEngine/Objects/TR4/Entity/Wraith.cpp | 12 ++++++------
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a74dc0ee6..234608089 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Bug fixes
* Fixed crashes when shooting, if gunflash or gunshell objects are not present in a level.
* Fixed Teleporter object.
+* Fixed Wraith objects not working correctly in flipped rooms.
## [Version 1.8.1](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8.1) - 2025-03-29
diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp
index 90860c590..e84ada397 100644
--- a/TombEngine/Objects/TR4/Entity/Wraith.cpp
+++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp
@@ -308,6 +308,11 @@ namespace TEN::Entities::TR4
item.Pose.Orientation.x += angleV;
}
+ // Translate wraith.
+ item.Pose.Position.x += item.Animation.Velocity.z * phd_sin(item.Pose.Orientation.y);
+ 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);
+
auto pointColl = GetPointCollision(item);
bool hasHitWall = false;
@@ -317,13 +322,8 @@ namespace TEN::Entities::TR4
hasHitWall = true;
}
- // Translate wraith.
- item.Pose.Position.x += item.Animation.Velocity.z * phd_sin(item.Pose.Orientation.y);
- 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.GetRoomNumber() != item.RoomNumber)
- ItemNewRoom(itemNumber, pointColl.GetRoomNumber());
+ ItemNewRoom(itemNumber, FindRoomNumber(item.Pose.Position, item.RoomNumber));
for (int linkItemNumber = g_Level.Rooms[item.RoomNumber].itemNumber; linkItemNumber != NO_VALUE; linkItemNumber = g_Level.Items[linkItemNumber].NextItem)
{
From 3a7d375dd99f023727fda5f2d10f91eee543e7ee Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 2 Apr 2025 06:12:06 +0200
Subject: [PATCH 34/53] Update tr5_teleporter.cpp
---
TombEngine/Objects/TR5/Object/tr5_teleporter.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp b/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
index a3166f832..0620d6397 100644
--- a/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
+++ b/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
@@ -38,6 +38,7 @@ void ControlTeleporter(short itemNumber)
else
{
Camera.fixedCamera = true;
+ LaraItem->DisableInterpolation = true;
LaraItem->Pose.Position.x = item->Pose.Position.x;
LaraItem->Pose.Position.z = item->Pose.Position.z;
LaraItem->Pose.Orientation.y = item->Pose.Orientation.y - ANGLE(180.0f);
From 5b9836dea06533d129373d7399b7ea620476e121 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 2 Apr 2025 06:15:57 +0200
Subject: [PATCH 35/53] Update tr5_teleporter.cpp
---
TombEngine/Objects/TR5/Object/tr5_teleporter.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp b/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
index 0620d6397..a71934996 100644
--- a/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
+++ b/TombEngine/Objects/TR5/Object/tr5_teleporter.cpp
@@ -1,13 +1,14 @@
#include "framework.h"
-#include "tr5_teleporter.h"
-#include "Game/items.h"
-#include "Specific/level.h"
-#include "Game/collision/collide_room.h"
-#include "Sound/sound.h"
-#include "Game/effects/weather.h"
-#include "Game/Lara/lara.h"
+#include "Objects/TR5/Object/tr5_teleporter.h"
+
#include "Game/camera.h"
+#include "Game/collision/collide_room.h"
#include "Game/collision/Point.h"
+#include "Game/effects/weather.h"
+#include "Game/items.h"
+#include "Game/Lara/lara.h"
+#include "Sound/sound.h"
+#include "Specific/level.h"
using namespace TEN::Collision::Point;
using namespace TEN::Effects::Environment;
From fc4cef38dfb006ec2749e44c220fc6a83402c3d8 Mon Sep 17 00:00:00 2001
From: MontyTRC89
Date: Thu, 3 Apr 2025 09:38:20 +0200
Subject: [PATCH 36/53] Fixed caustics when DDS compression is used
---
.../Renderer/ConstantBuffers/RoomBuffer.h | 2 +-
TombEngine/Renderer/Graphics/Texture2D.h | 42 -------------------
TombEngine/Renderer/Renderer.h | 2 +-
TombEngine/Renderer/RendererCompatibility.cpp | 19 ---------
TombEngine/Renderer/RendererDraw.cpp | 13 ++++--
TombEngine/Shaders/Rooms.fx | 42 ++++++++++---------
6 files changed, 35 insertions(+), 85 deletions(-)
diff --git a/TombEngine/Renderer/ConstantBuffers/RoomBuffer.h b/TombEngine/Renderer/ConstantBuffers/RoomBuffer.h
index d78a77965..c73f4f9ca 100644
--- a/TombEngine/Renderer/ConstantBuffers/RoomBuffer.h
+++ b/TombEngine/Renderer/ConstantBuffers/RoomBuffer.h
@@ -15,7 +15,7 @@ namespace TEN::Renderer::ConstantBuffers
int Padding;
//--
Vector2 CausticsStartUV;
- Vector2 CausticsScale;
+ Vector2 CausticsSize;
//--
Vector4 AmbientColor;
//--
diff --git a/TombEngine/Renderer/Graphics/Texture2D.h b/TombEngine/Renderer/Graphics/Texture2D.h
index 1608b7ea2..2a398def9 100644
--- a/TombEngine/Renderer/Graphics/Texture2D.h
+++ b/TombEngine/Renderer/Graphics/Texture2D.h
@@ -144,48 +144,6 @@ namespace TEN::Renderer::Graphics
Height = desc.Height;
}
- Texture2D(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, int x, int y, int width, int height)
- {
- Width = width;
- Height = height;
-
- D3D11_TEXTURE2D_DESC fromDesc = {};
- texture->GetDesc(&fromDesc);
-
- auto desc = D3D11_TEXTURE2D_DESC{};
- desc.Width = width;
- desc.Height = height;
- desc.Format = fromDesc.Format;
- desc.CPUAccessFlags = 0;
- desc.MiscFlags = 0;
- desc.MipLevels = 1;
- desc.ArraySize = 1;
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- throwIfFailed(device->CreateTexture2D(&desc, nullptr, &Texture));
-
- D3D11_BOX sourceRegion;
- sourceRegion.left = x;
- sourceRegion.right = x + width;
- sourceRegion.top = y;
- sourceRegion.bottom = y + height;
- sourceRegion.front = 0;
- sourceRegion.back = 1;
-
- context->CopySubresourceRegion(Texture.Get(), 0, 0, 0, 0, texture, 0, &sourceRegion);
-
- auto shaderDesc = D3D11_SHADER_RESOURCE_VIEW_DESC{};
- shaderDesc.Format = desc.Format;
- shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- shaderDesc.Texture2D.MostDetailedMip = 0;
- shaderDesc.Texture2D.MipLevels = 1;
-
- throwIfFailed(device->CreateShaderResourceView(Texture.Get(), &shaderDesc, ShaderResourceView.GetAddressOf()));
- }
-
~Texture2D() = default;
};
}
diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h
index 4e643388d..16c6325c2 100644
--- a/TombEngine/Renderer/Renderer.h
+++ b/TombEngine/Renderer/Renderer.h
@@ -340,7 +340,7 @@ namespace TEN::Renderer
// Special effects
- std::vector _causticTextures;
+ //std::vector _causticTextures;
RendererMirror* _currentMirror = nullptr;
// Transparency
diff --git a/TombEngine/Renderer/RendererCompatibility.cpp b/TombEngine/Renderer/RendererCompatibility.cpp
index 7ae2ef7d5..2239f8450 100644
--- a/TombEngine/Renderer/RendererCompatibility.cpp
+++ b/TombEngine/Renderer/RendererCompatibility.cpp
@@ -882,25 +882,6 @@ namespace TEN::Renderer
}
_spriteSequences[SpriteSequencesIds[i]] = sequence;
-
- if (SpriteSequencesIds[i] == ID_CAUSTIC_TEXTURES)
- {
- _causticTextures.clear();
- for (int j = 0; j < sequence.SpritesList.size(); j++)
- {
- _causticTextures.push_back(
- Texture2D(
- _device.Get(),
- _context.Get(),
- sequence.SpritesList[j]->Texture->Texture.Get(),
- sequence.SpritesList[j]->X,
- sequence.SpritesList[j]->Y,
- sequence.SpritesList[j]->Width,
- sequence.SpritesList[j]->Height
- )
- );
- }
- }
}
}
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 391f07fc6..dddca503e 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -2709,12 +2709,19 @@ namespace TEN::Renderer
if (rendererPass != RendererPass::GBuffer)
{
// Bind caustics texture.
- if (_causticTextures.size() > 0)
+ if (std::find(SpriteSequencesIds.begin(), SpriteSequencesIds.end(), ID_CAUSTIC_TEXTURES) != SpriteSequencesIds.end())
{
int nmeshes = -Objects[ID_CAUSTIC_TEXTURES].nmeshes;
int meshIndex = Objects[ID_CAUSTIC_TEXTURES].meshIndex;
- int causticsFrame = GlobalCounter % _causticTextures.size();
- BindTexture(TextureRegister::CausticsMap, &_causticTextures[causticsFrame], SamplerStateRegister::AnisotropicClamp);
+ int causticsFrame = GlobalCounter % nmeshes;
+ auto causticsSprite = _spriteSequences[ID_CAUSTIC_TEXTURES].SpritesList[causticsFrame];
+
+ BindTexture(TextureRegister::CausticsMap, causticsSprite->Texture, SamplerStateRegister::AnisotropicClamp);
+
+ _stRoom.CausticsSize = Vector2(
+ (float)causticsSprite->Width / (float)causticsSprite->Texture->Width,
+ (float)causticsSprite->Height / (float)causticsSprite->Texture->Height);
+ _stRoom.CausticsStartUV = causticsSprite->UV[0];
}
// Set shadow map data and bind shadow map texture.
diff --git a/TombEngine/Shaders/Rooms.fx b/TombEngine/Shaders/Rooms.fx
index 1ed9a57ba..b1da5c9ec 100644
--- a/TombEngine/Shaders/Rooms.fx
+++ b/TombEngine/Shaders/Rooms.fx
@@ -16,7 +16,7 @@ cbuffer RoomBuffer : register(b5)
int NumRoomLights;
int Padding;
float2 CausticsStartUV;
- float2 CausticsScale;
+ float2 CausticsSize;
float4 AmbientColor;
ShaderLight RoomLights[MAX_LIGHTS_PER_ROOM];
};
@@ -170,29 +170,33 @@ PixelShaderOutput PS(PixelShaderInput input)
}
}
- if (Caustics)
- {
- float attenuation = saturate(dot(float3(0.0f, -1.0f, 0.0f), normal));
+ if (Caustics)
+ {
+ float attenuation = saturate(dot(float3(0.0f, -1.0f, 0.0f), normal));
- float3 blending = abs(normal);
- blending = normalize(max(blending, 0.00001f));
- float b = (blending.x + blending.y + blending.z);
- blending /= float3(b, b, b);
+ float3 blending = abs(normal);
+ blending = normalize(max(blending, 0.00001f));
+ float b = (blending.x + blending.y + blending.z);
+ blending /= float3(b, b, b);
- float3 p = frac(input.WorldPosition.xyz / 2048.0f);
-
- float3 xaxis = CausticsTexture.SampleLevel(CausticsTextureSampler, float2(p.z, p.y), 0).xyz;
- float3 yaxis = CausticsTexture.SampleLevel(CausticsTextureSampler, float2(p.z, p.x), 0).xyz;
- float3 zaxis = CausticsTexture.SampleLevel(CausticsTextureSampler, float2(p.y, p.x), 0).xyz;
+ float3 p = frac(input.WorldPosition.xyz / 2048.0f);
+
+ float2 uv_x = CausticsStartUV + float2(p.z, p.y) * CausticsSize;
+ float2 uv_y = CausticsStartUV + float2(p.z, p.x) * CausticsSize;
+ float2 uv_z = CausticsStartUV + float2(p.y, p.x) * CausticsSize;
- float3 xc = xaxis * blending.x;
- float3 yc = yaxis * blending.y;
- float3 zc = zaxis * blending.z;
+ float3 xaxis = CausticsTexture.SampleLevel(CausticsTextureSampler, uv_x, 0).xyz;
+ float3 yaxis = CausticsTexture.SampleLevel(CausticsTextureSampler, uv_y, 0).xyz;
+ float3 zaxis = CausticsTexture.SampleLevel(CausticsTextureSampler, uv_z, 0).xyz;
- float3 caustics = xc + yc + zc;
+ float3 xc = xaxis * blending.x;
+ float3 yc = yaxis * blending.y;
+ float3 zc = zaxis * blending.z;
- lighting += (caustics * attenuation * 2.0f);
- }
+ float3 caustics = xc + yc + zc;
+
+ lighting += (caustics * attenuation * 2.0f);
+ }
lighting -= float3(input.FogBulbs.w, input.FogBulbs.w, input.FogBulbs.w);
output.Color.xyz = output.Color.xyz * lighting * occlusion;
From 3745cdadbdcc2c644d445281975e9c2bdda86df8 Mon Sep 17 00:00:00 2001
From: MontyTRC89
Date: Thu, 3 Apr 2025 10:50:02 +0200
Subject: [PATCH 37/53] Possible fix for GetJointPosition problem when objects
are off-screen
---
TombEngine/Renderer/RendererFrame.cpp | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp
index 6fddadff9..3e5f2ac53 100644
--- a/TombEngine/Renderer/RendererFrame.cpp
+++ b/TombEngine/Renderer/RendererFrame.cpp
@@ -422,12 +422,15 @@ namespace TEN::Renderer
// Clip object by frustum only if it doesn't cast shadows and is not in mirror room,
// otherwise disappearing shadows or reflections may be seen if object gets out of frustum.
+ bool inFrustum = true;
+
if (!isRoomReflected && obj.ShadowType == ShadowMode::None)
{
+ inFrustum = false;
+
// Get all spheres and check if frustum intersects any of them.
auto spheres = GetSpheres(itemNumber);
- bool inFrustum = false;
for (int i = 0; !inFrustum, i < spheres.size(); i++)
{
// Blow up sphere radius by half for cases of too small calculated spheres.
@@ -435,8 +438,8 @@ namespace TEN::Renderer
inFrustum = true;
}
- if (!inFrustum)
- continue;
+ // NOTE: removed continue loop here if not in frustum,
+ // for updating first positions and animations data
}
auto& newItem = _items[itemNumber];
@@ -487,6 +490,12 @@ namespace TEN::Renderer
for (int j = 0; j < MAX_BONES; j++)
newItem.InterpolatedAnimTransforms[j] = Matrix::Lerp(newItem.PrevAnimTransforms[j], newItem.AnimTransforms[j], GetInterpolationFactor(forceValue));
+ // NOTE: now at least positions and animations are updated,
+ // because even off-screen the correct position is required
+ // by GetJointPosition functions and similars
+ if (!inFrustum)
+ continue;
+
CalculateLightFades(&newItem);
CollectLightsForItem(&newItem);
From d2d6645fe86522ce073d615cb899b692a2d5b623 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 4 Apr 2025 08:57:06 +0200
Subject: [PATCH 38/53] Fallback for GetJointPosition
---
CHANGELOG.md | 4 ++++
TombEngine/Game/animation.cpp | 12 ++++++++++++
.../Internal/TEN/Objects/Moveable/MoveableObject.cpp | 6 +++---
3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 234608089..eb51790f1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,10 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed crashes when shooting, if gunflash or gunshell objects are not present in a level.
* Fixed Teleporter object.
* Fixed Wraith objects not working correctly in flipped rooms.
+* Fixed caustics not rendered correctly if texture compression was enabled.
+
+### Lua API changes
+* Fixed `Moveable.GetJointPosition` not returning correct results if moveable is invisible or not rendered.
## [Version 1.8.1](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8.1) - 2025-03-29
diff --git a/TombEngine/Game/animation.cpp b/TombEngine/Game/animation.cpp
index 04eb59905..3588ef746 100644
--- a/TombEngine/Game/animation.cpp
+++ b/TombEngine/Game/animation.cpp
@@ -689,6 +689,18 @@ void ClampRotation(Pose& outPose, short angle, short rotation)
Vector3i GetJointPosition(const ItemInfo& item, int jointIndex, const Vector3i& relOffset)
{
+ bool incorrectJoint = false;
+ if (jointIndex < 0 || jointIndex >= Objects[item.ObjectNumber].nmeshes)
+ {
+ TENLog("Unknown joint ID specified for object " + GetObjectName(item.ObjectNumber), LogLevel::Warning, LogConfig::All);
+ incorrectJoint = true;
+ }
+
+ // Always return object's root position if it's invisible, because we can't predict its
+ // joint position otherwise, since it's not animated.
+ if (incorrectJoint || Objects[item.ObjectNumber].drawRoutine == nullptr || item.Status == ITEM_INVISIBLE)
+ return Geometry::TranslatePoint(item.Pose.Position, item.Pose.Orientation, relOffset);
+
// Use matrices done in renderer to transform relative offset.
return Vector3i(g_Renderer.GetMoveableBonePosition(item.Index, jointIndex, relOffset.ToVector3()));
}
diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
index eb1ef5760..36028332a 100644
--- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
+++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
@@ -430,13 +430,13 @@ void Moveable::SetPosition(const Vec3& pos, sol::optional updateRoom)
/// Get the moveable's joint position with an optional relative offset.
// @function Moveable:GetJointPosition
-// @tparam int jointID Joint ID.
+// @tparam int jointIndex Index of a joint to get position.
// @tparam[opt] Vec3 offset Offset relative to the joint.
// @treturn Vec3 World position.
-Vec3 Moveable::GetJointPos(int jointID, sol::optional offset) const
+Vec3 Moveable::GetJointPos(int jointIndex, sol::optional offset) const
{
auto convertedOffset = offset.has_value() ? offset->ToVector3i() : Vector3i::Zero;
- return Vec3(GetJointPosition(_moveable, jointID, convertedOffset));
+ return Vec3(GetJointPosition(_moveable, jointIndex, convertedOffset));
}
/// Get the object's joint rotation
From ab55a7cf14bfa6c5389e8b86cdbe1bef5c471e8b Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 4 Apr 2025 09:08:55 +0200
Subject: [PATCH 39/53] Use Contains method where applicable
---
Documentation/doc/2 classes/Objects.Moveable.html | 8 ++++----
TombEngine/Game/Lara/lara_one_gun.cpp | 3 ++-
TombEngine/Game/camera.cpp | 3 ++-
TombEngine/Renderer/RendererDraw.cpp | 3 ++-
TombEngine/Renderer/RendererFrame.cpp | 2 +-
5 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html
index cddc5ebb0..45f4fa252 100644
--- a/Documentation/doc/2 classes/Objects.Moveable.html
+++ b/Documentation/doc/2 classes/Objects.Moveable.html
@@ -172,7 +172,7 @@
(e.g.
- Moveable:GetJointPosition(jointID[, offset])
+ Moveable:GetJointPosition(jointIndex[, offset])
Get the moveable's joint position with an optional relative offset.
@@ -771,7 +771,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
- Moveable:GetJointPosition(jointID[, offset])
+ Moveable:GetJointPosition(jointIndex[, offset])
Get the moveable's joint position with an optional relative offset.
@@ -780,9 +780,9 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
Parameters:
- jointID
+ jointIndex
int
- Joint ID.
+ Index of a joint to get position.
offset
Vec3
diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp
index 592b9d99c..32b7d60bf 100644
--- a/TombEngine/Game/Lara/lara_one_gun.cpp
+++ b/TombEngine/Game/Lara/lara_one_gun.cpp
@@ -32,6 +32,7 @@
#include "Specific/clock.h"
#include "Specific/Input/Input.h"
#include "Specific/level.h"
+#include "Specific/trutils.h"
using namespace TEN::Collision::Point;
using namespace TEN::Effects::Bubble;
@@ -1594,7 +1595,7 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p
for (auto* itemPtr : collObjects.Items)
{
// Object was already affected by collision, skip it.
- if (std::find(affectedObjects.begin(), affectedObjects.end(), itemPtr->Index) != affectedObjects.end())
+ if (TEN::Utils::Contains(affectedObjects, itemPtr->Index))
continue;
const auto& currentObject = Objects[itemPtr->ObjectNumber];
diff --git a/TombEngine/Game/camera.cpp b/TombEngine/Game/camera.cpp
index fa5f62f02..b6095f8f1 100644
--- a/TombEngine/Game/camera.cpp
+++ b/TombEngine/Game/camera.cpp
@@ -22,6 +22,7 @@
#include "Sound/sound.h"
#include "Specific/Input/Input.h"
#include "Specific/level.h"
+#include "Specific/trutils.h"
#include "Specific/winmain.h"
using namespace TEN::Collision::Point;
@@ -1392,7 +1393,7 @@ static std::vector FillCollideableItemList()
{
const auto& item = g_Level.Items[i];
- if (std::find(roomList.begin(), roomList.end(), item.RoomNumber) == roomList.end())
+ if (!TEN::Utils::Contains(roomList, (int)item.RoomNumber))
continue;
if (!g_Level.Rooms[item.RoomNumber].Active())
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 491f38b0b..341a7f986 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -31,6 +31,7 @@
#include "Renderer/Structures/RendererSortableObject.h"
#include "Specific/configuration.h"
#include "Specific/level.h"
+#include "Specific/trutils.h"
#include "Specific/winmain.h"
using namespace TEN::Effects::Hair;
@@ -2712,7 +2713,7 @@ namespace TEN::Renderer
if (rendererPass != RendererPass::GBuffer)
{
// Bind caustics texture.
- if (std::find(SpriteSequencesIds.begin(), SpriteSequencesIds.end(), ID_CAUSTIC_TEXTURES) != SpriteSequencesIds.end())
+ if (TEN::Utils::Contains(SpriteSequencesIds, (int)ID_CAUSTIC_TEXTURES))
{
int nmeshes = -Objects[ID_CAUSTIC_TEXTURES].nmeshes;
int meshIndex = Objects[ID_CAUSTIC_TEXTURES].meshIndex;
diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp
index 3e5f2ac53..d8d0fcdb0 100644
--- a/TombEngine/Renderer/RendererFrame.cpp
+++ b/TombEngine/Renderer/RendererFrame.cpp
@@ -835,7 +835,7 @@ namespace TEN::Renderer
}
// Light already on a list
- if (std::find(renderView.LightsToDraw.begin(), renderView.LightsToDraw.end(), light) != renderView.LightsToDraw.end())
+ if (TEN::Utils::Contains(renderView.LightsToDraw, light))
{
continue;
}
From 783d7f5fa35fe41979f1e3de04510e37b2a3d129 Mon Sep 17 00:00:00 2001
From: TrainWrack <120750885+TrainWrack@users.noreply.github.com>
Date: Sat, 5 Apr 2025 11:24:06 -0400
Subject: [PATCH 40/53] Remove active requirement from ObjectCamera
---
.../Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
index 36028332a..b11d4ab72 100644
--- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
+++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
@@ -1240,7 +1240,6 @@ bool Moveable::MeshExists(int index) const
// @tparam int mesh Mesh of a target moveable to use as a camera target.
void Moveable::AttachObjCamera(short camMeshId, Moveable& mov, short targetMeshId)
{
- if ((_moveable->Active || _moveable->IsLara()) && (mov._moveable->Active || mov._moveable->IsLara()))
ObjCamera(_moveable, camMeshId, mov._moveable, targetMeshId, true);
}
From 88b1971848604b81791781708aacc30986a9ae4f Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sun, 6 Apr 2025 01:39:37 +0200
Subject: [PATCH 41/53] Correct exclude blend mode
---
CHANGELOG.md | 1 +
TombEngine/Renderer/RendererInit.cpp | 10 +++++-----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eb51790f1..fecd0365f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed Teleporter object.
* Fixed Wraith objects not working correctly in flipped rooms.
* Fixed caustics not rendered correctly if texture compression was enabled.
+* Fixed exclusion blend mode not working correctly.
### Lua API changes
* Fixed `Moveable.GetJointPosition` not returning correct results if moveable is invisible or not rendered.
diff --git a/TombEngine/Renderer/RendererInit.cpp b/TombEngine/Renderer/RendererInit.cpp
index 46fac3c2f..81ee2c115 100644
--- a/TombEngine/Renderer/RendererInit.cpp
+++ b/TombEngine/Renderer/RendererInit.cpp
@@ -133,11 +133,11 @@ namespace TEN::Renderer
blendStateDesc.AlphaToCoverageEnable = false;
blendStateDesc.IndependentBlendEnable = false;
blendStateDesc.RenderTarget[0].BlendEnable = true;
- blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
- blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
- blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
- blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
- blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
+ blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_INV_DEST_COLOR;
+ blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_COLOR;
+ blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
+ blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
Utils::throwIfFailed(_device->CreateBlendState(&blendStateDesc, _excludeBlendState.GetAddressOf()));
From 517f5b30694bf194c1a80fc138170ee8b21377bd Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Mon, 7 Apr 2025 08:23:04 +0200
Subject: [PATCH 42/53] Use single version for TE and TEN
---
TombEngine/Resources.rc | 4 ++--
.../Internal/TEN/Objects/Moveable/MoveableObject.cpp | 2 +-
TombEngine/version.h | 9 +--------
3 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/TombEngine/Resources.rc b/TombEngine/Resources.rc
index 0fa0b9c9e..46163b7a4 100644
--- a/TombEngine/Resources.rc
+++ b/TombEngine/Resources.rc
@@ -28,7 +28,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
VS_VERSION_INFO VERSIONINFO
FILEVERSION TEN_MAJOR_VERSION,TEN_MINOR_VERSION,TEN_BUILD_NUMBER,TEN_REVISION_NUMBER
- PRODUCTVERSION TE_MAJOR_VERSION,TE_MINOR_VERSION,TE_BUILD_NUMBER,TE_REVISION_NUMBER
+ PRODUCTVERSION TEN_MAJOR_VERSION, TEN_MINOR_VERSION, TEN_BUILD_NUMBER, TEN_REVISION_NUMBER
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -49,7 +49,7 @@ BEGIN
VALUE "OriginalFilename", "TombEngine.exe"
VALUE "ProductName", "Tomb Engine"
VALUE "FileVersion", TEN_VERSION_STRING
- VALUE "ProductVersion", TE_VERSION_STRING
+ VALUE "ProductVersion", TEN_VERSION_STRING
END
END
BLOCK "VarFileInfo"
diff --git a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
index b11d4ab72..04e4e000b 100644
--- a/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
+++ b/TombEngine/Scripting/Internal/TEN/Objects/Moveable/MoveableObject.cpp
@@ -1240,7 +1240,7 @@ bool Moveable::MeshExists(int index) const
// @tparam int mesh Mesh of a target moveable to use as a camera target.
void Moveable::AttachObjCamera(short camMeshId, Moveable& mov, short targetMeshId)
{
- ObjCamera(_moveable, camMeshId, mov._moveable, targetMeshId, true);
+ ObjCamera(_moveable, camMeshId, mov._moveable, targetMeshId, true);
}
/// Borrow animation from an object
diff --git a/TombEngine/version.h b/TombEngine/version.h
index 654ddf744..a7bbed0aa 100644
--- a/TombEngine/version.h
+++ b/TombEngine/version.h
@@ -1,19 +1,12 @@
#pragma once
-#define TE_MAJOR_VERSION 1
-#define TE_MINOR_VERSION 8
-#define TE_BUILD_NUMBER 1
-#define TE_REVISION_NUMBER 0
-
#define TEN_MAJOR_VERSION 1
#define TEN_MINOR_VERSION 8
-#define TEN_BUILD_NUMBER 1
+#define TEN_BUILD_NUMBER 2
#define TEN_REVISION_NUMBER 0
#define TEST_BUILD 1
#define TOSTR(x) #x
#define MAKE_VERSION_STRING(major, minor, build, revision) TOSTR(major) "." TOSTR(minor) "." TOSTR(build) "." TOSTR(revision)
-
-#define TE_VERSION_STRING MAKE_VERSION_STRING(TE_MAJOR_VERSION, TE_MINOR_VERSION, TE_BUILD_NUMBER, TE_REVISION_NUMBER)
#define TEN_VERSION_STRING MAKE_VERSION_STRING(TEN_MAJOR_VERSION, TEN_MINOR_VERSION, TEN_BUILD_NUMBER, TEN_REVISION_NUMBER)
From b643eec16582a5b1738d1c6db51be5c862d4a1b2 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 9 Apr 2025 09:29:39 +0200
Subject: [PATCH 43/53] Added muzzle glow effect for firearms
---
CHANGELOG.md | 4 ++
.../doc/2 classes/Flow.Settings.html | 50 +++++++++++++++++++
TombEngine/Game/control/control.cpp | 1 +
TombEngine/Game/effects/tomb4fx.cpp | 46 +++++++++++++++++
TombEngine/Game/effects/tomb4fx.h | 1 +
TombEngine/Renderer/RendererDraw.cpp | 8 +--
TombEngine/Renderer/RendererDrawEffect.cpp | 41 +--------------
.../Internal/TEN/Flow/Settings/Settings.cpp | 28 +++++++----
.../Internal/TEN/Flow/Settings/Settings.h | 2 +
9 files changed, 126 insertions(+), 55 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fecd0365f..b5f5d1329 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,11 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed caustics not rendered correctly if texture compression was enabled.
* Fixed exclusion blend mode not working correctly.
+### New features
+* Added muzzle glow effect for firearms.
+
### Lua API changes
+* Added `muzzleGlow` and `muzzleOffset` parameters to weapon settings.
* Fixed `Moveable.GetJointPosition` not returning correct results if moveable is invisible or not rendered.
## [Version 1.8.1](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.8.1) - 2025-03-29
diff --git a/Documentation/doc/2 classes/Flow.Settings.html b/Documentation/doc/2 classes/Flow.Settings.html
index 6003f5cdc..c59098a2a 100644
--- a/Documentation/doc/2 classes/Flow.Settings.html
+++ b/Documentation/doc/2 classes/Flow.Settings.html
@@ -300,9 +300,17 @@
Display muzzle flash.
+ muzzleGlow
+ Display muzzle glow.
+
+
colorizeMuzzleFlash
Colorize muzzle flash.
+
+ muzzleOffset
+ Muzzle offset.
+
@@ -1214,6 +1222,27 @@
+
+
+
+ muzzleGlow
+
+
+ Display muzzle glow.
+
+
+
+
+ muzzleGlow
+ bool
+ specifies whether muzzle glow should be displayed or not. Applicable only for firearms.
+
+
+
+
+
+
+
@@ -1235,6 +1264,27 @@
+
+
+
+ muzzleOffset
+
+
+ Muzzle offset.
+
+
+
+
+ muzzleOffset
+ Vec3
+ specifies offset for spawning muzzle gunflash effects. Applicable only for firearms.
+
+
+
+
+
+
+
diff --git a/TombEngine/Game/control/control.cpp b/TombEngine/Game/control/control.cpp
index d5171cbae..b543b9ee5 100644
--- a/TombEngine/Game/control/control.cpp
+++ b/TombEngine/Game/control/control.cpp
@@ -194,6 +194,7 @@ GameStatus GamePhase(bool insideMenu)
UpdateBlood();
UpdateBubbles();
UpdateDebris();
+ UpdateGunFlashes();
UpdateGunShells();
UpdateFootprints();
UpdateSplashes();
diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp
index c97fd5a8b..12bd28a61 100644
--- a/TombEngine/Game/effects/tomb4fx.cpp
+++ b/TombEngine/Game/effects/tomb4fx.cpp
@@ -941,6 +941,52 @@ void TriggerGunShell(short hand, short objNum, LaraWeaponType weaponType)
}
}
+void UpdateGunFlashes()
+{
+ if (Lara.Control.Weapon.GunType == LaraWeaponType::None)
+ return;
+
+ const auto& settings = g_GameFlow->GetSettings()->Weapons[(int)Lara.Control.Weapon.GunType - 1];
+
+ if (!settings.MuzzleGlow)
+ return;
+
+ for (int hand = 0; hand < 2; hand++)
+ {
+ if ((hand ? Lara.RightArm.GunFlash : Lara.LeftArm.GunFlash) == 0)
+ continue;
+
+ auto& part = *GetFreeParticle();
+
+ part.on = true;
+ part.SpriteSeqID = ID_DEFAULT_SPRITES;
+ part.SpriteID = 11;
+ part.blendMode = BlendMode::Additive;
+
+ auto pos = GetJointPosition(LaraItem, hand ? LM_RHAND : LM_LHAND, settings.MuzzleOffset.ToVector3i());
+ part.x = pos.x;
+ part.y = pos.y;
+ part.z = pos.z;
+ part.roomNumber = LaraItem->RoomNumber;
+
+ part.sSize = part.size = part.dSize = 192;
+ part.scalar = 2;
+
+ part.xVel = part.yVel = part.zVel = 0;
+ part.gravity = part.friction = part.maxYvel = 0;
+
+ part.sR = part.dR = settings.FlashColor.GetR() / 2;
+ part.sG = part.dG = settings.FlashColor.GetG() / 2;
+ part.sB = part.dB = settings.FlashColor.GetB() / 2;
+
+ part.life = part.sLife = 2;
+ part.colFadeSpeed = 1;
+ part.fadeToBlack = 1;
+
+ part.flags = SP_SCALE | SP_DEF | SP_EXPDEF;
+ }
+}
+
void UpdateGunShells()
{
for (int i = 0; i < MAX_GUNSHELL; i++)
diff --git a/TombEngine/Game/effects/tomb4fx.h b/TombEngine/Game/effects/tomb4fx.h
index b65f8b41e..629d4e4bc 100644
--- a/TombEngine/Game/effects/tomb4fx.h
+++ b/TombEngine/Game/effects/tomb4fx.h
@@ -323,6 +323,7 @@ void TriggerBlood(int x, int y, int z, int unk, int num);
void UpdateBlood();
int GetFreeGunshell();
void TriggerGunShell(short hand, short objNum, LaraWeaponType weaponType);
+void UpdateGunFlashes();
void UpdateGunShells();
void AddWaterSparks(int x, int y, int z, int num);
void ExplodingDeath(short itemNumber, short flags); // BODY_ flags
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 341a7f986..f068a8fd1 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -2824,12 +2824,8 @@ namespace TEN::Renderer
}
else
{
- BindTexture(
- TextureRegister::ColorMap, &std::get<0>(_roomTextures[bucket.Texture]),
- SamplerStateRegister::AnisotropicClamp);
- BindTexture(
- TextureRegister::NormalMap, &std::get<1>(_roomTextures[bucket.Texture]),
- SamplerStateRegister::AnisotropicClamp);
+ BindTexture(TextureRegister::ColorMap, &std::get<0>(_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/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp
index cb903c2f6..04104ca09 100644
--- a/TombEngine/Renderer/RendererDrawEffect.cpp
+++ b/TombEngine/Renderer/RendererDrawEffect.cpp
@@ -1085,50 +1085,13 @@ namespace TEN::Renderer
if (!settings.MuzzleFlash)
return false;
- short length = 0;
- short zOffset = 0;
- short rotationX = 0;
-
if (Lara.Control.Weapon.GunType != LaraWeaponType::Flare &&
Lara.Control.Weapon.GunType != LaraWeaponType::Crossbow)
{
- switch (Lara.Control.Weapon.GunType)
- {
- case LaraWeaponType::Revolver:
- length = 192;
- zOffset = 68;
- rotationX = -14560;
- break;
-
- case LaraWeaponType::Uzi:
- length = 190;
- zOffset = 50;
- rotationX = -14560;
- break;
-
- case LaraWeaponType::HK:
- case LaraWeaponType::Shotgun:
- length = 300;
- zOffset = 92;
- rotationX = -14560;
- break;
-
- default:
- case LaraWeaponType::Pistol:
- length = 180;
- zOffset = 40;
- rotationX = -16830;
- break;
- }
-
// Use MP5 flash if available.
auto gunflash = GAME_OBJECT_ID::ID_GUN_FLASH;
if (Lara.Control.Weapon.GunType == LaraWeaponType::HK && Objects[GAME_OBJECT_ID::ID_GUN_FLASH2].loaded)
- {
gunflash = GAME_OBJECT_ID::ID_GUN_FLASH2;
- length += 20;
- zOffset += 10;
- }
if (!_moveableObjects[gunflash].has_value())
return false;
@@ -1167,8 +1130,8 @@ namespace TEN::Renderer
BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[flashBucket.Texture]), SamplerStateRegister::AnisotropicClamp);
- auto tMatrix = Matrix::CreateTranslation(0, length, zOffset);
- auto rotMatrix = Matrix::CreateRotationX(TO_RAD(rotationX));
+ auto tMatrix = Matrix::CreateTranslation(settings.MuzzleOffset);
+ auto rotMatrix = Matrix::CreateRotationX(TO_RAD(Lara.Control.Weapon.GunType == LaraWeaponType::Pistol ? -16830 : -14560)); // HACK
auto worldMatrix = Matrix::Identity;
if (Lara.LeftArm.GunFlash)
diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp
index 51cda08ee..88637ce35 100644
--- a/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp
+++ b/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp
@@ -25,15 +25,15 @@ namespace TEN::Scripting
// NOTE: Since Weapons array is bound to Lua directly and Lua accesses this array by native enum, where 0 is NONE, and 1 is PISTOLS,
// 0 index is omitted due to Lua indexing arrays starting from 1. 1 must be subtracted from initializer index.
- Weapons[(int)LaraWeaponType::Pistol - 1] = { 8.0f, BLOCK(8), 9, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 3, true, true, true, false };
- Weapons[(int)LaraWeaponType::Revolver - 1] = { 4.0f, BLOCK(8), 16, (int)BLOCK(0.65f), 21, 21, 6, ScriptColor(192, 128, 0), 9, 3, true, false, true, false };
- Weapons[(int)LaraWeaponType::Uzi - 1] = { 8.0f, BLOCK(8), 3, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 2, true, true, true, false };
- Weapons[(int)LaraWeaponType::Shotgun - 1] = { 10.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 3, 3, 6, ScriptColor(192, 128, 0), 12, 3, true, true, false, false };
- Weapons[(int)LaraWeaponType::HK - 1] = { 4.0f, BLOCK(12), 0, (int)BLOCK(0.50f), 4, 4, 30, ScriptColor(192, 128, 0), 12, 2, true, true, true, false };
- Weapons[(int)LaraWeaponType::Crossbow - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 5, 20, 10, ScriptColor(192, 128, 0), 0, 0, false, false, false, false };
- Weapons[(int)LaraWeaponType::GrenadeLauncher - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 30, 30, 10, ScriptColor(192, 128, 0), 0, 0, true, false, false, false };
- Weapons[(int)LaraWeaponType::RocketLauncher - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 30, 30, 1, ScriptColor(192, 128, 0), 0, 0, true, false, false, false };
- Weapons[(int)LaraWeaponType::HarpoonGun - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 6, 6, 10, ScriptColor(192, 128, 0), 0, 0, false, false, false, false };
+ Weapons[(int)LaraWeaponType::Pistol - 1] = { 8.0f, BLOCK(8), 9, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 3, true, true, true, true, false, Vec3(0, 180, 40) };
+ Weapons[(int)LaraWeaponType::Revolver - 1] = { 4.0f, BLOCK(8), 16, (int)BLOCK(0.65f), 21, 21, 6, ScriptColor(192, 128, 0), 9, 3, true, false, true, true, false, Vec3(0, 192, 68) };
+ Weapons[(int)LaraWeaponType::Uzi - 1] = { 8.0f, BLOCK(8), 3, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 2, true, true, true, true, false, Vec3(0, 190, 50) };
+ Weapons[(int)LaraWeaponType::Shotgun - 1] = { 10.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 3, 3, 6, ScriptColor(192, 128, 0), 12, 3, true, true, false, false, false, Vec3(0, 300, 92) };
+ Weapons[(int)LaraWeaponType::HK - 1] = { 4.0f, BLOCK(12), 0, (int)BLOCK(0.50f), 4, 4, 30, ScriptColor(192, 128, 0), 12, 2, true, true, true, true, false, Vec3(0, 320, 102) };
+ Weapons[(int)LaraWeaponType::Crossbow - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 5, 20, 10, ScriptColor(192, 128, 0), 0, 0, false, false, false, false, false, Vec3() };
+ Weapons[(int)LaraWeaponType::GrenadeLauncher - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 30, 30, 10, ScriptColor(192, 128, 0), 0, 0, true, false, false, false, false, Vec3() };
+ Weapons[(int)LaraWeaponType::RocketLauncher - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 30, 30, 1, ScriptColor(192, 128, 0), 0, 0, true, false, false, false, false, Vec3() };
+ Weapons[(int)LaraWeaponType::HarpoonGun - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 6, 6, 10, ScriptColor(192, 128, 0), 0, 0, false, false, false, false, false, Vec3() };
}
void Settings::Register(sol::table& parent)
@@ -309,9 +309,17 @@ namespace TEN::Scripting
// @tfield bool muzzleFlash specifies whether muzzle flash should be displayed or not. Applicable only for firearms.
"muzzleFlash", &WeaponSettings::MuzzleFlash,
+ /// Display muzzle glow.
+ // @tfield bool muzzleGlow specifies whether muzzle glow should be displayed or not. Applicable only for firearms.
+ "muzzleGlow", &WeaponSettings::MuzzleGlow,
+
/// Colorize muzzle flash.
// @tfield bool colorizeMuzzleFlash specifies whether muzzle flash should be tinted with the same color as gunflash color. Applicable only for firearms.
- "colorizeMuzzleFlash", &WeaponSettings::ColorizeMuzzleFlash);
+ "colorizeMuzzleFlash", &WeaponSettings::ColorizeMuzzleFlash,
+
+ /// Muzzle offset.
+ // @tfield Vec3 muzzleOffset specifies offset for spawning muzzle gunflash effects. Applicable only for firearms.
+ "muzzleOffset", &WeaponSettings::MuzzleOffset);
}
/// System
diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.h b/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.h
index 7b2d962ad..f4f110141 100644
--- a/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.h
+++ b/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.h
@@ -103,7 +103,9 @@ namespace TEN::Scripting
bool Smoke = false;
bool Shell = false;
bool MuzzleFlash = true;
+ bool MuzzleGlow = true;
bool ColorizeMuzzleFlash = false;
+ Vec3 MuzzleOffset = {};
static void Register(sol::table& parent);
};
From ba166aa6fa72943e19e23b9cc7e6ae719ce9e2b7 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 9 Apr 2025 09:48:40 +0200
Subject: [PATCH 44/53] Randomize glow angle
---
TombEngine/Game/effects/tomb4fx.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/TombEngine/Game/effects/tomb4fx.cpp b/TombEngine/Game/effects/tomb4fx.cpp
index 12bd28a61..b100e8ed3 100644
--- a/TombEngine/Game/effects/tomb4fx.cpp
+++ b/TombEngine/Game/effects/tomb4fx.cpp
@@ -969,6 +969,9 @@ void UpdateGunFlashes()
part.z = pos.z;
part.roomNumber = LaraItem->RoomNumber;
+ part.rotAng = ANGLE(TO_DEGREES(Random::GenerateAngle())) >> 4;
+ part.rotAdd = 0;
+
part.sSize = part.size = part.dSize = 192;
part.scalar = 2;
From c81feb7da14d430786622f59207d732b587bdc76 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Wed, 9 Apr 2025 23:47:12 +0200
Subject: [PATCH 45/53] Dehardcode gun smoke positions, calculate gunflash
offset
---
TombEngine/Game/Lara/lara_one_gun.cpp | 29 ++++---------------
TombEngine/Game/Lara/lara_two_guns.cpp | 21 ++------------
TombEngine/Renderer/RendererDrawEffect.cpp | 6 +++-
.../Internal/TEN/Flow/Settings/Settings.cpp | 10 +++----
4 files changed, 17 insertions(+), 49 deletions(-)
diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp
index 32b7d60bf..d651388ea 100644
--- a/TombEngine/Game/Lara/lara_one_gun.cpp
+++ b/TombEngine/Game/Lara/lara_one_gun.cpp
@@ -68,27 +68,6 @@ constexpr auto HK_RAPID_MODE_SHOT_INTERVAL = 3.0f;
constexpr auto SHOTGUN_PELLET_COUNT = 6;
-static Vector3i GetWeaponSmokeRelOffset(LaraWeaponType weaponType)
-{
- switch (weaponType)
- {
- case LaraWeaponType::HK:
- return Vector3i(0, 228, 96);
-
- case LaraWeaponType::Shotgun:
- return Vector3i(0, 228, 0);
-
- case LaraWeaponType::GrenadeLauncher:
- return Vector3i(0, 180, 80);
-
- case LaraWeaponType::RocketLauncher:
- return Vector3i(0, 84, 72);;
-
- default:
- return Vector3i::Zero;
- }
-}
-
void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType)
{
auto& player = *GetLaraInfo(&laraItem);
@@ -96,7 +75,7 @@ void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType)
if (player.LeftArm.GunSmoke > 0)
{
- auto relOffset = GetWeaponSmokeRelOffset(weaponType);
+ auto relOffset = g_GameFlow->GetSettings()->Weapons[(int)weaponType - 1].MuzzleOffset.ToVector3();
auto pos = GetJointPosition(&laraItem, LM_RHAND, relOffset);
if (laraItem.MeshBits.TestAny())
@@ -411,8 +390,10 @@ void FireShotgun(ItemInfo& laraItem)
if (!ammo.HasInfinite())
ammo--;
- auto pos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(0, 1508, 32));
- auto pos2 = GetJointPosition(&laraItem, LM_RHAND, Vector3i(0, 228, 32));
+ auto offset = g_GameFlow->GetSettings()->Weapons[(int)LaraWeaponType::Shotgun].MuzzleOffset.ToVector3i();
+
+ auto pos = GetJointPosition(&laraItem, LM_RHAND, offset + Vector3::UnitY * CLICK(2));
+ auto pos2 = GetJointPosition(&laraItem, LM_RHAND, offset);
player.LeftArm.GunSmoke = 32;
diff --git a/TombEngine/Game/Lara/lara_two_guns.cpp b/TombEngine/Game/Lara/lara_two_guns.cpp
index a044c4282..48a26e200 100644
--- a/TombEngine/Game/Lara/lara_two_guns.cpp
+++ b/TombEngine/Game/Lara/lara_two_guns.cpp
@@ -45,24 +45,6 @@ static WeaponAnimData GetWeaponAnimData(LaraWeaponType weaponType)
return ((it != ANIM_DATA_MAP.end()) ? it->second : ANIM_DATA_MAP.at(LaraWeaponType::None));
}
-static Vector3i GetWeaponSmokeRelOffset(LaraWeaponType weaponType, bool isRightWeapon)
-{
- switch (weaponType)
- {
- case LaraWeaponType::Pistol:
- return Vector3i(isRightWeapon ? -16 : 4, 128, 40);
-
- case LaraWeaponType::Revolver:
- return Vector3i(isRightWeapon ? -32 : 16, 160, 56);
-
- case LaraWeaponType::Uzi:
- return Vector3i(isRightWeapon ? -16 : 8, 140, 48);
-
- default:
- return Vector3i::Zero;
- }
-}
-
static void SetArmInfo(const ItemInfo& laraItem, ArmInfo& arm, int frame)
{
const auto& player = GetLaraInfo(laraItem);
@@ -118,8 +100,9 @@ static void AnimateWeapon(ItemInfo& laraItem, LaraWeaponType weaponType, bool& h
// Spawn weapon smoke.
if (laraItem.MeshBits.TestAny() && arm.GunSmoke)
{
- auto relOffset = GetWeaponSmokeRelOffset(weaponType, isRightWeapon);
+ auto relOffset = g_GameFlow->GetSettings()->Weapons[(int)weaponType - 1].MuzzleOffset.ToVector3();
auto pos = GetJointPosition(&laraItem, isRightWeapon ? LM_RHAND : LM_LHAND, relOffset);
+
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, weaponType, arm.GunSmoke);
}
diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp
index 04104ca09..ce6ed8034 100644
--- a/TombEngine/Renderer/RendererDrawEffect.cpp
+++ b/TombEngine/Renderer/RendererDrawEffect.cpp
@@ -1130,7 +1130,11 @@ namespace TEN::Renderer
BindTexture(TextureRegister::ColorMap, &std::get<0>(_moveablesTextures[flashBucket.Texture]), SamplerStateRegister::AnisotropicClamp);
- auto tMatrix = Matrix::CreateTranslation(settings.MuzzleOffset);
+
+ auto meshOffset = g_Level.Frames[GetAnimData(gunflash, 0).FramePtr].Offset;
+ auto offset = settings.MuzzleOffset + Vector3(meshOffset.x, meshOffset.z, meshOffset.y); // Offsets are inverted because of bone orientation.
+
+ auto tMatrix = Matrix::CreateTranslation(offset);
auto rotMatrix = Matrix::CreateRotationX(TO_RAD(Lara.Control.Weapon.GunType == LaraWeaponType::Pistol ? -16830 : -14560)); // HACK
auto worldMatrix = Matrix::Identity;
diff --git a/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp b/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp
index 88637ce35..cb65ca8d7 100644
--- a/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp
+++ b/TombEngine/Scripting/Internal/TEN/Flow/Settings/Settings.cpp
@@ -25,11 +25,11 @@ namespace TEN::Scripting
// NOTE: Since Weapons array is bound to Lua directly and Lua accesses this array by native enum, where 0 is NONE, and 1 is PISTOLS,
// 0 index is omitted due to Lua indexing arrays starting from 1. 1 must be subtracted from initializer index.
- Weapons[(int)LaraWeaponType::Pistol - 1] = { 8.0f, BLOCK(8), 9, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 3, true, true, true, true, false, Vec3(0, 180, 40) };
- Weapons[(int)LaraWeaponType::Revolver - 1] = { 4.0f, BLOCK(8), 16, (int)BLOCK(0.65f), 21, 21, 6, ScriptColor(192, 128, 0), 9, 3, true, false, true, true, false, Vec3(0, 192, 68) };
- Weapons[(int)LaraWeaponType::Uzi - 1] = { 8.0f, BLOCK(8), 3, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 2, true, true, true, true, false, Vec3(0, 190, 50) };
- Weapons[(int)LaraWeaponType::Shotgun - 1] = { 10.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 3, 3, 6, ScriptColor(192, 128, 0), 12, 3, true, true, false, false, false, Vec3(0, 300, 92) };
- Weapons[(int)LaraWeaponType::HK - 1] = { 4.0f, BLOCK(12), 0, (int)BLOCK(0.50f), 4, 4, 30, ScriptColor(192, 128, 0), 12, 2, true, true, true, true, false, Vec3(0, 320, 102) };
+ Weapons[(int)LaraWeaponType::Pistol - 1] = { 8.0f, BLOCK(8), 9, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 3, true, true, true, true, false, Vec3( 0, 120, 30) };
+ Weapons[(int)LaraWeaponType::Revolver - 1] = { 4.0f, BLOCK(8), 16, (int)BLOCK(0.65f), 21, 21, 6, ScriptColor(192, 128, 0), 9, 3, true, false, true, true, false, Vec3(-10, 130, 45) };
+ Weapons[(int)LaraWeaponType::Uzi - 1] = { 8.0f, BLOCK(8), 3, (int)BLOCK(0.65f), 1, 1, 30, ScriptColor(192, 128, 0), 9, 2, true, true, true, true, false, Vec3( 0, 110, 40) };
+ Weapons[(int)LaraWeaponType::Shotgun - 1] = { 10.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 3, 3, 6, ScriptColor(192, 128, 0), 12, 3, true, true, false, false, false, Vec3( 0, 210, 42) };
+ Weapons[(int)LaraWeaponType::HK - 1] = { 4.0f, BLOCK(12), 0, (int)BLOCK(0.50f), 4, 4, 30, ScriptColor(192, 128, 0), 12, 2, true, true, true, true, false, Vec3( 0, 220, 102) };
Weapons[(int)LaraWeaponType::Crossbow - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 5, 20, 10, ScriptColor(192, 128, 0), 0, 0, false, false, false, false, false, Vec3() };
Weapons[(int)LaraWeaponType::GrenadeLauncher - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 30, 30, 10, ScriptColor(192, 128, 0), 0, 0, true, false, false, false, false, Vec3() };
Weapons[(int)LaraWeaponType::RocketLauncher - 1] = { 8.0f, BLOCK(8), 0, (int)BLOCK(0.50f), 30, 30, 1, ScriptColor(192, 128, 0), 0, 0, true, false, false, false, false, Vec3() };
From ee5147eb4f0d18d83c42f14334dfc25abeb3de4b Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Thu, 10 Apr 2025 21:23:34 +0200
Subject: [PATCH 46/53] Fixed spamming of HK sound effects
---
CHANGELOG.md | 1 +
TombEngine/Game/Lara/lara_one_gun.cpp | 7 ++-----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5f5d1329..2fd24b052 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed Wraith objects not working correctly in flipped rooms.
* Fixed caustics not rendered correctly if texture compression was enabled.
* Fixed exclusion blend mode not working correctly.
+* Fixed HK sound effects.
### New features
* Added muzzle glow effect for firearms.
diff --git a/TombEngine/Game/Lara/lara_one_gun.cpp b/TombEngine/Game/Lara/lara_one_gun.cpp
index d651388ea..3dcefb301 100644
--- a/TombEngine/Game/Lara/lara_one_gun.cpp
+++ b/TombEngine/Game/Lara/lara_one_gun.cpp
@@ -231,9 +231,8 @@ void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType)
player.Control.Weapon.Timer = 0.0f;
}
}
- else if (player.Control.Weapon.Timer != 0.0f)
+ else if (weaponType == LaraWeaponType::HK && player.Control.Weapon.Timer != 0.0f)
{
- SoundEffect(SFX_TR4_EXPLOSION1, &laraItem.Pose, SoundEnvironment::Land, 1.0f, 0.4f);
SoundEffect(SFX_TR4_HK_FIRE, &laraItem.Pose);
}
else if (weaponType == LaraWeaponType::Shotgun && !IsHeld(In::Action) && !player.LeftArm.Locked)
@@ -312,9 +311,8 @@ void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType)
player.Control.Weapon.Timer = 0.0f;
}
}
- else if (player.Control.Weapon.Timer != 0.0f)
+ else if (weaponType == LaraWeaponType::HK && player.Control.Weapon.Timer != 0.0f)
{
- SoundEffect(SFX_TR4_EXPLOSION1, &laraItem.Pose, SoundEnvironment::Land, 1.0f, 0.4f);
SoundEffect(SFX_TR4_HK_FIRE, &laraItem.Pose);
}
@@ -1233,7 +1231,6 @@ void LasersightWeaponHandler(ItemInfo& item, LaraWeaponType weaponType)
if (playSound)
{
- SoundEffect(SFX_TR4_EXPLOSION1, nullptr, SoundEnvironment::Land, 1.0f, 0.4f);
SoundEffect(SFX_TR4_HK_FIRE, nullptr);
Camera.bounce = -16 - (GetRandomControl() & 0x1F);
}
From 218299193fc9b1b01aa5ccb9e60e93410396e442 Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Fri, 11 Apr 2025 03:11:05 +0200
Subject: [PATCH 47/53] Another method for SSAO fix
---
CHANGELOG.md | 1 +
TombEngine/Renderer/RendererDraw.cpp | 6 +-----
TombEngine/Shaders/InstancedStatics.fx | 3 +++
TombEngine/Shaders/Items.fx | 3 +++
TombEngine/Shaders/Rooms.fx | 3 +++
5 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2fd24b052..47356f0a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed Wraith objects not working correctly in flipped rooms.
* Fixed caustics not rendered correctly if texture compression was enabled.
* Fixed exclusion blend mode not working correctly.
+* Fixed SSAO incorrectly applied through alpha blended textures.
* Fixed HK sound effects.
### New features
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index f068a8fd1..1949fc062 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -3236,11 +3236,7 @@ namespace TEN::Renderer
case RendererPass::GBuffer:
if (blendMode != BlendMode::Opaque &&
blendMode != BlendMode::AlphaTest &&
- blendMode != BlendMode::FastAlphaBlend &&
- // WARNING: For G-Buffer step we consider alpha blend like alpha test
- // assuming that most of the geometry used in rooms, items and statics
- // are fences, foliages, trees... But it could fail with translucent surfaces!
- blendMode != BlendMode::AlphaBlend)
+ blendMode != BlendMode::FastAlphaBlend)
{
return false;
}
diff --git a/TombEngine/Shaders/InstancedStatics.fx b/TombEngine/Shaders/InstancedStatics.fx
index 26ed08921..e284579e9 100644
--- a/TombEngine/Shaders/InstancedStatics.fx
+++ b/TombEngine/Shaders/InstancedStatics.fx
@@ -110,6 +110,9 @@ PixelShaderOutput PS(PixelShaderInput input)
samplePosition = samplePosition * 0.5f + 0.5f;
samplePosition.y = 1.0f - samplePosition.y;
occlusion = pow(SSAOTexture.Sample(SSAOSampler, samplePosition).x, AmbientOcclusionExponent);
+
+ if (BlendMode == BLENDMODE_ALPHABLEND)
+ occlusion = lerp(occlusion, 1.0f, tex.w);
}
float3 color = (mode == 0) ?
diff --git a/TombEngine/Shaders/Items.fx b/TombEngine/Shaders/Items.fx
index c789da24c..d8a13d5dc 100644
--- a/TombEngine/Shaders/Items.fx
+++ b/TombEngine/Shaders/Items.fx
@@ -140,6 +140,9 @@ PixelShaderOutput PS(PixelShaderInput input)
samplePosition = samplePosition * 0.5f + 0.5f; // transform to range 0.0 - 1.0
samplePosition.y = 1.0f - samplePosition.y;
occlusion = pow(SSAOTexture.Sample(SSAOSampler, samplePosition).x, AmbientOcclusionExponent);
+
+ if (BlendMode == BLENDMODE_ALPHABLEND)
+ occlusion = lerp(occlusion, 1.0f, tex.w);
}
float3 color = (BoneLightModes[input.Bone / 4][input.Bone % 4] == 0) ?
diff --git a/TombEngine/Shaders/Rooms.fx b/TombEngine/Shaders/Rooms.fx
index b1da5c9ec..619e18972 100644
--- a/TombEngine/Shaders/Rooms.fx
+++ b/TombEngine/Shaders/Rooms.fx
@@ -141,6 +141,9 @@ PixelShaderOutput PS(PixelShaderInput input)
samplePosition = samplePosition * 0.5f + 0.5f; // transform to range 0.0 - 1.0
samplePosition.y = 1.0f - samplePosition.y;
occlusion = pow(SSAOTexture.Sample(SSAOSampler, samplePosition).x, AmbientOcclusionExponent);
+
+ if (BlendMode == BLENDMODE_ALPHABLEND)
+ occlusion = lerp(occlusion, 1.0f, output.Color.w);
}
lighting = DoShadow(input.WorldPosition, normal, lighting, -2.5f);
From 0128660f0747d8f15046fef5ca59784e5277388f Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sat, 12 Apr 2025 17:27:06 +0200
Subject: [PATCH 48/53] Change LDoc to properly format optional arguments and
defaults
---
Documentation/compiler/ldoc/ldoc/doc.lua | 15 +++++++--------
.../compiler/ldoc/ldoc/html/ldoc_ltp.lua | 6 +++---
Documentation/ldoc.ltp | 6 +++---
3 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/Documentation/compiler/ldoc/ldoc/doc.lua b/Documentation/compiler/ldoc/ldoc/doc.lua
index 30f8eafc5..52860ccba 100644
--- a/Documentation/compiler/ldoc/ldoc/doc.lua
+++ b/Documentation/compiler/ldoc/ldoc/doc.lua
@@ -868,20 +868,19 @@ function build_arg_list (names,pmods)
local opt
if m then
if not m.optchain then
- acc ((']'):rep(npending))
npending=0
end
opt = m.optchain or m.opt
- if opt then
- acc('[')
- npending=npending+1
- end
end
if i>1 then acc (', ') end
- acc(names[i])
- if opt and opt ~= true then acc('='..opt) end
+ if opt then
+ acc('[' .. names[i])
+ if opt ~= true then acc('='..opt) end
+ acc(']')
+ else
+ acc(names[i])
+ end
end
- acc ((']'):rep(npending))
return '('..table.concat(buffer)..')'
end
diff --git a/Documentation/compiler/ldoc/ldoc/html/ldoc_ltp.lua b/Documentation/compiler/ldoc/ldoc/html/ldoc_ltp.lua
index 31b09d72c..2efb79a43 100644
--- a/Documentation/compiler/ldoc/ldoc/html/ldoc_ltp.lua
+++ b/Documentation/compiler/ldoc/ldoc/html/ldoc_ltp.lua
@@ -215,12 +215,12 @@ return [==[
# end
$(M(item.params.map[p],item))
# if def == true then
- (optional )
+ (Optional. )
# elseif def then
- (default $(def))
+ (Default. $(def))
# end
# if item:readonly(p) then
- readonly
+ Read-only.
# end
# end
diff --git a/Documentation/ldoc.ltp b/Documentation/ldoc.ltp
index 77472d077..5034016d4 100644
--- a/Documentation/ldoc.ltp
+++ b/Documentation/ldoc.ltp
@@ -216,12 +216,12 @@
# end
$(M(item.params.map[p],item))
# if def == true then
- (optional )
+ Optional.
# elseif def then
- (default $(def))
+ Default: $(def).
# end
# if item:readonly(p) then
- readonly
+ Read-only.
# end
# end
From 73af37dbe15f194f50e828c8a5b6971da04a3cfb Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sun, 13 Apr 2025 16:19:58 +0200
Subject: [PATCH 49/53] Fixed lensflare enabled status not saved in a savegame
---
TombEngine/Game/savegame.cpp | 2 ++
.../flatbuffers/ten_savegame_generated.h | 30 ++++++++++++++-----
.../Specific/savegame/schema/ten_savegame.fbs | 1 +
3 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/TombEngine/Game/savegame.cpp b/TombEngine/Game/savegame.cpp
index 8f3f1394c..26b41d8ad 100644
--- a/TombEngine/Game/savegame.cpp
+++ b/TombEngine/Game/savegame.cpp
@@ -1143,6 +1143,7 @@ const std::vector SaveGame::Build()
levelData.add_sky_layer_2_color(level->GetSkyLayerColor(1));
levelData.add_sky_layer_2_speed(level->GetSkyLayerSpeed(1));
+ levelData.add_lensflare_enabled(level->LensFlare.GetEnabled());
levelData.add_lensflare_color(level->LensFlare.GetColor());
levelData.add_lensflare_pitch(level->LensFlare.GetPitch());
levelData.add_lensflare_yaw(level->LensFlare.GetYaw());
@@ -1844,6 +1845,7 @@ static void ParseLua(const Save::SaveGame* s, bool hubMode)
level->Layer2.CloudSpeed = s->level_data()->sky_layer_2_speed();
level->Layer2.SetColor(s->level_data()->sky_layer_2_color());
+ level->LensFlare.SetEnabled(s->level_data()->lensflare_enabled());
level->LensFlare.SetSunSpriteID(s->level_data()->lensflare_sprite_id());
level->LensFlare.SetPitch(s->level_data()->lensflare_pitch());
level->LensFlare.SetYaw(s->level_data()->lensflare_yaw());
diff --git a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h
index a99d79882..3c85b7494 100644
--- a/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h
+++ b/TombEngine/Specific/savegame/flatbuffers/ten_savegame_generated.h
@@ -571,6 +571,7 @@ struct LevelDataT : public flatbuffers::NativeTable {
std::unique_ptr horizon2_position{};
std::unique_ptr horizon2_orientation{};
float horizon2_transparency = 0.0f;
+ bool lensflare_enabled = false;
int32_t lensflare_sprite_id = 0;
float lensflare_pitch = 0.0f;
float lensflare_yaw = 0.0f;
@@ -610,14 +611,15 @@ struct LevelData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_HORIZON2_POSITION = 46,
VT_HORIZON2_ORIENTATION = 48,
VT_HORIZON2_TRANSPARENCY = 50,
- VT_LENSFLARE_SPRITE_ID = 52,
- VT_LENSFLARE_PITCH = 54,
- VT_LENSFLARE_YAW = 56,
- VT_LENSFLARE_COLOR = 58,
- VT_STARFIELD_STAR_COUNT = 60,
- VT_STARFIELD_METEOR_COUNT = 62,
- VT_STARFIELD_METEOR_SPAWN_DENSITY = 64,
- VT_STARFIELD_METEOR_VELOCITY = 66
+ VT_LENSFLARE_ENABLED = 52,
+ VT_LENSFLARE_SPRITE_ID = 54,
+ VT_LENSFLARE_PITCH = 56,
+ VT_LENSFLARE_YAW = 58,
+ VT_LENSFLARE_COLOR = 60,
+ VT_STARFIELD_STAR_COUNT = 62,
+ VT_STARFIELD_METEOR_COUNT = 64,
+ VT_STARFIELD_METEOR_SPAWN_DENSITY = 66,
+ VT_STARFIELD_METEOR_VELOCITY = 68
};
int32_t level_far_view() const {
return GetField(VT_LEVEL_FAR_VIEW, 0);
@@ -691,6 +693,9 @@ struct LevelData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
float horizon2_transparency() const {
return GetField(VT_HORIZON2_TRANSPARENCY, 0.0f);
}
+ bool lensflare_enabled() const {
+ return GetField(VT_LENSFLARE_ENABLED, 0) != 0;
+ }
int32_t lensflare_sprite_id() const {
return GetField(VT_LENSFLARE_SPRITE_ID, 0);
}
@@ -741,6 +746,7 @@ struct LevelData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField(verifier, VT_HORIZON2_POSITION) &&
VerifyField(verifier, VT_HORIZON2_ORIENTATION) &&
VerifyField(verifier, VT_HORIZON2_TRANSPARENCY) &&
+ VerifyField(verifier, VT_LENSFLARE_ENABLED) &&
VerifyField(verifier, VT_LENSFLARE_SPRITE_ID) &&
VerifyField(verifier, VT_LENSFLARE_PITCH) &&
VerifyField(verifier, VT_LENSFLARE_YAW) &&
@@ -832,6 +838,9 @@ struct LevelDataBuilder {
void add_horizon2_transparency(float horizon2_transparency) {
fbb_.AddElement(LevelData::VT_HORIZON2_TRANSPARENCY, horizon2_transparency, 0.0f);
}
+ void add_lensflare_enabled(bool lensflare_enabled) {
+ fbb_.AddElement(LevelData::VT_LENSFLARE_ENABLED, static_cast(lensflare_enabled), 0);
+ }
void add_lensflare_sprite_id(int32_t lensflare_sprite_id) {
fbb_.AddElement(LevelData::VT_LENSFLARE_SPRITE_ID, lensflare_sprite_id, 0);
}
@@ -893,6 +902,7 @@ inline flatbuffers::Offset CreateLevelData(
const TEN::Save::Vector3 *horizon2_position = 0,
const TEN::Save::EulerAngles *horizon2_orientation = 0,
float horizon2_transparency = 0.0f,
+ bool lensflare_enabled = false,
int32_t lensflare_sprite_id = 0,
float lensflare_pitch = 0.0f,
float lensflare_yaw = 0.0f,
@@ -928,6 +938,7 @@ inline flatbuffers::Offset CreateLevelData(
builder_.add_weather_strength(weather_strength);
builder_.add_weather_type(weather_type);
builder_.add_level_far_view(level_far_view);
+ builder_.add_lensflare_enabled(lensflare_enabled);
builder_.add_horizon2_enabled(horizon2_enabled);
builder_.add_horizon1_enabled(horizon1_enabled);
builder_.add_sky_layer_2_enabled(sky_layer_2_enabled);
@@ -9260,6 +9271,7 @@ inline void LevelData::UnPackTo(LevelDataT *_o, const flatbuffers::resolver_func
{ auto _e = horizon2_position(); if (_e) _o->horizon2_position = std::unique_ptr(new TEN::Save::Vector3(*_e)); }
{ auto _e = horizon2_orientation(); if (_e) _o->horizon2_orientation = std::unique_ptr(new TEN::Save::EulerAngles(*_e)); }
{ auto _e = horizon2_transparency(); _o->horizon2_transparency = _e; }
+ { auto _e = lensflare_enabled(); _o->lensflare_enabled = _e; }
{ auto _e = lensflare_sprite_id(); _o->lensflare_sprite_id = _e; }
{ auto _e = lensflare_pitch(); _o->lensflare_pitch = _e; }
{ auto _e = lensflare_yaw(); _o->lensflare_yaw = _e; }
@@ -9302,6 +9314,7 @@ inline flatbuffers::Offset CreateLevelData(flatbuffers::FlatBufferBui
auto _horizon2_position = _o->horizon2_position ? _o->horizon2_position.get() : 0;
auto _horizon2_orientation = _o->horizon2_orientation ? _o->horizon2_orientation.get() : 0;
auto _horizon2_transparency = _o->horizon2_transparency;
+ auto _lensflare_enabled = _o->lensflare_enabled;
auto _lensflare_sprite_id = _o->lensflare_sprite_id;
auto _lensflare_pitch = _o->lensflare_pitch;
auto _lensflare_yaw = _o->lensflare_yaw;
@@ -9336,6 +9349,7 @@ inline flatbuffers::Offset CreateLevelData(flatbuffers::FlatBufferBui
_horizon2_position,
_horizon2_orientation,
_horizon2_transparency,
+ _lensflare_enabled,
_lensflare_sprite_id,
_lensflare_pitch,
_lensflare_yaw,
diff --git a/TombEngine/Specific/savegame/schema/ten_savegame.fbs b/TombEngine/Specific/savegame/schema/ten_savegame.fbs
index bc41d27be..11d988d99 100644
--- a/TombEngine/Specific/savegame/schema/ten_savegame.fbs
+++ b/TombEngine/Specific/savegame/schema/ten_savegame.fbs
@@ -38,6 +38,7 @@ table LevelData {
horizon2_orientation: EulerAngles;
horizon2_transparency: float;
+ lensflare_enabled: bool;
lensflare_sprite_id: int32;
lensflare_pitch: float;
lensflare_yaw: float;
From 0d604678339363e1a806ef0baeac9d131e6a1c7e Mon Sep 17 00:00:00 2001
From: Lwmte <3331699+Lwmte@users.noreply.github.com>
Date: Sun, 13 Apr 2025 16:22:41 +0200
Subject: [PATCH 50/53] Fixed script API documentation mistakes
---
Documentation/doc/3 primitive classes/Flow.LensFlare.html | 4 ++--
Documentation/doc/3 primitive classes/Vec2.html | 2 +-
.../Scripting/Internal/TEN/Flow/LensFlare/LensFlare.cpp | 2 +-
TombEngine/Scripting/Internal/TEN/Types/Vec2/Vec2.cpp | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/doc/3 primitive classes/Flow.LensFlare.html b/Documentation/doc/3 primitive classes/Flow.LensFlare.html
index 493f9432b..172afbfdf 100644
--- a/Documentation/doc/3 primitive classes/Flow.LensFlare.html
+++ b/Documentation/doc/3 primitive classes/Flow.LensFlare.html
@@ -127,7 +127,7 @@
spriteID
- (Objects.ObjID.SpriteConstants ) Lens flare's sun sprite object ID.
+ (int) Lens flare's sun sprite ID in DEFAULT_SPRITES sequence.
pitch
@@ -178,7 +178,7 @@
spriteID
- (Objects.ObjID.SpriteConstants ) Lens flare's sun sprite object ID.
+ (int) Lens flare's sun sprite ID in DEFAULT_SPRITES sequence.
diff --git a/Documentation/doc/3 primitive classes/Vec2.html b/Documentation/doc/3 primitive classes/Vec2.html
index eb65b2271..4bedd88bf 100644
--- a/Documentation/doc/3 primitive classes/Vec2.html
+++ b/Documentation/doc/3 primitive classes/Vec2.html
@@ -354,7 +354,7 @@
Parameters:
- EmitLight(pos[, color][, radius][, shadows][, name])
+ EmitLight(pos, [color], [radius], [shadows], [name])
Emit dynamic light that lasts for a single frame.
- EmitSpotLight(pos, dir[, color][, radius][, falloff][, distance][, shadows][, name])
+ EmitSpotLight(pos, dir, [color], [radius], [falloff], [distance], [shadows], [name])
Emit dynamic directional spotlight that lasts for a single frame.
@@ -152,7 +152,7 @@
Emit blood.
- EmitAirBubble(pos[, size][, amp])
+ EmitAirBubble(pos, [size], [amp])
Emit an air bubble in a water room.
@@ -172,7 +172,7 @@
Get the wind vector for the current game frame.
- EmitStreamer(mov, tag, pos, dir[, rot][, startColor][, endColor][, width][, life][, vel][, expRate][, rotRate][, edgeFeatherMode][, lengthFeatherMode][, blendID])
+ EmitStreamer(mov, tag, pos, dir, [rot], [startColor], [endColor], [width], [life], [vel], [expRate], [rotRate], [edgeFeatherMode], [lengthFeatherMode], [blendID])
Emit an extending streamer effect.
@@ -454,7 +454,7 @@ EmitAdvancedParticle(particle)
- EmitLight(pos[, color][, radius][, shadows][, name])
+ EmitLight(pos, [color], [radius], [shadows], [name])
Emit dynamic light that lasts for a single frame.
@@ -471,22 +471,22 @@ EmitAdvancedParticle(particle)
color
Color
light color (default Color(255, 255, 255))
- (optional )
+ Optional.
radius
int
measured in "clicks" or 256 world units (default 20)
- (optional )
+ Optional.
shadows
bool
determines whether light should generate dynamic shadows for applicable moveables (default is false)
- (optional )
+ Optional.
name
string
if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
- (optional )
+ Optional.
@@ -497,7 +497,7 @@ EmitAdvancedParticle(particle)
- EmitSpotLight(pos, dir[, color][, radius][, falloff][, distance][, shadows][, name])
+ EmitSpotLight(pos, dir, [color], [radius], [falloff], [distance], [shadows], [name])
Emit dynamic directional spotlight that lasts for a single frame.
@@ -518,32 +518,32 @@ EmitAdvancedParticle(particle)
color
Color
(default Color(255, 255, 255))
- (optional )
+ Optional.
radius
int
overall radius at the endpoint of a light cone, measured in "clicks" or 256 world units (default 10)
- (optional )
+ Optional.
falloff
int
radius, at which light starts to fade out, measured in "clicks" (default 5)
- (optional )
+ Optional.
distance
int
distance, at which light cone fades out, measured in "clicks" (default 20)
- (optional )
+ Optional.
shadows
bool
determines whether light should generate dynamic shadows for applicable moveables (default is false)
- (optional )
+ Optional.
name
string
if provided, engine will interpolate this light for high framerate mode (be careful not to use same name for different lights)
- (optional )
+ Optional.
@@ -582,7 +582,7 @@ EmitAdvancedParticle(particle)
- EmitAirBubble(pos[, size][, amp])
+ EmitAirBubble(pos, [size], [amp])
Emit an air bubble in a water room.
@@ -598,12 +598,12 @@ EmitAdvancedParticle(particle)
size
float
Sprite size. Default: 32
- (optional )
+ Optional.
amp
float
Oscillation amplitude. Default: 32
- (optional )
+ Optional.
@@ -718,7 +718,7 @@ EmitAdvancedParticle(particle)
- EmitStreamer(mov, tag, pos, dir[, rot][, startColor][, endColor][, width][, life][, vel][, expRate][, rotRate][, edgeFeatherMode][, lengthFeatherMode][, blendID])
+ EmitStreamer(mov, tag, pos, dir, [rot], [startColor], [endColor], [width], [life], [vel], [expRate], [rotRate], [edgeFeatherMode], [lengthFeatherMode], [blendID])
Emit an extending streamer effect.
@@ -746,57 +746,57 @@ EmitAdvancedParticle(particle)
rot
float
Start rotation in degrees. Default: 0
- (optional )
+ Optional.
startColor
Color
Color at the start of life. Default: Color(255, 255, 255, 255))
- (optional )
+ Optional.
endColor
Color
Color at the end of life. Default: Color(0, 0, 0, 0))
- (optional )
+ Optional.
width
float
Width in world units. Default: 0
- (optional )
+ Optional.
life
float
Lifetime in seconds. Default: 1
- (optional )
+ Optional.
vel
float
Movement velocity in world units per second. Default: 0
- (optional )
+ Optional.
expRate
float
Width expansion rate in world units per second. Default: 0
- (optional )
+ Optional.
rotRate
float
Rotation rate in degrees per second. Default: 0
- (optional )
+ Optional.
edgeFeatherMode
StreamerFeatherMode
Edge feather mode. Default: Effects.StreamerFeatherMode.NONE
- (optional )
+ Optional.
lengthFeatherMode
StreamerFeatherMode
Length feather mode. UNIMPLEMENTED, currently will always leave a fading tail
- (optional )
+ Optional.
blendID
BlendID
Renderer blend ID. Default: Effects.BlendID.ALPHA_BLEND
- (optional )
+ Optional.
@@ -831,127 +831,127 @@ EmitAdvancedParticle(particle)
spriteSeqID
SpriteConstants
Sprite sequence slot ID. default: Objects.ObjID.DEFAULT_SPRITES
- (optional )
+ Optional.
spriteID
int
Sprite ID in the sprite sequence slot. default: 0
- (optional )
+ Optional.
life
float
Lifespan in seconds. default: 2
- (optional )
+ Optional.
maxYVel
float
Maximum vertical velocity in world units per second. default: 0
- (optional )
+ Optional.
gravity
float
Effect of gravity in world units per second. Positive value ascend, negative value descend. default: 0
- (optional )
+ Optional.
friction
float
Friction affecting velocity over time in world units per second. default: 0
- (optional )
+ Optional.
startRot
float
Rotation at start of life. default: random
- (optional )
+ Optional.
rotVel
float
Rotational velocity in degrees per second. default: 0
- (optional )
+ Optional.
startSize
float
Size at start of life. default: 10
- (optional )
+ Optional.
endSize
float
Size at end of life. default: 0
- (optional )
+ Optional.
startColor
Color
Color at start of life. default: Color(255, 255, 255)
- (optional )
+ Optional.
endColor
Color
Color at end of life. Note that this will finish long before the end of life due to internal math. default: Color(255, 255, 255)
- (optional )
+ Optional.
blendMode
BlendID
Render blend mode. default: TEN.Effects.BlendID.ALPHA_BLEND
- (optional )
+ Optional.
damage
bool
Harm the player on collision. default: false
- (optional )
+ Optional.
poison
bool
Poison the player on collision. default: false
- (optional )
+ Optional.
burn
bool
Burn the player on collision. default: false
- (optional )
+ Optional.
wind
bool
Affect position by wind in outside rooms. default: false
- (optional )
+ Optional.
damageHit
int
Player damage amount on collision. default: 2
- (optional )
+ Optional.
light
bool
Emit a colored light. CAUTION: Recommended only for a single particle. Too many particles with lights can overwhelm the lighting system. default: false
- (optional )
+ Optional.
lightRadius
int
Light radius in 1/4 blocks. default: 0
- (optional )
+ Optional.
lightFlicker
int
Interval at which the light should flicker. default: 0
- (optional )
+ Optional.
soundID
int
Sound ID to play. CAUTION: Recommended only for a single particle. Too many particles with sounds can overwhelm the sound system. default: none
- (optional )
+ Optional.
animated
bool
Play animates sprite sequence. default: false
- (optional )
+ Optional.
animType
ParticleAnimationType
Animation type of the sprite sequence. default: TEN.Effects.ParticleAnimationType.LOOP
- (optional )
+ Optional.
frameRate
float
Sprite sequence animation framerate. default: 1
- (optional )
+ Optional.
diff --git a/Documentation/doc/1 modules/Flow.html b/Documentation/doc/1 modules/Flow.html
index a8ae0a9b0..4a680cba5 100644
--- a/Documentation/doc/1 modules/Flow.html
+++ b/Documentation/doc/1 modules/Flow.html
@@ -175,7 +175,7 @@ scripts too.
Returns the level that the game control is running in that moment.
- EndLevel([index][, startPos])
+ EndLevel([index], [startPos])
Finishes the current level, with optional level index and start position index provided.
@@ -570,7 +570,7 @@ have an ID of 0, the second an ID of 1, and so on.
- EndLevel([index][, startPos])
+ EndLevel([index], [startPos])
Finishes the current level, with optional level index and start position index provided.
@@ -585,12 +585,12 @@ teleported to such object with OCB similar to provided second argument.
index
int
level index (default 0)
- (optional )
+ Optional.
startPos
int
player start position (default 0)
- (optional )
+ Optional.
@@ -959,7 +959,7 @@ Must be an integer value (0 means no secrets).
index
int
Flipmap group ID to check. If no group specified or group is -1, function returns overall flipmap status (on or off).
- (optional )
+ Optional.
diff --git a/Documentation/doc/1 modules/Input.html b/Documentation/doc/1 modules/Input.html
index c3439c75c..7cf9f7de0 100644
--- a/Documentation/doc/1 modules/Input.html
+++ b/Documentation/doc/1 modules/Input.html
@@ -124,7 +124,7 @@
- Vibrate(strength, time)
+ Vibrate(strength, [time])
Vibrate the game controller if the function is available and the setting is on.
@@ -162,7 +162,7 @@
- Vibrate(strength, time)
+ Vibrate(strength, [time])
Vibrate the game controller if the function is available and the setting is on.
@@ -177,7 +177,8 @@
time
float
- (default 0.3) Vibration time in seconds.
+ Vibration time in seconds.
+ Default: 0.3.
diff --git a/Documentation/doc/1 modules/Inventory.html b/Documentation/doc/1 modules/Inventory.html
index 45a377928..1c069126b 100644
--- a/Documentation/doc/1 modules/Inventory.html
+++ b/Documentation/doc/1 modules/Inventory.html
@@ -124,11 +124,11 @@
- GiveItem(objectID[, count][, addToPickupSummary])
+ GiveItem(objectID, [count], [addToPickupSummary])
Add an item to the player's inventory.
- TakeItem(Object[, count])
+ TakeItem(Object, [count])
Remove an item from the player's inventory.
@@ -162,7 +162,7 @@
- GiveItem(objectID[, count][, addToPickupSummary])
+ GiveItem(objectID, [count], [addToPickupSummary])
Add an item to the player's inventory.
@@ -178,12 +178,12 @@
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.
- (optional )
+ Optional.
addToPickupSummary
bool
If true, display the item in the pickup summary. Default is false.
- (optional )
+ Optional.
@@ -194,7 +194,7 @@
- TakeItem(Object[, count])
+ TakeItem(Object, [count])
Remove an item from the player's inventory.
@@ -210,7 +210,7 @@
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.
- (optional )
+ Optional.
diff --git a/Documentation/doc/1 modules/Sound.html b/Documentation/doc/1 modules/Sound.html
index 6f1305b02..be07997d5 100644
--- a/Documentation/doc/1 modules/Sound.html
+++ b/Documentation/doc/1 modules/Sound.html
@@ -144,7 +144,7 @@
Get current loudness level for specified track type.
- PlaySound(soundID[, position])
+ PlaySound(soundID, [position])
Play sound effect.
@@ -291,7 +291,7 @@
- PlaySound(soundID[, position])
+ PlaySound(soundID, [position])
Play sound effect.
@@ -307,7 +307,7 @@
position
Vec3
The 3D position of the sound, i.e. where the sound "comes from". If not given, the sound will not be positional.
- (optional )
+ Optional.
diff --git a/Documentation/doc/1 modules/Util.html b/Documentation/doc/1 modules/Util.html
index a9b7c3972..4981e18db 100644
--- a/Documentation/doc/1 modules/Util.html
+++ b/Documentation/doc/1 modules/Util.html
@@ -152,7 +152,7 @@
Pick a static mesh by the given display position.
- PrintLog(message, logLevel[, allowSpam])
+ PrintLog(message, logLevel, [allowSpam])
Write messages within the Log file
@@ -414,7 +414,7 @@ To be used with
- PrintLog(message, logLevel[, allowSpam])
+ PrintLog(message, logLevel, [allowSpam])
Write messages within the Log file
@@ -439,7 +439,7 @@ To be used with allowSpam
bool
true allows spamming of the message
- (optional )
+ Optional.
diff --git a/Documentation/doc/1 modules/View.html b/Documentation/doc/1 modules/View.html
index 557e35756..51c5b824e 100644
--- a/Documentation/doc/1 modules/View.html
+++ b/Documentation/doc/1 modules/View.html
@@ -176,11 +176,11 @@
Play a flyby sequence.
- GetFlybyPosition(seqID, progress[, loop])
+ GetFlybyPosition(seqID, progress, [loop])
Get a flyby sequence's position at a specified progress point in percent.
- GetFlybyRotation(seqID, progress[, loop])
+ GetFlybyRotation(seqID, progress, [loop])
Get a flyby sequence's rotation at a specified progress point in percent.
@@ -499,7 +499,7 @@
- GetFlybyPosition(seqID, progress[, loop])
+ GetFlybyPosition(seqID, progress, [loop])
Get a flyby sequence's position at a specified progress point in percent.
@@ -519,7 +519,7 @@
loop
bool
Smooth the position near start and end points, as if the sequence is looped.
- (optional )
+ Optional.
@@ -536,7 +536,7 @@
- GetFlybyRotation(seqID, progress[, loop])
+ GetFlybyRotation(seqID, progress, [loop])
Get a flyby sequence's rotation at a specified progress point in percent.
@@ -556,7 +556,7 @@
loop
bool
Smooth the position near start and end points, as if the sequence is looped.
- (optional )
+ Optional.
diff --git a/Documentation/doc/2 classes/Collision.Probe.html b/Documentation/doc/2 classes/Collision.Probe.html
index 19c7f4ec2..f10d87d34 100644
--- a/Documentation/doc/2 classes/Collision.Probe.html
+++ b/Documentation/doc/2 classes/Collision.Probe.html
@@ -122,7 +122,7 @@
- Probe(pos[, roomNumber])
+ Probe(pos, [roomNumber])
Create a Probe at a specified world position in a room.
@@ -220,7 +220,7 @@
- Probe(pos[, roomNumber])
+ Probe(pos, [roomNumber])
Create a Probe at a specified world position in a room.
@@ -236,7 +236,7 @@
roomNumber
int
Room number. Must be used if probing a position in an overlapping room.
- (optional )
+ Optional.
diff --git a/Documentation/doc/2 classes/Objects.Camera.html b/Documentation/doc/2 classes/Objects.Camera.html
index 630d1a44f..3ca2f2939 100644
--- a/Documentation/doc/2 classes/Objects.Camera.html
+++ b/Documentation/doc/2 classes/Objects.Camera.html
@@ -330,7 +330,7 @@
Target
Moveable
If you put a moveable, the camera will look at it. Otherwise, it will look at Lara.
- (optional )
+ Optional.
diff --git a/Documentation/doc/2 classes/Objects.LaraObject.html b/Documentation/doc/2 classes/Objects.LaraObject.html
index 41fefa5bc..7192dc620 100644
--- a/Documentation/doc/2 classes/Objects.LaraObject.html
+++ b/Documentation/doc/2 classes/Objects.LaraObject.html
@@ -229,7 +229,7 @@
poison
int
Poison strength. Maximum value is 128 (default 0)
- (optional )
+ Optional.
diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html
index 45f4fa252..5810dedcc 100644
--- a/Documentation/doc/2 classes/Objects.Moveable.html
+++ b/Documentation/doc/2 classes/Objects.Moveable.html
@@ -166,13 +166,13 @@
Get the moveable's position
- Moveable:SetPosition(position[, updateRoom])
+ Moveable:SetPosition(position, [updateRoom])
Set the moveable's position
If you are moving a moveable whose behaviour involves knowledge of room geometry,
(e.g.
- Moveable:GetJointPosition(jointIndex[, offset])
+ Moveable:GetJointPosition(jointIndex, [offset])
Get the moveable's joint position with an optional relative offset.
@@ -217,11 +217,11 @@
Set OCB (object code bit) of the moveable
- Moveable:SetEffect(effect[, timeout])
+ Moveable:SetEffect(effect, [timeout])
Set the effect for this moveable.
- Moveable:SetCustomEffect(color1, color2[, timeout])
+ Moveable:SetCustomEffect(color1, color2, [timeout])
Set custom colored burn effect to moveable
@@ -285,7 +285,7 @@
Retrieve the index of the current animation.
- Moveable:SetAnim(index[, slot])
+ Moveable:SetAnim(index, [slot])
Set the object's animation to the one specified by the given index.
@@ -364,7 +364,7 @@
if it is not swapped.
- Moveable:SwapMesh(index, slotIndex[, swapIndex])
+ Moveable:SwapMesh(index, slotIndex, [swapIndex])
Set state of specified mesh swap of object
Use this to swap specified mesh of an object.
@@ -741,7 +741,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
- Moveable:SetPosition(position[, updateRoom])
+ Moveable:SetPosition(position, [updateRoom])
Set the moveable's position
@@ -760,7 +760,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
updateRoom
bool
Will room changes be automatically detected? Set to false if you are using overlapping rooms (default: true)
- (optional )
+ Optional.
@@ -771,7 +771,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
- Moveable:GetJointPosition(jointIndex[, offset])
+ Moveable:GetJointPosition(jointIndex, [offset])
Get the moveable's joint position with an optional relative offset.
@@ -787,7 +787,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
offset
Vec3
Offset relative to the joint.
- (optional )
+ Optional.
@@ -1026,7 +1026,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
- Moveable:SetEffect(effect[, timeout])
+ Moveable:SetEffect(effect, [timeout])
Set the effect for this moveable.
@@ -1042,7 +1042,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
timeout
float
time (in seconds) after which effect turns off.
- (optional )
+ Optional.
@@ -1053,7 +1053,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
- Moveable:SetCustomEffect(color1, color2[, timeout])
+ Moveable:SetCustomEffect(color1, color2, [timeout])
Set custom colored burn effect to moveable
@@ -1073,7 +1073,7 @@ baddy:SetOnCollidedWithRoom(LevelFuncs.roomCollided)
timeout
float
Time (in seconds) after which effect turns off.
- (optional )
+ Optional.
@@ -1423,7 +1423,7 @@ sas:SetAIBits({1 , 0 ,
- Moveable:SetAnim(index[, slot])
+ Moveable:SetAnim(index, [slot])
Set the object's animation to the one specified by the given index.
@@ -1441,7 +1441,7 @@ sas:SetAIBits({1 , 0 , slot
int
slot ID of the desired anim (if omitted, moveable's own slot ID is used)
- (optional )
+ Optional.
@@ -1857,7 +1857,7 @@ sas:SetPosition(newPos, false )
- Moveable:SwapMesh(index, slotIndex[, swapIndex])
+ Moveable:SwapMesh(index, slotIndex, [swapIndex])
Set state of specified mesh swap of object
@@ -1878,7 +1878,7 @@ sas:SetPosition(newPos, false )
swapIndex
int
index of a mesh from meshswap slot to use
- (optional )
+ Optional.
diff --git a/Documentation/doc/2 classes/Strings.DisplayString.html b/Documentation/doc/2 classes/Strings.DisplayString.html
index d4b209327..4f1088fad 100644
--- a/Documentation/doc/2 classes/Strings.DisplayString.html
+++ b/Documentation/doc/2 classes/Strings.DisplayString.html
@@ -129,7 +129,7 @@ when you need to use screen-space coordinates.