Merge branch 'develop' into mod

This commit is contained in:
davidmarr 2024-12-26 11:59:22 +01:00
commit 7bf0ffef6c
181 changed files with 2452 additions and 1755 deletions

View file

@ -3,12 +3,25 @@
The dates are in European standard format where date is presented as **YYYY-MM-DD**. The dates are in European standard format where date is presented as **YYYY-MM-DD**.
TombEngine releases are located in this repository (alongside with Tomb Editor): https://github.com/TombEngine/TombEditorReleases TombEngine releases are located in this repository (alongside with Tomb Editor): https://github.com/TombEngine/TombEditorReleases
## Version 1.6 - xxxx-xx-xx ## Version 1.8 - xxxx-xx-xx
### Bug fixes
* Fixed static meshes with dynamic light mode not accepting room lights.
* Fixed antialiasing quality not changing after changing it in display settings.
### New Features
* Added realtime shader reloading in debug mode by pressing F9 key.
### Lua API changes
## [Version 1.7](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.3) - 2024-12-25
### Bug fixes ### Bug fixes
* Significantly improved renderer performance. * Significantly improved renderer performance.
* Improved engine performance around bridges. * Improved engine performance around bridges.
* Improved engine performance if weather or bubble effects are active. * Improved engine performance if weather or bubble effects are active.
* Improved engine start-up time.
* Fixed silent crashes if loaded level is corrupted or in incorrect format. * Fixed silent crashes if loaded level is corrupted or in incorrect format.
* Fixed occasional crashes if there are static meshes placed within room border walls. * Fixed occasional crashes if there are static meshes placed within room border walls.
* Fixed climbable pushables clipping Lara under the bridges when pulled. * Fixed climbable pushables clipping Lara under the bridges when pulled.
@ -30,19 +43,23 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
* Fixed incorrect object camera position. * Fixed incorrect object camera position.
* Fixed incorrect camera movement near walls after leaving look mode. * Fixed incorrect camera movement near walls after leaving look mode.
* Fixed binocular or lasersight camera not switching off correctly after flyby. * Fixed binocular or lasersight camera not switching off correctly after flyby.
* Fixed binocular or lasersight camera transitions.
* Fixed target highlighter still being active in binocular or lasersight mode.
* Fixed Lara's Home entry not working. * Fixed Lara's Home entry not working.
* Fixed exploding TR3 bosses. * Fixed exploding TR3 bosses.
* Fixed original issue with deactivation of Dart Emitter. * Fixed original issue with deactivation of Dart Emitter.
* Fixed original issue with weapon hotkeys available in binoculars or lasersight mode. * Fixed original issue with weapon hotkeys available in binoculars or lasersight mode.
* Fixed Electricity Wires object not doing instant kill when Lara is in close proximity.
* Fixed Lens Flare object not functioning properly. * Fixed Lens Flare object not functioning properly.
* Fixed lens flares not being occluded by static meshes and moveables. * Fixed lens flares not being occluded by static meshes and moveables.
* Fixed spotlight shadows. * Fixed spotlight shadows.
* Fixed Skeleton and Mummy not reacting to shotgun hits. * Fixed Skeleton and Mummy not reacting to shotgun hits.
### New Features ### New Features
* Added fast savegame reloading. * 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 ability to customize many hardcoded parameters, such as flare, weapon, and hair settings.
* Added dynamic shadow casting on objects and static meshes. * Added dynamic shadow casting on objects and static meshes.
* Added fast savegame reloading.
* Added ricochet sounds and make the effect more prominent. * Added ricochet sounds and make the effect more prominent.
* Allow camera shake during flybys. * Allow camera shake during flybys.
* Allow to run the engine without title level. * Allow to run the engine without title level.
@ -52,22 +69,22 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
### Lua API changes ### Lua API changes
* Added Flow.Statistics class, Flow.GetStatistics() and Flow.SetStatistics() functions. * Added Flow.Statistics class, Flow.GetStatistics() and Flow.SetStatistics() functions.
* Added Flow.GetFreezeMode() and Flow.SetFreezeMode() functions. * Added Flow.GetFreezeMode() and Flow.SetFreezeMode() functions.
* Added Flow.GetNextLevel() function to get script entry for incoming level, if it's about to start.
* Added Effects.EmitSpotLight() function for directional spotlights. * Added Effects.EmitSpotLight() function for directional spotlights.
* Added optional cast shadow and name parameters for Effects.EmitLight() function. * Added optional cast shadow and name parameters for Effects.EmitLight() function.
* Added Effects.GetWind() function to get current wind speed vector. * Added Effects.GetWind() function to get current wind speed vector.
* Added Moveable:GetCollidable() and Moveable:SetCollidable() functions. * Added Moveable:GetCollidable() and Moveable:SetCollidable() functions.
* Added Moveable:GetAnimSlot() and optional second argument for Moveable:SetAnim() to access different animation slots.
* Added Rotation:Direction() method to get directional vector. * Added Rotation:Direction() method to get directional vector.
* Added support for transparency value in Strings.DisplayString class. * Added support for transparency value in Strings.DisplayString class.
* Added extra argument for Sound.SetAmbientTrack() function to specify if new ambient track should play from the beginning. * Added extra argument for Sound.SetAmbientTrack() function to specify if new ambient track should play from the beginning.
* Added new View.CameraType enum entries and return it by View.GetCameraType(), when flyby camera or binoculars/lasersight is active. * Added new View.CameraType enum entries and return it by View.GetCameraType(), when flyby camera or binoculars/lasersight is active.
* Added new primitive Time class, which allows to manipulate and format game time without precision loss. * Added new primitive Time class, which allows to manipulate and format game time without precision loss.
* Allow to use TR4-like load cameras by playing fixed camera from OnEnd() event and removing loadScreenFile field from level's gameflow entry.
* Renamed Flow.WeaponType enumeration to Objects.WeaponType, and removed similar Objects.LaraWeaponType enumeration for consistency. * Renamed Flow.WeaponType enumeration to Objects.WeaponType, and removed similar Objects.LaraWeaponType enumeration for consistency.
* Renamed Objects.PlayerAmmoType to Objects.AmmoType for consistency. * Renamed Objects.PlayerAmmoType to Objects.AmmoType for consistency.
* Fixed Strings.DisplayString class not supporting some Unicode characters and empty lines in multiline strings. * Fixed Strings.DisplayString class not supporting some Unicode characters and empty lines in multiline strings.
* Fixed Strings.DisplayString not being deallocated after showing. * Fixed Strings.DisplayString not being deallocated after showing.
* Fixed GameVars not transferring between levels in hub mode. * Fixed GameVars not transferring between levels in hub mode.
* Fixed incorrect return value of Moveable:GetAnim() function, if animation from another slot is currently playing.
* Fixed incorrect behaviour of Moveable:GetJointRotation() function. * Fixed incorrect behaviour of Moveable:GetJointRotation() function.
* Fixed incorrect behaviour of Logic.EnableEvent() and Logic.DisableEvent() functions. * Fixed incorrect behaviour of Logic.EnableEvent() and Logic.DisableEvent() functions.
* Fixed Util.HasLineOfSight() not taking static meshes into consideration. * Fixed Util.HasLineOfSight() not taking static meshes into consideration.

View file

@ -12,7 +12,7 @@ new_type("luautil", "5 Lua utility modules", true)
not_luadoc = true not_luadoc = true
local version = "1.6" local version = "1.7"
project = " TombEngine" project = " TombEngine"
title = "TombEngine " .. version .. " Lua API" title = "TombEngine " .. version .. " Lua API"
description = "TombEngine " .. version .. " scripting interface" description = "TombEngine " .. version .. " scripting interface"

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -167,10 +167,6 @@ scripts too.</p>
<td class="summary">Returns the level that the game control is running in that moment.</td> <td class="summary">Returns the level that the game control is running in that moment.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#GetNextLevel">GetNextLevel()</a></td>
<td class="summary">Returns the level that is about to load.</td>
</tr>
<tr>
<td class="name" ><a href="#EndLevel">EndLevel([index][, startPos])</a></td> <td class="name" ><a href="#EndLevel">EndLevel([index][, startPos])</a></td>
<td class="summary">Finishes the current level, with optional level index and start position index provided.</td> <td class="summary">Finishes the current level, with optional level index and start position index provided.</td>
</tr> </tr>
@ -559,27 +555,6 @@ have an ID of 0, the second an ID of 1, and so on.
</dd>
<dt>
<a name = "GetNextLevel"></a>
<strong>GetNextLevel()</strong>
</dt>
<dd>
Returns the level that is about to load. If no new level is about to load, returns current level.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../2 classes/Flow.Level.html#">Level</a></span>
incoming new level or current level, if no new level is loading
</ol>
</dd> </dd>
<dt> <dt>
<a name = "EndLevel"></a> <a name = "EndLevel"></a>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -524,6 +524,14 @@ end
</code></pre> </code></pre>
</li> </li>
<li><span class="parameter">OnUseItem</span>
<span class="types"><span class="type">function</span></span>
Will be called when using an item from inventory.
</li>
<li><span class="parameter">OnFreeze</span>
<span class="types"><span class="type">function</span></span>
Will be called when any of the Freeze modes are activated.
</li>
</ul> </ul>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -122,7 +122,7 @@
<td class="summary">Ammo used.</td> <td class="summary">Ammo used.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#traveledDistance">traveledDistance</a></td> <td class="name" ><a href="#distanceTraveled">distanceTraveled</a></td>
<td class="summary">Distance traveled.</td> <td class="summary">Distance traveled.</td>
</tr> </tr>
<tr> <tr>
@ -197,8 +197,8 @@
</dd> </dd>
<dt> <dt>
<a name = "traveledDistance"></a> <a name = "distanceTraveled"></a>
<strong>traveledDistance</strong> <strong>distanceTraveled</strong>
</dt> </dt>
<dd> <dd>
Distance traveled. Distance traveled.
@ -206,7 +206,7 @@
<ul> <ul>
<li><span class="parameter">traveledDistance</span> <li><span class="parameter">distanceTraveled</span>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
amount of traveled distance in world units. One meter is 420 world units. amount of traveled distance in world units. One meter is 420 world units.
</li> </li>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -171,14 +171,26 @@ pickups, and Lara herself (see also <a href="../2 classes/Objects.LaraObject.htm
<td class="summary">Retrieve the index of the current animation.</td> <td class="summary">Retrieve the index of the current animation.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#Moveable:SetAnim">Moveable:SetAnim(index)</a></td> <td class="name" ><a href="#Moveable:SetAnim">Moveable:SetAnim(index[, slot])</a></td>
<td class="summary">Set the object's animation to the one specified by the given index.</td> <td class="summary">Set the object's animation to the one specified by the given index.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#Moveable:GetAnimSlot">Moveable:GetAnimSlot()</a></td>
<td class="summary">Retrieve the slot ID of the animation.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:GetFrame">Moveable:GetFrame()</a></td> <td class="name" ><a href="#Moveable:GetFrame">Moveable:GetFrame()</a></td>
<td class="summary">Retrieve frame number.</td> <td class="summary">Retrieve frame number.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#Moveable:SetFrame">Moveable:SetFrame(frame)</a></td>
<td class="summary">Set frame number.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:GetEndFrame">Moveable:GetEndFrame()</a></td>
<td class="summary">Get the end frame number of the moveable's active animation.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:SetVelocity">Moveable:SetVelocity(velocity)</a></td> <td class="name" ><a href="#Moveable:SetVelocity">Moveable:SetVelocity(velocity)</a></td>
<td class="summary">Set the object's velocity to specified value.</td> <td class="summary">Set the object's velocity to specified value.</td>
</tr> </tr>
@ -187,10 +199,6 @@ pickups, and Lara herself (see also <a href="../2 classes/Objects.LaraObject.htm
<td class="summary">Get the object's velocity.</td> <td class="summary">Get the object's velocity.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#Moveable:SetFrame">Moveable:SetFrame(frame)</a></td>
<td class="summary">Set frame number.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:GetHP">Moveable:GetHP()</a></td> <td class="name" ><a href="#Moveable:GetHP">Moveable:GetHP()</a></td>
<td class="summary">Get current HP (hit points/health points)</td> <td class="summary">Get current HP (hit points/health points)</td>
</tr> </tr>
@ -324,10 +332,6 @@ pickups, and Lara herself (see also <a href="../2 classes/Objects.LaraObject.htm
<td class="summary">Set AIBits of object <td class="summary">Set AIBits of object
Use this to force a moveable into a certain AI mode or modes, as if a certain nullmesh Use this to force a moveable into a certain AI mode or modes, as if a certain nullmesh
(or more than one) had suddenly spawned beneath their feet.</td> (or more than one) had suddenly spawned beneath their feet.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:GetEndFrame">Moveable:GetEndFrame()</a></td>
<td class="summary">Get the end frame number of the moveable's active animation.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#Moveable:GetRoom">Moveable:GetRoom()</a></td> <td class="name" ><a href="#Moveable:GetRoom">Moveable:GetRoom()</a></td>
@ -777,7 +781,7 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)</pre>
</dd> </dd>
<dt> <dt>
<a name = "Moveable:SetAnim"></a> <a name = "Moveable:SetAnim"></a>
<strong>Moveable:SetAnim(index)</strong> <strong>Moveable:SetAnim(index[, slot])</strong>
</dt> </dt>
<dd> <dd>
Set the object's animation to the one specified by the given index. Set the object's animation to the one specified by the given index.
@ -792,12 +796,40 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)</pre>
<span class="types"><span class="type">int</span></span> <span class="types"><span class="type">int</span></span>
the index of the desired anim the index of the desired anim
</li> </li>
<li><span class="parameter">slot</span>
<span class="types"><span class="type">int</span></span>
slot ID of the desired anim (if omitted, moveable's own slot ID is used)
(<em>optional</em>)
</li>
</ul> </ul>
</dd>
<dt>
<a name = "Moveable:GetAnimSlot"></a>
<strong>Moveable:GetAnimSlot()</strong>
</dt>
<dd>
Retrieve the slot ID of the animation.
In certain cases, moveable may play animations from another object slot. Use this
function when you need to identify such cases.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">int</span></span>
animation slot ID
</ol>
</dd> </dd>
<dt> <dt>
<a name = "Moveable:GetFrame"></a> <a name = "Moveable:GetFrame"></a>
@ -820,6 +852,54 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)</pre>
</dd>
<dt>
<a name = "Moveable:SetFrame"></a>
<strong>Moveable:SetFrame(frame)</strong>
</dt>
<dd>
Set frame number.
This will move the animation to the given frame.
The number of frames in an animation can be seen under the heading "End frame" in
the WadTool animation editor. If the animation has no frames, the only valid argument
is -1.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">frame</span>
<span class="types"><span class="type">int</span></span>
the new frame number
</li>
</ul>
</dd>
<dt>
<a name = "Moveable:GetEndFrame"></a>
<strong>Moveable:GetEndFrame()</strong>
</dt>
<dd>
Get the end frame number of the moveable's active animation.
This is the "End Frame" set in WADTool for the animation.()
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">int</span></span>
End frame number of the active animation.
</ol>
</dd> </dd>
<dt> <dt>
<a name = "Moveable:SetVelocity"></a> <a name = "Moveable:SetVelocity"></a>
@ -867,32 +947,6 @@ shiva:SetObjectID(TEN.Objects.ObjID.BIGMEDI_ITEM)</pre>
</dd>
<dt>
<a name = "Moveable:SetFrame"></a>
<strong>Moveable:SetFrame(frame)</strong>
</dt>
<dd>
Set frame number.
This will move the animation to the given frame.
The number of frames in an animation can be seen under the heading "End frame" in
the WadTool animation editor. If the animation has no frames, the only valid argument
is -1.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">frame</span>
<span class="types"><span class="type">int</span></span>
the new frame number
</li>
</ul>
</dd> </dd>
<dt> <dt>
<a name = "Moveable:GetHP"></a> <a name = "Moveable:GetHP"></a>
@ -1661,28 +1715,6 @@ baddy:SetOnKilled(LevelFuncs.baddyKilled)</pre>
sas:SetAIBits({<span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>})</pre> sas:SetAIBits({<span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>})</pre>
</ul> </ul>
</dd>
<dt>
<a name = "Moveable:GetEndFrame"></a>
<strong>Moveable:GetEndFrame()</strong>
</dt>
<dd>
Get the end frame number of the moveable's active animation.
This is the "End Frame" set in WADTool for the animation.()
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">int</span></span>
End frame number of the active animation.
</ol>
</dd> </dd>
<dt> <dt>
<a name = "Moveable:GetRoom"></a> <a name = "Moveable:GetRoom"></a>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -170,9 +170,9 @@ ACTOR1_SPEECH_HEAD1
ACTOR1_SPEECH_HEAD2 ACTOR1_SPEECH_HEAD2
ACTOR2_SPEECH_HEAD1 ACTOR2_SPEECH_HEAD1
ACTOR2_SPEECH_HEAD2 ACTOR2_SPEECH_HEAD2
LARA_BINOCULARS_MESH
LARA_EXTRA_MESH1 LARA_EXTRA_MESH1
LARA_EXTRA_MESH2 LARA_EXTRA_MESH2
LARA_EXTRA_MESH3
LARA_WATER_MESH LARA_WATER_MESH
LARA_PETROL_MESH LARA_PETROL_MESH
LARA_DIRT_MESH LARA_DIRT_MESH

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" /> <link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head> </head>
<body> <body>

View file

@ -3,7 +3,7 @@
<html> <html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head> <head>
<title>TombEngine 1.6 Lua API</title> <title>TombEngine 1.7 Lua API</title>
<link rel="stylesheet" href="ldoc.css" type="text/css" /> <link rel="stylesheet" href="ldoc.css" type="text/css" />
</head> </head>
<body> <body>
@ -107,7 +107,7 @@
<div id="content"> <div id="content">
<h2>TombEngine 1.6 scripting interface</h2> <h2>TombEngine 1.7 scripting interface</h2>
<p>Welcome to the TombEngine scripting API. This is a work in progress and some information might be wrong or outdated. Please also note that this is primarily a reference document, not a tutorial, so expect descriptions to be fairly sparse.</p> <p>Welcome to the TombEngine scripting API. This is a work in progress and some information might be wrong or outdated. Please also note that this is primarily a reference document, not a tutorial, so expect descriptions to be fairly sparse.</p>
<p>At the time of writing, there is a tutorial describing the basics of Lua, as well as a number of example scripts, on <a href="https://www.tombengine.com">the TombEngine website</a>.</p> <p>At the time of writing, there is a tutorial describing the basics of Lua, as well as a number of example scripts, on <a href="https://www.tombengine.com">the TombEngine website</a>.</p>

View file

@ -1,3 +1,4 @@
-- ldignore
local Util = {} local Util = {}
Util.ShortenTENCalls = function() Util.ShortenTENCalls = function()

View file

@ -57,7 +57,7 @@ test = Level.new()
test.nameKey = "level_test" test.nameKey = "level_test"
test.scriptFile = "Scripts\\Levels\\New_Level.lua" test.scriptFile = "Scripts\\Levels\\New_Level.lua"
test.ambientTrack = "108" test.ambientTrack = "108"
test.levelFile = "Data\\TestLevel.ten" test.levelFile = "Data\\Tut1_water.ten"
test.loadScreenFile = "Screens\\rome.jpg" test.loadScreenFile = "Screens\\rome.jpg"
-- 0 is no weather, 1 is rain, 2 is snow. -- 0 is no weather, 1 is rain, 2 is snow.

View file

@ -82,19 +82,19 @@ local settings = Flow.Settings.new()
settings.Weapons[WeaponType.REVOLVER].colorizeMuzzleFlash = false settings.Weapons[WeaponType.REVOLVER].colorizeMuzzleFlash = false
settings.Weapons[WeaponType.REVOLVER].pickupCount = 6 settings.Weapons[WeaponType.REVOLVER].pickupCount = 6
settings.Weapons[WeaponType.UZI].accuracy = 8 settings.Weapons[WeaponType.UZIS].accuracy = 8
settings.Weapons[WeaponType.UZI].targetingDistance = 8192 settings.Weapons[WeaponType.UZIS].targetingDistance = 8192
settings.Weapons[WeaponType.UZI].interval = 3 settings.Weapons[WeaponType.UZIS].interval = 3
settings.Weapons[WeaponType.UZI].waterLevel = 650 settings.Weapons[WeaponType.UZIS].waterLevel = 650
settings.Weapons[WeaponType.UZI].flashDuration = 2 settings.Weapons[WeaponType.UZIS].flashDuration = 2
settings.Weapons[WeaponType.UZI].flashRange = 9 settings.Weapons[WeaponType.UZIS].flashRange = 9
settings.Weapons[WeaponType.UZI].flashColor = Color(192, 128, 0) settings.Weapons[WeaponType.UZIS].flashColor = Color(192, 128, 0)
settings.Weapons[WeaponType.UZI].damage = 1 settings.Weapons[WeaponType.UZIS].damage = 1
settings.Weapons[WeaponType.UZI].smoke = true settings.Weapons[WeaponType.UZIS].smoke = true
settings.Weapons[WeaponType.UZI].shell = true settings.Weapons[WeaponType.UZIS].shell = true
settings.Weapons[WeaponType.UZI].muzzleFlash = true settings.Weapons[WeaponType.UZIS].muzzleFlash = true
settings.Weapons[WeaponType.UZI].colorizeMuzzleFlash = false settings.Weapons[WeaponType.UZIS].colorizeMuzzleFlash = false
settings.Weapons[WeaponType.UZI].pickupCount = 30 settings.Weapons[WeaponType.UZIS].pickupCount = 30
settings.Weapons[WeaponType.SHOTGUN].accuracy = 10 settings.Weapons[WeaponType.SHOTGUN].accuracy = 10
settings.Weapons[WeaponType.SHOTGUN].targetingDistance = 8192 settings.Weapons[WeaponType.SHOTGUN].targetingDistance = 8192

View file

@ -171,8 +171,10 @@ namespace TEN::Hud
void TargetHighlighterController::Update(const ItemInfo& playerItem) void TargetHighlighterController::Update(const ItemInfo& playerItem)
{ {
// Check if target highlighter is enabled. const auto& player = GetLaraInfo(playerItem);
if (!g_Configuration.EnableTargetHighlighter)
// Check if target highlighter is enabled or lasersight is active.
if (!g_Configuration.EnableTargetHighlighter || player.Control.Look.IsUsingBinoculars)
{ {
if (!_crosshairs.empty()) if (!_crosshairs.empty())
_crosshairs.clear(); _crosshairs.clear();
@ -180,8 +182,6 @@ namespace TEN::Hud
return; return;
} }
const auto& player = GetLaraInfo(playerItem);
// Loop over player targets. // Loop over player targets.
auto itemNumbers = std::vector<int>{}; auto itemNumbers = std::vector<int>{};
for (const auto* item : player.TargetList) for (const auto* item : player.TargetList)

View file

@ -0,0 +1,286 @@
#include "framework.h"
#include "Game/Lara/Optics.h"
#include "Game/camera.h"
#include "Game/control/los.h"
#include "Game/effects/effects.h"
#include "Game/items.h"
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_flare.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_one_gun.h"
#include "Game/Lara/lara_struct.h"
#include "Game/Lara/lara_two_guns.h"
#include "Game/Setup.h"
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
#include "Specific/Input/Input.h"
using namespace TEN::Input;
static void HandlePlayerOpticZoom(ItemInfo& item)
{
constexpr auto OPTICS_RANGE_MAX = ANGLE(8.5f);
constexpr auto OPTICS_RANGE_MIN = ANGLE(0.7f);
constexpr auto OPTICS_RANGE_RATE = ANGLE(0.35f);
auto& player = GetLaraInfo(item);
bool isSlow = IsHeld(In::Walk);
// Zoom optics.
if (player.Control.Look.IsUsingBinoculars || player.Control.Look.IsUsingLasersight)
{
short rangeRate = isSlow ? (OPTICS_RANGE_RATE / 2) : OPTICS_RANGE_RATE;
// NOTE: Zooming allowed with either StepLeft/StepRight or Walk/Sprint.
if ((IsHeld(In::StepLeft) && !IsHeld(In::StepRight)) ||
(IsHeld(In::Walk) && !IsHeld(In::Sprint)))
{
player.Control.Look.OpticRange -= rangeRate;
if (player.Control.Look.OpticRange < OPTICS_RANGE_MIN)
{
player.Control.Look.OpticRange = OPTICS_RANGE_MIN;
}
else
{
SoundEffect(SFX_TR4_BINOCULARS_ZOOM, nullptr, SoundEnvironment::Land, 0.9f);
}
}
else if ((IsHeld(In::StepRight) && !IsHeld(In::StepLeft)) ||
(IsHeld(In::Sprint) && !IsHeld(In::Walk)))
{
player.Control.Look.OpticRange += rangeRate;
if (player.Control.Look.OpticRange > OPTICS_RANGE_MAX)
{
player.Control.Look.OpticRange = OPTICS_RANGE_MAX;
}
else
{
SoundEffect(SFX_TR4_BINOCULARS_ZOOM, nullptr, SoundEnvironment::Land, 1.0f);
}
}
}
}
static void HandlePlayerOpticAnimations(ItemInfo& item)
{
auto& player = GetLaraInfo(item);
if (!player.Control.Look.IsUsingBinoculars && !player.Control.Look.IsUsingLasersight)
return;
int animNumber = Objects[ID_LARA_BINOCULARS_MESH].loaded ? LA_BINOCULARS_IDLE : LA_STAND_IDLE;
if (player.Control.Look.IsUsingLasersight)
{
switch (player.Control.Weapon.GunType)
{
case LaraWeaponType::Crossbow:
animNumber = Objects[ID_CROSSBOW_ANIM].animIndex + 2;
break;
case LaraWeaponType::Revolver:
animNumber = Objects[ID_REVOLVER_ANIM].animIndex + 3;
break;
case LaraWeaponType::HK:
animNumber = Objects[ID_HK_ANIM].animIndex + 2;
break;
}
}
else if (player.Control.Look.IsUsingBinoculars)
{
// Silently holster any weapon or drop any item currently in hand.
if (player.Control.Weapon.GunType == LaraWeaponType::Flare ||
player.Control.Weapon.GunType == LaraWeaponType::Torch)
{
CreateFlare(item, player.Control.Weapon.GunType == LaraWeaponType::Flare ? ID_FLARE_ITEM : ID_BURNING_TORCH_ITEM, 0);
UndrawFlareMeshes(item);
player.Torch.State = TorchState::Holding;
player.Torch.IsLit = false;
player.Flare.ControlLeft = false;
player.Flare.Life = 0;
player.Control.Weapon.GunType =
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
}
else if (player.Control.Weapon.GunType != LaraWeaponType::None &&
player.Control.HandStatus != HandStatus::Free)
{
if (player.Control.Weapon.GunType <= LaraWeaponType::Uzi)
{
UndrawPistolMesh(item, player.Control.Weapon.GunType, false);
UndrawPistolMesh(item, player.Control.Weapon.GunType, true);
}
else
{
if (player.Control.Weapon.WeaponItem != NO_VALUE)
{
KillItem(player.Control.Weapon.WeaponItem);
player.Control.Weapon.WeaponItem = NO_VALUE;
}
UndrawShotgunMeshes(item, player.Control.Weapon.GunType);
}
player.TargetEntity = nullptr;
}
int objNumber = Objects[ID_LARA_BINOCULARS_MESH].loaded ? ID_LARA_BINOCULARS_MESH : ID_LARA_SKIN;
item.Model.MeshIndex[LM_RHAND] = Objects[objNumber].meshIndex + LM_RHAND;
player.Control.HandStatus = HandStatus::Free;
}
player.LeftArm.Locked =
player.RightArm.Locked = false;
player.LeftArm.FrameNumber =
player.RightArm.FrameNumber = 0;
player.LeftArm.AnimNumber =
player.RightArm.AnimNumber = animNumber;
player.LeftArm.FrameBase =
player.RightArm.FrameBase = GetAnimData(animNumber).FramePtr;
}
static void ResetPlayerOpticAnimations(ItemInfo& item)
{
auto& player = GetLaraInfo(item);
ResetPlayerFlex(&item);
player.LeftArm.Locked =
player.RightArm.Locked = false;
player.LeftArm.AnimNumber =
player.RightArm.AnimNumber = 0;
player.LeftArm.FrameNumber =
player.RightArm.FrameNumber = 0;
player.RightArm.FrameBase =
player.LeftArm.FrameBase = GetAnimData(item).FramePtr;
player.Control.HandStatus = player.Control.Look.IsUsingLasersight ? HandStatus::WeaponReady : HandStatus::Free;
if (!player.Control.Look.IsUsingLasersight)
item.Model.MeshIndex[LM_RHAND] = item.Model.BaseMesh + LM_RHAND;
player.Control.Look.OpticRange = 0;
player.Control.Look.IsUsingBinoculars = player.Control.Look.IsUsingLasersight = false;
player.Inventory.IsBusy = false;
Camera.DisableInterpolation = true;
Camera.type = BinocularOldCamera;
Camera.bounce = 0;
AlterFOV(LastFOV);
SetScreenFadeIn(OPTICS_FADE_SPEED);
}
static void DoOpticsHighlight(const ItemInfo& item, const Vector3i& origin, const Vector3i& target)
{
auto origin2 = GameVector(origin, item.RoomNumber);
auto target2 = GameVector(target);
const auto& binocularsColor = g_GameFlow->GetSettings()->Camera.BinocularLightColor;
const auto& lasersightColor = g_GameFlow->GetSettings()->Camera.LasersightLightColor;
const auto& color = GetLaraInfo(item).Control.Look.IsUsingLasersight ? lasersightColor : binocularsColor;
SpawnDynamicLight(origin2.x, origin2.y, origin2.z, 12, color.GetR(), color.GetG(), color.GetB());
if (!LOS(&origin2, &target2))
{
int luma = sqrt(SQUARE(origin2.x - target2.x) + SQUARE(origin2.y - target2.y) + SQUARE(origin2.z - target2.z)) * CLICK(1);
if ((luma + 8) > 31)
luma = 31;
auto dir = origin2.ToVector3() - target2.ToVector3();
dir.Normalize();
dir *= BLOCK(1);
byte r = std::max(0, color.GetR() - luma);
byte g = std::max(0, color.GetG() - luma);
byte b = std::max(0, color.GetB() - luma);
SpawnDynamicLight(target2.x + dir.x, target2.y + dir.y, target2.z + dir.z, luma + 12, r, g, b);
}
}
bool HandlePlayerOptics(ItemInfo& item)
{
auto& player = GetLaraInfo(item);
bool breakOptics = true;
// Standing; can use optics.
if (item.Animation.ActiveState == LS_IDLE || item.Animation.AnimNumber == LA_STAND_IDLE)
breakOptics = false;
// Crouching; can use optics.
if ((player.Control.IsLow || !IsHeld(In::Crouch)) &&
(item.Animation.TargetState == LS_CROUCH_IDLE || item.Animation.AnimNumber == LA_CROUCH_IDLE))
{
breakOptics = false;
}
// If lasersight and Look is not held, exit optics.
if (player.Control.Look.IsUsingLasersight && !IsHeld(In::Look))
breakOptics = true;
// If lasersight and weapon is holstered, exit optics.
if (player.Control.Look.IsUsingLasersight && IsHeld(In::Draw))
breakOptics = true;
// Engage lasersight if available.
if (!breakOptics && !player.Control.Look.IsUsingLasersight && IsHeld(In::Look))
{
if (player.Control.HandStatus == HandStatus::WeaponReady &&
((player.Control.Weapon.GunType == LaraWeaponType::HK && player.Weapons[(int)LaraWeaponType::HK].HasLasersight) ||
(player.Control.Weapon.GunType == LaraWeaponType::Revolver && player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight) ||
(player.Control.Weapon.GunType == LaraWeaponType::Crossbow && player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight)))
{
player.Control.Look.OpticRange = OPTICS_RANGE_DEFAULT;
player.Control.Look.IsUsingBinoculars = true;
player.Control.Look.IsUsingLasersight = true;
player.Inventory.IsBusy = true;
Camera.DisableInterpolation = true;
BinocularOldCamera = Camera.oldType;
SetScreenFadeIn(OPTICS_FADE_SPEED);
}
}
// Not using optics; return early.
if (!player.Control.Look.IsUsingBinoculars && !player.Control.Look.IsUsingLasersight)
return true;
AlterFOV(7 * (ANGLE(11.5f) - player.Control.Look.OpticRange), false);
// Handle various binocular controls.
if (!player.Control.Look.IsUsingLasersight)
{
if (IsClicked(In::Deselect) ||
IsClicked(In::Roll) ||
IsClicked(In::Jump) ||
IsClicked(In::Draw) ||
IsClicked(In::Look) ||
IsHeld(In::Flare))
{
breakOptics = true;
}
}
// Handle lasersight highlight.
if (player.Control.Look.IsUsingLasersight || IsHeld(In::Action))
{
if (!player.Control.Look.IsUsingLasersight)
ClearAction(In::Action);
auto origin = Camera.pos.ToVector3i();
auto target = Camera.target.ToVector3i();
DoOpticsHighlight(item, origin, target);
}
if (!breakOptics)
{
HandlePlayerOpticAnimations(item);
HandlePlayerOpticZoom(item);
return true;
}
else
{
ResetPlayerOpticAnimations(item);
return false;
}
}

View file

@ -0,0 +1,10 @@
#pragma once
#include "Specific/clock.h"
struct ItemInfo;
constexpr auto OPTICS_FADE_SPEED = 6.0f / FPS;
constexpr auto OPTICS_RANGE_DEFAULT = ANGLE(0.7f);
bool HandlePlayerOptics(ItemInfo& item);

View file

@ -38,7 +38,7 @@ namespace TEN::Entities::Player
} }
if (IsHeld(In::Action)) if (IsHeld(In::Action))
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 31, 150, 150, 150); SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 31, 150, 150, 150);
if (IsHeld(In::Jump)) if (IsHeld(In::Jump))
{ {

View file

@ -572,7 +572,7 @@ void HandleWeapon(ItemInfo& laraItem)
player.Control.HandStatus = HandStatus::WeaponUndraw; player.Control.HandStatus = HandStatus::WeaponUndraw;
} }
} }
else if (player.Inventory.TotalFlares) else if (player.Inventory.TotalFlares && !player.Control.Look.IsUsingBinoculars)
{ {
if (player.Inventory.TotalFlares != -1) if (player.Inventory.TotalFlares != -1)
player.Inventory.TotalFlares--; player.Inventory.TotalFlares--;
@ -837,7 +837,7 @@ void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo)
} }
// TODO: Include snowmobile gun in GetAmmo(), otherwise the player won't be able to shoot while controlling it. -- TokyoSU 2023.04.21 // TODO: Include snowmobile gun in GetAmmo(), otherwise the player won't be able to shoot while controlling it. -- TokyoSU 2023.04.21
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient) FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient)
{ {
auto& player = *GetLaraInfo(&laraItem); auto& player = *GetLaraInfo(&laraItem);
auto& ammo = GetAmmo(player, weaponType); auto& ammo = GetAmmo(player, weaponType);
@ -872,14 +872,14 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, Ite
GetFloor(pos.x, pos.y, pos.z, &roomNumber); GetFloor(pos.x, pos.y, pos.z, &roomNumber);
vOrigin.RoomNumber = roomNumber; vOrigin.RoomNumber = roomNumber;
if (&targetEntity == nullptr) if (targetEntity == nullptr)
{ {
auto vTarget = GameVector(target); auto vTarget = GameVector(target);
GetTargetOnLOS(&vOrigin, &vTarget, false, true); GetTargetOnLOS(&vOrigin, &vTarget, false, true);
return FireWeaponType::Miss; return FireWeaponType::Miss;
} }
auto spheres = targetEntity.GetSpheres(); auto spheres = targetEntity->GetSpheres();
int closestJointIndex = NO_VALUE; int closestJointIndex = NO_VALUE;
float closestDist = INFINITY; float closestDist = INFINITY;
for (int i = 0; i < spheres.size(); i++) for (int i = 0; i < spheres.size(); i++)
@ -909,7 +909,7 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, Ite
// NOTE: It seems that entities hit by the player in the normal way must have GetTargetOnLOS return false. // NOTE: It seems that entities hit by the player in the normal way must have GetTargetOnLOS return false.
// It's strange, but this replicates original behaviour until we fully understand what is happening. // It's strange, but this replicates original behaviour until we fully understand what is happening.
if (!GetTargetOnLOS(&vOrigin, &vTarget, false, true)) if (!GetTargetOnLOS(&vOrigin, &vTarget, false, true))
HitTarget(&laraItem, &targetEntity, &vTarget, weapon.Damage, false, closestJointIndex); HitTarget(&laraItem, targetEntity, &vTarget, weapon.Damage, false, closestJointIndex);
return FireWeaponType::PossibleHit; return FireWeaponType::PossibleHit;
} }

View file

@ -61,7 +61,7 @@ GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo& laraItem, LaraWeaponType weapon
void HandleWeapon(ItemInfo& laraItem); void HandleWeapon(ItemInfo& laraItem);
void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo); void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo);
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient); FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient);
void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo); void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo);
void LaraTargetInfo(ItemInfo& laraItem, const WeaponInfo& weaponInfo); void LaraTargetInfo(ItemInfo& laraItem, const WeaponInfo& weaponInfo);

View file

@ -20,6 +20,7 @@
#include "Sound/sound.h" #include "Sound/sound.h"
#include "Specific/clock.h" #include "Specific/clock.h"
#include "Specific/level.h" #include "Specific/level.h"
#include "Specific/trutils.h"
using namespace TEN::Collision::Point; using namespace TEN::Collision::Point;
using namespace TEN::Entities::Effects; using namespace TEN::Entities::Effects;
@ -496,7 +497,7 @@ bool DoFlareLight(ItemInfo& item, const Vector3i& pos, int flareLife)
auto color = (flareColor * intensity * std::clamp(mult, 0.0f, 1.0f)); auto color = (flareColor * intensity * std::clamp(mult, 0.0f, 1.0f));
// Spawn dynamic light. // Spawn dynamic light.
TriggerDynamicPointLight(lightPos, Color(color), falloff, false); SpawnDynamicPointLight(lightPos, Color(color), falloff, false, GetHash(item.Name));
// Spawn lensflare if brightness is not 0. // Spawn lensflare if brightness is not 0.
if (settings.LensflareBrightness > EPSILON) if (settings.LensflareBrightness > EPSILON)

View file

@ -448,70 +448,6 @@ static void ClearPlayerLookAroundActions(const ItemInfo& item)
} }
} }
static void SetPlayerOptics(ItemInfo* item)
{
constexpr auto OPTIC_RANGE_DEFAULT = ANGLE(0.7f);
auto& player = GetLaraInfo(*item);
bool breakOptics = true;
// Standing; can use optics.
if (item->Animation.ActiveState == LS_IDLE || item->Animation.AnimNumber == LA_STAND_IDLE)
breakOptics = false;
// Crouching; can use optics.
if ((player.Control.IsLow || !IsHeld(In::Crouch)) &&
(item->Animation.TargetState == LS_CROUCH_IDLE || item->Animation.AnimNumber == LA_CROUCH_IDLE))
{
breakOptics = false;
}
// If lasersight and Look is not held, exit optics.
if (player.Control.Look.IsUsingLasersight && !IsHeld(In::Look))
breakOptics = true;
// If lasersight and weapon is holstered, exit optics.
if (player.Control.Look.IsUsingLasersight && IsHeld(In::Draw))
breakOptics = true;
// Engage lasersight if available.
if (!player.Control.Look.IsUsingLasersight && !breakOptics && IsHeld(In::Look))
{
if (player.Control.HandStatus == HandStatus::WeaponReady &&
((player.Control.Weapon.GunType == LaraWeaponType::HK && player.Weapons[(int)LaraWeaponType::HK].HasLasersight) ||
(player.Control.Weapon.GunType == LaraWeaponType::Revolver && player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight) ||
(player.Control.Weapon.GunType == LaraWeaponType::Crossbow && player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight)))
{
player.Control.Look.OpticRange = OPTIC_RANGE_DEFAULT;
player.Control.Look.IsUsingBinoculars = true;
player.Control.Look.IsUsingLasersight = true;
player.Inventory.IsBusy = true;
Camera.DisableInterpolation = true;
BinocularOldCamera = Camera.oldType;
return;
}
}
if (!breakOptics)
return;
// Not using optics; return early.
if (!player.Control.Look.IsUsingBinoculars && !player.Control.Look.IsUsingLasersight)
return;
player.Control.Look.OpticRange = 0;
player.Control.Look.IsUsingBinoculars = false;
player.Control.Look.IsUsingLasersight = false;
player.Inventory.IsBusy = false;
Camera.DisableInterpolation = true;
Camera.type = BinocularOldCamera;
Camera.bounce = 0;
AlterFOV(LastFOV);
}
static short NormalizeLookAroundTurnRate(short turnRate, short opticRange) static short NormalizeLookAroundTurnRate(short turnRate, short opticRange)
{ {
constexpr auto ZOOM_LEVEL_MAX = ANGLE(10.0f); constexpr auto ZOOM_LEVEL_MAX = ANGLE(10.0f);
@ -525,9 +461,6 @@ static short NormalizeLookAroundTurnRate(short turnRate, short opticRange)
void HandlePlayerLookAround(ItemInfo& item, bool invertXAxis) void HandlePlayerLookAround(ItemInfo& item, bool invertXAxis)
{ {
constexpr auto OPTIC_RANGE_MAX = ANGLE(8.5f);
constexpr auto OPTIC_RANGE_MIN = ANGLE(0.7f);
constexpr auto OPTIC_RANGE_RATE = ANGLE(0.35f);
constexpr auto TURN_RATE_MAX = ANGLE(4.0f); constexpr auto TURN_RATE_MAX = ANGLE(4.0f);
constexpr auto TURN_RATE_ACCEL = ANGLE(0.75f); constexpr auto TURN_RATE_ACCEL = ANGLE(0.75f);
@ -535,44 +468,8 @@ void HandlePlayerLookAround(ItemInfo& item, bool invertXAxis)
// Set optics. // Set optics.
Camera.type = CameraType::Look; Camera.type = CameraType::Look;
SetPlayerOptics(LaraItem);
bool isSlow = IsHeld(In::Walk); bool isSlow = IsHeld(In::Walk);
// Zoom optics.
if (player.Control.Look.IsUsingBinoculars || player.Control.Look.IsUsingLasersight)
{
short rangeRate = isSlow ? (OPTIC_RANGE_RATE / 2) : OPTIC_RANGE_RATE;
// NOTE: Zooming allowed with either StepLeft/StepRight or Walk/Sprint.
if ((IsHeld(In::StepLeft) && !IsHeld(In::StepRight)) ||
(IsHeld(In::Walk) && !IsHeld(In::Sprint)))
{
player.Control.Look.OpticRange -= rangeRate;
if (player.Control.Look.OpticRange < OPTIC_RANGE_MIN)
{
player.Control.Look.OpticRange = OPTIC_RANGE_MIN;
}
else
{
SoundEffect(SFX_TR4_BINOCULARS_ZOOM, nullptr, SoundEnvironment::Land, 0.9f);
}
}
else if ((IsHeld(In::StepRight) && !IsHeld(In::StepLeft)) ||
(IsHeld(In::Sprint) && !IsHeld(In::Walk)))
{
player.Control.Look.OpticRange += rangeRate;
if (player.Control.Look.OpticRange > OPTIC_RANGE_MAX)
{
player.Control.Look.OpticRange = OPTIC_RANGE_MAX;
}
else
{
SoundEffect(SFX_TR4_BINOCULARS_ZOOM, nullptr, SoundEnvironment::Land, 1.0f);
}
}
}
auto axisCoeff = Vector2::Zero; auto axisCoeff = Vector2::Zero;
// Determine X axis coefficient. // Determine X axis coefficient.

View file

@ -395,7 +395,7 @@ void FireShotgun(ItemInfo& laraItem)
armOrient.y + scatter * (GetRandomControl() - ANGLE(90.0f)) / 65536, armOrient.y + scatter * (GetRandomControl() - ANGLE(90.0f)) / 65536,
0); 0);
if (FireWeapon(LaraWeaponType::Shotgun, *player.TargetEntity, laraItem, wobbledArmOrient) != FireWeaponType::NoAmmo) if (FireWeapon(LaraWeaponType::Shotgun, player.TargetEntity, laraItem, wobbledArmOrient) != FireWeaponType::NoAmmo)
hasFired = true; hasFired = true;
// HACK: Compensate for spending 6 units of shotgun ammo. -- Lwmte, 18.11.22 // HACK: Compensate for spending 6 units of shotgun ammo. -- Lwmte, 18.11.22
@ -972,7 +972,7 @@ void RocketControl(short itemNumber)
// Trigger fire, smoke, and light. // Trigger fire, smoke, and light.
TriggerRocketSmoke(wx + rocketItem.Pose.Position.x, wy + rocketItem.Pose.Position.y, wz + rocketItem.Pose.Position.z); TriggerRocketSmoke(wx + rocketItem.Pose.Position.x, wy + rocketItem.Pose.Position.y, wz + rocketItem.Pose.Position.z);
TriggerRocketFire(wx + rocketItem.Pose.Position.x, wy + rocketItem.Pose.Position.y, wz + rocketItem.Pose.Position.z); TriggerRocketFire(wx + rocketItem.Pose.Position.x, wy + rocketItem.Pose.Position.y, wz + rocketItem.Pose.Position.z);
TriggerDynamicLight( SpawnDynamicLight(
wx + rocketItem.Pose.Position.x + (GetRandomControl() & 15) - 8, wx + rocketItem.Pose.Position.x + (GetRandomControl() & 15) - 8,
wy + rocketItem.Pose.Position.y + (GetRandomControl() & 15) - 8, wy + rocketItem.Pose.Position.y + (GetRandomControl() & 15) - 8,
wz + rocketItem.Pose.Position.z + (GetRandomControl() & 15) - 8, wz + rocketItem.Pose.Position.z + (GetRandomControl() & 15) - 8,
@ -1152,7 +1152,7 @@ void FireHK(ItemInfo& laraItem, bool inaccurateMode)
Weapons[(int)LaraWeaponType::HK].Damage = damage / 3; Weapons[(int)LaraWeaponType::HK].Damage = damage / 3;
} }
if (FireWeapon(LaraWeaponType::HK, *player.TargetEntity, laraItem, angles) != FireWeaponType::NoAmmo) if (FireWeapon(LaraWeaponType::HK, player.TargetEntity, laraItem, angles) != FireWeaponType::NoAmmo)
{ {
player.LeftArm.GunSmoke = 12; player.LeftArm.GunSmoke = 12;
@ -1305,12 +1305,12 @@ void RifleHandler(ItemInfo& laraItem, LaraWeaponType weaponType)
if (weaponType == LaraWeaponType::Shotgun || weaponType == LaraWeaponType::HK) if (weaponType == LaraWeaponType::Shotgun || weaponType == LaraWeaponType::HK)
{ {
auto pos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(0, -64, 0)); auto pos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(0, -64, 0));
TriggerDynamicPointLight(pos.ToVector3(), color, CLICK(settings.FlashRange)); SpawnDynamicPointLight(pos.ToVector3(), color, CLICK(settings.FlashRange));
} }
else if (weaponType == LaraWeaponType::Revolver) else if (weaponType == LaraWeaponType::Revolver)
{ {
auto pos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(0, -32, 0)); auto pos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(0, -32, 0));
TriggerDynamicPointLight(pos.ToVector3(), color, CLICK(settings.FlashRange)); SpawnDynamicPointLight(pos.ToVector3(), color, CLICK(settings.FlashRange));
} }
} }
} }

View file

@ -154,7 +154,7 @@ static void AnimateWeapon(ItemInfo& laraItem, LaraWeaponType weaponType, bool& h
arm.Orientation.y + laraItem.Pose.Orientation.y, arm.Orientation.y + laraItem.Pose.Orientation.y,
0); 0);
if (FireWeapon(weaponType, *player.TargetEntity, laraItem, armOrient) != FireWeaponType::NoAmmo) if (FireWeapon(weaponType, player.TargetEntity, laraItem, armOrient) != FireWeaponType::NoAmmo)
{ {
arm.GunSmoke = 28; arm.GunSmoke = 28;
TriggerGunShell(isRightWeapon ? true : false, ID_GUNSHELL, weaponType); TriggerGunShell(isRightWeapon ? true : false, ID_GUNSHELL, weaponType);
@ -321,7 +321,7 @@ void HandlePistols(ItemInfo& laraItem, LaraWeaponType weaponType)
auto lightPos = Random::GeneratePointInSphere(sphere); auto lightPos = Random::GeneratePointInSphere(sphere);
int range = abs(Random::GenerateInt(settings.FlashRange - 2, settings.FlashRange + 2)); int range = abs(Random::GenerateInt(settings.FlashRange - 2, settings.FlashRange + 2));
TriggerDynamicPointLight(lightPos, color, CLICK(range)); SpawnDynamicPointLight(lightPos, color, CLICK(range));
} }
} }

View file

@ -12,6 +12,7 @@
#include "Game/Lara/lara.h" #include "Game/Lara/lara.h"
#include "Game/Lara/lara_fire.h" #include "Game/Lara/lara_fire.h"
#include "Game/Lara/lara_helpers.h" #include "Game/Lara/lara_helpers.h"
#include "Game/Lara/Optics.h"
#include "Game/room.h" #include "Game/room.h"
#include "Game/savegame.h" #include "Game/savegame.h"
#include "Game/Setup.h" #include "Game/Setup.h"
@ -50,6 +51,7 @@ struct OLD_CAMERA
}; };
bool ItemCameraOn; bool ItemCameraOn;
GameVector LastPosition;
GameVector LastTarget; GameVector LastTarget;
GameVector LastIdeal; GameVector LastIdeal;
GameVector Ideals[5]; GameVector Ideals[5];
@ -58,7 +60,6 @@ int CameraSnaps = 0;
int TargetSnaps = 0; int TargetSnaps = 0;
GameVector LookCamPosition; GameVector LookCamPosition;
GameVector LookCamTarget; GameVector LookCamTarget;
Vector3i CamOldPos;
CAMERA_INFO Camera; CAMERA_INFO Camera;
GameVector ForcedFixedCamera; GameVector ForcedFixedCamera;
int UseForcedFixedCamera; int UseForcedFixedCamera;
@ -945,50 +946,13 @@ void BinocularCamera(ItemInfo* item)
{ {
auto& player = GetLaraInfo(*item); auto& player = GetLaraInfo(*item);
if (!player.Control.Look.IsUsingLasersight)
{
if (IsClicked(In::Deselect) ||
IsClicked(In::Draw) ||
IsClicked(In::Look) ||
IsHeld(In::Flare))
{
ResetPlayerFlex(item);
player.Control.Look.OpticRange = 0;
player.Control.Look.IsUsingBinoculars = false;
player.Inventory.IsBusy = false;
Camera.type = BinocularOldCamera;
Camera.DisableInterpolation = true;
Camera.target = LastTarget;
AlterFOV(LastFOV);
return;
}
if (IsHeld(In::Action))
{
ClearAction(In::Action);
auto origin = Camera.pos.ToVector3i();
auto target = Camera.target.ToVector3i();
LaraTorch(&origin, &target);
}
}
AlterFOV(7 * (ANGLE(11.5f) - player.Control.Look.OpticRange), false); AlterFOV(7 * (ANGLE(11.5f) - player.Control.Look.OpticRange), false);
int x = item->Pose.Position.x; int x = item->Pose.Position.x;
int y = item->Pose.Position.y - CLICK(2); int y = item->Pose.Position.y + GameBoundingBox(item).Y1;
int z = item->Pose.Position.z; int z = item->Pose.Position.z;
auto pointColl = GetPointCollision(Vector3i(x, y, z), item->RoomNumber); auto pointColl = GetPointCollision(Vector3i(x, y, z), item->RoomNumber);
if (pointColl.GetCeilingHeight() <= (y - CLICK(1)))
{
y -= CLICK(1);
}
else
{
y = pointColl.GetCeilingHeight() + CLICK(0.25f);
}
Camera.pos.x = x; Camera.pos.x = x;
Camera.pos.y = y; Camera.pos.y = y;
@ -1083,18 +1047,24 @@ static bool CalculateDeathCamera(const ItemInfo& item)
void CalculateCamera(const CollisionInfo& coll) void CalculateCamera(const CollisionInfo& coll)
{ {
CamOldPos.x = Camera.pos.x; if (ItemCameraOn)
CamOldPos.y = Camera.pos.y; return;
CamOldPos.z = Camera.pos.z;
if (!HandlePlayerOptics(*LaraItem))
{
Camera.pos = LastPosition;
Camera.target = LastTarget;
}
if (Lara.Control.Look.IsUsingBinoculars) if (Lara.Control.Look.IsUsingBinoculars)
{ {
BinocularCamera(LaraItem); BinocularCamera(LaraItem);
return; return;
} }
else
if (ItemCameraOn) {
return; LastPosition = Camera.pos;
}
if (UseForcedFixedCamera != 0) if (UseForcedFixedCamera != 0)
{ {
@ -1386,7 +1356,7 @@ void ItemPushCamera(GameBoundingBox* bounds, Pose* pos, short radius)
auto pointColl = GetPointCollision(Camera.pos.ToVector3i(), Camera.pos.RoomNumber); auto pointColl = GetPointCollision(Camera.pos.ToVector3i(), Camera.pos.RoomNumber);
if (pointColl.GetFloorHeight() == NO_HEIGHT || Camera.pos.y > pointColl.GetFloorHeight() || Camera.pos.y < pointColl.GetCeilingHeight()) if (pointColl.GetFloorHeight() == NO_HEIGHT || Camera.pos.y > pointColl.GetFloorHeight() || Camera.pos.y < pointColl.GetCeilingHeight())
Camera.pos = GameVector(CamOldPos, pointColl.GetRoomNumber()); Camera.pos = GameVector(LastPosition.ToVector3i(), pointColl.GetRoomNumber());
} }
bool CheckItemCollideCamera(ItemInfo* item) bool CheckItemCollideCamera(ItemInfo* item)

View file

@ -20,6 +20,7 @@
#include "Math/Math.h" #include "Math/Math.h"
#include "Scripting/Include/ScriptInterfaceGame.h" #include "Scripting/Include/ScriptInterfaceGame.h"
#include "Sound/sound.h" #include "Sound/sound.h"
#include "Specific/winmain.h"
using namespace TEN::Collision::Floordata; using namespace TEN::Collision::Floordata;
using namespace TEN::Collision::Point; using namespace TEN::Collision::Point;
@ -330,6 +331,11 @@ void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll)
bool TestLaraPosition(const ObjectCollisionBounds& bounds, ItemInfo* item, ItemInfo* laraItem) bool TestLaraPosition(const ObjectCollisionBounds& bounds, ItemInfo* item, ItemInfo* laraItem)
{ {
if (DebugMode)
{
DrawDebugBox(bounds.BoundingBox.ToBoundingOrientedBox(item->Pose), Color(1.0f, 0.0f, 0.0f), RendererDebugPage::CollisionStats);
}
auto deltaOrient = laraItem->Pose.Orientation - item->Pose.Orientation; auto deltaOrient = laraItem->Pose.Orientation - item->Pose.Orientation;
if (deltaOrient.x < bounds.OrientConstraint.first.x || deltaOrient.x > bounds.OrientConstraint.second.x || if (deltaOrient.x < bounds.OrientConstraint.first.x || deltaOrient.x > bounds.OrientConstraint.second.x ||
deltaOrient.y < bounds.OrientConstraint.first.y || deltaOrient.y > bounds.OrientConstraint.second.y || deltaOrient.y < bounds.OrientConstraint.first.y || deltaOrient.y > bounds.OrientConstraint.second.y ||
@ -341,11 +347,7 @@ bool TestLaraPosition(const ObjectCollisionBounds& bounds, ItemInfo* item, ItemI
auto pos = (laraItem->Pose.Position - item->Pose.Position).ToVector3(); auto pos = (laraItem->Pose.Position - item->Pose.Position).ToVector3();
auto rotMatrix = item->Pose.Orientation.ToRotationMatrix(); auto rotMatrix = item->Pose.Orientation.ToRotationMatrix();
// This solves once for all the minus sign hack of CreateFromYawPitchRoll. // NOTE: Transpose = faster inverse.
// In reality it should be the inverse, but the inverse of a rotation matrix is equal to the transpose
// and transposing a matrix is faster.
// It's the only piece of code that does it, because we want Lara's location relative to the identity frame
// of the object we are test against.
rotMatrix = rotMatrix.Transpose(); rotMatrix = rotMatrix.Transpose();
pos = Vector3::Transform(pos, rotMatrix); pos = Vector3::Transform(pos, rotMatrix);

View file

@ -546,7 +546,7 @@ namespace TEN::Collision::Floordata
// For bridges with zero thickness (which is incorrect setup, but still possible), break out of // For bridges with zero thickness (which is incorrect setup, but still possible), break out of
// infinite loop caused by infinite traversal over the same height value. // infinite loop caused by infinite traversal over the same height value.
int nextPos = sector->GetBridgeSurfaceHeight(pos, !isBottom); int nextPos = sector->GetBridgeSurfaceHeight(pos, !isBottom);
if (nextPos = pos.y) if (nextPos == pos.y)
nextPos += (isBottom ? 1 : -1); nextPos += (isBottom ? 1 : -1);
// Set vertical position to lowest bridge ceiling height or highest bridge floor height. // Set vertical position to lowest bridge ceiling height or highest bridge floor height.

View file

@ -744,7 +744,7 @@ static void SpawnCreatureGunEffect(const ItemInfo& item, const CreatureMuzzleFla
auto muzzlePos = muzzleFlash.Bite; auto muzzlePos = muzzleFlash.Bite;
auto pos = GetJointPosition(item, muzzlePos); auto pos = GetJointPosition(item, muzzlePos);
TriggerDynamicLight(pos.x, pos.y, pos.z, 15, 128, 64, 16); SpawnDynamicLight(pos.x, pos.y, pos.z, 15, 128, 64, 16);
if (muzzleFlash.UseSmoke) if (muzzleFlash.UseSmoke)
{ {

View file

@ -262,6 +262,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo
{ {
Lara.Control.Weapon.HasFired = true; Lara.Control.Weapon.HasFired = true;
Lara.Control.Weapon.Fired = true; Lara.Control.Weapon.Fired = true;
Lara.RightArm.GunFlash = Weapons[(int)Lara.Control.Weapon.GunType].FlashTime;
if (Lara.Control.Weapon.GunType == LaraWeaponType::Revolver) if (Lara.Control.Weapon.GunType == LaraWeaponType::Revolver)
SoundEffect(SFX_TR4_REVOLVER_FIRE, nullptr); SoundEffect(SFX_TR4_REVOLVER_FIRE, nullptr);
@ -442,12 +443,6 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo
} }
} }
if (drawTarget && (hasHit || !result))
{
auto& color = g_GameFlow->GetSettings()->Camera.LasersightLightColor;
TriggerDynamicLight(target2.x, target2.y, target2.z, 64, color.GetR(), color.GetG(), color.GetB());
}
return hitProcessed; return hitProcessed;
} }

View file

@ -168,7 +168,7 @@ namespace TEN::Control::Volumes
if (candidate.Status == VolumeStateStatus::Leaving) if (candidate.Status == VolumeStateStatus::Leaving)
{ {
if ((GlobalCounter - candidate.Timestamp) > VOLUME_BUSY_TIMEOUT) if ((SaveGame::Statistics.Level.TimeTaken - candidate.Timestamp) > VOLUME_BUSY_TIMEOUT)
candidate.Status = VolumeStateStatus::Outside; candidate.Status = VolumeStateStatus::Outside;
} }
else if (candidate.Status != VolumeStateStatus::Outside) else if (candidate.Status != VolumeStateStatus::Outside)
@ -191,7 +191,7 @@ namespace TEN::Control::Volumes
{ {
VolumeStateStatus::Entering, VolumeStateStatus::Entering,
activator, activator,
GlobalCounter SaveGame::Statistics.Level.TimeTaken
}); });
HandleEvent(set.Events[(int)EventType::Enter], activator); HandleEvent(set.Events[(int)EventType::Enter], activator);
@ -199,7 +199,7 @@ namespace TEN::Control::Volumes
else else
{ {
entryPtr->Status = VolumeStateStatus::Inside; entryPtr->Status = VolumeStateStatus::Inside;
entryPtr->Timestamp = GlobalCounter; entryPtr->Timestamp = SaveGame::Statistics.Level.TimeTaken;
HandleEvent(set.Events[(int)EventType::Inside], activator); HandleEvent(set.Events[(int)EventType::Inside], activator);
} }
@ -209,10 +209,10 @@ namespace TEN::Control::Volumes
// Only fire leave event when a certain timeout has passed. // Only fire leave event when a certain timeout has passed.
// This helps to filter out borderline cases when moving around volumes. // This helps to filter out borderline cases when moving around volumes.
if ((GlobalCounter - entryPtr->Timestamp) > VOLUME_LEAVE_TIMEOUT) if ((SaveGame::Statistics.Level.TimeTaken - entryPtr->Timestamp) > VOLUME_LEAVE_TIMEOUT)
{ {
entryPtr->Status = VolumeStateStatus::Leaving; entryPtr->Status = VolumeStateStatus::Leaving;
entryPtr->Timestamp = GlobalCounter; entryPtr->Timestamp = SaveGame::Statistics.Level.TimeTaken;
HandleEvent(set.Events[(int)EventType::Leave], activator); HandleEvent(set.Events[(int)EventType::Leave], activator);
} }

View file

@ -0,0 +1,24 @@
#include "framework.h"
#include "Game/effects/Light.h"
#include "Renderer/Renderer.h"
using TEN::Renderer::g_Renderer;
namespace TEN::Effects::Light
{
void SpawnDynamicPointLight(const Vector3& pos, const Color& color, float falloff, bool castShadows, int hash)
{
g_Renderer.AddDynamicPointLight(pos, falloff, color, castShadows, hash);
}
void SpawnDynamicSpotLight(const Vector3& pos, const Vector3& dir, const Color& color, float radius, float falloff, float dist, bool castShadows, int hash)
{
g_Renderer.AddDynamicSpotLight(pos, dir, radius, falloff, dist, color, castShadows, hash);
}
void SpawnDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b)
{
g_Renderer.AddDynamicPointLight(Vector3(x, y, z), float(falloff * UCHAR_MAX), Color(r / (float)CHAR_MAX, g / (float)CHAR_MAX, b / (float)CHAR_MAX), false);
}
}

View file

@ -0,0 +1,10 @@
#pragma once
namespace TEN::Effects::Light
{
void SpawnDynamicPointLight(const Vector3& pos, const Color& color, float falloff, bool castShadows = false, int hash = 0);
void SpawnDynamicSpotLight(const Vector3& pos, const Vector3& dir, const Color& color, float radius, float falloff, float dist, bool castShadows = false, int hash = 0);
// DEPRECATED!!! Use SpawnDynamicPointLight() instead and phase out this legacy function.
void SpawnDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b);
}

View file

@ -10,6 +10,7 @@
#include "Game/effects/Drip.h" #include "Game/effects/Drip.h"
#include "Game/effects/explosion.h" #include "Game/effects/explosion.h"
#include "Game/effects/item_fx.h" #include "Game/effects/item_fx.h"
#include "Game/effects/Light.h"
#include "Game/effects/Ripple.h" #include "Game/effects/Ripple.h"
#include "Game/effects/smoke.h" #include "Game/effects/smoke.h"
#include "Game/effects/spark.h" #include "Game/effects/spark.h"
@ -33,6 +34,7 @@ using namespace TEN::Effects::Drip;
using namespace TEN::Effects::Environment; using namespace TEN::Effects::Environment;
using namespace TEN::Effects::Explosion; using namespace TEN::Effects::Explosion;
using namespace TEN::Effects::Items; using namespace TEN::Effects::Items;
using namespace TEN::Effects::Light;
using namespace TEN::Effects::Ripple; using namespace TEN::Effects::Ripple;
using namespace TEN::Effects::Spark; using namespace TEN::Effects::Spark;
using namespace TEN::Math; using namespace TEN::Math;
@ -430,7 +432,7 @@ void UpdateSparks()
else else
falloff = 31; falloff = 31;
TriggerDynamicLight(x, y, z, falloff, r, g, b); SpawnDynamicLight(x, y, z, falloff, r, g, b);
} }
else else
{ {
@ -438,11 +440,11 @@ void UpdateSparks()
if (spark->flags & SP_COLOR) if (spark->flags & SP_COLOR)
{ {
TriggerDynamicLight(x, y, z, falloff, spark->dR, spark->dG, spark->dB); SpawnDynamicLight(x, y, z, falloff, spark->dR, spark->dG, spark->dB);
} }
else else
{ {
TriggerDynamicLight(x, y, z, falloff, g, b, r); SpawnDynamicLight(x, y, z, falloff, g, b, r);
} }
} }
} }
@ -1247,22 +1249,6 @@ void KillAllCurrentItems(short itemNumber)
// TODO: Reimplement this functionality. // TODO: Reimplement this functionality.
} }
void TriggerDynamicPointLight(const Vector3& pos, const Color& color, float falloff, bool castShadows, int hash)
{
g_Renderer.AddDynamicPointLight(pos, falloff , color, castShadows, hash);
}
void TriggerDynamicSpotLight(const Vector3& pos, const Vector3& dir, const Color& color, float radius, float falloff, float distance, bool castShadows, int hash)
{
g_Renderer.AddDynamicSpotLight(pos, dir, radius, falloff, distance, color, castShadows, hash);
}
// Deprecated. Use above version instead.
void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b)
{
g_Renderer.AddDynamicPointLight(Vector3(x, y, z), (float)(falloff * UCHAR_MAX), Color(r / (float)UCHAR_MAX, g / (float)UCHAR_MAX, b / (float)UCHAR_MAX), false);
}
void SpawnPlayerWaterSurfaceEffects(const ItemInfo& item, int waterHeight, int waterDepth) void SpawnPlayerWaterSurfaceEffects(const ItemInfo& item, int waterHeight, int waterDepth)
{ {
const auto& player = GetLaraInfo(item); const auto& player = GetLaraInfo(item);
@ -1919,7 +1905,7 @@ void ProcessEffects(ItemInfo* item)
MAX_LIGHT_FALLOFF - std::clamp(MAX_LIGHT_FALLOFF - item->Effect.Count, 0, MAX_LIGHT_FALLOFF); MAX_LIGHT_FALLOFF - std::clamp(MAX_LIGHT_FALLOFF - item->Effect.Count, 0, MAX_LIGHT_FALLOFF);
auto pos = GetJointPosition(item, 0); auto pos = GetJointPosition(item, 0);
TriggerDynamicLight( SpawnDynamicLight(
pos.x, pos.y, pos.z, falloff, pos.x, pos.y, pos.z, falloff,
std::clamp(Random::GenerateInt(-32, 32) + int(item->Effect.LightColor.x * UCHAR_MAX), 0, UCHAR_MAX), std::clamp(Random::GenerateInt(-32, 32) + int(item->Effect.LightColor.x * UCHAR_MAX), 0, UCHAR_MAX),
std::clamp(Random::GenerateInt(-32, 32) + int(item->Effect.LightColor.y * UCHAR_MAX), 0, UCHAR_MAX), std::clamp(Random::GenerateInt(-32, 32) + int(item->Effect.LightColor.y * UCHAR_MAX), 0, UCHAR_MAX),

View file

@ -1,8 +1,12 @@
#pragma once #pragma once
#include "Math/Math.h"
#include "Game/Items.h" #include "Game/Items.h"
#include "Game/effects/Light.h"
#include "Math/Math.h"
#include "Renderer/RendererEnums.h" #include "Renderer/RendererEnums.h"
using namespace TEN::Effects::Light;
enum class LaraWeaponType; enum class LaraWeaponType;
enum GAME_OBJECT_ID : short; enum GAME_OBJECT_ID : short;
struct CollisionInfo; struct CollisionInfo;
@ -299,9 +303,6 @@ void DoLotsOfBlood(int x, int y, int z, int speed, short direction, short roomNu
void ControlWaterfallMist(short itemNumber); void ControlWaterfallMist(short itemNumber);
void TriggerWaterfallMist(const ItemInfo& item); void TriggerWaterfallMist(const ItemInfo& item);
void KillAllCurrentItems(short itemNumber); void KillAllCurrentItems(short itemNumber);
void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byte b);
void TriggerDynamicPointLight(const Vector3& pos, const Color& color, float falloff, bool castShadows = false, int hash = 0);
void TriggerDynamicSpotLight(const Vector3& pos, const Vector3& dir, const Color& color, float radius, float falloff, float distance, bool castShadows = false, int hash = 0);
void TriggerRocketFlame(int x, int y, int z, int xv, int yv, int zv, int itemNumber); void TriggerRocketFlame(int x, int y, int z, int xv, int yv, int zv, int itemNumber);
void TriggerRocketSmoke(int x, int y, int z); void TriggerRocketSmoke(int x, int y, int z);
void TriggerFlashSmoke(int x, int y, int z, short roomNumber); void TriggerFlashSmoke(int x, int y, int z, short roomNumber);

View file

@ -1380,7 +1380,7 @@ void UpdateShockwaves()
{ {
auto lightColor = Color(shockwave.r / (float)UCHAR_MAX, shockwave.g / (float)UCHAR_MAX, shockwave.b / (float)UCHAR_MAX); auto lightColor = Color(shockwave.r / (float)UCHAR_MAX, shockwave.g / (float)UCHAR_MAX, shockwave.b / (float)UCHAR_MAX);
auto pos = Vector3(shockwave.x, shockwave.y, shockwave.z); auto pos = Vector3(shockwave.x, shockwave.y, shockwave.z);
TriggerDynamicPointLight(pos, lightColor, shockwave.life / 4.0f); SpawnDynamicPointLight(pos, lightColor, shockwave.life / 4.0f);
} }
if (shockwave.style != (int)ShockwaveStyle::Knockback) if (shockwave.style != (int)ShockwaveStyle::Knockback)

View file

@ -12,6 +12,7 @@
#include "Game/Lara/lara.h" #include "Game/Lara/lara.h"
#include "Game/Lara/lara_fire.h" #include "Game/Lara/lara_fire.h"
#include "Game/Lara/lara_helpers.h" #include "Game/Lara/lara_helpers.h"
#include "Game/Lara/Optics.h"
#include "Game/Lara/lara_one_gun.h" #include "Game/Lara/lara_one_gun.h"
#include "Game/Lara/lara_two_guns.h" #include "Game/Lara/lara_two_guns.h"
#include "Game/pickup/pickup.h" #include "Game/pickup/pickup.h"
@ -620,6 +621,10 @@ namespace TEN::Gui
CurrentSettings.Configuration.ScreenWidth = screenResolution.x; CurrentSettings.Configuration.ScreenWidth = screenResolution.x;
CurrentSettings.Configuration.ScreenHeight = screenResolution.y; CurrentSettings.Configuration.ScreenHeight = screenResolution.y;
// Determine whether we should update AA shaders.
bool shouldRecompileAAShaders = g_Configuration.AntialiasingMode != CurrentSettings.Configuration.AntialiasingMode &&
CurrentSettings.Configuration.AntialiasingMode != AntialiasingMode::Low;
g_Configuration = CurrentSettings.Configuration; g_Configuration = CurrentSettings.Configuration;
SaveConfiguration(); SaveConfiguration();
@ -627,6 +632,7 @@ namespace TEN::Gui
g_Renderer.ChangeScreenResolution(CurrentSettings.Configuration.ScreenWidth, CurrentSettings.Configuration.ScreenHeight, g_Renderer.ChangeScreenResolution(CurrentSettings.Configuration.ScreenWidth, CurrentSettings.Configuration.ScreenHeight,
CurrentSettings.Configuration.EnableWindowedMode); CurrentSettings.Configuration.EnableWindowedMode);
g_Renderer.ReloadShaders(shouldRecompileAAShaders);
g_Renderer.SetGraphicsSettingsChanged(); g_Renderer.SetGraphicsSettingsChanged();
MenuToDisplay = fromPauseMenu ? Menu::Pause : Menu::Options; MenuToDisplay = fromPauseMenu ? Menu::Pause : Menu::Options;
@ -2057,8 +2063,6 @@ namespace TEN::Gui
auto& player = GetLaraInfo(item); auto& player = GetLaraInfo(item);
short prevOpticRange = player.Control.Look.OpticRange;
player.Control.Look.OpticRange = 0;
player.Inventory.OldBusy = false; player.Inventory.OldBusy = false;
item.MeshBits = ALL_JOINT_BITS; item.MeshBits = ALL_JOINT_BITS;
@ -2201,26 +2205,11 @@ namespace TEN::Gui
(player.Control.IsLow && !IsHeld(In::Crouch))) && (player.Control.IsLow && !IsHeld(In::Crouch))) &&
!UseSpotCam && !TrackCameraInit) !UseSpotCam && !TrackCameraInit)
{ {
Camera.DisableInterpolation = true; SetScreenFadeIn(OPTICS_FADE_SPEED);
player.Control.Look.OpticRange = ANGLE(0.7f); BinocularOldCamera = Camera.oldType;
player.Control.Look.OpticRange = OPTICS_RANGE_DEFAULT;
player.Control.Look.IsUsingBinoculars = true; player.Control.Look.IsUsingBinoculars = true;
player.Inventory.OldBusy = true; player.Inventory.OldBusy = true;
// TODO: To prevent Lara from crouching or performing other actions, the inherent state of
// LA_BINOCULARS_IDLE must be changed to LS_IDLE. @Sezz 2022.05.19
//SetAnimation(item, LA_BINOCULARS_IDLE);
if (player.Control.HandStatus != HandStatus::Free)
player.Control.HandStatus = HandStatus::WeaponUndraw;
}
if (prevOpticRange != ANGLE(0.0f))
{
player.Control.Look.OpticRange = prevOpticRange;
}
else
{
BinocularOldCamera = Camera.oldType;
} }
InventoryItemChosen = NO_VALUE; InventoryItemChosen = NO_VALUE;
@ -3303,6 +3292,7 @@ namespace TEN::Gui
while (g_Synchronizer.Synced()) while (g_Synchronizer.Synced())
{ {
TimeInMenu++; TimeInMenu++;
GlobalCounter++;
SaveGame::Statistics.Game.TimeTaken++; SaveGame::Statistics.Game.TimeTaken++;
SaveGame::Statistics.Level.TimeTaken++; SaveGame::Statistics.Level.TimeTaken++;
@ -3451,7 +3441,7 @@ namespace TEN::Gui
needleOrient.Lerp(EulerAngles(0, item->Pose.Orientation.y, 0), LERP_ALPHA); needleOrient.Lerp(EulerAngles(0, item->Pose.Orientation.y, 0), LERP_ALPHA);
float wibble = std::sin((float(GlobalCounter & 0x3F) / (float)0x3F) * PI_MUL_2); float wibble = std::sin((float(GlobalCounter & 0x3F) / (float)0x3F) * PI_MUL_2);
CompassNeedleAngle = needleOrient.y + ANGLE(wibble / 2); CompassNeedleAngle = needleOrient.y + ANGLE(wibble);
// HACK: Needle is rotated in the draw function. // HACK: Needle is rotated in the draw function.
const auto& invObject = InventoryObjectTable[INV_OBJECT_COMPASS]; const auto& invObject = InventoryObjectTable[INV_OBJECT_COMPASS];

View file

@ -8,6 +8,7 @@
#include "Game/effects/tomb4fx.h" #include "Game/effects/tomb4fx.h"
#include "Game/effects/effects.h" #include "Game/effects/effects.h"
#include "Game/effects/explosion.h" #include "Game/effects/explosion.h"
#include "Game/effects/Light.h"
#include "Game/effects/Bubble.h" #include "Game/effects/Bubble.h"
#include "Game/Lara/lara.h" #include "Game/Lara/lara.h"
#include "Game/items.h" #include "Game/items.h"
@ -16,9 +17,10 @@
#include "Sound/sound.h" #include "Sound/sound.h"
#include "Specific/level.h" #include "Specific/level.h"
using namespace TEN::Collision::Point;; using namespace TEN::Collision::Point;
using namespace TEN::Effects::Bubble; using namespace TEN::Effects::Bubble;
using namespace TEN::Effects::Explosion; using namespace TEN::Effects::Explosion;
using namespace TEN::Effects::Light;
using namespace TEN::Math; using namespace TEN::Math;
constexpr auto MUTANT_SHARD_DAMAGE = 30; constexpr auto MUTANT_SHARD_DAMAGE = 30;
@ -130,7 +132,7 @@ void ControlMissile(short fxNumber)
break; break;
case ID_PROJ_BOMB: case ID_PROJ_BOMB:
TriggerDynamicLight(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 14, 180, 100, 0); SpawnDynamicLight(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 14, 180, 100, 0);
break; break;
} }
} }

View file

@ -259,7 +259,7 @@ namespace TEN::Effects::Boss
SoundEffect(SFX_TR3_BLAST_CIRCLE, &shockwavePos); SoundEffect(SFX_TR3_BLAST_CIRCLE, &shockwavePos);
} }
TriggerDynamicLight( SpawnDynamicLight(
item.Pose.Position.x, item.Pose.Position.x,
item.Pose.Position.y - CLICK(2), item.Pose.Position.y - CLICK(2),
item.Pose.Position.z, item.Pose.Position.z,

View file

@ -399,6 +399,6 @@ namespace TEN::Entities::Effects
} }
if (fx.flag1 == (int)MissileType::ClawMutantPlasma) if (fx.flag1 == (int)MissileType::ClawMutantPlasma)
TriggerDynamicLight(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 8, 0, 64, 128); SpawnDynamicLight(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 8, 0, 64, 128);
} }
} }

View file

@ -94,7 +94,7 @@ namespace TEN::Entities::Effects
// Constant flames. // Constant flames.
SoundEffect(SFX_TR4_FLAME_EMITTER, &item->Pose); SoundEffect(SFX_TR4_FLAME_EMITTER, &item->Pose);
TriggerSuperJetFlame(item, -256 - (3072 * GlobalCounter & 0x1C00), GlobalCounter & 1); TriggerSuperJetFlame(item, -256 - (3072 * GlobalCounter & 0x1C00), GlobalCounter & 1);
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z,
(GetRandomControl() & 3) + 20, (GetRandomControl() & 3) + 20,
(GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x3F) + 192,
(GetRandomControl() & 0x1F) + 96, 0); (GetRandomControl() & 0x1F) + 96, 0);
@ -163,14 +163,14 @@ namespace TEN::Entities::Effects
TriggerSuperJetFlame(item, jetFlameVel, GlobalCounter & 1); TriggerSuperJetFlame(item, jetFlameVel, GlobalCounter & 1);
} }
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z,
(-jetFlameVel >> 10) - (GetRandomControl() & 1) + 16, (-jetFlameVel >> 10) - (GetRandomControl() & 1) + 16,
(GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x3F) + 192,
(GetRandomControl() & 0x1F) + 96, 0); (GetRandomControl() & 0x1F) + 96, 0);
} }
else else
{ {
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z,
10 - (GetRandomControl() & 1), 10 - (GetRandomControl() & 1),
(GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x3F) + 192,
(GetRandomControl() & 0x1F) + 96, 0); (GetRandomControl() & 0x1F) + 96, 0);
@ -184,7 +184,7 @@ namespace TEN::Entities::Effects
// Normal flames. // Normal flames.
AddFire(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber, 2.0f); AddFire(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, item->RoomNumber, 2.0f);
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z,
16 - (GetRandomControl() & 1), 16 - (GetRandomControl() & 1),
(GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x3F) + 192,
(GetRandomControl() & 0x1F) + 96, 0); (GetRandomControl() & 0x1F) + 96, 0);
@ -241,7 +241,7 @@ namespace TEN::Entities::Effects
{ {
if (item->ItemFlags[3]) if (item->ItemFlags[3])
{ {
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z,
10, 10,
(((GetRandomControl() & 0x3F) + 192) * item->ItemFlags[3]) >> 8, (((GetRandomControl() & 0x3F) + 192) * item->ItemFlags[3]) >> 8,
((GetRandomControl() & 0x1F) + 96 * item->ItemFlags[3]) >> 8, ((GetRandomControl() & 0x1F) + 96 * item->ItemFlags[3]) >> 8,
@ -249,7 +249,7 @@ namespace TEN::Entities::Effects
} }
else else
{ {
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z,
10, 10,
(GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x3F) + 192,
(GetRandomControl() & 0x1F) + 96, (GetRandomControl() & 0x1F) + 96,
@ -488,7 +488,7 @@ namespace TEN::Entities::Effects
} }
SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item->Pose); SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item->Pose);
TriggerDynamicLight(x, item->Pose.Position.y, z, 12, (GetRandomControl() & 0x3F) + 192, ((GetRandomControl() >> 4) & 0x1F) + 96, 0); SpawnDynamicLight(x, item->Pose.Position.y, z, 12, (GetRandomControl() & 0x3F) + 192, ((GetRandomControl() >> 4) & 0x1F) + 96, 0);
auto pos = item->Pose.Position; auto pos = item->Pose.Position;
if (ItemNearLara(pos, FLAME_BIG_RADIUS)) if (ItemNearLara(pos, FLAME_BIG_RADIUS))

View file

@ -159,7 +159,7 @@ void ElectricityWiresControl(short itemNumber)
continue; continue;
if (((GetRandomControl() & 0x0F) < 8) && flashingNode == currentEndNode) if (((GetRandomControl() & 0x0F) < 8) && flashingNode == currentEndNode)
TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 0, ((GetRandomControl() & 0x3F) + 96) / 2, (GetRandomControl() & 0x3F) + 128); SpawnDynamicLight(pos.x, pos.y, pos.z, 10, 0, ((GetRandomControl() & 0x3F) + 96) / 2, (GetRandomControl() & 0x3F) + 128);
for (int s = 0; s < 3; s++) for (int s = 0; s < 3; s++)
{ {
@ -222,7 +222,7 @@ void ElectricityWiresControl(short itemNumber)
isWaterNearby = true; isWaterNearby = true;
} }
bool instantKill = BoundingSphere(Vector3(pos.x, pos.y, pos.z), CLICK(0.25f)).Intersects(npcBox); bool instantKill = BoundingSphere(Vector3(pos.x, pos.y, pos.z), BLOCK(0.25f)).Intersects(npcBox);
if (isWaterNearby || instantKill) if (isWaterNearby || instantKill)
{ {
@ -253,7 +253,7 @@ void ElectricityWiresControl(short itemNumber)
TriggerElectricitySparks(itemPtr, j, false); TriggerElectricitySparks(itemPtr, j, false);
} }
TriggerDynamicLight( SpawnDynamicLight(
itemPtr->Pose.Position.x, itemPtr->Pose.Position.x,
itemPtr->Pose.Position.y, itemPtr->Pose.Position.y,
itemPtr->Pose.Position.z, itemPtr->Pose.Position.z,

View file

@ -188,7 +188,7 @@ namespace TEN::Entities::Generic
Random::GenerateFloat(0.4f, 0.5f), Random::GenerateFloat(0.4f, 0.5f),
0.0f); 0.0f);
float lightFalloff = Random::GenerateFloat(0.04f, 0.045f); float lightFalloff = Random::GenerateFloat(0.04f, 0.045f);
TriggerDynamicLight(pos.x, pos.y, pos.z, lightFalloff * UCHAR_MAX, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX); SpawnDynamicLight(pos.x, pos.y, pos.z, lightFalloff * UCHAR_MAX, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX);
if (!(Wibble & 3)) if (!(Wibble & 3))
TriggerTorchFlame(laraItem->Index, 0); TriggerTorchFlame(laraItem->Index, 0);
@ -287,7 +287,7 @@ namespace TEN::Entities::Generic
Random::GenerateFloat(0.4f, 0.5f), Random::GenerateFloat(0.4f, 0.5f),
0.0f); 0.0f);
float lightFalloff = Random::GenerateFloat(0.04f, 0.045f); float lightFalloff = Random::GenerateFloat(0.04f, 0.045f);
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, lightFalloff * UCHAR_MAX, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX); SpawnDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, lightFalloff * UCHAR_MAX, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX);
if (!(Wibble & 7)) if (!(Wibble & 7))
TriggerTorchFlame(itemNumber, 1); TriggerTorchFlame(itemNumber, 1);
@ -296,33 +296,6 @@ namespace TEN::Entities::Generic
} }
} }
void LaraTorch(Vector3i* origin, Vector3i* target)
{
auto pos1 = GameVector(*origin, LaraItem->RoomNumber);
auto pos2 = GameVector(*target);
const auto& color = g_GameFlow->GetSettings()->Camera.BinocularLightColor;
TriggerDynamicLight(pos1.x, pos1.y, pos1.z, 12, color.GetR(), color.GetG(), color.GetB());
if (!LOS(&pos1, &pos2))
{
int l = sqrt(pow(pos1.x - pos2.x, 2) + pow(pos1.y - pos2.y, 2) + pow(pos1.z - pos2.z, 2)) * CLICK(1);
if (l + 8 > 31)
l = 31;
auto dir = pos1.ToVector3() - pos2.ToVector3();
dir.Normalize();
dir *= BLOCK(1);
byte r = std::max(0, color.GetR() - l);
byte g = std::max(0, color.GetG() - l);
byte b = std::max(0, color.GetB() - l);
TriggerDynamicLight(pos2.x + dir.x, pos2.y + dir.y, pos2.z + dir.z, l + 12, r, g, b);
}
}
void FireCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll) void FireCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
{ {
auto* torchItem = &g_Level.Items[itemNumber]; auto* torchItem = &g_Level.Items[itemNumber];

View file

@ -10,6 +10,5 @@ namespace TEN::Entities::Generic
void DoFlameTorch(); void DoFlameTorch();
void GetFlameTorch(); void GetFlameTorch();
void TorchControl(short itemNumber); void TorchControl(short itemNumber);
void LaraTorch(Vector3i* origin, Vector3i* target);
void FireCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll); void FireCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
} }

View file

@ -74,26 +74,26 @@ namespace TEN::Entities::Creatures::TR2
// Spawn light. // Spawn light.
auto lightPos = item.Pose.Position.ToVector3() + Vector3(0.0f, -CLICK(1), 0.0f); auto lightPos = item.Pose.Position.ToVector3() + Vector3(0.0f, -CLICK(1), 0.0f);
auto lightColor = Color(0.0f,Random::GenerateFloat(0.7f, 1.0f), Random::GenerateFloat(0.2f, 0.3f)); auto lightColor = Color(0.0f,Random::GenerateFloat(0.7f, 1.0f), Random::GenerateFloat(0.2f, 0.3f));
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(6), BLOCK(12))); SpawnDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(6), BLOCK(12)));
// Handle transformation. // Handle transformation.
if (effectTimer == timeExplosion1) if (effectTimer == timeExplosion1)
{ {
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24))); SpawnDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24)));
SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM); SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM);
SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose); SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose);
} }
if (effectTimer == timeExplosion2) if (effectTimer == timeExplosion2)
{ {
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24))); SpawnDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24)));
SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM2); SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM2);
SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose); SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose);
} }
if (effectTimer == timeExplosion3) if (effectTimer == timeExplosion3)
{ {
TriggerDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24))); SpawnDynamicPointLight(lightPos, lightColor, Random::GenerateFloat(BLOCK(12), BLOCK(24)));
SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM3); SpawnBartoliTransformEffect(item, ID_SPHERE_OF_DOOM3);
SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose); SoundEffect(SFX_TR2_MARCO_BARTOLLI_TRANSFORM, &item.Pose);
item.Animation.FrameNumber = animationFrameEnd; item.Animation.FrameNumber = animationFrameEnd;

View file

@ -195,7 +195,7 @@ namespace TEN::Entities::Creatures::TR2
Random::GenerateFloat(0.2f, 0.3f)); Random::GenerateFloat(0.2f, 0.3f));
float falloff = Random::GenerateFloat(BLOCK(6), BLOCK(20)); float falloff = Random::GenerateFloat(BLOCK(6), BLOCK(20));
TriggerDynamicPointLight(pos, color, falloff); SpawnDynamicPointLight(pos, color, falloff);
} }
break; break;
@ -207,7 +207,7 @@ namespace TEN::Entities::Creatures::TR2
Random::GenerateFloat(0.0f, 0.1f)); Random::GenerateFloat(0.0f, 0.1f));
float falloff = Random::GenerateFloat(BLOCK(6), BLOCK(12)); float falloff = Random::GenerateFloat(BLOCK(6), BLOCK(12));
TriggerDynamicPointLight(pos, color, falloff); SpawnDynamicPointLight(pos, color, falloff);
} }
break; break;
} }

View file

@ -81,12 +81,12 @@ namespace TEN::Entities::Creatures::TR2
{ {
if (item->Animation.ActiveState != WORKER_FLAME_STATE_ATTACK && item->Animation.ActiveState != WORKER_FLAME_STATE_WALK_FORWARD_ATTACK) if (item->Animation.ActiveState != WORKER_FLAME_STATE_ATTACK && item->Animation.ActiveState != WORKER_FLAME_STATE_WALK_FORWARD_ATTACK)
{ {
TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 10, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7); SpawnDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 10, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7);
TriggerPilotFlame(itemNumber, WorkerFlamethrowerBite.BoneID); TriggerPilotFlame(itemNumber, WorkerFlamethrowerBite.BoneID);
} }
else else
{ {
TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 14, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7); SpawnDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 14, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7);
ThrowFire(itemNumber, WorkerFlamethrowerBite.BoneID, WorkerFlamethrowerOffset, WorkerFlamethrowerOffset); ThrowFire(itemNumber, WorkerFlamethrowerBite.BoneID, WorkerFlamethrowerOffset, WorkerFlamethrowerOffset);
} }

View file

@ -680,8 +680,8 @@ namespace TEN::Entities::Vehicles
lara->RightArm.Orientation.y + laraItem->Pose.Orientation.y, lara->RightArm.Orientation.y + laraItem->Pose.Orientation.y,
0); 0);
FireWeapon(LaraWeaponType::Snowmobile, *lara->TargetEntity, *laraItem, angles); FireWeapon(LaraWeaponType::Snowmobile, lara->TargetEntity, *laraItem, angles);
FireWeapon(LaraWeaponType::Snowmobile, *lara->TargetEntity, *laraItem, angles); FireWeapon(LaraWeaponType::Snowmobile, lara->TargetEntity, *laraItem, angles);
SoundEffect(weapon.SampleNum, &laraItem->Pose); SoundEffect(weapon.SampleNum, &laraItem->Pose);
skidooItem->ItemFlags[0] = 4; skidooItem->ItemFlags[0] = 4;
} }

View file

@ -147,7 +147,7 @@ namespace TEN::Entities::Creatures::TR3
float closestDist = INFINITY; float closestDist = INFINITY;
for (auto& targetItem : g_Level.Items) for (auto& targetItem : g_Level.Items)
{ {
if (!Objects.CheckID(targetItem.ObjectNumber) || targetItem.Index == itemNumber || targetItem.RoomNumber == NO_VALUE) if (!Objects.CheckID(targetItem.ObjectNumber, true) || targetItem.Index == itemNumber || targetItem.RoomNumber == NO_VALUE)
continue; continue;
if (SameZone(&creature, &targetItem) && item.TriggerFlags < 0) if (SameZone(&creature, &targetItem) && item.TriggerFlags < 0)

View file

@ -228,7 +228,7 @@ namespace TEN::Entities::Creatures::TR3
SpawnElectricity(origin.ToVector3(), target.ToVector3(), Random::GenerateInt(25, 50), 100, 200, 200, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)(int)ElectricityFlags::ThinOut, 4, 12); SpawnElectricity(origin.ToVector3(), target.ToVector3(), Random::GenerateInt(25, 50), 100, 200, 200, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)(int)ElectricityFlags::ThinOut, 4, 12);
SpawnElectricity(origin.ToVector3(), target.ToVector3(), Random::GenerateInt(25, 50), 100, 250, 255, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)(int)ElectricityFlags::ThinOut, 2, 12); SpawnElectricity(origin.ToVector3(), target.ToVector3(), Random::GenerateInt(25, 50), 100, 250, 255, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)(int)ElectricityFlags::ThinOut, 2, 12);
TriggerDynamicLight(origin.x, origin.y, origin.z, 20, 0, 255, 0); SpawnDynamicLight(origin.x, origin.y, origin.z, 20, 0, 255, 0);
SpawnLizard(item); SpawnLizard(item);
} }
else else
@ -256,7 +256,7 @@ namespace TEN::Entities::Creatures::TR3
SpawnElectricity(origin.ToVector3(), target.ToVector3(), 1, 20, 160, 160, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)ElectricityFlags::Spline | (int)ElectricityFlags::MoveEnd, 12, 12); SpawnElectricity(origin.ToVector3(), target.ToVector3(), 1, 20, 160, 160, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)ElectricityFlags::Spline | (int)ElectricityFlags::MoveEnd, 12, 12);
SpawnElectricity(origin.ToVector3(), target.ToVector3(), 1, 80, 160, 160, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)ElectricityFlags::Spline | (int)ElectricityFlags::MoveEnd, 5, 12); SpawnElectricity(origin.ToVector3(), target.ToVector3(), 1, 80, 160, 160, 30, (int)(int)(int)ElectricityFlags::ThinIn | (int)ElectricityFlags::Spline | (int)ElectricityFlags::MoveEnd, 5, 12);
TriggerDynamicLight(origin.x, origin.y, origin.z, 20, 0, 255, 255); SpawnDynamicLight(origin.x, origin.y, origin.z, 20, 0, 255, 255);
auto hitPos = Vector3i::Zero; auto hitPos = Vector3i::Zero;
if (ObjectOnLOS2(&origin, &target, &hitPos, nullptr, ID_LARA) == creature.Enemy->Index) if (ObjectOnLOS2(&origin, &target, &hitPos, nullptr, ID_LARA) == creature.Enemy->Index)

View file

@ -179,7 +179,7 @@ namespace TEN::Entities::Creatures::TR3
auto pos = GetJointPosition(item, SealMutantGasBite.BoneID, Vector3(0.0f, -SEAL_MUTANT_FLAME_LIGHT_Y_OFFSET, 0.0f)); auto pos = GetJointPosition(item, SealMutantGasBite.BoneID, Vector3(0.0f, -SEAL_MUTANT_FLAME_LIGHT_Y_OFFSET, 0.0f));
auto color = Color(Random::GenerateFloat(0.75f, 1.0f), Random::GenerateFloat(0.4f, 0.5f), Random::GenerateFloat(0.0f, 0.25f)); auto color = Color(Random::GenerateFloat(0.75f, 1.0f), Random::GenerateFloat(0.4f, 0.5f), Random::GenerateFloat(0.0f, 0.25f));
float falloff = Random::GenerateFloat(BLOCK(1.5f), BLOCK(2.5f)); float falloff = Random::GenerateFloat(BLOCK(1.5f), BLOCK(2.5f));
TriggerDynamicPointLight(pos.ToVector3(), color, falloff); SpawnDynamicPointLight(pos.ToVector3(), color, falloff);
} }
} }
else if (TestAnimFrameRange(item, 1, 124)) else if (TestAnimFrameRange(item, 1, 124))

View file

@ -224,7 +224,7 @@ namespace TEN::Entities::Creatures::TR3
(item.Animation.AnimNumber == GetAnimIndex(item, SOPHIALEIGH_ANIM_SCEPTER_SHOOT) && item.Animation.FrameNumber > GetFrameIndex(&item, 39) && item.Animation.FrameNumber < GetFrameIndex(&item, 47)) || (item.Animation.AnimNumber == GetAnimIndex(item, SOPHIALEIGH_ANIM_SCEPTER_SHOOT) && item.Animation.FrameNumber > GetFrameIndex(&item, 39) && item.Animation.FrameNumber < GetFrameIndex(&item, 47)) ||
(item.Animation.AnimNumber == GetAnimIndex(item, SOPHIALEIGH_ANIM_SCEPTER_SMALL_SHOOT) && item.Animation.FrameNumber > GetFrameIndex(&item, 14) && item.Animation.FrameNumber < GetFrameIndex(&item, 18))) (item.Animation.AnimNumber == GetAnimIndex(item, SOPHIALEIGH_ANIM_SCEPTER_SMALL_SHOOT) && item.Animation.FrameNumber > GetFrameIndex(&item, 14) && item.Animation.FrameNumber < GetFrameIndex(&item, 18)))
{ {
TriggerDynamicLight( SpawnDynamicLight(
pos.x, pos.y, pos.z, pos.x, pos.y, pos.z,
item.ItemFlags[1] + SOPHIALEIGH_LIGHTNING_GLOW_SIZE, item.ItemFlags[1] + SOPHIALEIGH_LIGHTNING_GLOW_SIZE,
SOPHIALEIGH_EFFECT_COLOR.x * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.y * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.z * UCHAR_MAX); SOPHIALEIGH_EFFECT_COLOR.x * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.y * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.z * UCHAR_MAX);
@ -234,7 +234,7 @@ namespace TEN::Entities::Creatures::TR3
} }
else if (item.Animation.AnimNumber == GetAnimIndex(item, SOPHIALEIGH_ANIM_SUMMON_END) && item.Animation.FrameNumber >= GetFrameIndex(&item, 3) && item.ItemFlags[1] > 0) else if (item.Animation.AnimNumber == GetAnimIndex(item, SOPHIALEIGH_ANIM_SUMMON_END) && item.Animation.FrameNumber >= GetFrameIndex(&item, 3) && item.ItemFlags[1] > 0)
{ {
TriggerDynamicLight( SpawnDynamicLight(
pos.x, pos.y, pos.z, pos.x, pos.y, pos.z,
item.ItemFlags[1] + SOPHIALEIGH_LIGHTNING_GLOW_SIZE, item.ItemFlags[1] + SOPHIALEIGH_LIGHTNING_GLOW_SIZE,
SOPHIALEIGH_EFFECT_COLOR.x * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.y * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.z * UCHAR_MAX); SOPHIALEIGH_EFFECT_COLOR.x * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.y * UCHAR_MAX, SOPHIALEIGH_EFFECT_COLOR.z * UCHAR_MAX);

View file

@ -116,7 +116,7 @@ namespace TEN::Entities::Creatures::TR3
Random::GenerateFloat(0.75f, 1.0f), Random::GenerateFloat(0.75f, 1.0f),
Random::GenerateFloat(0.5f, 0.6f), Random::GenerateFloat(0.5f, 0.6f),
Random::GenerateFloat(0.0f, 0.25f)); Random::GenerateFloat(0.0f, 0.25f));
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, 2 * item.ItemFlags[0] + 8, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX); SpawnDynamicLight(lightPos.x, lightPos.y, lightPos.z, 2 * item.ItemFlags[0] + 8, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX);
autoGun.MuzzleFlash[0].Bite = TwinAutoGunLeftBite; autoGun.MuzzleFlash[0].Bite = TwinAutoGunLeftBite;
autoGun.MuzzleFlash[0].SwitchToMuzzle2 = true; autoGun.MuzzleFlash[0].SwitchToMuzzle2 = true;
@ -139,7 +139,7 @@ namespace TEN::Entities::Creatures::TR3
Random::GenerateFloat(0.75f, 1.0f), Random::GenerateFloat(0.75f, 1.0f),
Random::GenerateFloat(0.5f, 0.6f), Random::GenerateFloat(0.5f, 0.6f),
Random::GenerateFloat(0.0f, 0.25f)); Random::GenerateFloat(0.0f, 0.25f));
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, 2 * item.ItemFlags[0] + 8, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX); SpawnDynamicLight(lightPos.x, lightPos.y, lightPos.z, 2 * item.ItemFlags[0] + 8, lightColor.R() * UCHAR_MAX, lightColor.G() * UCHAR_MAX, lightColor.B() * UCHAR_MAX);
autoGun.MuzzleFlash[1].Bite = TwinAutoGunRightBite; autoGun.MuzzleFlash[1].Bite = TwinAutoGunRightBite;
autoGun.MuzzleFlash[1].SwitchToMuzzle2 = true; autoGun.MuzzleFlash[1].SwitchToMuzzle2 = true;

Some files were not shown because too many files have changed in this diff Show more