Merge branch 'develop' into sezz_target_highlighter

This commit is contained in:
Sezz 2023-07-31 20:21:56 +10:00
commit c484013e29
341 changed files with 6386 additions and 4889 deletions

View file

@ -1,24 +1,54 @@
Version 1.1.1
==============
* Fix burning torch not working properly if there is more than 256 objects in a level.
Version 1.1.0
==============
* Fix enemies shooting Lara through static meshes and moveables.
* Fix skeletons and mummies not affected by explosive weapons.
* Fix skeletons and mummies not being affected by explosive weapons.
* Fix crash on loading if static meshes with IDs above maximum are present.
* Fix various crashes specific to 64-bit build.
* Fix random crashes when playing audio tracks with names longer than 15 symbols.
* Fix crashes when trying to play .wav audio tracks on some Windows 11 systems.
* Fix last selected gun type not preserved after level jump.
* Fix incorrect vertical position after reloading a savegame made while standing on a bridge.
* Fix sprint value going below zero.
* Fix fog bulb density formula.
* Fix electricity effect crashing 64-bit version of the engine.
* Fix clockwork beetle activation crashing the game.
* Fix corrupted vehicle positions after savegame reload.
* Fix default ambience overlapping current one when loading a savegame.
* Fix doppelganger being limited to be in a single room.
* Add multiple doppelgangers by using the same OCB for the origin nullmesh and doppelganger.
* Implement separate audio track channel for playing voiceovers with subtitles.
* Fix doppelganger being limited to a single room.
* Fix bat AI, damage value, and incorrect collision after death.
* Fix regeneration for pickups with OCB 128.
* Fix raising blocks still shaking without OCB.
* Fix spiky ceiling, improve collision, and allow setting velocity via OCB.
* Fix TR1 winged mutant pathfinding and damage issues and add new OCBs.
* Fix TR1 Natla facing angle, bomb and shard projectiles, shooting anim in the second phase.
* Fix last inventory item position not being saved.
* Fix some puzzle hole objects crashing the game on item insertion.
* Fix incorrect harpoon bolt speed and angle when shooting vertically.
* Fix black shatter debris.
* Fix Lara's shadow projecting only her joints on some occasions.
* Fix sun and spot bulbs direction and sheen casts.
* Fix room collector freezing game on some occasions.
* Fix incorrect culling for scaled static meshes.
* Fix normal mapping.
* Add ability to save screenshot in the "Screenshots" subfolder by pressing the "Print screen" key.
* Implement separate audio track channel for playing voiceovers with subtitles in .srt format.
* Don't stop ambience when Lara dies.
* Pause all sounds when entering inventory or pause menu.
* Preserve hit points on level jump.
* Improve deflection against slopes.
* Move and rotate Lara together with dynamic bridge objects.
* Move and rotate activated pickups together with dynamic bridge objects.
* Move and rotate Lara and activated pickups together with dynamic bridge objects.
* Reduce camera bounce.
* Improve spiky wall collision accuracy.
* Expand control settings page.
* Allow key bindings for previously hardcoded actions (weapon hotkeys, vehicle controls).
* Add input actions for weapon scroll.
* Add splash effect to rockets and grenades when they enter water.
* Allow multiple doppelgangers by using the same OCB for the origin nullmesh and doppelganger.
* Add TR1 skateboard kid.
* Add TR1 Kold.

View file

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

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -506,7 +507,7 @@
</li>
<li><span class="parameter">speed</span>
<span class="types"><span class="type">float</span></span>
(default 1.0). Speed in "amount" per second. A value of 1 will make the flash take one second. Clamped to [0.005, 1.0]
(default 1.0). Speed in "amount" per second. Value of 1 will make flash take one second. Clamped to [0.005, 1.0].
</li>
</ul>
@ -522,7 +523,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -669,7 +670,7 @@ Specify which translations in the strings table correspond to which languages.
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -245,7 +246,7 @@ Similar to <a href="../1 modules/Inventory.html#GiveItem">GiveItem</a> but repla
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -408,7 +409,7 @@ end
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -126,7 +127,7 @@
<td class="summary">Shows the mode of the game camera.</td>
</tr>
<tr>
<td class="name" ><a href="#PlayAudioTrack">PlayAudioTrack(name, loop)</a></td>
<td class="name" ><a href="#PlayAudioTrack">PlayAudioTrack(name, type)</a></td>
<td class="summary">Play an audio track</td>
</tr>
<tr>
@ -138,10 +139,18 @@
<td class="summary">Stop any audio tracks currently playing</td>
</tr>
<tr>
<td class="name" ><a href="#StopAudioTrack">StopAudioTrack(looped)</a></td>
<td class="name" ><a href="#StopAudioTrack">StopAudioTrack(type)</a></td>
<td class="summary">Stop audio track that is currently playing</td>
</tr>
<tr>
<td class="name" ><a href="#GetAudioTrackLoudness">GetAudioTrackLoudness(type)</a></td>
<td class="summary">Get current loudness level for specified track type</td>
</tr>
<tr>
<td class="name" ><a href="#GetCurrentSubtitle">GetCurrentSubtitle()</a></td>
<td class="summary">Get current subtitle string for a voice track currently playing.</td>
</tr>
<tr>
<td class="name" ><a href="#PlaySound">PlaySound(sound[, position])</a></td>
<td class="summary">Play sound effect</td>
</tr>
@ -150,6 +159,10 @@
<td class="summary">Check if the sound effect is playing</td>
</tr>
<tr>
<td class="name" ><a href="#IsAudioTrackPlaying">IsAudioTrackPlaying(Track)</a></td>
<td class="summary">Check if the audio track is playing</td>
</tr>
<tr>
<td class="name" ><a href="#FlipMap">FlipMap(flipmap)</a></td>
<td class="summary">Do FlipMap with specific ID</td>
</tr>
@ -410,7 +423,7 @@ eyes of the creatures would be.
</dd>
<dt>
<a name = "PlayAudioTrack"></a>
<strong>PlayAudioTrack(name, loop)</strong>
<strong>PlayAudioTrack(name, type)</strong>
</dt>
<dd>
Play an audio track
@ -423,9 +436,9 @@ eyes of the creatures would be.
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
of track (without file extension) to play
</li>
<li><span class="parameter">loop</span>
<span class="types"><span class="type">bool</span></span>
if true, the track will loop; if false, it won't (default: false)
<li><span class="parameter">type</span>
<span class="types"><a class="type" href="../4 enums/Misc.SoundTrackType.html#">SoundTrackType</a></span>
of the audio track to play
</li>
</ul>
@ -473,7 +486,7 @@ eyes of the creatures would be.
</dd>
<dt>
<a name = "StopAudioTrack"></a>
<strong>StopAudioTrack(looped)</strong>
<strong>StopAudioTrack(type)</strong>
</dt>
<dd>
Stop audio track that is currently playing
@ -482,9 +495,9 @@ eyes of the creatures would be.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">looped</span>
<span class="types"><span class="type">bool</span></span>
if set, stop looped audio track, if not, stop one-shot audio track
<li><span class="parameter">type</span>
<span class="types"><a class="type" href="../4 enums/Misc.SoundTrackType.html#">SoundTrackType</a></span>
of the audio track
</li>
</ul>
@ -492,6 +505,57 @@ eyes of the creatures would be.
</dd>
<dt>
<a name = "GetAudioTrackLoudness"></a>
<strong>GetAudioTrackLoudness(type)</strong>
</dt>
<dd>
Get current loudness level for specified track type
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">type</span>
<span class="types"><a class="type" href="../4 enums/Misc.SoundTrackType.html#">SoundTrackType</a></span>
of the audio track
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">float</span></span>
current loudness of a specified audio track
</ol>
</dd>
<dt>
<a name = "GetCurrentSubtitle"></a>
<strong>GetCurrentSubtitle()</strong>
</dt>
<dd>
Get current subtitle string for a voice track currently playing.
Subtitle file must be in .srt format, have same filename as voice track, and be placed in same directory as voice track.
Returns nil if no voice track is playing or no subtitle present.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
current subtitle string
</ol>
</dd>
<dt>
<a name = "PlaySound"></a>
@ -541,6 +605,28 @@ eyes of the creatures would be.
</dd>
<dt>
<a name = "IsAudioTrackPlaying"></a>
<strong>IsAudioTrackPlaying(Track)</strong>
</dt>
<dd>
Check if the audio track is playing
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">Track</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
filename to check. Should be without extension and without full directory path.
</li>
</ul>
</dd>
<dt>
<a name = "FlipMap"></a>
@ -915,7 +1001,7 @@ PrintLog(<span class="string">'test error log'</span>, LogLevel.ERROR)
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -465,7 +466,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -205,7 +206,7 @@ with a call to <a href="../1 modules/Strings.html#ShowString">ShowString</a>, or
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -106,7 +107,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -233,7 +234,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -191,7 +192,7 @@ EXAMINE
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -536,7 +537,7 @@ Must be at least 4.</p>
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -106,7 +107,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -146,7 +147,7 @@ has an unrecoverable error, the game will close.
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -204,7 +205,7 @@ Less is more. City of The Dead, for example, uses a speed value of 16.
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -407,7 +408,7 @@ aiObj:SetObjectID(TEN.Objects.ObjID.AI_PATROL1)</pre>
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -320,7 +321,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -671,7 +672,7 @@ ROCKETLAUNCHER
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -1859,7 +1860,7 @@ sas:SetPosition(destinationPosition, <span class="keyword">false</span>)</pre>
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -334,7 +335,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -270,7 +271,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -268,7 +269,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -554,7 +555,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -431,7 +432,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -407,7 +408,7 @@ varDisplayString:SetFlags({ TEN.Strings.DisplayStringOption.SHADOW, TEN.Strings.
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -109,7 +110,7 @@
</tr>
<tr>
<td class="name" ><a href="#a">a</a></td>
<td class="summary">(int) alpha component (255 is opaque, 0 is invisible)</td>
<td class="summary">(int) alpha component (255 = opaque, 0 = invisible)</td>
</tr>
</table>
<h2><a href="#Functions">Functions</a></h2>
@ -191,7 +192,7 @@
<strong>a</strong>
</dt>
<dd>
(int) alpha component (255 is opaque, 0 is invisible)
(int) alpha component (255 = opaque, 0 = invisible)
@ -322,7 +323,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -257,7 +258,7 @@ All values will be clamped to [0.0f, 360.0f].</p>
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -259,7 +260,7 @@ numbers, this will be less accurate at smaller lengths.
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -285,7 +286,7 @@ However, this function would return it as (0, 1, 1).
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -152,7 +153,7 @@ ALPHABLEND
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -150,7 +151,7 @@ CUSTOM
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <here>Misc.ActionID</here></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -119,19 +120,46 @@
BACK
LEFT
RIGHT
CROUCH
SPRINT
STEP_LEFT
STEP_RIGHT
WALK
SPRINT
CROUCH
JUMP
ROLL
ACTION
DRAW
FLARE
LOOK
ROLL
INVENTORY
ACCELERATE
REVERSE
SPEED
SLOW
BRAKE
FIRE
FLARE
SMALL_MEDIPACK
LARGE_MEDIPACK
PREVIOUS_WEAPON
NEXT_WEAPON
WEAPON_1
WEAPON_2
WEAPON_3
WEAPON_4
WEAPON_5
WEAPON_6
WEAPON_7
WEAPON_8
WEAPON_9
WEAPON_10
SELECT
DESELECT
PAUSE
STEPLEFT
STEPRIGHT
INVENTORY
SAVE
LOAD
</code></pre>
@ -159,7 +187,7 @@ STEPRIGHT
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-24 14:47:38 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <here>Misc.CameraType</here></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -148,7 +149,7 @@ OBJECT
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <here>Misc.LogLevel</here></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -144,7 +145,7 @@ ERROR
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -0,0 +1,153 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>TombEngine</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>1 Modules</h2>
<ul class="nowrap">
<li> <a href="../1 modules/Effects.html">Effects</a></li>
<li> <a href="../1 modules/Flow.html">Flow</a></li>
<li> <a href="../1 modules/Inventory.html">Inventory</a></li>
<li> <a href="../1 modules/Logic.html">Logic</a></li>
<li> <a href="../1 modules/Misc.html">Misc</a></li>
<li> <a href="../1 modules/Objects.html">Objects</a></li>
<li> <a href="../1 modules/Strings.html">Strings</a></li>
</ul>
<h2>2 Classes</h2>
<ul class="nowrap">
<li> <a href="../2 classes/Flow.Animations.html">Flow.Animations</a></li>
<li> <a href="../2 classes/Flow.Fog.html">Flow.Fog</a></li>
<li> <a href="../2 classes/Flow.InventoryItem.html">Flow.InventoryItem</a></li>
<li> <a href="../2 classes/Flow.Level.html">Flow.Level</a></li>
<li> <a href="../2 classes/Flow.Mirror.html">Flow.Mirror</a></li>
<li> <a href="../2 classes/Flow.Settings.html">Flow.Settings</a></li>
<li> <a href="../2 classes/Flow.SkyLayer.html">Flow.SkyLayer</a></li>
<li> <a href="../2 classes/Objects.AIObject.html">Objects.AIObject</a></li>
<li> <a href="../2 classes/Objects.Camera.html">Objects.Camera</a></li>
<li> <a href="../2 classes/Objects.LaraObject.html">Objects.LaraObject</a></li>
<li> <a href="../2 classes/Objects.Moveable.html">Objects.Moveable</a></li>
<li> <a href="../2 classes/Objects.Room.html">Objects.Room</a></li>
<li> <a href="../2 classes/Objects.Sink.html">Objects.Sink</a></li>
<li> <a href="../2 classes/Objects.SoundSource.html">Objects.SoundSource</a></li>
<li> <a href="../2 classes/Objects.Static.html">Objects.Static</a></li>
<li> <a href="../2 classes/Objects.Volume.html">Objects.Volume</a></li>
<li> <a href="../2 classes/Strings.DisplayString.html">Strings.DisplayString</a></li>
</ul>
<h2>3 Primitive Classes</h2>
<ul class="nowrap">
<li> <a href="../3 primitive classes/Color.html">Color</a></li>
<li> <a href="../3 primitive classes/Rotation.html">Rotation</a></li>
<li> <a href="../3 primitive classes/Vec2.html">Vec2</a></li>
<li> <a href="../3 primitive classes/Vec3.html">Vec3</a></li>
</ul>
<h2>4 Enums</h2>
<ul class="nowrap">
<li> <a href="../4 enums/Effects.BlendID.html">Effects.BlendID</a></li>
<li> <a href="../4 enums/Effects.EffectID.html">Effects.EffectID</a></li>
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <here>Misc.SoundTrackType</here></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
</ul>
<h2>5 Lua utility modules</h2>
<ul class="nowrap">
<li> <a href="../5 lua utility modules/EventSequence.html">EventSequence</a></li>
<li> <a href="../5 lua utility modules/Timer.html">Timer</a></li>
</ul>
</div>
<div id="content">
<h1>Enum <code>Misc.SoundTrackType</code></h1>
<p>Constants for the type of the audio tracks.</p>
<p>
</p>
<h2><a href="#Misc_SoundTrackType_constants">Misc.SoundTrackType constants </a></h2>
<table class="function_list">
<tr>
<td class="name" ><a href="#CONSTANT_STRING_HERE">CONSTANT_STRING_HERE</a></td>
<td class="summary">Table of sound track type constants (for use with sound track functions).</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header has-description"><a name="Misc_SoundTrackType_constants"></a>Misc.SoundTrackType constants </h2>
<div class="section-description">
<p>The following constants are inside SoundTrackType.</p>
<pre><code>ONESHOT
LOOPED
VOICE
</code></pre>
</div>
<dl class="function">
<dt>
<a name = "CONSTANT_STRING_HERE"></a>
<strong>CONSTANT_STRING_HERE</strong>
</dt>
<dd>
Table of sound track type constants (for use with sound track functions).
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <here>Objects.ObjID</here></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -275,9 +276,7 @@ WINGED_MUMMY
CENTAUR_MUTANT
DOPPELGANGER
NATLA
WINGED_NATLA
GIANT_MUTANT
PROJ_NATLA
PROJ_SHARD
PROJ_BOMB
YETI
@ -345,6 +344,8 @@ BOSS_EXPLOSION_SHOCKWAVE
BOSS_EXPLOSION_RING
CLAW_MUTANT
WASP_MUTANT
SKATEBOARD
SKATEBOARD_KID
SPRINGBOARD
ROLLING_SPINDLE
DISK_SHOOTER
@ -873,7 +874,7 @@ AI_X2
LARA_START_POS
TELEPORTER
LIFT_TELEPORTER
LASERS
LASER_BARRIER
STEAM_LASERS
FLOOR_LASERS
KILL_ALL_TRIGGERS
@ -907,7 +908,7 @@ WATERFALL6
WATERFALLSS1
WATERFALLSS2
FISHTANK
BACON_REFERENCE
DOPPELGANGER_ORIGIN
CORPSE
WRAITH_TRAP
MESHSWAP1
@ -1321,7 +1322,7 @@ PC_SAVE_INV_ITEM
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <here>Objects.RoomFlagID</here></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -149,7 +150,7 @@ NOLENSFLARE
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <here>Objects.RoomReverb</here></li>
@ -147,7 +148,7 @@ PIPE
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -347,7 +348,7 @@ LevelFuncs.SpawnBaddy = <span class="keyword">function</span>(baddy, name, pos)
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="../4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="../4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="../4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="../4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="../4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="../4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="../4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -520,7 +521,7 @@ LevelFuncs.TriggerTimer = <span class="keyword">function</span>(obj)
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -3,7 +3,7 @@
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>TombEngine 1.0.9 Lua API</title>
<title>TombEngine 1.1.0 Lua API</title>
<link rel="stylesheet" href="ldoc.css" type="text/css" />
</head>
<body>
@ -74,6 +74,7 @@
<li> <a href="4 enums/Misc.ActionID.html">Misc.ActionID</a></li>
<li> <a href="4 enums/Misc.CameraType.html">Misc.CameraType</a></li>
<li> <a href="4 enums/Misc.LogLevel.html">Misc.LogLevel</a></li>
<li> <a href="4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></li>
<li> <a href="4 enums/Objects.ObjID.html">Objects.ObjID</a></li>
<li> <a href="4 enums/Objects.RoomFlagID.html">Objects.RoomFlagID</a></li>
<li> <a href="4 enums/Objects.RoomReverb.html">Objects.RoomReverb</a></li>
@ -89,7 +90,7 @@
<div id="content">
<h2>TombEngine 1.0.9 scripting interface</h2>
<h2>TombEngine 1.1.0 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>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>
@ -254,6 +255,10 @@ local door = GetMoveableByName("door_type4_14")
<td class="name" ><a href="4 enums/Misc.LogLevel.html">Misc.LogLevel</a></td>
<td class="summary">Constants for LogLevel IDs.</td>
</tr>
<tr>
<td class="name" ><a href="4 enums/Misc.SoundTrackType.html">Misc.SoundTrackType</a></td>
<td class="summary">Constants for the type of the audio tracks.</td>
</tr>
<tr>
<td class="name" ><a href="4 enums/Objects.ObjID.html">Objects.ObjID</a></td>
<td class="summary">Constants for object IDs.</td>
@ -283,7 +288,7 @@ local door = GetMoveableByName("door_type4_14")
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="https://github.com/hispidence/TEN-LDoc">TEN-LDoc</a> (a fork of <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a>)</i>
<i style="float:right;">Last updated 2023-06-03 11:42:57 </i>
<i style="float:right;">Last updated 2023-07-20 12:10:11 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

View file

@ -356,7 +356,7 @@
<parameter>
<name>speed</name>
<type>float</type>
<description>(default 1.0). Speed in "amount" per second. A value of 1 will make the flash take one second. Clamped to [0.005, 1.0]</description>
<description>(default 1.0). Speed in "amount" per second. Value of 1 will make flash take one second. Clamped to [0.005, 1.0].</description>
</parameter>
</parameters>
</function>
@ -1013,9 +1013,9 @@ eyes of the creatures would be.</description>
<description>of track (without file extension) to play</description>
</parameter>
<parameter>
<name>loop</name>
<type>bool</type>
<description>if true, the track will loop; if false, it won't (default: false)</description>
<name>type</name>
<type>Misc.SoundTrackType</type>
<description>of the audio track to play</description>
</parameter>
</parameters>
</function>
@ -1045,13 +1045,46 @@ eyes of the creatures would be.</description>
<summary>Stop audio track that is currently playing</summary>
<parameters>
<parameter>
<name>looped</name>
<type>bool</type>
<description>if set, stop looped audio track, if not, stop one-shot audio track</description>
<name>type</name>
<type>Misc.SoundTrackType</type>
<description>of the audio track</description>
</parameter>
</parameters>
</function>
<function>
<module>Misc</module>
<name>GetAudioTrackLoudness</name>
<summary>Get current loudness level for specified track type</summary>
<parameters>
<parameter>
<name>type</name>
<type>Misc.SoundTrackType</type>
<description>of the audio track</description>
</parameter>
</parameters>
<returns>
<return>
<type>float</type>
<description>current loudness of a specified audio track</description>
</return>
</returns>
</function>
<function>
<module>Misc</module>
<name>GetCurrentSubtitle</name>
<summary>Get current subtitle string for a voice track currently playing.</summary>
<description>Subtitle file must be in .srt format, have same filename as voice track, and be placed in same directory as voice track.
Returns nil if no voice track is playing or no subtitle present.</description>
<returns>
<return>
<type>string</type>
<description>current subtitle string</description>
</return>
</returns>
</function>
<function>
<module>Misc</module>
<name>PlaySound</name>
@ -1083,6 +1116,19 @@ eyes of the creatures would be.</description>
</parameters>
</function>
<function>
<module>Misc</module>
<name>IsAudioTrackPlaying</name>
<summary>Check if the audio track is playing</summary>
<parameters>
<parameter>
<name>Track</name>
<type>string</type>
<description>filename to check. Should be without extension and without full directory path.</description>
</parameter>
</parameters>
</function>
<function>
<module>Misc</module>
<name>FlipMap</name>

View file

@ -125,7 +125,10 @@ Timer = {
else
t.remainingTime = t.remainingTime + t.totalTime
end
t.func(table.unpack(t.funcArgs))
if (t.func ~= nil) then
t.func(table.unpack(t.funcArgs))
end
end
end

View file

@ -5,6 +5,48 @@ corresponding to languages in the table at the end of this file.
local strings =
{
actions_accelerate = { "Accelerate" },
actions_reverse = { "Reverse" },
actions_speed = { "Speed" },
actions_slow = { "Slow" },
actions_brake = { "Brake/Dismount" },
actions_fire = { "Fire" },
actions_action = { "Action" },
actions_sprint = { "Sprint" },
actions_draw = { "Draw" },
actions_crouch = { "Crouch" },
actions_inventory = { "Inventory" },
actions_jump = { "Jump" },
actions_look = { "Look" },
actions_backward = { "Backward" },
actions_forward = { "Forward" },
actions_left = { "Left" },
actions_right = { "Right" },
actions_roll = { "Roll" },
actions_step_left = { "Step Left" },
actions_step_right = { "Step Right" },
actions_pause = { "Pause" },
actions_walk = { "Walk" },
actions_save = { "Save" },
actions_load = { "Load" },
actions_select = { "Select" },
actions_deselect = { "Deselect" },
actions_large_medipack = { "Large Medipack" },
actions_flare = { "Flare" },
actions_next_weapon = { "Next Weapon" },
actions_previous_weapon = { "Previous Weapon" },
actions_small_medipack = { "Small Medipack" },
actions_weapon_1 = { "Weapon 1" },
actions_weapon_2 = { "Weapon 2" },
actions_weapon_3 = { "Weapon 3" },
actions_weapon_4 = { "Weapon 4" },
actions_weapon_5 = { "Weapon 5" },
actions_weapon_6 = { "Weapon 6" },
actions_weapon_7 = { "Weapon 7" },
actions_weapon_8 = { "Weapon 8" },
actions_weapon_9 = { "Weapon 9" },
actions_weapon_10 = { "Weapon 10" },
window_title = { "TombEngine" },
all = { "All" },
apply = { "Apply" },
automatic_targeting = { "Automatic Targeting" },
@ -18,24 +60,7 @@ local strings =
combine = { "Combine" },
combine_with = { "Combine With" },
controls = { "Controls" },
controls_action = { "Action" },
controls_sprint = { "Sprint" },
controls_draw_weapon = { "Draw Weapon" },
controls_crouch = { "Crouch" },
controls_inventory = { "Inventory" },
controls_jump = { "Jump" },
controls_look = { "Look" },
controls_move_backward = { "Move Backward" },
controls_move_forward = { "Move Forward" },
controls_move_left = { "Move Left" },
controls_move_right = { "Move Right" },
controls_roll = { "Roll" },
controls_step_left = { "Step Left" },
controls_step_right = { "Step Right" },
controls_pause = { "Pause" },
controls_use_flare = { "Use Flare" },
controls_walk = { "Walk" },
controls_defaults = { "Reset to Defaults" },
reset_to_defaults = { "Reset to Defaults" },
crossbow = { "Crossbow" },
crossbow_normal_ammo = { "Crossbow Normal Ammo" },
crossbow_poison_ammo = { "Crossbow Poison Ammo" },
@ -54,6 +79,7 @@ local strings =
exit_game = { "Exit Game" },
exit_to_title = { "Exit to Title" },
flares = { "Flares" },
general_actions = { "General Actions"},
grenade_launcher = { "Grenade Launcher" },
grenade_launcher_normal_ammo = { "Grenade Launcher Normal Ammo" },
grenade_launcher_super_ammo = { "Grenade Launcher Super Ammo" },
@ -70,6 +96,7 @@ local strings =
lara_home = { "Lara's Home" },
large_medipack = { "Large Medipack" },
lasersight = { "Lasersight" },
menu_actions = { "Menu Actions" },
music_volume = { "Music Volume" },
new_game = { "New Game" },
none = { "None" },
@ -125,6 +152,8 @@ local strings =
waiting_for_input = { "Waiting For Input" },
windowed = { "Windowed" },
load_game = { "Load Game" },
quick_actions = { "Quick Actions" },
vehicle_actions = { "Vehicle Actions" },
test_level = { "Test Level" },
torch2 = { "Torch 2" },
waterskin_small_empty = { "Small Waterskin (Empty)" },
@ -141,13 +170,7 @@ local strings =
mechanical_scarab = { "Mechanical Scarab With Winding Key" },
mechanical_scarab_1 = { "Mechanical Scarab (No Winding Key)" },
mechanical_scarab_2 = { "Mechanical Scarab Winding Key" },
title = { "Title" },
accelerate = { "Accelerate" },
reverse = { "Reverse" },
speed = { "Speed" },
slow = { "Slow" },
brake = { "Brake" },
fire = { "Fire" }
title = { "Title" }
}
TEN.Flow.SetStrings(strings)

View file

@ -10,7 +10,7 @@ namespace TEN::Hud
{
static constexpr auto LIFE_MAX = 3.0f;
GAME_OBJECT_ID ObjectID = ID_NO_OBJECT;
GAME_OBJECT_ID ObjectID = GAME_OBJECT_ID::ID_NO_OBJECT;
unsigned int Count = 0;
Vector2 Position2D = Vector2::Zero;

View file

@ -38,6 +38,7 @@
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
#include "Scripting/Include/ScriptInterfaceLevel.h"
#include "Sound/sound.h"
#include "Specific/winmain.h"
using namespace TEN::Control::Volumes;
using namespace TEN::Effects::Hair;
@ -491,6 +492,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
if (lara->Status.Stamina < LARA_STAMINA_MAX && item->Animation.ActiveState != LS_SPRINT)
lara->Status.Stamina++;
HandlePlayerQuickActions(*item);
RumbleLaraHealthCondition(item);
bool isWater = TestEnvironment(ENV_FLAG_WATER, item);
@ -588,7 +590,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
if (item->Animation.ActiveState == LS_SWAN_DIVE ||
item->Animation.ActiveState == LS_FREEFALL_DIVE)
{
item->Pose.Position.y = waterHeight + (SECTOR(1) - 24);
item->Pose.Position.y = waterHeight + (BLOCK(1) - 24);
}
SetAnimation(item, LA_WADE);
@ -707,9 +709,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
}
if (TestEnvironment(ENV_FLAG_DAMAGE, item) && item->HitPoints > 0)
{
item->HitPoints--;
}
if (item->HitPoints <= 0)
{
@ -861,6 +861,12 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
}
Statistics.Game.Distance += (int)round(Vector3::Distance(prevPos.ToVector3(), item->Pose.Position.ToVector3()));
if (DebugMode)
{
DrawNearbyPathfinding(GetCollision(item).BottomBlock->Box);
DrawNearbySectorFlags(*item);
}
}
void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
@ -931,9 +937,7 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
// Test for flags and triggers.
ProcessSectorFlags(item);
TestTriggers(item, false);
TestVolumes(Lara.ItemNumber, &coll->Setup);
DrawNearbyPathfinding(GetCollision(item).BottomBlock->Box);
TestVolumes(item->Index, &coll->Setup);
}
void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll)
@ -1005,7 +1009,7 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll)
ProcessSectorFlags(item);
TestTriggers(item, false);
TestVolumes(Lara.ItemNumber);
TestVolumes(item->Index);
}
void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
@ -1094,7 +1098,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
ProcessSectorFlags(item);
TestTriggers(item, false);
TestVolumes(Lara.ItemNumber);
TestVolumes(item->Index);
}
void LaraCheat(ItemInfo* item, CollisionInfo* coll)

View file

@ -103,7 +103,7 @@ void lara_as_vault(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableObjectPush = false;
coll->Setup.EnableSpasm = false;
EaseOutLaraHeight(item, lara->Context.ProjectedFloorHeight - item->Pose.Position.y);
EasePlayerVerticalPosition(item, lara->Context.ProjectedFloorHeight - item->Pose.Position.y);
item->Pose.Orientation.Lerp(lara->Context.TargetOrientation, 0.4f);
item->Animation.TargetState = LS_IDLE;
@ -252,13 +252,13 @@ void lara_as_run_forward(ItemInfo* item, CollisionInfo* coll)
return;
}
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_FAST_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE, LARA_LEAN_MAX);
}
if (TrInput & IN_JUMP || lara->Control.RunJumpQueued)
if (IsHeld(In::Jump) || lara->Control.RunJumpQueued)
{
if (!(TrInput & IN_SPRINT) && lara->Control.Count.Run >= LARA_RUN_JUMP_TIME &&
TestLaraRunJumpForward(item, coll))
@ -418,8 +418,8 @@ void lara_as_idle(ItemInfo* item, CollisionInfo* coll)
if (!IsHeld(In::Jump) || isSwamp) // JUMP locks orientation outside swamps.
{
// Sidestep locks orientation.
if ((IsHeld(In::LeftStep) || (IsHeld(In::Walk) && IsHeld(In::Left))) ||
(IsHeld(In::RightStep) || (IsHeld(In::Walk) && IsHeld(In::Right))))
if ((IsHeld(In::StepLeft) || (IsHeld(In::Walk) && IsHeld(In::Left))) ||
(IsHeld(In::StepRight) || (IsHeld(In::Walk) && IsHeld(In::Right))))
{
ModulateLaraTurnRateY(item, 0, 0, 0);
}
@ -508,7 +508,7 @@ void lara_as_idle(ItemInfo* item, CollisionInfo* coll)
}
}
if (IsHeld(In::LeftStep) || (IsHeld(In::Walk) && IsHeld(In::Left)))
if (IsHeld(In::StepLeft) || (IsHeld(In::Walk) && IsHeld(In::Left)))
{
if (TestLaraStepLeft(item, coll))
item->Animation.TargetState = LS_STEP_LEFT;
@ -517,7 +517,7 @@ void lara_as_idle(ItemInfo* item, CollisionInfo* coll)
return;
}
else if (IsHeld(In::RightStep) || (IsHeld(In::Walk) && IsHeld(In::Right)))
else if (IsHeld(In::StepRight) || (IsHeld(In::Walk) && IsHeld(In::Right)))
{
if (TestLaraStepRight(item, coll))
item->Animation.TargetState = LS_STEP_RIGHT;
@ -571,7 +571,7 @@ void PseudoLaraAsWadeIdle(ItemInfo* item, CollisionInfo* coll)
{
auto* lara = GetLaraInfo(item);
if (TrInput & IN_JUMP && TestLaraJumpUp(item, coll))
if (IsHeld(In::Jump) && TestLaraJumpUp(item, coll))
{
item->Animation.TargetState = LS_JUMP_PREPARE;
lara->Control.JumpDirection = JumpDirection::Up;
@ -798,7 +798,7 @@ void lara_as_run_back(ItemInfo* item, CollisionInfo* coll)
{
auto* lara = GetLaraInfo(item);
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_MED_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE / 4, LARA_LEAN_MAX / 3);
@ -822,7 +822,6 @@ void lara_col_run_back(ItemInfo* item, CollisionInfo* coll)
lara->Control.MoveAngle = item->Pose.Orientation.y + ANGLE(180.0f);
item->Animation.Velocity.y = 0;
item->Animation.IsAirborne = false;
coll->Setup.BlockFloorSlopeDown = true;
coll->Setup.LowerFloorBound = NO_LOWER_BOUND;
coll->Setup.UpperFloorBound = -STEPUP_HEIGHT;
coll->Setup.LowerCeilingBound = 0;
@ -885,7 +884,7 @@ void lara_as_turn_right_slow(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_MED_FAST_TURN_RATE_MAX);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
SetLaraJumpDirection(item, coll);
if (lara->Control.JumpDirection != JumpDirection::None)
@ -994,7 +993,7 @@ void PsuedoLaraAsWadeTurnRightSlow(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_WADE_TURN_RATE_MAX);
if (TrInput & IN_JUMP && TestLaraJumpUp(item, coll))
if (IsHeld(In::Jump) && TestLaraJumpUp(item, coll))
{
item->Animation.TargetState = LS_JUMP_PREPARE;
lara->Control.JumpDirection = JumpDirection::Up;
@ -1131,7 +1130,7 @@ void lara_as_turn_left_slow(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_MED_FAST_TURN_RATE_MAX);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
SetLaraJumpDirection(item, coll);
if (lara->Control.JumpDirection != JumpDirection::None)
@ -1240,7 +1239,7 @@ void PsuedoLaraAsWadeTurnLeftSlow(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_WADE_TURN_RATE_MAX);
if (TrInput & IN_JUMP && TestLaraJumpUp(item, coll))
if (IsHeld(In::Jump) && TestLaraJumpUp(item, coll))
{
item->Animation.TargetState = LS_JUMP_PREPARE;
lara->Control.JumpDirection = JumpDirection::Up;
@ -1465,7 +1464,7 @@ void lara_as_walk_back(ItemInfo* item, CollisionInfo* coll)
return;
}
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SLOW_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE / 4, LARA_LEAN_MAX / 3);
@ -1486,7 +1485,7 @@ void PseudoLaraAsSwampWalkBack(ItemInfo* item, CollisionInfo* coll)
{
auto* lara = GetLaraInfo(item);
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SLOW_TURN_RATE_MAX / 3);
ModulateLaraLean(item, coll, LARA_LEAN_RATE / 3, LARA_LEAN_MAX / 3);
@ -1563,7 +1562,7 @@ void lara_as_turn_right_fast(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, LARA_MED_TURN_RATE_MAX, LARA_FAST_TURN_RATE_MAX);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
SetLaraJumpDirection(item, coll);
if (lara->Control.JumpDirection != JumpDirection::None)
@ -1690,7 +1689,7 @@ void lara_as_turn_left_fast(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, LARA_MED_TURN_RATE_MAX, LARA_FAST_TURN_RATE_MAX);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
SetLaraJumpDirection(item, coll);
if (lara->Control.JumpDirection != JumpDirection::None)
@ -1826,7 +1825,7 @@ void lara_as_step_right(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, 0, 0, 0);
else
{
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SLOW_TURN_RATE_MAX);
}
@ -1920,7 +1919,7 @@ void lara_as_step_left(ItemInfo* item, CollisionInfo* coll)
ModulateLaraTurnRateY(item, 0, 0, 0);
else
{
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SLOW_TURN_RATE_MAX);
}
@ -2143,7 +2142,7 @@ void lara_as_wade_forward(ItemInfo* item, CollisionInfo* coll)
return;
}
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_MED_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE / 2, LARA_LEAN_MAX);
@ -2175,7 +2174,7 @@ void PseudoLaraAsSwampWadeForward(ItemInfo* item, CollisionInfo* coll)
{
auto* lara = GetLaraInfo(item);
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SWAMP_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE / 3, LARA_LEAN_MAX * 0.6f);
@ -2264,13 +2263,13 @@ void lara_as_sprint(ItemInfo* item, CollisionInfo* coll)
return;
}
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SLOW_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE, LARA_LEAN_MAX);
}
if (TrInput & IN_JUMP || lara->Control.RunJumpQueued)
if (IsHeld(In::Jump) || lara->Control.RunJumpQueued)
{
if (TrInput & IN_WALK || !g_GameFlow->HasSprintJump())
{
@ -2400,7 +2399,7 @@ void lara_as_sprint_dive(ItemInfo* item, CollisionInfo* coll)
if (lara->Control.Count.Run > LARA_RUN_JUMP_TIME)
lara->Control.Count.Run = LARA_RUN_JUMP_TIME;
if (TrInput & (IN_LEFT | IN_RIGHT))
if (IsHeld(In::Left) || IsHeld(In::Right))
{
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_SLOW_TURN_RATE_MAX);
ModulateLaraLean(item, coll, LARA_LEAN_RATE, LARA_LEAN_MAX * 0.6f);

View file

@ -35,10 +35,7 @@ void lara_as_swimcheat(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_ACTION)
TriggerDynamicLight(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, 31, 150, 150, 150);
if (TrInput & IN_OPTION)
lara->Control.TurnRate = -ANGLE(12.0f);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.Velocity.y += LARA_SWIM_VELOCITY_ACCEL * 2;
if (item->Animation.Velocity.y > LARA_SWIM_VELOCITY_MAX * 2)

View file

@ -378,7 +378,7 @@ void lara_as_climb_idle(ItemInfo* item, CollisionInfo* coll)
item->Animation.TargetState = LS_LADDER_RIGHT;
lara->Control.MoveAngle = item->Pose.Orientation.y + ANGLE(90.0f);
}
else if (TrInput & IN_JUMP)
else if (IsHeld(In::Jump))
{
if (item->Animation.AnimNumber == LA_LADDER_IDLE)
{
@ -619,8 +619,8 @@ int LaraClimbRightCornerTest(ItemInfo* item, CollisionInfo* coll)
if (angle && angle != SOUTH)
{
x = (item->Pose.Position.x & -SECTOR(1)) - (item->Pose.Position.z % SECTOR(1)) + SECTOR(1);
z = (item->Pose.Position.z & -SECTOR(1)) - (item->Pose.Position.x % SECTOR(1)) + SECTOR(1);
x = (item->Pose.Position.x & -BLOCK(1)) - (item->Pose.Position.z % BLOCK(1)) + BLOCK(1);
z = (item->Pose.Position.z & -BLOCK(1)) - (item->Pose.Position.x % BLOCK(1)) + BLOCK(1);
}
else
{
@ -649,24 +649,24 @@ int LaraClimbRightCornerTest(ItemInfo* item, CollisionInfo* coll)
switch (angle)
{
case NORTH:
x = ((item->Pose.Position.x + SECTOR(1)) & -SECTOR(1)) - (item->Pose.Position.z % SECTOR(1)) + SECTOR(1);
z = ((item->Pose.Position.z + SECTOR(1)) & -SECTOR(1)) - (item->Pose.Position.x % SECTOR(1)) + SECTOR(1);
x = ((item->Pose.Position.x + BLOCK(1)) & -BLOCK(1)) - (item->Pose.Position.z % BLOCK(1)) + BLOCK(1);
z = ((item->Pose.Position.z + BLOCK(1)) & -BLOCK(1)) - (item->Pose.Position.x % BLOCK(1)) + BLOCK(1);
break;
case SOUTH:
x = ((item->Pose.Position.x - SECTOR(1)) & -SECTOR(1)) - (item->Pose.Position.z % SECTOR(1)) + SECTOR(1);
z = ((item->Pose.Position.z - SECTOR(1)) & -SECTOR(1)) - (item->Pose.Position.x % SECTOR(1)) + SECTOR(1);
x = ((item->Pose.Position.x - BLOCK(1)) & -BLOCK(1)) - (item->Pose.Position.z % BLOCK(1)) + BLOCK(1);
z = ((item->Pose.Position.z - BLOCK(1)) & -BLOCK(1)) - (item->Pose.Position.x % BLOCK(1)) + BLOCK(1);
break;
case EAST:
x = ((item->Pose.Position.z ^ item->Pose.Position.x) % SECTOR(1)) ^ (item->Pose.Position.x + SECTOR(1));
z = (item->Pose.Position.z ^ ((item->Pose.Position.z ^ item->Pose.Position.x) % SECTOR(1))) - SECTOR(1);
x = ((item->Pose.Position.z ^ item->Pose.Position.x) % BLOCK(1)) ^ (item->Pose.Position.x + BLOCK(1));
z = (item->Pose.Position.z ^ ((item->Pose.Position.z ^ item->Pose.Position.x) % BLOCK(1))) - BLOCK(1);
break;
case WEST:
default:
x = (item->Pose.Position.x ^ (item->Pose.Position.z ^ item->Pose.Position.x) % SECTOR(1)) - SECTOR(1);
z = ((item->Pose.Position.z ^ item->Pose.Position.x) % SECTOR(1)) ^ (item->Pose.Position.z + SECTOR(1));
x = (item->Pose.Position.x ^ (item->Pose.Position.z ^ item->Pose.Position.x) % BLOCK(1)) - BLOCK(1);
z = ((item->Pose.Position.z ^ item->Pose.Position.x) % BLOCK(1)) ^ (item->Pose.Position.z + BLOCK(1));
break;
}
@ -713,8 +713,8 @@ int LaraClimbLeftCornerTest(ItemInfo* item, CollisionInfo* coll)
}
else
{
x = (item->Pose.Position.x & -SECTOR(1)) - (item->Pose.Position.z & WALL_MASK) + SECTOR(1);
z = (item->Pose.Position.z & -SECTOR(1)) - (item->Pose.Position.x & WALL_MASK) + SECTOR(1);
x = (item->Pose.Position.x & -BLOCK(1)) - (item->Pose.Position.z & WALL_MASK) + BLOCK(1);
z = (item->Pose.Position.z & -BLOCK(1)) - (item->Pose.Position.x & WALL_MASK) + BLOCK(1);
}
int shift = 0;
@ -738,24 +738,24 @@ int LaraClimbLeftCornerTest(ItemInfo* item, CollisionInfo* coll)
switch (angle)
{
case NORTH:
x = (item->Pose.Position.x ^ ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK)) - SECTOR(1);
z = ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK) ^ (item->Pose.Position.z + SECTOR(1));
x = (item->Pose.Position.x ^ ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK)) - BLOCK(1);
z = ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK) ^ (item->Pose.Position.z + BLOCK(1));
break;
case SOUTH:
x = ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK) ^ (item->Pose.Position.x + SECTOR(1));
z = ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK) ^ (item->Pose.Position.z - SECTOR(1));
x = ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK) ^ (item->Pose.Position.x + BLOCK(1));
z = ((item->Pose.Position.z ^ item->Pose.Position.x) & WALL_MASK) ^ (item->Pose.Position.z - BLOCK(1));
break;
case EAST:
x = ((item->Pose.Position.x + SECTOR(1)) & -SECTOR(1)) - (item->Pose.Position.z & WALL_MASK) + SECTOR(1);
z = ((item->Pose.Position.z + SECTOR(1)) & -SECTOR(1)) - (item->Pose.Position.x & WALL_MASK) + SECTOR(1);
x = ((item->Pose.Position.x + BLOCK(1)) & -BLOCK(1)) - (item->Pose.Position.z & WALL_MASK) + BLOCK(1);
z = ((item->Pose.Position.z + BLOCK(1)) & -BLOCK(1)) - (item->Pose.Position.x & WALL_MASK) + BLOCK(1);
break;
case WEST:
default:
x = (item->Pose.Position.x & -SECTOR(1)) - (item->Pose.Position.z & WALL_MASK);
z = (item->Pose.Position.z & -SECTOR(1)) - (item->Pose.Position.x & WALL_MASK);
x = (item->Pose.Position.x & -BLOCK(1)) - (item->Pose.Position.z & WALL_MASK);
z = (item->Pose.Position.z & -BLOCK(1)) - (item->Pose.Position.x & WALL_MASK);
break;
}

View file

@ -633,8 +633,8 @@ void LaraWaterCurrent(ItemInfo* item, CollisionInfo* coll)
const auto& sink = g_Level.Sinks[lara->Context.WaterCurrentActive - 1];
short headingAngle = Geometry::GetOrientToPoint(item->Pose.Position.ToVector3(), sink.Position).y;
lara->Context.WaterCurrentPull.x += ((sink.Strength * SECTOR(1) * phd_sin(headingAngle)) - lara->Context.WaterCurrentPull.x) / 16;
lara->Context.WaterCurrentPull.z += ((sink.Strength * SECTOR(1) * phd_cos(headingAngle)) - lara->Context.WaterCurrentPull.z) / 16;
lara->Context.WaterCurrentPull.x += ((sink.Strength * BLOCK(1) * phd_sin(headingAngle)) - lara->Context.WaterCurrentPull.x) / 16;
lara->Context.WaterCurrentPull.z += ((sink.Strength * BLOCK(1) * phd_cos(headingAngle)) - lara->Context.WaterCurrentPull.z) / 16;
item->Pose.Position.y += (sink.Position.y - item->Pose.Position.y) / 16;
}

View file

@ -40,7 +40,7 @@ void lara_as_crouch_idle(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -65,7 +65,7 @@ void lara_as_crouch_idle(ItemInfo* item, CollisionInfo* coll)
if (TrInput & (IN_LEFT | IN_RIGHT))
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_CRAWL_TURN_RATE_MAX);
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_ROLL || (TrInput & IN_FORWARD && TrInput & IN_BACK))
@ -157,7 +157,7 @@ void lara_as_crouch_roll(ItemInfo* item, CollisionInfo* coll)
lara->Control.CanLook = false;
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -230,7 +230,7 @@ void lara_as_crouch_turn_left(ItemInfo* item, CollisionInfo* coll)
auto* lara = GetLaraInfo(item);
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -243,7 +243,7 @@ void lara_as_crouch_turn_left(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_LOOK)
LookUpDown(item);
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_SPRINT && TestLaraCrouchRoll(item, coll) &&
@ -287,7 +287,7 @@ void lara_as_crouch_turn_right(ItemInfo* item, CollisionInfo* coll)
auto* lara = GetLaraInfo(item);
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -300,7 +300,7 @@ void lara_as_crouch_turn_right(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_LOOK)
LookUpDown(item);
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_SPRINT && TestLaraCrouchRoll(item, coll) &&
@ -344,11 +344,11 @@ void lara_as_crouch_turn_180(ItemInfo* item, CollisionInfo* coll)
auto* lara = GetLaraInfo(item);
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & (IN_FORWARD | IN_BACK) && TestLaraCrouchToCrawl(item))
@ -381,7 +381,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
{
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -409,7 +409,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
if (TrInput & (IN_LEFT | IN_RIGHT))
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL, 0, LARA_CRAWL_TURN_RATE_MAX);
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_ROLL || (TrInput & IN_FORWARD && TrInput & IN_BACK))
@ -419,7 +419,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
}
if ((TrInput & IN_SPRINT && TestLaraCrouchRoll(item, coll)) ||
(TrInput & (IN_DRAW | IN_FLARE) &&
((IsHeld(In::Draw) || IsHeld(In::Flare)) &&
!IsStandingWeapon(item, lara->Control.Weapon.GunType) && HasStateDispatch(item, LS_CROUCH_IDLE)))
{
item->Animation.TargetState = LS_CROUCH_IDLE;
@ -431,7 +431,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
{
auto crawlVaultResult = TestLaraCrawlVault(item, coll);
if (TrInput & (IN_ACTION | IN_JUMP) && crawlVaultResult.Success &&
if ((IsHeld(In::Action) || IsHeld(In::Jump)) && crawlVaultResult.Success &&
g_GameFlow->HasCrawlExtended())
{
item->Animation.TargetState = crawlVaultResult.TargetState;
@ -447,7 +447,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
}
else if (TrInput & IN_BACK)
{
if (TrInput & (IN_ACTION | IN_JUMP) && TestLaraCrawlToHang(item, coll))
if ((IsHeld(In::Action) || IsHeld(In::Jump)) && TestLaraCrawlToHang(item, coll))
{
item->Animation.TargetState = LS_CRAWL_TO_HANG;
DoLaraCrawlToHangSnap(item, coll);
@ -532,7 +532,7 @@ void lara_as_crawl_forward(ItemInfo* item, CollisionInfo* coll)
lara->Control.HandStatus = HandStatus::Busy;
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -548,7 +548,7 @@ void lara_as_crawl_forward(ItemInfo* item, CollisionInfo* coll)
ModulateLaraCrawlFlex(item, LARA_CRAWL_FLEX_RATE, LARA_CRAWL_FLEX_MAX);
}
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_SPRINT && TestLaraCrouchRoll(item, coll))
@ -628,7 +628,7 @@ void lara_as_crawl_back(ItemInfo* item, CollisionInfo* coll)
lara->Control.HandStatus = HandStatus::Busy;
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -644,7 +644,7 @@ void lara_as_crawl_back(ItemInfo* item, CollisionInfo* coll)
ModulateLaraCrawlFlex(item, LARA_CRAWL_FLEX_RATE, LARA_CRAWL_FLEX_MAX);
}
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_BACK)
@ -715,7 +715,7 @@ void lara_as_crawl_turn_left(ItemInfo* item, CollisionInfo* coll)
lara->Control.HandStatus = HandStatus::Busy;
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -725,7 +725,7 @@ void lara_as_crawl_turn_left(ItemInfo* item, CollisionInfo* coll)
return;
}
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_SPRINT && TestLaraCrouchRoll(item, coll))
@ -776,7 +776,7 @@ void lara_as_crawl_turn_right(ItemInfo* item, CollisionInfo* coll)
lara->Control.HandStatus = HandStatus::Busy;
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
@ -786,7 +786,7 @@ void lara_as_crawl_turn_right(ItemInfo* item, CollisionInfo* coll)
return;
}
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
if (TrInput & IN_SPRINT && TestLaraCrouchRoll(item, coll))
@ -835,11 +835,11 @@ void lara_as_crawl_turn_180(ItemInfo* item, CollisionInfo* coll)
auto* lara = GetLaraInfo(item);
coll->Setup.EnableSpasm = false;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
AlignLaraToSurface(item);
if ((TrInput & IN_CROUCH || lara->Control.KeepLow) &&
if ((IsHeld(In::Crouch) || lara->Control.KeepLow) &&
lara->Control.WaterStatus != WaterStatus::Wade)
{
item->Animation.TargetState = LS_CRAWL_IDLE;
@ -864,7 +864,7 @@ void lara_col_crawl_to_hang(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableObjectPush = true;
coll->Setup.EnableSpasm = false;
Camera.targetAngle = 0;
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
ResetPlayerLean(item, 1 / 6.0f);

View file

@ -519,7 +519,7 @@ void HandleWeapon(ItemInfo& laraItem)
else if (player.Control.HandStatus == HandStatus::Free)
{
// Draw weapon.
if (IsHeld(In::DrawWeapon))
if (IsHeld(In::Draw))
{
// No weapon - no any actions.
if (player.Control.Weapon.LastGunType != LaraWeaponType::None)
@ -547,7 +547,7 @@ void HandleWeapon(ItemInfo& laraItem)
}
}
if ((IsHeld(In::DrawWeapon) && player.Control.Weapon.LastGunType != LaraWeaponType::None) ||
if ((IsHeld(In::Draw) && player.Control.Weapon.LastGunType != LaraWeaponType::None) ||
player.Control.Weapon.RequestGunType != player.Control.Weapon.GunType)
{
if (player.Control.IsLow &&
@ -596,7 +596,7 @@ void HandleWeapon(ItemInfo& laraItem)
}
else if (player.Control.HandStatus == HandStatus::WeaponReady)
{
if (IsHeld(In::DrawWeapon) ||
if (IsHeld(In::Draw) ||
player.Control.Weapon.RequestGunType != player.Control.Weapon.GunType)
{
player.Control.HandStatus = HandStatus::WeaponUndraw;

View file

@ -130,7 +130,7 @@ void lara_col_hang(ItemInfo* item, CollisionInfo* coll)
}
// TODO: Allow direction locking just like with standing jumps. Needs new ledge jump prepare state? -- Sezz 24.10.2022
if (TrInput & IN_JUMP && TestLaraLedgeJump(item, coll))
if (IsHeld(In::Jump) && TestLaraLedgeJump(item, coll))
{
if (TrInput & IN_BACK)
item->Animation.TargetState = LS_JUMP_FORWARD;

View file

@ -13,6 +13,7 @@
#include "Game/Lara/lara_collide.h"
#include "Game/Lara/lara_fire.h"
#include "Game/Lara/lara_tests.h"
#include "Game/savegame.h"
#include "Game/Setup.h"
#include "Math/Math.h"
#include "Renderer/Renderer11.h"
@ -68,7 +69,7 @@ void HandleLaraMovementParameters(ItemInfo* item, CollisionInfo* coll)
lara->Control.RunJumpQueued = false;
// Reset lean.
if ((!lara->Control.IsMoving || (lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))) &&
if ((!lara->Control.IsMoving || (lara->Control.IsMoving && !(IsHeld(In::Left) || IsHeld(In::Right)))) &&
(!lara->Control.IsLow && item->Animation.ActiveState != LS_DEATH)) // HACK: Don't interfere with surface alignment in crouch, crawl, and death states.
{
ResetPlayerLean(item, 1 / 6.0f);
@ -76,20 +77,186 @@ void HandleLaraMovementParameters(ItemInfo* item, CollisionInfo* coll)
// Reset crawl flex.
if (!(TrInput & IN_LOOK) && coll->Setup.Height > LARA_HEIGHT - LARA_HEADROOM && // HACK
(!item->Animation.Velocity.z || (item->Animation.Velocity.z && !(TrInput & (IN_LEFT | IN_RIGHT)))))
(!item->Animation.Velocity.z || (item->Animation.Velocity.z && !(IsHeld(In::Left) || IsHeld(In::Right)))))
{
ResetPlayerFlex(item, 0.1f);
}
// Apply and reset turn rate.
item->Pose.Orientation.y += lara->Control.TurnRate;
if (!(TrInput & (IN_LEFT | IN_RIGHT)))
if (!(IsHeld(In::Left) || IsHeld(In::Right)))
lara->Control.TurnRate = 0;
lara->Control.IsLow = false;
lara->Control.IsMonkeySwinging = false;
}
static void UsePlayerMedipack(ItemInfo& item)
{
auto& player = GetLaraInfo(item);
// Can't use medipack; return early.
if (item.HitPoints <= 0 ||
(item.HitPoints >= LARA_HEALTH_MAX && player.Status.Poison == 0))
{
return;
}
bool hasUsedMedipack = false;
if (IsClicked(In::SmallMedipack) &&
player.Inventory.TotalSmallMedipacks != 0)
{
hasUsedMedipack = true;
item.HitPoints += LARA_HEALTH_MAX / 2;
if (item.HitPoints > LARA_HEALTH_MAX)
item.HitPoints = LARA_HEALTH_MAX;
if (player.Inventory.TotalSmallMedipacks != -1)
player.Inventory.TotalSmallMedipacks--;
}
else if (IsClicked(In::LargeMedipack) &&
player.Inventory.TotalLargeMedipacks != 0)
{
hasUsedMedipack = true;
item.HitPoints = LARA_HEALTH_MAX;
if (player.Inventory.TotalLargeMedipacks != -1)
player.Inventory.TotalLargeMedipacks--;
}
if (hasUsedMedipack)
{
player.Status.Poison = 0;
Statistics.Game.HealthUsed++;
SoundEffect(SFX_TR4_MENU_MEDI, nullptr, SoundEnvironment::Always);
}
}
static std::optional<LaraWeaponType> GetPlayerScrolledWeaponType(const ItemInfo& item, LaraWeaponType currentWeaponType, bool getPrev)
{
static const auto SCROLL_WEAPON_TYPES = std::vector<LaraWeaponType>
{
LaraWeaponType::Pistol,
LaraWeaponType::Shotgun,
LaraWeaponType::Uzi,
LaraWeaponType::Revolver,
LaraWeaponType::GrenadeLauncher,
LaraWeaponType::Crossbow,
LaraWeaponType::HarpoonGun,
LaraWeaponType::HK,
LaraWeaponType::RocketLauncher
};
auto& player = GetLaraInfo(item);
// Get vector index for current weapon type.
auto currentIndex = std::optional<unsigned int>(std::nullopt);
for (int i = 0; i < SCROLL_WEAPON_TYPES.size(); i++)
{
if (SCROLL_WEAPON_TYPES[i] == currentWeaponType)
{
currentIndex = i;
break;
}
}
// Invalid current weapon type; return nullopt.
if (!currentIndex.has_value())
return std::nullopt;
// Getter for next index.
auto getNextIndex = [getPrev](unsigned int index)
{
return (index + (getPrev ? ((unsigned int)SCROLL_WEAPON_TYPES.size() - 1) : 1)) % (unsigned int)SCROLL_WEAPON_TYPES.size();
};
// Get next valid weapon type in sequence.
unsigned int nextIndex = getNextIndex(*currentIndex);
while (nextIndex != *currentIndex)
{
auto nextWeaponType = SCROLL_WEAPON_TYPES[nextIndex];
if (player.Weapons[(int)nextWeaponType].Present)
return nextWeaponType;
nextIndex = getNextIndex(nextIndex);
}
// No valid weapon type; return nullopt.
return std::nullopt;
}
void HandlePlayerQuickActions(ItemInfo& item)
{
auto& player = GetLaraInfo(item);
// Handle medipacks.
if (IsClicked(In::SmallMedipack) || IsClicked(In::LargeMedipack))
UsePlayerMedipack(item);
// Handle weapon scroll requests.
if (IsClicked(In::PreviousWeapon) || IsClicked(In::NextWeapon))
{
bool getPrev = IsClicked(In::PreviousWeapon);
auto weaponType = GetPlayerScrolledWeaponType(item, player.Control.Weapon.GunType, getPrev);
if (weaponType.has_value())
player.Control.Weapon.RequestGunType = *weaponType;
}
// Handle weapon requests.
if (IsClicked(In::Weapon1) && player.Weapons[(int)LaraWeaponType::Pistol].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::Pistol;
if (IsClicked(In::Weapon2) && player.Weapons[(int)LaraWeaponType::Shotgun].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::Shotgun;
if (IsClicked(In::Weapon3) && player.Weapons[(int)LaraWeaponType::Uzi].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::Uzi;
if (IsClicked(In::Weapon4) && player.Weapons[(int)LaraWeaponType::Revolver].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::Revolver;
if (IsClicked(In::Weapon5) && player.Weapons[(int)LaraWeaponType::GrenadeLauncher].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::GrenadeLauncher;
if (IsClicked(In::Weapon6) && player.Weapons[(int)LaraWeaponType::Crossbow].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::Crossbow;
if (IsClicked(In::Weapon7) && player.Weapons[(int)LaraWeaponType::HarpoonGun].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::HarpoonGun;
if (IsClicked(In::Weapon8) && player.Weapons[(int)LaraWeaponType::HK].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::HK;
if (IsClicked(In::Weapon9) && player.Weapons[(int)LaraWeaponType::RocketLauncher].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::RocketLauncher;
// TODO: 10th possible weapon, probably grapple gun.
/*if (IsClicked(In::Weapon10) && player.Weapons[(int)LaraWeaponType::].Present)
player.Control.Weapon.RequestGunType = LaraWeaponType::;*/
// TODO: Could theoretically remove SwitchTarget and instead do unique behaviour handling using only Look. -- Sezz 2023.07.08
// HACK: Handle target switch when locked on to an entity.
if (player.Control.HandStatus == HandStatus::WeaponReady &&
player.TargetEntity != nullptr)
{
if (IsClicked(In::Look))
{
ActionMap[(int)In::SwitchTarget].Update(true);
}
else
{
ClearAction(In::SwitchTarget);
}
}
else
{
ClearAction(In::SwitchTarget);
}
}
bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll)
{
auto* lara = GetLaraInfo(item);
@ -229,7 +396,7 @@ void HandlePlayerAirBubbles(ItemInfo* item)
SoundEffect(SFX_TR4_LARA_BUBBLES, &item->Pose, SoundEnvironment::Water);
const auto& level = *g_GameFlow->GetLevel(CurrentLevel);
auto pos = (level.GetLaraType() == LaraType::Divesuit) ?
GetJointPosition(item, LM_TORSO, Vector3i(0, -192, -160)).ToVector3() :
GetJointPosition(item, LM_HEAD, Vector3i(0, -4, -64)).ToVector3();
@ -243,12 +410,9 @@ void HandlePlayerAirBubbles(ItemInfo* item)
// Potential solutions:
// 1. Consider floor tilt when translating objects.
// 2. Object parenting. -- Sezz 2022.10.28
void EaseOutLaraHeight(ItemInfo* item, int height)
void EasePlayerVerticalPosition(ItemInfo* item, int height)
{
constexpr auto LINEAR_THRESHOLD = STEPUP_HEIGHT / 2;
constexpr auto EASING_THRESHOLD_MIN = BLOCK(1.0f / 64);
constexpr auto LINEAR_RATE = 50;
constexpr auto EASING_ALPHA = 0.35f;
constexpr auto LINEAR_RATE_MIN = 50.0f;
// Check for wall.
if (height == NO_HEIGHT)
@ -261,18 +425,12 @@ void EaseOutLaraHeight(ItemInfo* item, int height)
return;
}
int easingThreshold = std::max(abs(item->Animation.Velocity.z), EASING_THRESHOLD_MIN);
// Handle regular case.
if (abs(height) > LINEAR_THRESHOLD)
float linearRate = std::max(LINEAR_RATE_MIN, abs(item->Animation.Velocity.z));
if (abs(height) > linearRate)
{
int sign = std::copysign(1, height);
item->Pose.Position.y += LINEAR_RATE * sign;
}
else if (abs(height) > easingThreshold)
{
int vPos = item->Pose.Position.y;
item->Pose.Position.y = (int)round(Lerp(vPos, vPos + height, EASING_ALPHA));
item->Pose.Position.y += linearRate * sign;
}
else
{
@ -306,12 +464,12 @@ void DoLaraStep(ItemInfo* item, CollisionInfo* coll)
}
}
EaseOutLaraHeight(item, coll->Middle.Floor);
EasePlayerVerticalPosition(item, coll->Middle.Floor);
}
void DoLaraMonkeyStep(ItemInfo* item, CollisionInfo* coll)
{
EaseOutLaraHeight(item, coll->Middle.Ceiling);
EasePlayerVerticalPosition(item, coll->Middle.Ceiling);
}
void DoLaraCrawlToHangSnap(ItemInfo* item, CollisionInfo* coll)
@ -513,7 +671,7 @@ void ModulateLaraSwimTurnRates(ItemInfo* item, CollisionInfo* coll)
auto* lara = GetLaraInfo(item);
/*if (TrInput & (IN_FORWARD | IN_BACK))
ModulateLaraTurnRateX(item, 0, 0, 0);*/
ModulateLaraTurnRateX(item, 0, 0, 0);*/
if (TrInput & IN_FORWARD)
item->Pose.Orientation.x -= ANGLE(3.0f);
@ -609,16 +767,16 @@ void UpdateLaraSubsuitAngles(ItemInfo* item)
else if (lara->Control.TurnRate < 0)
lara->Control.Subsuit.Velocity[1] += 2 * abs(lara->Control.TurnRate);
if (lara->Control.Subsuit.Velocity[0] > SECTOR(1.5f))
lara->Control.Subsuit.Velocity[0] = SECTOR(1.5f);
if (lara->Control.Subsuit.Velocity[0] > BLOCK(1.5f))
lara->Control.Subsuit.Velocity[0] = BLOCK(1.5f);
if (lara->Control.Subsuit.Velocity[1] > SECTOR(1.5f))
lara->Control.Subsuit.Velocity[1] = SECTOR(1.5f);
if (lara->Control.Subsuit.Velocity[1] > BLOCK(1.5f))
lara->Control.Subsuit.Velocity[1] = BLOCK(1.5f);
if (lara->Control.Subsuit.Velocity[0] != 0 || lara->Control.Subsuit.Velocity[1] != 0)
{
auto mul1 = (float)abs(lara->Control.Subsuit.Velocity[0]) / SECTOR(8);
auto mul2 = (float)abs(lara->Control.Subsuit.Velocity[1]) / SECTOR(8);
auto mul1 = (float)abs(lara->Control.Subsuit.Velocity[0]) / BLOCK(8);
auto mul2 = (float)abs(lara->Control.Subsuit.Velocity[1]) / BLOCK(8);
auto vol = ((mul1 + mul2) * 5.0f) + 0.5f;
SoundEffect(SFX_TR5_VEHICLE_DIVESUIT_ENGINE, &item->Pose, SoundEnvironment::Water, 1.0f + (mul1 + mul2), vol);
}
@ -686,7 +844,7 @@ void ModulateLaraSlideVelocity(ItemInfo* item, CollisionInfo* coll)
//lara->ExtraVelocity.y += slideVelocity * phd_sin(steepness);
}
//else
//lara->ExtraVelocity.x += minVelocity;
//lara->ExtraVelocity.x += minVelocity;
}
void AlignLaraToSurface(ItemInfo* item, float alpha)
@ -737,7 +895,7 @@ void SetLaraRunJumpQueue(ItemInfo* item, CollisionInfo* coll)
auto* lara = GetLaraInfo(item);
int y = item->Pose.Position.y;
int distance = SECTOR(1);
int distance = BLOCK(1);
auto probe = GetCollision(item, item->Pose.Orientation.y, distance, -coll->Setup.Height);
if ((TestLaraRunJumpForward(item, coll) || // Area close ahead is permissive...

View file

@ -12,12 +12,13 @@ struct VaultTestResult;
// -----------------------------
void HandleLaraMovementParameters(ItemInfo* item, CollisionInfo* coll);
void HandlePlayerQuickActions(ItemInfo& item);
bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll);
void HandlePlayerWetnessDrips(ItemInfo& item);
void HandlePlayerDiveBubbles(ItemInfo& item);
void HandlePlayerAirBubbles(ItemInfo* item);
void EaseOutLaraHeight(ItemInfo* item, int height);
void EasePlayerVerticalPosition(ItemInfo* item, int height);
void DoLaraStep(ItemInfo* item, CollisionInfo* coll);
void DoLaraMonkeyStep(ItemInfo* item, CollisionInfo* coll);
void DoLaraCrawlToHangSnap(ItemInfo* item, CollisionInfo* coll);

View file

@ -12,31 +12,36 @@
using namespace TEN::Hud;
void InitializeLara(bool restore)
LaraInfo lBackup = {};
int lHitPoints = 0;
void BackupLara()
{
if (Lara.ItemNumber == NO_ITEM)
if (LaraItem == nullptr || LaraItem->Index == NO_ITEM)
return;
LaraInfo lBackup = {};
if (restore)
memcpy(&lBackup, &Lara, sizeof(LaraInfo));
memcpy(&lBackup, &Lara, sizeof(LaraInfo));
lHitPoints = LaraItem->HitPoints;
}
short itemNumber = Lara.ItemNumber;
void InitializeLara(bool restore)
{
if (LaraItem == nullptr || LaraItem->Index == NO_ITEM)
return;
ZeroMemory(&Lara, sizeof(LaraInfo));
LaraItem->Data = &Lara;
LaraItem->Collidable = false;
LaraItem->Location.roomNumber = LaraItem->RoomNumber;
LaraItem->Location.yNumber = LaraItem->Pose.Position.y;
ZeroMemory(&Lara, sizeof(LaraInfo));
Lara.Status.Air = LARA_AIR_MAX;
Lara.Status.Exposure = LARA_EXPOSURE_MAX;
Lara.Status.Poison = 0;
Lara.Status.Stamina = LARA_STAMINA_MAX;
Lara.Control.CanLook = true;
Lara.ItemNumber = itemNumber;
Lara.HitDirection = -1;
Lara.Control.Weapon.WeaponItem = NO_ITEM;
Lara.Context.WaterSurfaceDist = 100;
@ -46,13 +51,18 @@ void InitializeLara(bool restore)
Lara.Location = -1;
Lara.HighestLocation = -1;
Lara.Control.Rope.Ptr = -1;
LaraItem->HitPoints = LARA_HEALTH_MAX;
Lara.Control.HandStatus = HandStatus::Free;
if (restore)
InitializeLaraLevelJump(itemNumber, &lBackup);
{
InitializeLaraLevelJump(LaraItem->Index, &lBackup);
LaraItem->HitPoints = lHitPoints;
}
else
{
InitializeLaraDefaultInventory();
LaraItem->HitPoints = LARA_HEALTH_MAX;
}
InitializeLaraMeshes(LaraItem);
InitializeLaraAnims(LaraItem);
@ -143,10 +153,9 @@ void InitializeLaraAnims(ItemInfo* item)
}
}
void InitializeLaraLoad(short itemNum)
void InitializeLaraLoad(short itemNumber)
{
Lara.ItemNumber = itemNum;
LaraItem = &g_Level.Items[itemNum];
LaraItem = &g_Level.Items[itemNumber];
}
void InitializeLaraLevelJump(short itemNum, LaraInfo* lBackup)
@ -157,6 +166,7 @@ void InitializeLaraLevelJump(short itemNum, LaraInfo* lBackup)
// Restore inventory.
// It restores even puzzle/key items, to reset them, a ResetHub analog must be made.
lara->Inventory = lBackup->Inventory;
lara->Control.Weapon.LastGunType = lBackup->Control.Weapon.LastGunType;
memcpy(&lara->Weapons, &lBackup->Weapons, sizeof(CarriedWeaponInfo) * int(LaraWeaponType::NumWeapons));
// If no flare present, quit

View file

@ -1,6 +1,7 @@
#pragma once
#include "Game/Lara/lara_struct.h"
void BackupLara();
void InitializeLara(bool restore);
void InitializeLaraMeshes(ItemInfo* item);
void InitializeLaraAnims(ItemInfo* item);

View file

@ -265,12 +265,12 @@ void lara_as_jump_prepare(ItemInfo* item, CollisionInfo* coll)
}
// JUMP key repressed without directional key; cancel directional jump lock.
if (DbInput & IN_JUMP && !IsDirectionActionHeld())
if (IsClicked(In::Jump) && !IsDirectionalActionHeld())
lara->Control.JumpDirection = JumpDirection::None;
if (((TrInput & IN_FORWARD &&
!(TrInput & IN_BACK && lara->Control.JumpDirection == JumpDirection::Back)) || // Back jump takes priority in this exception.
!IsDirectionActionHeld() && lara->Control.JumpDirection == JumpDirection::Forward) &&
!IsDirectionalActionHeld() && lara->Control.JumpDirection == JumpDirection::Forward) &&
TestLaraJumpForward(item, coll))
{
item->Animation.TargetState = LS_JUMP_FORWARD;
@ -278,7 +278,7 @@ void lara_as_jump_prepare(ItemInfo* item, CollisionInfo* coll)
return;
}
else if ((TrInput & IN_BACK ||
!IsDirectionActionHeld() && lara->Control.JumpDirection == JumpDirection::Back) &&
!IsDirectionalActionHeld() && lara->Control.JumpDirection == JumpDirection::Back) &&
TestLaraJumpBack(item, coll))
{
item->Animation.TargetState = LS_JUMP_BACK;
@ -287,7 +287,7 @@ void lara_as_jump_prepare(ItemInfo* item, CollisionInfo* coll)
}
if ((TrInput & IN_LEFT ||
!IsDirectionActionHeld() && lara->Control.JumpDirection == JumpDirection::Left) &&
!IsDirectionalActionHeld() && lara->Control.JumpDirection == JumpDirection::Left) &&
TestLaraJumpLeft(item, coll))
{
item->Animation.TargetState = LS_JUMP_LEFT;
@ -295,7 +295,7 @@ void lara_as_jump_prepare(ItemInfo* item, CollisionInfo* coll)
return;
}
else if ((TrInput & IN_RIGHT ||
!IsDirectionActionHeld() && lara->Control.JumpDirection == JumpDirection::Right) &&
!IsDirectionalActionHeld() && lara->Control.JumpDirection == JumpDirection::Right) &&
TestLaraJumpRight(item, coll))
{
item->Animation.TargetState = LS_JUMP_RIGHT;

View file

@ -57,7 +57,7 @@ void lara_as_monkey_idle(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_ACTION && lara->Control.CanMonkeySwing)
{
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.TargetState = LS_JUMP_FORWARD;
lara->Control.HandStatus = HandStatus::Free;
@ -497,7 +497,7 @@ void lara_as_monkey_turn_left(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_ACTION && lara->Control.CanMonkeySwing)
{
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.TargetState = LS_JUMP_FORWARD;
lara->Control.HandStatus = HandStatus::Free;
@ -576,7 +576,7 @@ void lara_as_monkey_turn_right(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_ACTION && lara->Control.CanMonkeySwing)
{
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.TargetState = LS_JUMP_FORWARD;
lara->Control.HandStatus = HandStatus::Free;

View file

@ -37,7 +37,7 @@ void lara_as_pickup(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableSpasm = false;
Camera.targetAngle = -ANGLE(130.0f);
Camera.targetElevation = -ANGLE(15.0f);
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
if (TestLastFrame(item))
item->Animation.TargetState = GetNextAnimState(item);
@ -54,7 +54,7 @@ void lara_as_pickup_flare(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableSpasm = false;
Camera.targetAngle = ANGLE(130.0f);
Camera.targetElevation = -ANGLE(15.0f);
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
if (item->Animation.FrameNumber == (GetAnimData(*item).frameEnd - 1))
lara->Control.HandStatus = HandStatus::Free;
@ -75,7 +75,7 @@ void lara_as_switch_on(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableSpasm = false;
Camera.targetAngle = ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
Camera.speed = 6;
}
@ -90,7 +90,7 @@ void lara_as_switch_off(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableSpasm = false;
Camera.targetAngle = ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
Camera.speed = 6;
}
@ -129,7 +129,7 @@ void lara_as_use_key(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableSpasm = false;
Camera.targetAngle = -ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
}
// State: LS_USE_PUZZLE (43)
@ -143,7 +143,7 @@ void lara_as_use_puzzle(ItemInfo* item, CollisionInfo* coll)
coll->Setup.EnableSpasm = false;
Camera.targetAngle = -ANGLE(80.0f);
Camera.targetElevation = -ANGLE(25.0f);
Camera.targetDistance = SECTOR(1);
Camera.targetDistance = BLOCK(1);
if (TestLastFrame(item) && item->ItemFlags[0])
{
@ -266,7 +266,7 @@ void lara_as_horizontal_bar_swing(ItemInfo* item, CollisionInfo* coll)
if (TrInput & IN_ACTION)
{
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
item->Animation.TargetState = LS_HORIZONTAL_BAR_LEAP;
item->Animation.TargetState = LS_HORIZONTAL_BAR_SWING;
@ -502,7 +502,7 @@ void lara_col_rope_swing(ItemInfo* item, CollisionInfo* coll)
{
auto* lara = GetLaraInfo(item);
Camera.targetDistance = SECTOR(2);
Camera.targetDistance = BLOCK(2);
UpdateRopeSwing(item);
RopeSwingCollision(item, coll, true);
@ -550,7 +550,7 @@ void lara_col_rope_swing(ItemInfo* item, CollisionInfo* coll)
item->Animation.FrameNumber = GetAnimData(item).frameBase;
}
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
JumpOffRope(item);
}
else if (item->Animation.FrameNumber == GetAnimData(LA_ROPE_IDLE_TO_SWING).frameBase + 15)
@ -618,7 +618,7 @@ void lara_as_pole_idle(ItemInfo* item, CollisionInfo* coll)
}
// TODO: Add forward jump.
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.TargetState = LS_JUMP_BACK;
return;
@ -707,7 +707,7 @@ void lara_as_pole_up(ItemInfo* item, CollisionInfo* coll)
if (TrInput & (IN_LEFT | IN_RIGHT))
ModulateLaraTurnRateY(item, LARA_POLE_TURN_RATE_ACCEL, 0, LARA_POLE_TURN_RATE_MAX, true);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.TargetState = LS_POLE_IDLE;
return;
@ -756,7 +756,7 @@ void lara_as_pole_down(ItemInfo* item, CollisionInfo* coll)
if (TrInput & (IN_LEFT | IN_RIGHT))
ModulateLaraTurnRateY(item, LARA_POLE_TURN_RATE_ACCEL, 0, LARA_POLE_TURN_RATE_MAX, true);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
{
item->Animation.TargetState = LS_POLE_IDLE;
return;

View file

@ -9,6 +9,7 @@
#include "Game/control/los.h"
#include "Game/effects/Bubble.h"
#include "Game/effects/debris.h"
#include "Game/effects/Drip.h"
#include "Game/effects/effects.h"
#include "Game/effects/item_fx.h"
#include "Game/effects/Ripple.h"
@ -31,6 +32,7 @@
#include "Specific/level.h"
using namespace TEN::Effects::Bubble;
using namespace TEN::Effects::Drip;
using namespace TEN::Effects::Environment;
using namespace TEN::Effects::Items;
using namespace TEN::Effects::Ripple;
@ -44,6 +46,9 @@ constexpr auto GRENADE_FLASH_TIMEOUT = 4;
constexpr auto HARPOON_VELOCITY = BLOCK(0.25f);
constexpr auto HARPOON_TIME = 10 * FPS;
constexpr auto BOLT_VELOCITY = BLOCK(0.25f);
constexpr auto BOLT_TIME = 10 * FPS;
constexpr auto BOLT_STUCK_LIFE = 5 * FPS;
constexpr auto ROCKET_VELOCITY = CLICK(2);
constexpr auto ROCKET_TIME = 4.5f * FPS;
constexpr auto GRENADE_VELOCITY = BLOCK(1 / 8.0f);
@ -204,7 +209,7 @@ void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType)
break;
case LaraWeaponType::Crossbow:
FireCrossbow(laraItem, nullptr);
FireCrossbow(laraItem);
break;
case LaraWeaponType::HK:
@ -556,109 +561,112 @@ void UndrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType)
}
}
ItemInfo* FireHarpoon(ItemInfo& laraItem)
bool FireHarpoon(ItemInfo& laraItem, const std::optional<Pose>& pose)
{
auto& player = *GetLaraInfo(&laraItem);
auto& ammo = GetAmmo(player, LaraWeaponType::HarpoonGun);
if (!ammo)
return nullptr;
return false;
player.Control.Weapon.HasFired = true;
// Create a new item for harpoon.
short itemNumber = CreateItem();
int itemNumber = CreateItem();
if (itemNumber == NO_ITEM)
return nullptr;
return false;
auto& harpoonItem = g_Level.Items[itemNumber];
harpoonItem.ObjectNumber = ID_HARPOON;
harpoonItem.Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
if (!ammo.HasInfinite())
ammo--;
auto& item = g_Level.Items[itemNumber];
item.Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
item.ObjectNumber = ID_HARPOON;
item.RoomNumber = laraItem.RoomNumber;
auto jointPos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(-2, 373, 77));
int floorHeight = GetCollision(jointPos.x, jointPos.y, jointPos.z, item.RoomNumber).Position.Floor;
if (floorHeight >= jointPos.y)
if (pose.has_value())
{
item.Pose.Position = jointPos;
harpoonItem.Pose.Position = pose->Position;
harpoonItem.RoomNumber = laraItem.RoomNumber;
InitializeItem(itemNumber);
harpoonItem.Pose.Orientation = EulerAngles(
player.LeftArm.Orientation.x + laraItem.Pose.Orientation.x,
player.LeftArm.Orientation.y + laraItem.Pose.Orientation.y,
0);
}
else
{
item.Pose.Position = Vector3i(laraItem.Pose.Position.x, jointPos.y, laraItem.Pose.Position.z);
item.RoomNumber = laraItem.RoomNumber;
auto jointPos = GetJointPosition(&laraItem, LM_RHAND, Vector3i(-2, 373, 77));
harpoonItem.RoomNumber = laraItem.RoomNumber;
int floorHeight = GetCollision(jointPos.x, jointPos.y, jointPos.z, harpoonItem.RoomNumber).Position.Floor;
if (floorHeight >= jointPos.y)
{
harpoonItem.Pose.Position = jointPos;
}
else
{
harpoonItem.Pose.Position = Vector3i(laraItem.Pose.Position.x, jointPos.y, laraItem.Pose.Position.z);
harpoonItem.RoomNumber = laraItem.RoomNumber;
}
InitializeItem(itemNumber);
harpoonItem.Pose.Orientation.x = player.LeftArm.Orientation.x + laraItem.Pose.Orientation.x;
harpoonItem.Pose.Orientation.z = 0;
harpoonItem.Pose.Orientation.y = player.LeftArm.Orientation.y + laraItem.Pose.Orientation.y;
if (!player.LeftArm.Locked)
harpoonItem.Pose.Orientation += player.ExtraTorsoRot;
}
InitializeItem(itemNumber);
harpoonItem.Animation.Velocity.z = HARPOON_VELOCITY;
harpoonItem.HitPoints = HARPOON_TIME;
item.Pose.Orientation = EulerAngles(
player.LeftArm.Orientation.x + laraItem.Pose.Orientation.x,
player.LeftArm.Orientation.y + laraItem.Pose.Orientation.y,
0);
AddActiveItem(itemNumber);
if (!player.LeftArm.Locked)
item.Pose.Orientation += player.ExtraTorsoRot;
item.Pose.Orientation.z = 0;
item.Animation.Velocity.z = HARPOON_VELOCITY * phd_cos(item.Pose.Orientation.x);
item.Animation.Velocity.y = -HARPOON_VELOCITY * phd_sin(item.Pose.Orientation.x);
item.HitPoints = HARPOON_TIME;
harpoonItem.ItemFlags[0] = (int)ProjectileType::Harpoon;
Rumble(0.2f, 0.1f);
AddActiveItem(itemNumber);
Statistics.Level.AmmoUsed++;
Statistics.Game.AmmoUsed++;
return &item;
return true;
}
void HarpoonBoltControl(short itemNumber)
{
auto& harpoonItem = g_Level.Items[itemNumber];
if (harpoonItem.HitPoints < HARPOON_TIME)
{
if (harpoonItem.HitPoints > 0)
harpoonItem.HitPoints--;
if (harpoonItem.HitPoints == 0)
{
harpoonItem.HitPoints--;
}
else
{
ExplodeItemNode(&harpoonItem, 0, 0, BODY_EXPLODE);
ExplodeItemNode(&harpoonItem, 0, 0, BODY_DO_EXPLOSION);
KillItem(itemNumber);
}
return;
}
harpoonItem.Pose.Orientation.z += ANGLE(35.0f);
if (!TestEnvironment(ENV_FLAG_WATER, harpoonItem.RoomNumber))
if (TestEnvironment(ENV_FLAG_WATER, &harpoonItem))
{
harpoonItem.Pose.Orientation.x -= ANGLE(1.0f);
if (harpoonItem.Animation.Velocity.z > 64.0f)
harpoonItem.Animation.Velocity.z -= harpoonItem.Animation.Velocity.z / 16;
if (harpoonItem.Pose.Orientation.x < ANGLE(-90.0f))
harpoonItem.Pose.Orientation.x = ANGLE(-90.0f);
harpoonItem.Animation.Velocity.y = -HARPOON_VELOCITY * phd_sin(harpoonItem.Pose.Orientation.x);
harpoonItem.Animation.Velocity.z = HARPOON_VELOCITY * phd_cos(harpoonItem.Pose.Orientation.x);
}
else
{
if (Wibble & 4)
SpawnBubble(harpoonItem.Pose.Position.ToVector3(), harpoonItem.RoomNumber, (int)BubbleFlags::HighAmplitude);
harpoonItem.Animation.Velocity.y = -HARPOON_VELOCITY * phd_sin(harpoonItem.Pose.Orientation.x) / 2;
harpoonItem.Animation.Velocity.z = HARPOON_VELOCITY * phd_cos(harpoonItem.Pose.Orientation.x) / 2;
if (GlobalCounter & 1)
SpawnBubble(harpoonItem.Pose.Position.ToVector3(), harpoonItem.RoomNumber);
}
auto prevPos = harpoonItem.Pose.Position;
TranslateItem(&harpoonItem, harpoonItem.Pose.Orientation, harpoonItem.Animation.Velocity.z);
HandleProjectile(harpoonItem, *LaraItem, harpoonItem.Pose.Position, ProjectileType::Harpoon, Weapons[(int)LaraWeaponType::HarpoonGun].Damage);
int damage = Weapons[(int)LaraWeaponType::HarpoonGun].Damage;
HandleProjectile(harpoonItem, *LaraItem, prevPos, (ProjectileType)harpoonItem.ItemFlags[0], damage);
}
void FireGrenade(ItemInfo& laraItem)
@ -983,7 +991,7 @@ void RocketControl(short itemNumber)
HandleProjectile(rocketItem, *LaraItem, prevPos, ProjectileType::Explosive, Weapons[(int)LaraWeaponType::RocketLauncher].ExplosiveDamage);
}
void FireCrossbow(ItemInfo& laraItem, Pose* pos)
void FireCrossbow(ItemInfo& laraItem, const std::optional<Pose>& pose)
{
auto& player = *GetLaraInfo(&laraItem);
auto& ammo = GetAmmo(player, LaraWeaponType::Crossbow);
@ -1004,14 +1012,14 @@ void FireCrossbow(ItemInfo& laraItem, Pose* pos)
if (!ammo.HasInfinite())
ammo--;
if (pos)
if (pose.has_value())
{
boltItem.Pose.Position = pos->Position;
boltItem.Pose.Position = pose->Position;
boltItem.RoomNumber = laraItem.RoomNumber;
InitializeItem(itemNumber);
boltItem.Pose.Orientation = pos->Orientation;
boltItem.Pose.Orientation = pose->Orientation;
}
else
{
@ -1040,8 +1048,8 @@ void FireCrossbow(ItemInfo& laraItem, Pose* pos)
}
}
boltItem.Animation.Velocity.z = 512.0f;
boltItem.HitPoints = HARPOON_TIME;
boltItem.Animation.Velocity.z = BOLT_VELOCITY;
boltItem.HitPoints = BOLT_TIME;
AddActiveItem(itemNumber);
@ -1074,7 +1082,7 @@ void FireCrossBowFromLaserSight(ItemInfo& laraItem, GameVector* origin, GameVect
{
auto orient = Geometry::GetOrientToPoint(origin->ToVector3(), target->ToVector3());
auto boltPose = Pose(origin->x, origin->y, origin->z, orient);
FireCrossbow(laraItem, &boltPose);
FireCrossbow(laraItem, boltPose);
}
void CrossbowBoltControl(short itemNumber)
@ -1412,18 +1420,31 @@ bool EmitFromProjectile(ItemInfo& projectile, ProjectileType type)
bool TestProjectileNewRoom(ItemInfo& item, const CollisionResult& coll)
{
// Has projectile changed room?
// Check if projectile changed room.
if (item.RoomNumber == coll.RoomNumber)
return false;
// If currently in water and previously on land, add a ripple.
// If currently in water and previously on land, spawn ripple.
if (TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) != TestEnvironment(ENV_FLAG_WATER, coll.RoomNumber))
{
const auto& player = GetLaraInfo(item);
int floorDiff = abs(coll.Position.Floor - item.Pose.Position.y);
int ceilingDiff = abs(coll.Position.Ceiling - item.Pose.Position.y);
int yPoint = (floorDiff > ceilingDiff) ? coll.Position.Ceiling : coll.Position.Floor;
SpawnRipple(Vector3(item.Pose.Position.x, yPoint, item.Pose.Position.z), item.RoomNumber, Random::GenerateInt(8, 16));
if (player.Control.Weapon.GunType != LaraWeaponType::GrenadeLauncher && player.Control.Weapon.GunType != LaraWeaponType::RocketLauncher)
{
SpawnSplashDrips(
Vector3(item.Pose.Position.x, yPoint, item.Pose.Position.z),
item.RoomNumber, 3, false);
SpawnRipple(Vector3(item.Pose.Position.x, yPoint, item.Pose.Position.z), item.RoomNumber, Random::GenerateInt(8, 16));
}
else
{
Splash(&item);
}
}
ItemNewRoom(item.Index, coll.RoomNumber);
@ -1458,8 +1479,8 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p
bool hasHit = false;
bool hasHitNotByEmitter = false;
bool isExplosive = type >= ProjectileType::Explosive;
bool isShatterable = type != ProjectileType::Harpoon;
bool isExplosive = (type >= ProjectileType::Explosive);
bool isShatterable = (type != ProjectileType::Harpoon);
// For non-grenade projectiles, check for room collision.
if (type < ProjectileType::Grenade)
@ -1467,7 +1488,6 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p
if (pointColl.Position.Floor < projectile.Pose.Position.y ||
pointColl.Position.Ceiling > projectile.Pose.Position.y)
{
projectile.Pose.Position = prevPos;
hasHit =
hasHitNotByEmitter = true;
}
@ -1620,18 +1640,16 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p
DoDamage(itemPtr, damage);
}
}
}
else if (itemPtr->ObjectNumber >= ID_SMASH_OBJECT1 &&
itemPtr->ObjectNumber <= ID_SMASH_OBJECT8)
{
doShatter = hasHit = true;
// Smash objects are legacy objects from TRC. Let's make them explode in the legacy way.
// Smash objects are legacy objects from TRC. Make them explode in legacy way.
ExplodeItemNode(itemPtr, 0, 0, 128);
short currentItemNumber = (itemPtr - CollidedItems[0]);
SmashObject(currentItemNumber);
KillItem(currentItemNumber);
SmashObject(itemPtr->Index);
KillItem(itemPtr->Index);
}
}
@ -1651,7 +1669,7 @@ void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& p
}
else if (doShatter)
{
ExplodeItemNode(&projectile, 0, 0, BODY_EXPLODE);
ExplodeItemNode(&projectile, 0, 0, BODY_DO_EXPLOSION);
}
switch (type)

View file

@ -1,9 +1,9 @@
#pragma once
#include "Math/Math.h"
using namespace TEN::Math;
enum class LaraWeaponType;
class GameVector;
class Pose;
class Vector3i;
struct ItemInfo;
enum class GrenadeType
@ -34,13 +34,13 @@ void UndrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
void DrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
void UndrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
ItemInfo* FireHarpoon(ItemInfo& laraItem);
bool FireHarpoon(ItemInfo& laraItem, const std::optional<Pose>& pose = std::nullopt);
void HarpoonBoltControl(short itemNumber);
void FireGrenade(ItemInfo& laraItem);
void GrenadeControl(short itemNumber);
void FireRocket(ItemInfo& laraItem);
void RocketControl(short itemNumber);
void FireCrossbow(ItemInfo& laraItem, Pose* pos);
void FireCrossbow(ItemInfo& laraItem, const std::optional<Pose>& pose = std::nullopt);
void FireCrossBowFromLaserSight(ItemInfo& laraItem, GameVector* origin, GameVector* target);
void CrossbowBoltControl(short itemNumber);

View file

@ -361,7 +361,7 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll)
if (GetClimbFlags(probeUp.BottomBlock) & slopeData.ClimbOrient &&
InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, CLICK(3), CLICK(4)))
{
if (GetCollision(probeUp.Block, up.x, up.y, up.z).Position.Ceiling - item->Pose.Position.y <= (SECTOR(1.5f) - 80)) // Check if a wall is actually there.
if (GetCollision(probeUp.Block, up.x, up.y, up.z).Position.Ceiling - item->Pose.Position.y <= (BLOCK(1.5f) - 80)) // Check if a wall is actually there.
{
AlignToEdge(item, FORWARD_ALIGNMENT);
SetAnimation(item, LA_OVERHANG_SLOPE_LADDER_CONVEX_START);
@ -451,7 +451,7 @@ void lara_as_slopeclimb(ItemInfo* item, CollisionInfo* coll)
return;
Camera.targetElevation = -ANGLE(16.75f);
Camera.targetDistance = SECTOR(1.75f);
Camera.targetDistance = BLOCK(1.75f);
Camera.speed = 15;
}
@ -470,7 +470,7 @@ void lara_as_slopefall(ItemInfo* item, CollisionInfo* coll)
return;
Camera.targetElevation = -ANGLE(16.75f);
Camera.targetDistance = SECTOR(1.75f);
Camera.targetDistance = BLOCK(1.75f);
Camera.speed = 15;
}
@ -547,7 +547,7 @@ void lara_as_slopehang(ItemInfo* item, CollisionInfo* coll)
if (Camera.type != CameraType::Chase)
return;
Camera.targetElevation = -SECTOR(1);
Camera.targetElevation = -BLOCK(1);
Camera.targetDistance = CLICK(6.5f);
Camera.speed = 15;
}
@ -604,7 +604,7 @@ void lara_as_slopeshimmy(ItemInfo* item, CollisionInfo* coll)
if (Camera.type != CameraType::Chase)
return;
Camera.targetElevation = -SECTOR(1);
Camera.targetElevation = -BLOCK(1);
Camera.targetDistance = CLICK(6.5f);
Camera.speed = 15;
@ -634,7 +634,7 @@ void lara_as_slopeclimbup(ItemInfo* item, CollisionInfo* coll)
if (Camera.type != CameraType::Chase)
return; // If camera mode isn't chase (0) then don't change camera angles.
Camera.targetElevation = SECTOR(2);
Camera.targetElevation = BLOCK(2);
Camera.targetDistance = CLICK(7);
Camera.speed = 15;
@ -697,12 +697,12 @@ void lara_as_sclimbstart(ItemInfo* item, CollisionInfo* coll)
Camera.flags = CF_FOLLOW_CENTER;
int distance = TestLaraWall(item, 0, SECTOR(1.5f), 0) ? SECTOR(1) : CLICK(6.5f);
int distance = TestLaraWall(item, 0, BLOCK(1.5f)) ? BLOCK(1) : CLICK(6.5f);
if (item->Animation.FrameNumber < GetAnimData(item).frameEnd)
{
Camera.targetDistance = distance;
Camera.targetElevation = int(SECTOR(3) * frac);
Camera.targetElevation = int(BLOCK(3) * frac);
Camera.targetAngle = int(-ANGLE(180.0f) * frac);
Camera.targetspeed = 15;
}
@ -710,7 +710,7 @@ void lara_as_sclimbstart(ItemInfo* item, CollisionInfo* coll)
{
Camera.targetDistance = distance;
Camera.targetElevation = SECTOR(3);
Camera.targetElevation = BLOCK(3);
Camera.targetAngle = 0;
Camera.targetspeed = 15;
}
@ -757,13 +757,13 @@ void lara_as_sclimbstop(ItemInfo* item, CollisionInfo* coll)
{
Camera.targetAngle = (short)(-ANGLE(90.0f) * frac);
Camera.targetDistance = SECTOR(1.75f) - int(CLICK(2) * frac);
Camera.targetDistance = BLOCK(1.75f) - int(CLICK(2) * frac);
Camera.targetspeed = 15;
}
else
{
Camera.targetAngle = ANGLE(90.0f);
Camera.targetDistance = SECTOR(1.25f);
Camera.targetDistance = BLOCK(1.25f);
Camera.targetspeed = 15;
}
}

View file

@ -66,7 +66,7 @@ void lara_as_slide_forward(ItemInfo* item, CollisionInfo* coll)
else
ApproachLaraTargetOrientation(item, direction);*/
if (TrInput & IN_JUMP && TestLaraSlideJump(item, coll))
if (IsHeld(In::Jump) && TestLaraSlideJump(item, coll))
{
item->Animation.TargetState = LS_JUMP_FORWARD;
StopSoundEffect(SFX_TR4_LARA_SLIPPING);
@ -175,7 +175,7 @@ void lara_as_slide_back(ItemInfo* item, CollisionInfo* coll)
else
ApproachLaraTargetOrientation(item, direction);*/
if (TrInput & IN_JUMP && TestLaraSlideJump(item, coll))
if (IsHeld(In::Jump) && TestLaraSlideJump(item, coll))
{
item->Animation.TargetState = LS_JUMP_BACK;
StopSoundEffect(SFX_TR4_LARA_SLIPPING);

View file

@ -1280,7 +1280,7 @@ struct PlayerContextData
int ProjectedFloorHeight = 0;
float CalcJumpVelocity = 0;
Pose NextCornerPos = Pose::Zero;
EulerAngles TargetOrientation = EulerAngles::Zero;
EulerAngles TargetOrientation = EulerAngles::Zero; // TargetOrient
int WaterSurfaceDist = 0;
short WaterCurrentActive = 0; // Sink number? Often used as bool.
@ -1300,8 +1300,6 @@ struct LaraInfo
{
static constexpr auto TARGET_COUNT_MAX = 8;
int ItemNumber = 0; // TODO: Remove. No longer necessary since ItemInfo already has it. -- Sezz 2023.04.09
LaraControlData Control = {};
PlayerContextData Context = {};
PlayerStatusData Status = {};
@ -1319,13 +1317,12 @@ struct LaraInfo
ArmInfo RightArm = {};
ItemInfo* TargetEntity = nullptr; // TargetEntityPtr. Should use item number instead?
std::array<ItemInfo*, TARGET_COUNT_MAX> TargetList = {};
std::array<ItemInfo*, TARGET_COUNT_MAX> LastTargets = {};
std::array<ItemInfo*, TARGET_COUNT_MAX> TargetList = {};
std::array<ItemInfo*, TARGET_COUNT_MAX> LastTargets = {};
// TODO: Rewrite and restore spasm effect. Also move to PlayerEffectData?
int HitFrame = 0; // Frame index.
int HitDirection = 0; // Cardinal direction.
FX_INFO* SpasmEffect = nullptr; // Not saved.
int HitFrame = 0; // Frame index.
int HitDirection = 0; // Cardinal direction.
int ExtraAnim = 0; // Item number? Only ever set to NO_ITEM or 1.

View file

@ -60,7 +60,7 @@ void lara_as_surface_idle(ItemInfo* item, CollisionInfo* coll)
if (TrInput & (IN_LEFT | IN_RIGHT))
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL * 1.25f, 0, LARA_MED_TURN_RATE_MAX);
if (DbInput & IN_JUMP)
if (IsClicked(In::Jump))
{
SetLaraSwimDiveAnimation(item);
return;
@ -125,7 +125,7 @@ void lara_as_surface_swim_forward(ItemInfo* item, CollisionInfo* coll)
if (!(TrInput & IN_FORWARD))
item->Animation.TargetState = LS_ONWATER_IDLE;
if (DbInput & IN_JUMP)
if (IsClicked(In::Jump))
SetLaraSwimDiveAnimation(item);
item->Animation.Velocity.y += LARA_SWIM_VELOCITY_ACCEL;
@ -167,7 +167,7 @@ void lara_as_surface_swim_left(ItemInfo* item, CollisionInfo* coll)
if (!(TrInput & IN_LSTEP || (TrInput & IN_WALK && TrInput & IN_LEFT)))
item->Animation.TargetState = LS_ONWATER_IDLE;
if (DbInput & IN_JUMP)
if (IsClicked(In::Jump))
SetLaraSwimDiveAnimation(item);
item->Animation.Velocity.y += LARA_SWIM_VELOCITY_ACCEL;
@ -206,7 +206,7 @@ void lara_as_surface_swim_right(ItemInfo* item, CollisionInfo* coll)
if (!(TrInput & IN_RSTEP || (TrInput & IN_WALK && TrInput & IN_RIGHT)))
item->Animation.TargetState = LS_ONWATER_IDLE;
if (DbInput & IN_JUMP)
if (IsClicked(In::Jump))
SetLaraSwimDiveAnimation(item);
item->Animation.Velocity.y += LARA_SWIM_VELOCITY_ACCEL;
@ -239,7 +239,7 @@ void lara_as_surface_swim_back(ItemInfo* item, CollisionInfo* coll)
if (TrInput & (IN_LEFT | IN_RIGHT))
ModulateLaraTurnRateY(item, LARA_TURN_RATE_ACCEL * 1.25f, 0, LARA_SLOW_MED_TURN_RATE_MAX);
if (DbInput & IN_JUMP)
if (IsClicked(In::Jump))
SetLaraSwimDiveAnimation(item);
if (!(TrInput & IN_BACK))

View file

@ -51,7 +51,7 @@ void lara_as_underwater_idle(ItemInfo* item, CollisionInfo* coll)
else
ModulateLaraSwimTurnRates(item, coll);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
item->Animation.TargetState = LS_UNDERWATER_SWIM_FORWARD;
item->Animation.Velocity.y -= LARA_SWIM_VELOCITY_DECEL;
@ -96,7 +96,7 @@ void lara_as_underwater_swim_forward(ItemInfo* item, CollisionInfo* coll)
if (item->Animation.Velocity.y > LARA_SWIM_VELOCITY_MAX)
item->Animation.Velocity.y = LARA_SWIM_VELOCITY_MAX;
if (!(TrInput & IN_JUMP))
if (!(IsHeld(In::Jump)))
item->Animation.TargetState = LS_UNDERWATER_INERTIA;
}
@ -130,7 +130,7 @@ void lara_as_underwater_inertia(ItemInfo* item, CollisionInfo* coll)
else
ModulateLaraSubsuitSwimTurnRates(item);
if (TrInput & IN_JUMP)
if (IsHeld(In::Jump))
item->Animation.TargetState = LS_UNDERWATER_SWIM_FORWARD;
item->Animation.Velocity.y -= LARA_SWIM_VELOCITY_DECEL;

View file

@ -53,8 +53,8 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo
if (frontLeft.Position.Ceiling > (item->Pose.Position.y - coll->Setup.Height) || frontRight.Position.Ceiling > (item->Pose.Position.y - coll->Setup.Height))
return false;
//g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xl, left, item->pos.Position.z + zl), 64, Vector4::One, RENDERER_DEBUG_PAGE::LARA_STATS);
//g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xr, right, item->pos.Position.z + zr), 64, Vector4::One, RENDERER_DEBUG_PAGE::LARA_STATS);
//g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xl, left, item->pos.Position.z + zl), 64, Vector4::One, RendererDebugPage::CollisionStats);
//g_Renderer.AddDebugSphere(Vector3(item->pos.Position.x + xr, right, item->pos.Position.z + zr), 64, Vector4::One, RendererDebugPage::CollisionStats);
// Determine ledge probe embed offset.
// We use 0.2f radius extents here for two purposes. First - we can't guarantee that shifts weren't already applied
@ -71,7 +71,7 @@ bool TestValidLedge(ItemInfo* item, CollisionInfo* coll, bool ignoreHeadroom, bo
return false;
// Determine allowed slope difference for a given collision radius
auto slopeDelta = ((float)STEPUP_HEIGHT / (float)SECTOR(1)) * (coll->Setup.Radius * 2);
auto slopeDelta = ((float)STEPUP_HEIGHT / (float)BLOCK(1)) * (coll->Setup.Radius * 2);
// Discard if there is a slope beyond tolerance delta
if (abs(left - right) >= slopeDelta)
@ -773,24 +773,16 @@ bool TestLaraHangSideways(ItemInfo* item, CollisionInfo* coll, short angle)
return !res;
}
bool TestLaraWall(ItemInfo* item, int distance, int height, int side)
bool TestLaraWall(ItemInfo* item, float dist, float height)
{
float s = phd_sin(item->Pose.Orientation.y);
float c = phd_cos(item->Pose.Orientation.y);
auto start = GameVector(
item->Pose.Position.x + (side * c),
item->Pose.Position.y + height,
item->Pose.Position.z + (-side * s),
auto origin = GameVector(
Geometry::TranslatePoint(item->Pose.Position, item->Pose.Orientation.y, 0.0f, height),
item->RoomNumber);
auto target = GameVector(
Geometry::TranslatePoint(item->Pose.Position, item->Pose.Orientation.y, dist, height),
item->RoomNumber);
auto end = GameVector(
item->Pose.Position.x + (distance * s) + (side * c),
item->Pose.Position.y + height,
item->Pose.Position.z + (distance * c) + (-side * s),
item->RoomNumber);
return !LOS(&start, &end);
return !LOS(&origin, &target);
}
bool TestLaraFacingCorner(ItemInfo* item, short angle, int distance)
@ -1046,11 +1038,11 @@ bool TestLaraLadderClimbOut(ItemInfo* item, CollisionInfo* coll) // NEW function
break;
case SOUTH:
item->Pose.Position.z = (item->Pose.Position.z & -SECTOR(1)) + LARA_RADIUS + 1;
item->Pose.Position.z = (item->Pose.Position.z & -BLOCK(1)) + LARA_RADIUS + 1;
break;
case WEST:
item->Pose.Position.x = (item->Pose.Position.x & -SECTOR(1)) + LARA_RADIUS + 1;
item->Pose.Position.x = (item->Pose.Position.x & -BLOCK(1)) + LARA_RADIUS + 1;
break;
}
@ -1202,11 +1194,11 @@ bool TestLaraPose(ItemInfo* item, CollisionInfo* coll)
if (TestEnvironment(ENV_FLAG_SWAMP, item))
return false;
if (!(TrInput & (IN_FLARE | IN_DRAW)) && // Avoid unsightly concurrent actions.
if (!IsHeld(In::Draw) && !IsHeld(In::Flare) && // Avoid unsightly concurrent actions.
lara->Control.HandStatus == HandStatus::Free && // Hands are free.
(lara->Control.Weapon.GunType != LaraWeaponType::Flare || // Flare is not being handled.
lara->Flare.Life) &&
lara->Context.Vehicle == NO_ITEM) // Not in a vehicle.
lara->Context.Vehicle == NO_ITEM) // Not in a vehicle.
{
return true;
}
@ -1638,7 +1630,7 @@ bool TestLaraCrouchRoll(ItemInfo* item, CollisionInfo* coll)
// Assess continuity of path.
int distance = 0;
auto probeA = GetCollision(item);
while (distance < SECTOR(1))
while (distance < BLOCK(1))
{
distance += CLICK(1);
auto probeB = GetCollision(item, item->Pose.Orientation.y, distance, -LARA_HEIGHT_CRAWL);
@ -1673,7 +1665,7 @@ bool TestLaraCrouchToCrawl(ItemInfo* item)
{
auto* lara = GetLaraInfo(item);
if (!(TrInput & (IN_FLARE | IN_DRAW)) && // Avoid unsightly concurrent actions.
if (!IsHeld(In::Draw) && !IsHeld(In::Flare) && // Avoid unsightly concurrent actions.
lara->Control.HandStatus == HandStatus::Free && // Hands are free.
(lara->Control.Weapon.GunType != LaraWeaponType::Flare || // Not handling flare. TODO: Should be allowed, but the flare animation bugs out right now. @Sezz 2022.03.18
lara->Flare.Life))
@ -2292,7 +2284,7 @@ CrawlVaultTestResult TestLaraCrawlExitJump(ItemInfo* item, CollisionInfo* coll)
CrawlVaultTestResult TestLaraCrawlVault(ItemInfo* item, CollisionInfo* coll)
{
if (!(TrInput & (IN_ACTION | IN_JUMP)))
if (!(IsHeld(In::Action) || IsHeld(In::Jump)))
return CrawlVaultTestResult{ false };
// Crawl vault exit down 1 step.
@ -2538,7 +2530,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl
bool atLeastOnePoleCollided = false;
if (GetCollidedObjects(item, SECTOR(1), true, CollidedItems, nullptr, false) &&
if (GetCollidedObjects(item, BLOCK(1), true, CollidedItems, nullptr, false) &&
CollidedItems[0] != nullptr)
{
auto laraBox = GameBoundingBox(item).ToBoundingOrientedBox(item->Pose);
@ -2555,7 +2547,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl
auto sphere = BoundingSphere(spherePos, poleProbeCollRadius);
auto offsetSphere = BoundingSphere(spherePos + sphereOffset2D, poleProbeCollRadius);
//g_Renderer.AddDebugSphere(sphere.Center, 16.0f, Vector4(1, 0, 0, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
//g_Renderer.AddDebugSphere(sphere.Center, 16.0f, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats);
int i = 0;
while (CollidedItems[i] != nullptr)
@ -2569,7 +2561,7 @@ bool TestLaraPoleCollision(ItemInfo* item, CollisionInfo* coll, bool goingUp, fl
auto poleBox = GameBoundingBox(object).ToBoundingOrientedBox(object->Pose);
poleBox.Extents = poleBox.Extents + Vector3(coll->Setup.Radius, 0.0f, coll->Setup.Radius);
//g_Renderer.AddDebugBox(poleBox, Vector4(0, 0, 1, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
//g_Renderer.AddDebugBox(poleBox, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats);
if (poleBox.Intersects(sphere) || poleBox.Intersects(offsetSphere))
{

View file

@ -29,7 +29,7 @@ CornerTestResult TestItemAtNextCornerPosition(ItemInfo* item, CollisionInfo* col
bool TestHangSwingIn(ItemInfo* item, CollisionInfo* coll);
bool TestLaraHangSideways(ItemInfo* item, CollisionInfo* coll, short angle);
bool TestLaraWall(ItemInfo* item, int distance, int height, int side = 0);
bool TestLaraWall(ItemInfo* item, float dist, float height);
bool TestLaraFacingCorner(ItemInfo* item, short angle, int distance);
bool LaraPositionOnLOS(ItemInfo* item, short angle, int distance);
int LaraFloorFront(ItemInfo* item, short angle, int distance);

View file

@ -31,8 +31,9 @@ using namespace TEN::Effects::Hair;
using namespace TEN::Entities;
using namespace TEN::Entities::Switches;
ObjectInfo Objects[ID_NUMBER_OBJECTS];
STATIC_INFO StaticObjects[MAX_STATICS];
ObjectHandler Objects;
StaticInfo StaticObjects[MAX_STATICS];
void InitializeGameFlags()
{
@ -49,7 +50,6 @@ void InitializeSpecialEffects()
memset(&FireSparks, 0, MAX_SPARKS_FIRE * sizeof(FIRE_SPARKS));
memset(&SmokeSparks, 0, MAX_SPARKS_SMOKE * sizeof(SMOKE_SPARKS));
memset(&Gunshells, 0, MAX_GUNSHELL * sizeof(GUNSHELL_STRUCT));
memset(&Gunflashes, 0, (MAX_GUNFLASH * sizeof(GUNFLASH_STRUCT)));
memset(&Blood, 0, MAX_SPARKS_BLOOD * sizeof(BLOOD_STRUCT));
memset(&Splashes, 0, MAX_SPLASHES * sizeof(SPLASH_STRUCT));
memset(&ShockWaves, 0, MAX_SHOCKWAVE * sizeof(SHOCKWAVE_STRUCT));

View file

@ -142,7 +142,58 @@ struct ObjectInfo
}
};
struct STATIC_INFO
class ObjectHandler
{
private:
ObjectInfo Objects[ID_NUMBER_OBJECTS];
ObjectInfo& GetFirstAvailableObject()
{
for (int i = 0; i < ID_NUMBER_OBJECTS; i++)
{
if (Objects[i].loaded)
return Objects[i];
}
return Objects[0];
}
public:
void Initialize()
{
std::memset(Objects, 0, sizeof(ObjectInfo) * GAME_OBJECT_ID::ID_NUMBER_OBJECTS);
}
bool CheckID(int index, bool isSilent = false)
{
if (index == GAME_OBJECT_ID::ID_NO_OBJECT || index >= GAME_OBJECT_ID::ID_NUMBER_OBJECTS)
{
if (!isSilent)
{
TENLog("Attempted to access unavailable slot ID (" + std::to_string(index) + "). " +
"Check if last accessed item exists in level.", LogLevel::Warning, LogConfig::Debug);
}
return false;
}
return true;
}
ObjectInfo& operator[](int index)
{
if (CheckID(index))
{
return Objects[index];
}
else
{
return GetFirstAvailableObject();
}
}
};
struct StaticInfo
{
int meshNumber;
int flags;
@ -158,8 +209,8 @@ constexpr auto SF_SHATTERABLE = 0x02;
constexpr auto GRAVITY = 6.0f;
constexpr auto SWAMP_GRAVITY = GRAVITY / 3.0f;
extern ObjectInfo Objects[ID_NUMBER_OBJECTS];
extern STATIC_INFO StaticObjects[MAX_STATICS];
extern ObjectHandler Objects;
extern StaticInfo StaticObjects[MAX_STATICS];
void InitializeGameFlags();
void InitializeSpecialEffects();

View file

@ -234,6 +234,9 @@ void AnimateItem(ItemInfo* item)
unsigned int frameCount = GetNonZeroFrameCount(*animPtr);
int currentFrame = item->Animation.FrameNumber - animPtr->frameBase;
auto animAccel = (animPtr->VelocityEnd - animPtr->VelocityStart) / frameCount;
auto animVel = animPtr->VelocityStart + (animAccel * currentFrame);
if (item->Animation.IsAirborne)
{
if (item->IsLara())
@ -258,7 +261,7 @@ void AnimateItem(ItemInfo* item)
else
{
item->Animation.Velocity.y += (item->Animation.Velocity.y >= 128.0f) ? 1.0f : GRAVITY;
item->Animation.Velocity.z += (animPtr->VelocityEnd.z - animPtr->VelocityStart.z) / frameCount;
item->Animation.Velocity.z += animAccel.z;
item->Pose.Position.y += item->Animation.Velocity.y;
}
@ -273,25 +276,23 @@ void AnimateItem(ItemInfo* item)
{
if (item->IsLara())
{
const auto& player = *GetLaraInfo(item);
const auto& player = GetLaraInfo(*item);
if (player.Control.WaterStatus == WaterStatus::Wade && TestEnvironment(ENV_FLAG_SWAMP, item))
item->Animation.Velocity.z = (animPtr->VelocityStart.z / 2) + ((((animPtr->VelocityEnd.z - animPtr->VelocityStart.z) / frameCount) * currentFrame) / 4);
else
item->Animation.Velocity.z = animPtr->VelocityStart.z + (((animPtr->VelocityEnd.z - animPtr->VelocityStart.z) / frameCount) * currentFrame);
bool isInSwamp = (player.Control.WaterStatus == WaterStatus::Wade && TestEnvironment(ENV_FLAG_SWAMP, item));
item->Animation.Velocity.z = isInSwamp ? (animVel.z / 2) : animVel.z;
}
else
{
item->Animation.Velocity.x = animPtr->VelocityStart.x + (((animPtr->VelocityEnd.x - animPtr->VelocityStart.x) / frameCount) * currentFrame);
item->Animation.Velocity.z = animPtr->VelocityStart.z + (((animPtr->VelocityEnd.z - animPtr->VelocityStart.z) / frameCount) * currentFrame);
item->Animation.Velocity.x = animVel.x;
item->Animation.Velocity.z = animVel.z;
}
}
if (item->IsLara())
{
const auto& player = *GetLaraInfo(item);
const auto& player = GetLaraInfo(*item);
item->Animation.Velocity.x = animPtr->VelocityStart.x + (((animPtr->VelocityEnd.x - animPtr->VelocityStart.x) / frameCount) * currentFrame);
item->Animation.Velocity.x = animVel.x;
if (player.Control.Rope.Ptr != -1)
DelAlignLaraToRope(item);

View file

@ -26,9 +26,9 @@ using namespace TEN::Effects::Environment;
using namespace TEN::Entities::Generic;
using namespace TEN::Input;
constexpr auto PARTICLE_FADE_THRESHOLD = SECTOR(14);
constexpr auto COLL_CHECK_THRESHOLD = SECTOR(4);
constexpr auto COLL_CANCEL_THRESHOLD = SECTOR(2);
constexpr auto PARTICLE_FADE_THRESHOLD = BLOCK(14);
constexpr auto COLL_CHECK_THRESHOLD = BLOCK(4);
constexpr auto COLL_CANCEL_THRESHOLD = BLOCK(2);
constexpr auto COLL_DISCARD_THRESHOLD = CLICK(0.5f);
constexpr auto CAMERA_RADIUS = CLICK(1);
@ -93,7 +93,7 @@ void LookAt(CAMERA_INFO* cam, short roll)
float fov = TO_RAD(CurrentFOV / 1.333333f);
float r = TO_RAD(roll);
float levelFarView = g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * float(SECTOR(1));
float levelFarView = g_GameFlow->GetLevel(CurrentLevel)->GetFarView() * float(BLOCK(1));
g_Renderer.UpdateCameraMatrices(cam, r, fov, levelFarView);
}
@ -119,7 +119,7 @@ inline void RumbleFromBounce()
void InitializeCamera()
{
Camera.shift = LaraItem->Pose.Position.y - SECTOR(1);
Camera.shift = LaraItem->Pose.Position.y - BLOCK(1);
LastTarget.x = LaraItem->Pose.Position.x;
LastTarget.y = Camera.shift;
@ -136,7 +136,7 @@ void InitializeCamera()
Camera.pos.z = LastTarget.z - 100;
Camera.pos.RoomNumber = LaraItem->RoomNumber;
Camera.targetDistance = SECTOR(1.5f);
Camera.targetDistance = BLOCK(1.5f);
Camera.item = NULL;
Camera.numberFrames = 1;
Camera.type = CameraType::Chase;
@ -218,7 +218,7 @@ void MoveCamera(GameVector* ideal, int speed)
if (Camera.bounce <= 0)
{
int bounce = -Camera.bounce;
int bounce2 = -Camera.bounce >> 2;
int bounce2 = bounce / 2;
Camera.target.x += GetRandomControl() % bounce - bounce2;
Camera.target.y += GetRandomControl() % bounce - bounce2;
Camera.target.z += GetRandomControl() % bounce - bounce2;
@ -243,9 +243,9 @@ void MoveCamera(GameVector* ideal, int speed)
{
LOSAndReturnTarget(&Camera.target, &Camera.pos, 0);
if (abs(Camera.pos.x - ideal->x) < SECTOR(0.5f) &&
abs(Camera.pos.y - ideal->y) < SECTOR(0.5f) &&
abs(Camera.pos.z - ideal->z) < SECTOR(0.5f))
if (abs(Camera.pos.x - ideal->x) < BLOCK(0.5f) &&
abs(Camera.pos.y - ideal->y) < BLOCK(0.5f) &&
abs(Camera.pos.z - ideal->z) < BLOCK(0.5f))
{
to.x = Camera.pos.x;
to.y = Camera.pos.y;
@ -538,7 +538,7 @@ void ChaseCamera(ItemInfo* item)
void DoThumbstickCamera()
{
if (!g_Configuration.EnableThumbstickCameraControl)
if (!g_Configuration.EnableThumbstickCamera)
return;
if (Camera.laraNode == -1 && (Camera.target.x == OldCam.target.x &&
@ -560,7 +560,7 @@ void UpdateCameraElevation()
if (Camera.laraNode != -1)
{
auto pos = GetJointPosition(LaraItem, Camera.laraNode, Vector3i::Zero);
auto pos1 = GetJointPosition(LaraItem, Camera.laraNode, Vector3i(0, -CLICK(1), SECTOR(2)));
auto pos1 = GetJointPosition(LaraItem, Camera.laraNode, Vector3i(0, -CLICK(1), BLOCK(2)));
pos = pos1 - pos;
Camera.actualAngle = Camera.targetAngle + phd_atan(pos.z, pos.x);
}
@ -637,7 +637,7 @@ void CombatCamera(ItemInfo* item)
UpdateCameraElevation();
Camera.targetDistance = SECTOR(1.5f);
Camera.targetDistance = BLOCK(1.5f);
int distance = Camera.targetDistance * phd_cos(Camera.actualElevation);
for (int i = 0; i < 5; i++)
@ -955,7 +955,7 @@ void LookCamera(ItemInfo* item)
}
}
auto pos2 = GetJointPosition(item, LM_HEAD, Vector3i(0, 0, -SECTOR(1)));
auto pos2 = GetJointPosition(item, LM_HEAD, Vector3i(0, 0, -BLOCK(1)));
auto pos3 = GetJointPosition(item, LM_HEAD, Vector3i(0, 0, CLICK(8)));
int dx = (pos2.x - pos.x) >> 3;
@ -1171,7 +1171,7 @@ void BinocularCamera(ItemInfo* item)
if (!LaserSight)
{
if (IsClicked(In::Deselect) ||
IsClicked(In::DrawWeapon) ||
IsClicked(In::Draw) ||
IsClicked(In::Look) ||
IsHeld(In::Flare))
{
@ -1216,10 +1216,10 @@ void BinocularCamera(ItemInfo* item)
Camera.pos.z = z;
Camera.pos.RoomNumber = probe.RoomNumber;
int l = SECTOR(20.25f) * phd_cos(headXRot);
int l = BLOCK(20.25f) * phd_cos(headXRot);
int tx = x + l * phd_sin(item->Pose.Orientation.y + headYRot);
int ty = y - SECTOR(20.25f) * phd_sin(headXRot);
int ty = y - BLOCK(20.25f) * phd_sin(headXRot);
int tz = z + l * phd_cos(item->Pose.Orientation.y + headYRot);
if (Camera.oldType == CameraType::Fixed)
@ -1289,7 +1289,10 @@ void BinocularCamera(ItemInfo* item)
void ConfirmCameraTargetPos()
{
auto pos = GetJointPosition(LaraItem, LM_TORSO);
auto pos = Vector3i(
LaraItem->Pose.Position.x,
LaraItem->Pose.Position.y - (LaraCollision.Setup.Height / 2),
LaraItem->Pose.Position.z);
if (Camera.laraNode != -1)
{
@ -1529,7 +1532,7 @@ void CalculateCamera()
Camera.item = NULL;
Camera.targetElevation = 0;
Camera.targetAngle = 0;
Camera.targetDistance = SECTOR(1.5f);
Camera.targetDistance = BLOCK(1.5f);
Camera.flags = 0;
Camera.laraNode = -1;
}
@ -1847,8 +1850,9 @@ void ItemsCollideCamera()
if (TestBoundsCollideCamera(bounds, item->Pose, CAMERA_RADIUS))
ItemPushCamera(&bounds, &item->Pose, rad);
TEN::Renderer::g_Renderer.AddDebugBox(bounds.ToBoundingOrientedBox(item->Pose),
Vector4(1.0f, 0.0f, 0.0f, 1.0f), RENDERER_DEBUG_PAGE::LARA_STATS);
TEN::Renderer::g_Renderer.AddDebugBox(
bounds.ToBoundingOrientedBox(item->Pose),
Vector4(1.0f, 0.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats);
}
itemList.clear(); // Done
@ -1874,8 +1878,9 @@ void ItemsCollideCamera()
if (TestBoundsCollideCamera(bounds, mesh->pos, CAMERA_RADIUS))
ItemPushCamera(&bounds, &mesh->pos, rad);
TEN::Renderer::g_Renderer.AddDebugBox(bounds.ToBoundingOrientedBox(mesh->pos),
Vector4(1.0f, 0.0f, 0.0f, 1.0f), RENDERER_DEBUG_PAGE::LARA_STATS);
TEN::Renderer::g_Renderer.AddDebugBox(
bounds.ToBoundingOrientedBox(mesh->pos),
Vector4(1.0f, 0.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats);
}
staticList.clear(); // Done
@ -1896,7 +1901,7 @@ void UpdateMikePos(ItemInfo* item)
}
else
{
int phdPerspective = g_Configuration.Width / 2 * phd_cos(CurrentFOV / 2) / phd_sin(CurrentFOV / 2);
int phdPerspective = g_Configuration.ScreenWidth / 2 * phd_cos(CurrentFOV / 2) / phd_sin(CurrentFOV / 2);
Camera.actualAngle = phd_atan(Camera.target.z - Camera.pos.z, Camera.target.x - Camera.pos.x);
Camera.mikePos.x = Camera.pos.x + phdPerspective * phd_sin(Camera.actualAngle);

View file

@ -312,19 +312,18 @@ void TestForObjectOnLedge(ItemInfo* item, CollisionInfo* coll)
auto origin = Vector3(
item->Pose.Position.x + (sinHeading * (coll->Setup.Radius)),
item->Pose.Position.y - (height + CLICK(1)),
item->Pose.Position.z + (cosHeading * (coll->Setup.Radius))
);
item->Pose.Position.z + (cosHeading * (coll->Setup.Radius)));
auto mxR = Matrix::CreateFromYawPitchRoll(TO_RAD(coll->Setup.ForwardAngle), 0.0f, 0.0f);
auto direction = (Matrix::CreateTranslation(Vector3::UnitZ) * mxR).Translation();
// g_Renderer.AddDebugSphere(origin, 16, Vector4::One, RENDERER_DEBUG_PAGE::DIMENSION_STATS);
// g_Renderer.AddDebugSphere(origin, 16, Vector4::One, RendererDebugPage::CollisionStats);
for (auto i : g_Level.Rooms[item->RoomNumber].neighbors)
{
if (!g_Level.Rooms[i].Active())
continue;
short itemNumber = g_Level.Rooms[i].itemNumber;
int itemNumber = g_Level.Rooms[i].itemNumber;
while (itemNumber != NO_ITEM)
{
auto* item2 = &g_Level.Items[itemNumber];
@ -979,7 +978,7 @@ bool CollideSolidBounds(ItemInfo* item, const GameBoundingBox& box, const Pose&
itemBounds.Extents = itemBounds.Extents - Vector3(BLOCK(1));
// Draw static bounds.
g_Renderer.AddDebugBox(staticBounds, Vector4(1, 0.3f, 0, 1), RENDERER_DEBUG_PAGE::DIMENSION_STATS);
g_Renderer.AddDebugBox(staticBounds, Vector4(1, 0.3f, 0, 1), RendererDebugPage::CollisionStats);
// Calculate horizontal item collision bounds according to radius.
GameBoundingBox collBox;
@ -1010,7 +1009,7 @@ bool CollideSolidBounds(ItemInfo* item, const GameBoundingBox& box, const Pose&
bool prevHorIntersects = staticBounds.Intersects(prevCollBounds);
// Draw item coll bounds.
g_Renderer.AddDebugBox(collBounds, intersects ? Vector4(1, 0, 0, 1) : Vector4(0, 1, 0, 1), RENDERER_DEBUG_PAGE::DIMENSION_STATS);
g_Renderer.AddDebugBox(collBounds, intersects ? Vector4(1, 0, 0, 1) : Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats);
// Decompose static bounds into top/bottom plane vertices.
Vector3 corners[8];
@ -1990,17 +1989,19 @@ void CreatureCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll
}
}
void TrapCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
void TrapCollision(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll)
{
auto* item = &g_Level.Items[itemNumber];
auto& item = g_Level.Items[itemNumber];
if (item->Status == ITEM_ACTIVE)
if (item.Status == ITEM_ACTIVE)
{
if (!TestBoundsCollide(item, laraItem, coll->Setup.Radius))
if (!TestBoundsCollide(&item, playerItem, coll->Setup.Radius))
return;
TestCollision(item, laraItem);
TestCollision(&item, playerItem);
}
else if (item.Status != ITEM_INVISIBLE)
{
ObjectCollision(itemNumber, playerItem, coll);
}
else if (item->Status != ITEM_INVISIBLE)
ObjectCollision(itemNumber, laraItem, coll);
}

View file

@ -8,7 +8,7 @@ struct ItemInfo;
struct MESH_INFO;
constexpr auto MAX_COLLIDED_OBJECTS = 1024;
constexpr auto ITEM_RADIUS_YMAX = SECTOR(3);
constexpr auto ITEM_RADIUS_YMAX = BLOCK(3);
constexpr auto VEHICLE_COLLISION_TERMINAL_VELOCITY = 30.0f;

View file

@ -74,13 +74,13 @@ void SnapItemToGrid(ItemInfo* item, CollisionInfo* coll)
int FindGridShift(int x, int z)
{
if ((x / SECTOR(1)) == (z / SECTOR(1)))
if ((x / BLOCK(1)) == (z / BLOCK(1)))
return 0;
if ((z / SECTOR(1)) <= (x / SECTOR(1)))
if ((z / BLOCK(1)) <= (x / BLOCK(1)))
return (-1 - (x & WALL_MASK));
else
return ((SECTOR(1) + 1) - (x & WALL_MASK));
return ((BLOCK(1) + 1) - (x & WALL_MASK));
}
// Test if the axis-aligned bounding box collides with geometry at all.
@ -114,18 +114,24 @@ bool TestItemRoomCollisionAABB(ItemInfo* item)
return collided;
}
// Overload used to quickly get point/room collision parameters at a given item's position.
CollisionResult GetCollision(ItemInfo* item)
// Overload used to quickly get point collision parameters at a given item's position.
CollisionResult GetCollision(const ItemInfo& item)
{
auto newRoomNumber = item->RoomNumber;
auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &newRoomNumber);
auto probe = GetCollision(floor, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z);
auto newRoomNumber = item.RoomNumber;
auto floor = GetFloor(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, &newRoomNumber);
auto probe = GetCollision(floor, item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z);
probe.RoomNumber = newRoomNumber;
return probe;
}
// Overload used to probe point/room collision parameters from a given item's position.
// Deprecated.
CollisionResult GetCollision(ItemInfo* item)
{
return GetCollision(*item);
}
// Overload used to probe point collision parameters from a given item's position.
CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down, float right)
{
short tempRoomNumber = item->RoomNumber;
@ -140,8 +146,8 @@ CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward,
return GetCollision(point.x, point.y, point.z, adjacentRoomNumber);
}
// Overload used to probe point/room collision parameters from a given position.
CollisionResult GetCollision(Vector3i pos, int roomNumber, short headingAngle, float forward, float down, float right)
// Overload used to probe point collision parameters from a given position.
CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down, float right)
{
short tempRoomNumber = roomNumber;
auto location = ROOM_VECTOR{ GetFloor(pos.x, pos.y, pos.z, &tempRoomNumber)->Room, pos.y };
@ -151,11 +157,17 @@ CollisionResult GetCollision(Vector3i pos, int roomNumber, short headingAngle, f
return GetCollision(point.x, point.y, point.z, adjacentRoomNumber);
}
// Overload used as a universal wrapper across collisional code to replace
// triads of roomNumber-GetFloor()-GetFloorHeight() operations.
// The advantage is that it does NOT modify the incoming roomNumber argument,
// instead storing one modified by GetFloor() within the returned CollisionResult struct.
// Overload used as universal wrapper across collisional code replacing
// triads of roomNumber-GetFloor()-GetFloorHeight() calls.
// Advantage is that it does NOT modify incoming roomNumber argument,
// instead storing one modified by GetFloor() within a returned CollisionResult struct.
// This way, no external variables are modified as output arguments.
CollisionResult GetCollision(const Vector3i& pos, int roomNumber)
{
return GetCollision(pos.x, pos.y, pos.z, roomNumber);
}
// Deprecated.
CollisionResult GetCollision(int x, int y, int z, short roomNumber)
{
auto room = roomNumber;
@ -166,9 +178,10 @@ CollisionResult GetCollision(int x, int y, int z, short roomNumber)
return result;
}
CollisionResult GetCollision(const GameVector& point)
// NOTE: To be used only when absolutely necessary.
CollisionResult GetCollision(const GameVector& pos)
{
return GetCollision(point.x, point.y, point.z, point.RoomNumber);
return GetCollision(pos.x, pos.y, pos.z, pos.RoomNumber);
}
// A reworked legacy GetFloorHeight() function which writes data
@ -218,10 +231,52 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, bool resetRoom)
GetCollisionInfo(coll, item, Vector3i::Zero, resetRoom);
}
void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom)
static void SetSectorAttribs(CollisionPosition& sectorAttribs, const CollisionSetup& collSetup, const CollisionResult& pointColl,
const Vector3i& probePos, int realRoomNumber)
{
constexpr auto ASPECT_ANGLE_DELTA_MAX = ANGLE(90.0f);
auto floorNormal = GetSurfaceNormal(pointColl.FloorTilt, true);
short aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal);
short aspectAngleDelta = Geometry::GetShortestAngle(collSetup.ForwardAngle, aspectAngle);
if (collSetup.BlockFloorSlopeUp &&
sectorAttribs.FloorSlope &&
sectorAttribs.Floor <= STEPUP_HEIGHT &&
sectorAttribs.Floor >= -STEPUP_HEIGHT &&
abs(aspectAngleDelta) >= ASPECT_ANGLE_DELTA_MAX)
{
sectorAttribs.Floor = MAX_HEIGHT;
}
else if (collSetup.BlockFloorSlopeDown &&
sectorAttribs.FloorSlope &&
sectorAttribs.Floor <= STEPUP_HEIGHT &&
sectorAttribs.Floor >= -STEPUP_HEIGHT &&
abs(aspectAngleDelta) <= ASPECT_ANGLE_DELTA_MAX)
{
sectorAttribs.Floor = MAX_HEIGHT;
}
else if (collSetup.BlockCeilingSlope &&
sectorAttribs.CeilingSlope)
{
sectorAttribs.Floor = MAX_HEIGHT;
}
else if (collSetup.BlockDeathFloorDown &&
sectorAttribs.Floor >= CLICK(0.5f) &&
pointColl.BottomBlock->Flags.Death)
{
sectorAttribs.Floor = MAX_HEIGHT;
}
else if (collSetup.BlockMonkeySwingEdge)
{
auto monkeyPointColl = GetCollision(probePos.x, probePos.y + collSetup.Height, probePos.z, realRoomNumber);
if (!monkeyPointColl.BottomBlock->Flags.Monkeyswing)
sectorAttribs.Floor = MAX_HEIGHT;
}
}
void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom)
{
// Player collision has several more precise checks for bridge collisions.
// Therefore, we should differentiate these code paths.
bool doPlayerCollision = item->IsLara();
@ -357,7 +412,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
probePos.x = entityPos.x + xFront;
probePos.z = entityPos.z + zFront;
g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(1, 0, 0, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(1, 0, 0, 1), RendererDebugPage::CollisionStats);
collResult = GetCollision(probePos.x, probePos.y, probePos.z, topRoomNumber);
@ -405,46 +460,14 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
if (height != NO_HEIGHT)
height -= (doPlayerCollision ? entityPos.y : probePos.y);
auto floorNormal = GetSurfaceNormal(collResult.FloorTilt, true);
short aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal);
short aspectAngleDelta = Geometry::GetShortestAngle(coll->Setup.ForwardAngle, aspectAngle);
if (coll->Setup.BlockFloorSlopeUp &&
coll->Front.FloorSlope &&
abs(aspectAngleDelta) >= ASPECT_ANGLE_DELTA_MAX)
{
coll->Front.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockFloorSlopeDown &&
coll->Front.FloorSlope &&
abs(aspectAngleDelta) <= ASPECT_ANGLE_DELTA_MAX)
{
coll->Front.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockCeilingSlope &&
coll->Front.CeilingSlope)
{
coll->Front.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockDeathFloorDown &&
coll->Front.Floor >= CLICK(0.5f) &&
collResult.BottomBlock->Flags.Death)
{
coll->Front.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockMonkeySwingEdge)
{
auto monkeyProbe = GetCollision(probePos.x, probePos.y + coll->Setup.Height, probePos.z, realRoomNumber);
if (!monkeyProbe.BottomBlock->Flags.Monkeyswing)
coll->Front.Floor = MAX_HEIGHT;
}
SetSectorAttribs(coll->Front, coll->Setup, collResult, probePos, realRoomNumber);
// TEST 4: MIDDLE-LEFT PROBE
probePos.x = entityPos.x + xLeft;
probePos.z = entityPos.z + zLeft;
g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 0, 1, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 0, 1, 1), RendererDebugPage::CollisionStats);
collResult = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber);
@ -472,38 +495,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
coll->MiddleLeft.Floor = height;
coll->MiddleLeft.Ceiling = ceiling;
floorNormal = GetSurfaceNormal(collResult.FloorTilt, true);
aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal);
aspectAngleDelta = Geometry::GetShortestAngle(coll->Setup.ForwardAngle, aspectAngle);
if (coll->Setup.BlockFloorSlopeUp &&
coll->MiddleLeft.FloorSlope &&
abs(aspectAngleDelta) >= ASPECT_ANGLE_DELTA_MAX)
{
coll->MiddleLeft.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockFloorSlopeDown &&
coll->MiddleLeft.FloorSlope &&
abs(aspectAngleDelta) <= ASPECT_ANGLE_DELTA_MAX)
{
coll->MiddleLeft.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockCeilingSlope &&
coll->MiddleLeft.CeilingSlope)
{
coll->MiddleLeft.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockDeathFloorDown &&
coll->MiddleLeft.Floor >= CLICK(0.5f) &&
collResult.BottomBlock->Flags.Death)
{
coll->MiddleLeft.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockMonkeySwingEdge &&
!GetCollision(probePos.x, probePos.y + coll->Setup.Height, probePos.z, item->RoomNumber).BottomBlock->Flags.Monkeyswing)
{
coll->MiddleLeft.Floor = MAX_HEIGHT;
}
SetSectorAttribs(coll->MiddleLeft, coll->Setup, collResult, probePos, realRoomNumber);
// TEST 5: FRONT-LEFT PROBE
@ -533,45 +525,14 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
coll->FrontLeft.Floor = height;
coll->FrontLeft.Ceiling = ceiling;
floorNormal = GetSurfaceNormal(collResult.FloorTilt, true);
aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal);
aspectAngleDelta = Geometry::GetShortestAngle(coll->Setup.ForwardAngle, aspectAngle);
if (coll->Setup.BlockFloorSlopeUp &&
coll->FrontLeft.FloorSlope &&
abs(aspectAngleDelta) >= ASPECT_ANGLE_DELTA_MAX)
{
coll->FrontLeft.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockFloorSlopeDown &&
coll->FrontLeft.FloorSlope &&
abs(aspectAngleDelta) <= ASPECT_ANGLE_DELTA_MAX)
{
coll->FrontLeft.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockCeilingSlope &&
coll->FrontLeft.CeilingSlope)
{
coll->FrontLeft.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockDeathFloorDown &&
coll->FrontLeft.Floor >= CLICK(0.5f) &&
collResult.BottomBlock->Flags.Death)
{
coll->FrontLeft.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockMonkeySwingEdge &&
!GetCollision(probePos.x, probePos.y + coll->Setup.Height, probePos.z, item->RoomNumber).BottomBlock->Flags.Monkeyswing)
{
coll->FrontLeft.Floor = MAX_HEIGHT;
}
SetSectorAttribs(coll->FrontLeft, coll->Setup, collResult, probePos, realRoomNumber);
// TEST 6: MIDDLE-RIGHT PROBE
probePos.x = entityPos.x + xRight;
probePos.z = entityPos.z + zRight;
g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 1, 0, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
g_Renderer.AddDebugSphere(probePos.ToVector3(), 32, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats);
collResult = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber);
@ -599,38 +560,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
coll->MiddleRight.Floor = height;
coll->MiddleRight.Ceiling = ceiling;
floorNormal = GetSurfaceNormal(collResult.FloorTilt, true);
aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal);
aspectAngleDelta = Geometry::GetShortestAngle(coll->Setup.ForwardAngle, aspectAngle);
if (coll->Setup.BlockFloorSlopeUp &&
coll->MiddleRight.FloorSlope &&
abs(aspectAngleDelta) >= ASPECT_ANGLE_DELTA_MAX)
{
coll->MiddleRight.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockFloorSlopeDown &&
coll->MiddleRight.FloorSlope &&
abs(aspectAngleDelta) <= ASPECT_ANGLE_DELTA_MAX)
{
coll->MiddleRight.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockCeilingSlope &&
coll->MiddleRight.CeilingSlope)
{
coll->MiddleRight.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockDeathFloorDown &&
coll->MiddleRight.Floor >= CLICK(0.5f) &&
collResult.BottomBlock->Flags.Death)
{
coll->MiddleRight.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockMonkeySwingEdge &&
!GetCollision(probePos.x, probePos.y + coll->Setup.Height, probePos.z, item->RoomNumber).BottomBlock->Flags.Monkeyswing)
{
coll->MiddleRight.Floor = MAX_HEIGHT;
}
SetSectorAttribs(coll->MiddleRight, coll->Setup, collResult, probePos, realRoomNumber);
// TEST 7: FRONT-RIGHT PROBE
@ -660,38 +590,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
coll->FrontRight.Floor = height;
coll->FrontRight.Ceiling = ceiling;
floorNormal = GetSurfaceNormal(collResult.FloorTilt, true);
aspectAngle = Geometry::GetSurfaceAspectAngle(floorNormal);
aspectAngleDelta = Geometry::GetShortestAngle(coll->Setup.ForwardAngle, aspectAngle);
if (coll->Setup.BlockFloorSlopeUp &&
coll->FrontRight.FloorSlope &&
abs(aspectAngleDelta) >= ASPECT_ANGLE_DELTA_MAX)
{
coll->FrontRight.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockFloorSlopeDown &&
coll->FrontRight.FloorSlope &&
abs(aspectAngleDelta) <= ASPECT_ANGLE_DELTA_MAX)
{
coll->FrontRight.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockCeilingSlope &&
coll->FrontRight.CeilingSlope)
{
coll->FrontRight.Floor = MAX_HEIGHT;
}
else if (coll->Setup.BlockDeathFloorDown &&
coll->FrontRight.Floor >= CLICK(0.5f) &&
collResult.BottomBlock->Flags.Death)
{
coll->FrontRight.Floor = STOP_SIZE;
}
else if (coll->Setup.BlockMonkeySwingEdge &&
!GetCollision(probePos.x, probePos.y + coll->Setup.Height, probePos.z, item->RoomNumber).BottomBlock->Flags.Monkeyswing)
{
coll->FrontRight.Floor = MAX_HEIGHT;
}
SetSectorAttribs(coll->FrontRight, coll->Setup, collResult, probePos, realRoomNumber);
// TEST 8: SOLID STATIC MESHES
@ -979,7 +878,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance)
}
// Debug probe point
// g_Renderer.AddDebugSphere(Vector3(eX, y, eZ), 16, Vector4(1, 1, 0, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
// g_Renderer.AddDebugSphere(Vector3(eX, y, eZ), 16, Vector4(1, 1, 0, 1), RendererDebugPage::CollisionStats);
// Determine front floor probe offset.
// It is needed to identify if there is bridge or ceiling split in front.
@ -1021,7 +920,7 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance)
auto fpZ = eZ + floorProbeOffset * cosForwardAngle;
// Debug probe point.
// g_Renderer.AddDebugSphere(Vector3(fpX, y, fpZ), 16, Vector4(0, 1, 0, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
// g_Renderer.AddDebugSphere(Vector3(fpX, y, fpZ), 16, Vector4(0, 1, 0, 1), RendererDebugPage::CollisionStats);
// Get true room number and block, based on derived height
room = GetRoom(item->Location, fpX, height, fpZ).roomNumber;
@ -1086,17 +985,17 @@ short GetNearestLedgeAngle(ItemInfo* item, CollisionInfo* coll, float& distance)
auto splitAngle = (useCeilingLedge ? block->CeilingCollision.SplitAngle : block->FloorCollision.SplitAngle);
// Get horizontal block corner coordinates.
auto fX = floor(eX / SECTOR(1)) * SECTOR(1) - 1;
auto fZ = floor(eZ / SECTOR(1)) * SECTOR(1) - 1;
auto cX = fX + SECTOR(1) + 1;
auto cZ = fZ + SECTOR(1) + 1;
auto fX = floor(eX / BLOCK(1)) * BLOCK(1) - 1;
auto fZ = floor(eZ / BLOCK(1)) * BLOCK(1) - 1;
auto cX = fX + BLOCK(1) + 1;
auto cZ = fZ + BLOCK(1) + 1;
// Debug used block
// g_Renderer.AddDebugSphere(Vector3(round(eX / WALL_SIZE) * WALL_SIZE + 512, y, round(eZ / WALL_SIZE) * WALL_SIZE + 512), 16, Vector4(1, 1, 1, 1), RENDERER_DEBUG_PAGE::LARA_STATS);
// g_Renderer.AddDebugSphere(Vector3(round(eX / BLOCK(1)) * BLOCK(1) + BLOCK(0.5f), y, round(eZ / BLOCK(1)) * BLOCK(1) + BLOCK(0.5f)), 16, Vector4::One, RendererDebugPage::CollisionStats);
// Get split angle coordinates.
auto sX = fX + 1 + SECTOR(0.5f);
auto sZ = fZ + 1 + SECTOR(0.5f);
auto sX = fX + 1 + BLOCK(0.5f);
auto sZ = fZ + 1 + BLOCK(0.5f);
auto sShiftX = coll->Setup.Radius * sin(splitAngle);
auto sShiftZ = coll->Setup.Radius * cos(splitAngle);
@ -1267,7 +1166,7 @@ void AlterFloorHeight(ItemInfo* item, int height)
short roomNumber = item->RoomNumber;
FloorInfo* floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber);
FloorInfo* ceiling = GetFloor(item->Pose.Position.x, height + item->Pose.Position.y - SECTOR(1), item->Pose.Position.z, &roomNumber);
FloorInfo* ceiling = GetFloor(item->Pose.Position.x, height + item->Pose.Position.y - BLOCK(1), item->Pose.Position.z, &roomNumber);
floor->FloorCollision.Planes[0].z += height;
floor->FloorCollision.Planes[1].z += height;
@ -1328,8 +1227,8 @@ int GetWaterDepth(int x, int y, int z, short roomNumber)
short roomIndex = NO_ROOM;
do
{
int zFloor = (z - room->z) / SECTOR(1);
int xFloor = (x - room->x) / SECTOR(1);
int zFloor = (z - room->z) / BLOCK(1);
int xFloor = (x - room->x) / BLOCK(1);
if (zFloor <= 0)
{
@ -1416,8 +1315,8 @@ int GetWaterHeight(int x, int y, int z, short roomNumber)
short adjoiningRoom = NO_ROOM;
do
{
int xBlock = (x - room->x) / SECTOR(1);
int zBlock = (z - room->z) / SECTOR(1);
int xBlock = (x - room->x) / BLOCK(1);
int zBlock = (z - room->z) / BLOCK(1);
if (zBlock <= 0)
{

View file

@ -11,7 +11,7 @@ enum RoomEnvFlags;
constexpr auto NO_LOWER_BOUND = -NO_HEIGHT; // Used by coll->Setup.LowerFloorBound.
constexpr auto NO_UPPER_BOUND = NO_HEIGHT; // Used by coll->Setup.UpperFloorBound.
constexpr auto COLLISION_CHECK_DISTANCE = SECTOR(8);
constexpr auto COLLISION_CHECK_DISTANCE = BLOCK(8);
enum CollisionType
{
@ -126,11 +126,13 @@ struct CollisionInfo
[[nodiscard]] bool TestItemRoomCollisionAABB(ItemInfo* item);
CollisionResult GetCollision(const ItemInfo& item);
CollisionResult GetCollision(ItemInfo* item);
CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f);
CollisionResult GetCollision(Vector3i pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f);
CollisionResult GetCollision(const Vector3i& pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f);
CollisionResult GetCollision(const Vector3i& pos, int roomNumber);
CollisionResult GetCollision(int x, int y, int z, short roomNumber);
CollisionResult GetCollision(const GameVector& point);
CollisionResult GetCollision(const GameVector& pos);
CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z);
void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false);

View file

@ -1,10 +1,12 @@
#include "framework.h"
#include "Game/collision/floordata.h"
#include "Game/collision/collide_room.h"
#include "Game/items.h"
#include "Game/room.h"
#include "Game/Setup.h"
#include "Math/Math.h"
#include "Renderer/Renderer11.h"
#include "Specific/level.h"
using namespace TEN::Collision::Floordata;
@ -750,6 +752,10 @@ namespace TEN::Collision::Floordata
void AddBridge(int itemNumber, int x, int z)
{
const auto& item = g_Level.Items[itemNumber];
if (!Objects.CheckID(item.ObjectNumber))
return;
x += item.Pose.Position.x;
z += item.Pose.Position.z;
@ -788,6 +794,10 @@ namespace TEN::Collision::Floordata
void RemoveBridge(int itemNumber, int x, int z)
{
const auto& item = g_Level.Items[itemNumber];
if (!Objects.CheckID(item.ObjectNumber))
return;
x += item.Pose.Position.x;
z += item.Pose.Position.z;
@ -862,7 +872,12 @@ namespace TEN::Collision::Floordata
void UpdateBridgeItem(int itemNumber, bool forceRemoval)
{
auto item = &g_Level.Items[itemNumber];
if (!Objects[item->ObjectNumber].loaded) return;
if (!Objects.CheckID(item->ObjectNumber))
return;
if (!Objects[item->ObjectNumber].loaded)
return;
// Force removal if object was killed
if (item->Flags & IFLAG_KILLED)
@ -924,4 +939,103 @@ namespace TEN::Collision::Floordata
return false;
}
static void DrawSectorFlagLabel(const Vector3& pos, const std::string& string, const Vector4& color, float verticalOffset)
{
constexpr auto LABEL_SCALE = 0.8f;
constexpr auto HALF_BLOCK = BLOCK(0.5f);
// Get 2D label position.
auto labelPos = pos + Vector3(HALF_BLOCK, 0.0f, HALF_BLOCK);
auto labelPos2D = g_Renderer.Get2DPosition(labelPos);
// Draw label.
if (labelPos2D.has_value())
{
*labelPos2D += Vector2(0.0f, verticalOffset);
g_Renderer.AddDebugString(string, *labelPos2D, color, LABEL_SCALE, 0, RendererDebugPage::CollisionStats);
}
}
void DrawNearbySectorFlags(const ItemInfo& item)
{
constexpr auto DRAW_RANGE = BLOCK(3);
constexpr auto STRING_SPACING = -20.0f;
constexpr auto STOPPER_COLOR = Vector4(1.0f, 0.4f, 0.4f, 1.0f);
constexpr auto DEATH_COLOR = Vector4(0.4f, 1.0f, 0.4f, 1.0f);
constexpr auto MONKEY_SWING_COLOR = Vector4(1.0f, 0.4f, 0.4f, 1.0f);
constexpr auto BEETLE_MINECART_RIGHT_COLOR = Vector4(0.4f, 0.4f, 1.0f, 1.0f);
constexpr auto ACTIVATOR_MINECART_LEFT_COLOR = Vector4(1.0f, 0.4f, 1.0f, 1.0f);
constexpr auto MINECART_STOP_COLOR = Vector4(0.4f, 1.0f, 1.0f, 1.0f);
// Only check sectors in player vicinity.
const auto& room = g_Level.Rooms[item.RoomNumber];
int minX = std::max(item.Pose.Position.x - DRAW_RANGE, room.x) / BLOCK(1);
int maxX = std::min(item.Pose.Position.x + DRAW_RANGE, room.x + (room.xSize * BLOCK(1))) / BLOCK(1);
int minZ = std::max(item.Pose.Position.z - DRAW_RANGE, room.z) / BLOCK(1);
int maxZ = std::min(item.Pose.Position.z + DRAW_RANGE, room.z + (room.zSize * BLOCK(1))) / BLOCK(1);
auto pointColl = GetCollision(item);
auto pos = item.Pose.Position.ToVector3();
// Draw sector flag labels.
for (int x = minX; x < maxX; x++)
{
for (int z = minZ; z < maxZ; z++)
{
pos.x = BLOCK(x);
pos.z = BLOCK(z);
pointColl = GetCollision(pos, item.RoomNumber);
pos.y = pointColl.Position.Floor;
float verticalOffset = STRING_SPACING;
// Stopper
if (pointColl.Block->Stopper)
{
DrawSectorFlagLabel(pos, "Stopper", STOPPER_COLOR, verticalOffset);
verticalOffset += STRING_SPACING;
}
// Death
if (pointColl.Block->Flags.Death)
{
DrawSectorFlagLabel(pos, "Death", DEATH_COLOR, verticalOffset);
verticalOffset += STRING_SPACING;
}
// Monkey Swing
if (pointColl.Block->Flags.Monkeyswing)
{
DrawSectorFlagLabel(pos, "Monkey Swing", MONKEY_SWING_COLOR, verticalOffset);
verticalOffset += STRING_SPACING;
}
// Beetle / Minecart Right
if (pointColl.Block->Flags.MarkBeetle)
{
auto labelString = std::string("Beetle") + (!pointColl.Block->Flags.MinecartStop() ? " / Minecart Right" : "");
DrawSectorFlagLabel(pos, labelString, BEETLE_MINECART_RIGHT_COLOR, verticalOffset);
verticalOffset += STRING_SPACING;
}
// Activator / Minecart Left
if (pointColl.Block->Flags.MarkTriggerer)
{
auto labelString = std::string("Activator") + (!pointColl.Block->Flags.MinecartStop() ? " / Minecart Left" : "");
DrawSectorFlagLabel(pos, labelString, ACTIVATOR_MINECART_LEFT_COLOR, verticalOffset);
verticalOffset += STRING_SPACING;
}
// Minecart Stop
if (pointColl.Block->Flags.MinecartStop())
{
DrawSectorFlagLabel(pos, "Minecart Stop", MINECART_STOP_COLOR, verticalOffset);
verticalOffset += STRING_SPACING;
}
}
}
}
}

View file

@ -189,4 +189,6 @@ namespace TEN::Collision::Floordata
void UpdateBridgeItem(int itemNumber, bool forceRemoval = false);
bool TestMaterial(MaterialType refMaterial, const std::vector<MaterialType>& materialList);
void DrawNearbySectorFlags(const ItemInfo& item);
}

View file

@ -19,9 +19,7 @@ int GetSpheres(ItemInfo* item, SPHERE* ptr, int worldSpace, Matrix local)
return 0;
BoundingSphere spheres[MAX_SPHERES];
short itemNumber = (item - g_Level.Items.data());
int num = g_Renderer.GetSpheres(itemNumber, spheres, worldSpace, local);
int num = g_Renderer.GetSpheres(item->Index, spheres, worldSpace, local);
for (int i = 0; i < MAX_SPHERES; i++)
{

View file

@ -24,10 +24,10 @@
using namespace TEN::Effects::Smoke;
constexpr auto ESCAPE_DIST = SECTOR(5);
constexpr auto STALK_DIST = SECTOR(3);
constexpr auto ESCAPE_DIST = BLOCK(5);
constexpr auto STALK_DIST = BLOCK(3);
constexpr auto REACHED_GOAL_RADIUS = 640;
constexpr auto ATTACK_RANGE = SQUARE(SECTOR(3));
constexpr auto ATTACK_RANGE = SQUARE(BLOCK(3));
constexpr auto ESCAPE_CHANCE = 0x800;
constexpr auto RECOVER_CHANCE = 0x100;
constexpr auto BIFF_AVOID_TURN = ANGLE(11.25f);
@ -59,14 +59,14 @@ void DrawBox(int boxIndex, Vector3 color)
float z = ((float)currBox.top + (float)(currBox.bottom - currBox.top) / 2.0f) * 1024.0f;
auto center = Vector3(z, y, x);
auto corner = Vector3(currBox.bottom * SECTOR(1), currBox.height + CLICK(1), currBox.right * SECTOR(1));
auto corner = Vector3(currBox.bottom * BLOCK(1), currBox.height + CLICK(1), currBox.right * BLOCK(1));
auto extents = (corner - center) * 0.9f;
auto dBox = BoundingOrientedBox(center, extents, Vector4::UnitY);
for (int i = 0; i <= 10; i++)
{
dBox.Extents = extents + Vector3(i);
TEN::Renderer::g_Renderer.AddDebugBox(dBox, Vector4(color.x, color.y, color.z, 1), RENDERER_DEBUG_PAGE::LOGIC_STATS);
TEN::Renderer::g_Renderer.AddDebugBox(dBox, Vector4(color.x, color.y, color.z, 1), RendererDebugPage::PathfindingStats);
}
}
@ -75,11 +75,16 @@ void DrawNearbyPathfinding(int boxIndex)
if (boxIndex == NO_BOX)
return;
DrawBox(boxIndex, Vector3(0, 1, 1));
auto& currBox = g_Level.Boxes[boxIndex];
auto index = currBox.overlapIndex;
// Grey flag box.
auto currentBoxColor = Vector3(0.0f, 1.0f, 1.0f);
if (currBox.flags & BLOCKABLE)
currentBoxColor = (currBox.flags & BLOCKED) ? Vector3(1.0f, 0.0f, 0.0f) : Vector3(0.0f, 1.0f, 0.0f);
DrawBox(boxIndex, currentBoxColor);
while (true)
{
if (index >= g_Level.Overlaps.size())
@ -287,10 +292,10 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt)
boxHeight - height > LOT->Step ||
boxHeight - height < LOT->Drop))
{
xPos = item->Pose.Position.x / SECTOR(1);
zPos = item->Pose.Position.z / SECTOR(1);
shiftX = prevPos.x / SECTOR(1);
shiftZ = prevPos.z / SECTOR(1);
xPos = item->Pose.Position.x / BLOCK(1);
zPos = item->Pose.Position.z / BLOCK(1);
shiftX = prevPos.x / BLOCK(1);
shiftZ = prevPos.z / BLOCK(1);
if (xPos < shiftX)
item->Pose.Position.x = prevPos.x & (~WALL_MASK);
@ -346,23 +351,23 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt)
shiftX = radius - xPos;
}
}
else if (xPos > SECTOR(1) - radius)
else if (xPos > BLOCK(1) - radius)
{
if (BadFloor(x + radius, y, z, height, nextHeight, roomNumber, LOT))
shiftX = SECTOR(1) - radius - xPos;
shiftX = BLOCK(1) - radius - xPos;
else if (!shiftZ && BadFloor(x + radius, y, z - radius, height, nextHeight, roomNumber, LOT))
{
if (item->Pose.Orientation.y > -ANGLE(45.0f) && item->Pose.Orientation.y < ANGLE(135.0f))
shiftZ = radius - zPos;
else
shiftX = SECTOR(1) - radius - xPos;
shiftX = BLOCK(1) - radius - xPos;
}
}
}
else if (zPos > SECTOR(1) - radius)
else if (zPos > BLOCK(1) - radius)
{
if (BadFloor(x, y, z + radius, height, nextHeight, roomNumber, LOT))
shiftZ = SECTOR(1) - radius - zPos;
shiftZ = BLOCK(1) - radius - zPos;
if (xPos < radius)
{
@ -373,19 +378,19 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt)
if (item->Pose.Orientation.y > -ANGLE(45.0f) && item->Pose.Orientation.y < ANGLE(135.0f))
shiftX = radius - xPos;
else
shiftZ = SECTOR(1) - radius - zPos;
shiftZ = BLOCK(1) - radius - zPos;
}
}
else if (xPos > SECTOR(1) - radius)
else if (xPos > BLOCK(1) - radius)
{
if (BadFloor(x + radius, y, z, height, nextHeight, roomNumber, LOT))
shiftX = SECTOR(1) - radius - xPos;
shiftX = BLOCK(1) - radius - xPos;
else if (!shiftZ && BadFloor(x + radius, y, z + radius, height, nextHeight, roomNumber, LOT))
{
if (item->Pose.Orientation.y > -ANGLE(135.0f) && item->Pose.Orientation.y < ANGLE(45.0f))
shiftX = SECTOR(1) - radius - xPos;
shiftX = BLOCK(1) - radius - xPos;
else
shiftZ = SECTOR(1) - radius - zPos;
shiftZ = BLOCK(1) - radius - zPos;
}
}
}
@ -394,10 +399,10 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt)
if (BadFloor(x - radius, y, z, height, nextHeight, roomNumber, LOT))
shiftX = radius - xPos;
}
else if (xPos > SECTOR(1) - radius)
else if (xPos > BLOCK(1) - radius)
{
if (BadFloor(x + radius, y, z, height, nextHeight, roomNumber, LOT))
shiftX = SECTOR(1) - radius - xPos;
shiftX = BLOCK(1) - radius - xPos;
}
item->Pose.Position.x += shiftX;
@ -566,7 +571,7 @@ void CreatureKill(ItemInfo* creatureItem, int creatureAnimNumber, int playerAnim
playerItem.Animation.Velocity = Vector3::Zero;
if (creatureItem->RoomNumber != playerItem.RoomNumber)
ItemNewRoom(player.ItemNumber, creatureItem->RoomNumber);
ItemNewRoom(playerItem.Index, creatureItem->RoomNumber);
AnimateItem(&playerItem);
@ -788,39 +793,53 @@ void CreatureHealth(ItemInfo* item)
}
}
void CreatureDie(short itemNumber, bool explode)
void CreatureDie(int itemNumber, bool doExplosion)
{
auto* item = &g_Level.Items[itemNumber];
auto* object = &Objects[item->ObjectNumber];
item->HitPoints = NOT_TARGETABLE;
item->Collidable = false;
if (explode)
int flags = 0;
if (doExplosion)
{
switch (object->hitEffect)
const auto& item = g_Level.Items[itemNumber];
const auto& object = Objects[item.ObjectNumber];
switch (object.hitEffect)
{
case HitEffect::Blood:
ExplodingDeath(itemNumber, BODY_EXPLODE | BODY_GIBS);
flags |= BODY_DO_EXPLOSION | BODY_GIBS;
break;
case HitEffect::Smoke:
ExplodingDeath(itemNumber, BODY_EXPLODE | BODY_NO_BOUNCE);
flags |= BODY_DO_EXPLOSION | BODY_NO_BOUNCE;
break;
default:
ExplodingDeath(itemNumber, BODY_EXPLODE);
flags |= BODY_DO_EXPLOSION;
break;
}
}
CreatureDie(itemNumber, doExplosion, flags);
}
void CreatureDie(int itemNumber, bool doExplosion, int flags)
{
auto& item = g_Level.Items[itemNumber];
item.HitPoints = NOT_TARGETABLE;
item.Collidable = false;
if (doExplosion)
{
ExplodingDeath(itemNumber, flags);
KillItem(itemNumber);
}
else
{
RemoveActiveItem(itemNumber);
}
DisableEntityAI(itemNumber);
item->Flags |= IFLAG_KILLED | IFLAG_INVISIBLE;
DropPickups(item);
item.Flags |= IFLAG_KILLED | IFLAG_INVISIBLE;
DropPickups(&item);
}
bool BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumber, LOTInfo* LOT)
@ -938,8 +957,8 @@ void TargetBox(LOTInfo* LOT, int boxNumber)
auto* box = &g_Level.Boxes[boxNumber];
// Maximize target precision. DO NOT change bracket precedence!
LOT->Target.x = (int)((box->top * SECTOR(1)) + (float)GetRandomControl() * (((float)(box->bottom - box->top) - 1.0f) / 32.0f) + CLICK(2.0f));
LOT->Target.z = (int)((box->left * SECTOR(1)) + (float)GetRandomControl() * (((float)(box->right - box->left) - 1.0f) / 32.0f) + CLICK(2.0f));
LOT->Target.x = (int)((box->top * BLOCK(1)) + (float)GetRandomControl() * (((float)(box->bottom - box->top) - 1.0f) / 32.0f) + CLICK(2.0f));
LOT->Target.z = (int)((box->left * BLOCK(1)) + (float)GetRandomControl() * (((float)(box->right - box->left) - 1.0f) / 32.0f) + CLICK(2.0f));
LOT->RequiredBox = boxNumber;
if (LOT->Fly == NO_FLYING)
@ -1116,10 +1135,10 @@ bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber)
return false;
auto* box = &g_Level.Boxes[boxNumber];
int xRange = STALK_DIST + ((box->bottom - box->top) * SECTOR(1));
int zRange = STALK_DIST + ((box->right - box->left) * SECTOR(1));
int x = (box->top + box->bottom) * SECTOR(1) / 2 - enemy->Pose.Position.x;
int z = (box->left + box->right) * SECTOR(1) / 2 - enemy->Pose.Position.z;
int xRange = STALK_DIST + ((box->bottom - box->top) * BLOCK(1));
int zRange = STALK_DIST + ((box->right - box->left) * BLOCK(1));
int x = (box->top + box->bottom) * BLOCK(1) / 2 - enemy->Pose.Position.x;
int z = (box->left + box->right) * BLOCK(1) / 2 - enemy->Pose.Position.z;
if (x > xRange || x < -xRange || z > zRange || z < -zRange)
return false;
@ -1183,8 +1202,8 @@ int CreatureVault(short itemNumber, short angle, int vault, int shift)
auto* item = &g_Level.Items[itemNumber];
auto* creature = GetCreatureInfo(item);
int xBlock = item->Pose.Position.x / SECTOR(1);
int zBlock = item->Pose.Position.z / SECTOR(1);
int xBlock = item->Pose.Position.x / BLOCK(1);
int zBlock = item->Pose.Position.z / BLOCK(1);
int y = item->Pose.Position.y;
short roomNumber = item->RoomNumber;
@ -1224,8 +1243,8 @@ int CreatureVault(short itemNumber, short angle, int vault, int shift)
}
// Jump
int newXblock = item->Pose.Position.x / SECTOR(1);
int newZblock = item->Pose.Position.z / SECTOR(1);
int newXblock = item->Pose.Position.x / BLOCK(1);
int newZblock = item->Pose.Position.z / BLOCK(1);
if (zBlock == newZblock)
{
@ -1234,12 +1253,12 @@ int CreatureVault(short itemNumber, short angle, int vault, int shift)
if (xBlock < newXblock)
{
item->Pose.Position.x = (newXblock * SECTOR(1)) - shift;
item->Pose.Position.x = (newXblock * BLOCK(1)) - shift;
item->Pose.Orientation.y = ANGLE(90.0f);
}
else
{
item->Pose.Position.x = (xBlock * SECTOR(1)) + shift;
item->Pose.Position.x = (xBlock * BLOCK(1)) + shift;
item->Pose.Orientation.y = -ANGLE(90.0f);
}
}
@ -1247,12 +1266,12 @@ int CreatureVault(short itemNumber, short angle, int vault, int shift)
{
if (zBlock < newZblock)
{
item->Pose.Position.z = (newZblock * SECTOR(1)) - shift;
item->Pose.Position.z = (newZblock * BLOCK(1)) - shift;
item->Pose.Orientation.y = 0;
}
else
{
item->Pose.Position.z = (zBlock * SECTOR(1)) + shift;
item->Pose.Position.z = (zBlock * BLOCK(1)) + shift;
item->Pose.Orientation.y = -ANGLE(180.0f);
}
}
@ -1550,8 +1569,8 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI)
vector.y = item->Pose.Position.y - enemy->Pose.Position.y;
short angle = phd_atan(vector.z, vector.x);
if (vector.x > SECTOR(31.25f) || vector.x < -SECTOR(31.25f) ||
vector.z > SECTOR(31.25f) || vector.z < -SECTOR(31.25f))
if (vector.x > BLOCK(31.25f) || vector.x < -BLOCK(31.25f) ||
vector.z > BLOCK(31.25f) || vector.z < -BLOCK(31.25f))
{
AI->distance = INT_MAX;
AI->verticalDistance = INT_MAX;
@ -1809,7 +1828,7 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent)
case MoodType::Stalk:
if (creature->Alerted && AI->zoneNumber != AI->enemyZone)
{
if (AI->distance > SECTOR(3))
if (AI->distance > BLOCK(3))
creature->Mood = MoodType::Stalk;
else
creature->Mood = MoodType::Bored;
@ -1830,7 +1849,7 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent)
(GetRandomControl() < ESCAPE_CHANCE ||
AI->zoneNumber != AI->enemyZone))
creature->Mood = MoodType::Stalk;
else if (AI->zoneNumber != AI->enemyZone && AI->distance > SECTOR(6))
else if (AI->zoneNumber != AI->enemyZone && AI->distance > BLOCK(6))
creature->Mood = MoodType::Bored;
break;
@ -1872,10 +1891,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
auto* box = &g_Level.Boxes[boxNumber];
int boxLeft = ((int)box->left * SECTOR(1));
int boxRight = ((int)box->right * SECTOR(1)) - 1;
int boxTop = ((int)box->top * SECTOR(1));
int boxBottom = ((int)box->bottom * SECTOR(1)) - 1;
int boxLeft = ((int)box->left * BLOCK(1));
int boxRight = ((int)box->right * BLOCK(1)) - 1;
int boxTop = ((int)box->top * BLOCK(1));
int boxBottom = ((int)box->bottom * BLOCK(1)) - 1;
int left = boxLeft;
int right = boxRight;
int top = boxTop;
@ -1888,26 +1907,26 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
if (LOT->Fly != NO_FLYING)
{
if (target->y > box->height - SECTOR(1))
target->y = box->height - SECTOR(1);
if (target->y > box->height - BLOCK(1))
target->y = box->height - BLOCK(1);
}
else if(target->y > box->height)
target->y = box->height;
boxLeft = ((int)box->left * SECTOR(1));
boxRight = ((int)box->right * SECTOR(1)) - 1;
boxTop = ((int)box->top * SECTOR(1));
boxBottom = ((int)box->bottom * SECTOR(1)) - 1;
boxLeft = ((int)box->left * BLOCK(1));
boxRight = ((int)box->right * BLOCK(1)) - 1;
boxTop = ((int)box->top * BLOCK(1));
boxBottom = ((int)box->bottom * BLOCK(1)) - 1;
if (item->Pose.Position.z >= boxLeft &&
item->Pose.Position.z <= boxRight &&
item->Pose.Position.x >= boxTop &&
item->Pose.Position.x <= boxBottom)
{
left = ((int)box->left * SECTOR(1));
right = ((int)box->right * SECTOR(1)) - 1;
top = ((int)box->top * SECTOR(1));
bottom = ((int)box->bottom * SECTOR(1)) - 1;
left = ((int)box->left * BLOCK(1));
right = ((int)box->right * BLOCK(1)) - 1;
top = ((int)box->top * BLOCK(1));
bottom = ((int)box->bottom * BLOCK(1)) - 1;
}
else
{
@ -2102,8 +2121,8 @@ void AdjustStopperFlag(ItemInfo* item, int direction)
auto* floor = GetSector(room, x - room->x, z - room->z);
floor->Stopper = !floor->Stopper;
x = item->Pose.Position.x + SECTOR(1) * phd_sin(direction);
z = item->Pose.Position.z + SECTOR(1) * phd_cos(direction);
x = item->Pose.Position.x + BLOCK(1) * phd_sin(direction);
z = item->Pose.Position.z + BLOCK(1) * phd_cos(direction);
room = &g_Level.Rooms[GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).RoomNumber];
floor = GetSector(room, x - room->x, z - room->z);
@ -2124,7 +2143,7 @@ void InitializeItemBoxData()
{
for (const auto& mesh : room.mesh)
{
long index = ((mesh.pos.Position.z - room.z) / SECTOR(1)) + room.zSize * ((mesh.pos.Position.x - room.x) / SECTOR(1));
long index = ((mesh.pos.Position.z - room.z) / BLOCK(1)) + room.zSize * ((mesh.pos.Position.x - room.x) / BLOCK(1));
if (index > room.floor.size())
continue;

View file

@ -98,7 +98,8 @@ void CreatureFloat(short itemNumber);
void CreatureJoint(ItemInfo* item, short joint, short required, short maxAngle = ANGLE(70.0f));
void CreatureTilt(ItemInfo* item, short angle);
short CreatureTurn(ItemInfo* item, short maxTurn);
void CreatureDie(short itemNumber, bool explode);
void CreatureDie(int itemNumber, bool doExplosion);
void CreatureDie(int itemNumber, bool doExplosion, int flags);
bool BadFloor(int x, int y, int z, int boxHeight, int nextHeight, short roomNumber, LOTInfo* LOT);
int CreatureCreature(short itemNumber);
bool ValidBox(ItemInfo* item, short zoneNumber, short boxNumber);

View file

@ -218,7 +218,6 @@ GameStatus ControlPhase(int numFrames)
UpdateSparkParticles();
UpdateSmokeParticles();
UpdateSimpleParticles();
UpdateDrips();
UpdateExplosionParticles();
UpdateShockwaves();
UpdateBeetleSwarm();
@ -305,16 +304,12 @@ GameStatus DoLevel(int levelIndex, bool loadGame)
InitializeScripting(levelIndex, loadGame);
InitializeNodeScripts();
// Initialize menu and inventory state.
g_Gui.Initialize();
// Initialize game variables and optionally load game.
InitializeOrLoadGame(loadGame);
// Prepare title menu, if necessary.
if (isTitle)
{
g_Gui.SetMenuToDisplay(Menu::Title);
g_Gui.SetSelectedOption(0);
}
// DoGameLoop() returns only when level has ended.
return DoGameLoop(levelIndex);
}
@ -457,8 +452,8 @@ void InitializeScripting(int levelIndex, bool loadGame)
g_GameStringsHandler->SetCallbackDrawString([](std::string const key, D3DCOLOR col, int x, int y, int flags)
{
g_Renderer.AddString(
float(x) / float(g_Configuration.Width) * SCREEN_SPACE_RES.x,
float(y) / float(g_Configuration.Height) * SCREEN_SPACE_RES.y,
float(x) / float(g_Configuration.ScreenWidth) * SCREEN_SPACE_RES.x,
float(y) / float(g_Configuration.ScreenHeight) * SCREEN_SPACE_RES.y,
key.c_str(), col, flags);
});
}
@ -638,7 +633,7 @@ GameStatus HandleMenuCalls(bool isTitle)
if (g_Gui.CallPause())
result = GameStatus::ExitToTitle;
}
else if ((IsClicked(In::Option) || g_Gui.GetEnterInventory() != NO_ITEM) &&
else if ((IsClicked(In::Inventory) || g_Gui.GetEnterInventory() != NO_ITEM) &&
LaraItem->HitPoints > 0 && !BinocularOn)
{
if (g_Gui.CallInventory(LaraItem, true))

View file

@ -315,11 +315,11 @@ void FloorShake(ItemInfo* item)
int y = abs(item->Pose.Position.y - Camera.pos.y);
int z = abs(item->Pose.Position.z - Camera.pos.z);
if (x < SECTOR(16) &&
y < SECTOR(16) &&
z < SECTOR(16))
if (x < BLOCK(16) &&
y < BLOCK(16) &&
z < BLOCK(16))
{
Camera.bounce = 66 * ((pow(x, 2) + pow(y, 2) + pow(z, 2)) / CLICK(1) - pow(SECTOR(1), 2)) / pow(SECTOR(1), 2);
Camera.bounce = 66 * ((pow(x, 2) + pow(y, 2) + pow(z, 2)) / CLICK(1) - pow(BLOCK(1), 2)) / pow(BLOCK(1), 2);
}
}

View file

@ -606,7 +606,7 @@ int xLOS(GameVector* origin, GameVector* target)
break;
}
x -= SECTOR(1);
x -= BLOCK(1);
y -= dy;
z -= dz;
}
@ -656,7 +656,7 @@ int xLOS(GameVector* origin, GameVector* target)
break;
}
x += SECTOR(1);
x += BLOCK(1);
y += dy;
z += dz;
}
@ -726,7 +726,7 @@ int zLOS(GameVector* origin, GameVector* target)
break;
}
z -= SECTOR(1);
z -= BLOCK(1);
x -= dx;
y -= dy;
}
@ -776,7 +776,7 @@ int zLOS(GameVector* origin, GameVector* target)
break;
}
z += SECTOR(1);
z += BLOCK(1);
x += dx;
y += dy;
}

View file

@ -117,16 +117,16 @@ void InitializeSlot(short itemNumber, bool makeTarget)
// Can fly.
case LotType::Flyer:
creature->LOT.Step = SECTOR(20);
creature->LOT.Drop = -SECTOR(20);
creature->LOT.Step = BLOCK(20);
creature->LOT.Drop = -BLOCK(20);
creature->LOT.Fly = DEFAULT_FLY_UPDOWN_SPEED;
creature->LOT.Zone = ZoneType::Flyer;
break;
// Can swim.
case LotType::Water:
creature->LOT.Step = SECTOR(20);
creature->LOT.Drop = -SECTOR(20);
creature->LOT.Step = BLOCK(20);
creature->LOT.Drop = -BLOCK(20);
creature->LOT.Zone = ZoneType::Water;
if (item->ObjectNumber == ID_CROCODILE)
@ -197,7 +197,7 @@ void InitializeSlot(short itemNumber, bool makeTarget)
}
ClearLOT(&creature->LOT);
if (itemNumber != Lara.ItemNumber)
if (itemNumber != LaraItem->Index)
CreateZone(item);
SlotsUsed++;

View file

@ -30,7 +30,7 @@ namespace TEN::Control::Volumes
if (roomNumber == Camera.pos.RoomNumber)
{
g_Renderer.AddDebugBox(volume.Box,
Vector4(color, 0.0f, color, 1.0f), RENDERER_DEBUG_PAGE::LARA_STATS);
Vector4(color, 0.0f, color, 1.0f), RendererDebugPage::CollisionStats);
}
return volume.Box.Intersects(box);
@ -38,7 +38,7 @@ namespace TEN::Control::Volumes
if (roomNumber == Camera.pos.RoomNumber)
{
g_Renderer.AddDebugSphere(volume.Sphere.Center, volume.Sphere.Radius,
Vector4(color, 0.0f, color, 1.0f), RENDERER_DEBUG_PAGE::LARA_STATS);
Vector4(color, 0.0f, color, 1.0f), RendererDebugPage::CollisionStats);
}
return volume.Sphere.Intersects(box);
@ -171,7 +171,7 @@ namespace TEN::Control::Volumes
auto box = (coll != nullptr) ?
ConstructRoughBox(item, *coll) : GameBoundingBox(&item).ToBoundingOrientedBox(item.Pose);
g_Renderer.AddDebugBox(box, Vector4(1.0f, 1.0f, 0.0f, 1.0f), RENDERER_DEBUG_PAGE::LARA_STATS);
g_Renderer.AddDebugBox(box, Vector4(1.0f, 1.0f, 0.0f, 1.0f), RendererDebugPage::CollisionStats);
if (item.IsLara() || item.Index == Lara.Context.Vehicle)
{

View file

@ -24,7 +24,7 @@ bool ExplodeItemNode(ItemInfo* item, int node, int noXZVel, int bits)
if (1 << node & item->MeshBits.ToPackedBits())
{
int number = bits;
if (number == BODY_EXPLODE)
if (number == BODY_DO_EXPLOSION)
number = -64;
GetSpheres(item, CreatureSpheres, SPHERES_SPACE_WORLD | SPHERES_SPACE_BONE_ORIGIN, Matrix::Identity);

View file

@ -1146,7 +1146,7 @@ void TriggerWaterfallMist(const ItemInfo& item)
if (item.TriggerFlags != 0)
{
size = item.TriggerFlags % 100;
width = std::clamp(int(round(item.TriggerFlags / 100) * 100) / 2, 0, SECTOR(8));
width = std::clamp(int(round(item.TriggerFlags / 100) * 100) / 2, 0, BLOCK(8));
}
float cos = phd_cos(angle);

View file

@ -157,8 +157,8 @@ struct Particle
BLEND_MODES blendMode;
unsigned char extras;
signed char dynamic;
unsigned char fxObj;
unsigned char roomNumber;
int fxObj;
int roomNumber;
unsigned char nodeNumber; // ParticleNodeOffsetIDs enum.
};
@ -211,9 +211,10 @@ extern FX_INFO EffectList[NUM_EFFECTS];
template <typename TEffect>
TEffect& GetNewEffect(std::vector<TEffect>& effects, unsigned int countMax)
{
assertion(effects.size() <= countMax, "Too many particle effects.");
// Add and return new effect.
assert(effects.size() <= countMax);
if (effects.size() != countMax)
if (effects.size() < countMax)
return effects.emplace_back();
TEffect* effectPtr = nullptr;

View file

@ -29,7 +29,7 @@ namespace TEN::Effects::Hair
// Get world matrix from head bone.
auto worldMatrix = Matrix::Identity;
g_Renderer.GetBoneMatrix(player.ItemNumber, LM_HEAD, &worldMatrix);
g_Renderer.GetBoneMatrix(item.Index, LM_HEAD, &worldMatrix);
// Apply base offset to world matrix.
auto relOffset = GetRelBaseOffset(hairUnitIndex, isYoung);

View file

@ -30,6 +30,9 @@ using namespace TEN::Collision::Floordata;
using namespace TEN::Math;
using TEN::Renderer::g_Renderer;
// NOTE: This fixes body part exploding instantly if entity is on ground.
constexpr auto BODY_PART_SPAWN_VERTICAL_OFFSET = CLICK(1);
char LaserSightActive = 0;
char LaserSightCol = 0;
int NextGunshell = 0;
@ -43,12 +46,11 @@ int NextSmokeSpark = 0;
int NextBlood = 0;
int NextGunShell = 0;
GUNFLASH_STRUCT Gunflashes[MAX_GUNFLASH];
FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE];
SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE];
GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL];
BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD];
SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE];
FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE];
SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE];
GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL];
BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD];
SHOCKWAVE_STRUCT ShockWaves[MAX_SHOCKWAVE];
FIRE_LIST Fires[MAX_FIRE_LIST];
int GetFreeFireSpark()
@ -1168,7 +1170,7 @@ void ExplodeVehicle(ItemInfo* laraItem, ItemInfo* vehicle)
auto* lara = GetLaraInfo(laraItem);
ExplodingDeath(lara->Context.Vehicle, BODY_EXPLODE | BODY_STONE_SOUND);
ExplodingDeath(lara->Context.Vehicle, BODY_DO_EXPLOSION | BODY_STONE_SOUND);
KillItem(lara->Context.Vehicle);
vehicle->Status = ITEM_DEACTIVATED;
SoundEffect(SFX_TR4_EXPLOSION1, &laraItem->Pose);
@ -1192,6 +1194,10 @@ void ExplodingDeath(short itemNumber, short flags)
auto world = item->Pose.Orientation.ToRotationMatrix();
// If only BODY_PART_EXPLODE flag exists but not BODY_EXPLODE, add it.
if ((flags & BODY_PART_EXPLODE) && !(flags & BODY_DO_EXPLOSION))
flags |= BODY_DO_EXPLOSION;
for (int i = 0; i < obj->nmeshes; i++)
{
Matrix boneMatrix;
@ -1203,7 +1209,7 @@ void ExplodingDeath(short itemNumber, short flags)
item->MeshBits.Clear(i);
if (i == 0 || ((GetRandomControl() & 3) != 0 && (flags & BODY_EXPLODE)))
if (i == 0 || ((GetRandomControl() & 3) != 0 && (flags & BODY_DO_EXPLOSION)))
{
short fxNumber = CreateNewEffect(item->RoomNumber);
if (fxNumber != NO_ITEM)
@ -1211,26 +1217,26 @@ void ExplodingDeath(short itemNumber, short flags)
FX_INFO* fx = &EffectList[fxNumber];
fx->pos.Position.x = boneMatrix.Translation().x;
fx->pos.Position.y = boneMatrix.Translation().y;
fx->pos.Position.y = boneMatrix.Translation().y - BODY_PART_SPAWN_VERTICAL_OFFSET;
fx->pos.Position.z = boneMatrix.Translation().z;
fx->roomNumber = item->RoomNumber;
fx->pos.Orientation.x = 0;
fx->pos.Orientation.y = GetRandomControl() * 2;
fx->pos.Orientation.y = Random::GenerateAngle();
if (!(flags & 0x10))
if (!(flags & BODY_NO_RAND_VELOCITY))
{
if (flags & 0x20)
if (flags & BODY_MORE_RAND_VELOCITY)
fx->speed = GetRandomControl() >> 12;
else
fx->speed = GetRandomControl() >> 8;
}
if (flags & 0x40)
if (flags & BODY_NO_VERTICAL_VELOCITY)
fx->fallspeed = 0;
else
{
if ((flags & 0x80) == 0)
if (flags & BODY_LESS_IMPULSE)
fx->fallspeed = -(GetRandomControl() >> 8);
else
fx->fallspeed = -(GetRandomControl() >> 12);

View file

@ -10,20 +10,19 @@ struct ItemInfo;
enum BodyPartFlags
{
BODY_NO_BOUNCE = (1 << 0),
BODY_GIBS = (1 << 1),
BODY_EXPLODE = (1 << 8),
BODY_NO_BOUNCE_ALT = (1 << 9),
BODY_STONE_SOUND = (1 << 11)
};
struct Matrix3D
{
short m00, m01, m02;
short m10, m11, m12;
short m20, m21, m22;
short pad;
int tx, ty, tz;
BODY_NO_BOUNCE = (1 << 0), // No bounce.
BODY_GIBS = (1 << 1), // Add blood and SFX_TR4_LARA_THUD upon floor collision.
BODY_PART_EXPLODE = (1 << 2), // Explode upon impact. Requires BODY_EXPLODE flag.
BODY_NO_FLAME = (1 << 3), // No flame.
BODY_NO_RAND_VELOCITY = (1 << 4), // No random velocity.
BODY_MORE_RAND_VELOCITY = (1 << 5), // Add more randomness to velocity.
BODY_NO_VERTICAL_VELOCITY = (1 << 6), // No vertical velocity.
BODY_LESS_IMPULSE = (1 << 7), // Add less vertical velocity than normal. TODO: Weird name.
BODY_DO_EXPLOSION = (1 << 8), // Explode.
BODY_NO_BOUNCE_ALT = (1 << 9), // Same as BODY_NO_BOUNCE, but with delay before despawning.
BODY_STONE_SOUND = (1 << 11), // Do impact sound if stone. NOTE: BODY_GIBS also add sound, but this one is prioritary.
BODY_NO_SMOKE = (1 << 12), // Remove smoke upon despawn or shatter.
BODY_NO_SHATTER_EFFECT = (1 << 13), // Remove shatter effect upon despawn.
};
struct SMOKE_SPARKS
@ -59,12 +58,6 @@ struct SMOKE_SPARKS
byte mirror;
};
struct GUNFLASH_STRUCT
{
Matrix3D matrix;
short on;
};
struct SHOCKWAVE_STRUCT
{
int x;
@ -219,7 +212,6 @@ constexpr auto MAX_GUNFLASH = 4;
constexpr auto MAX_GUNSHELL = 24;
constexpr auto MAX_SHOCKWAVE = 16;
extern GUNFLASH_STRUCT Gunflashes[MAX_GUNFLASH];
extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE];
extern SMOKE_SPARKS SmokeSparks[MAX_SPARKS_SMOKE];
extern GUNSHELL_STRUCT Gunshells[MAX_GUNSHELL];
@ -254,7 +246,7 @@ int GetFreeGunshell();
void TriggerGunShell(short hand, short objNum, LaraWeaponType weaponType);
void UpdateGunShells();
void AddWaterSparks(int x, int y, int z, int num);
void ExplodingDeath(short itemNumber, short flags); // EXPLODE_ flags
void ExplodingDeath(short itemNumber, short flags); // BODY_ flags
int GetFreeShockwave();
void TriggerShockwave(Pose* pos, short innerRad, short outerRad, int speed, unsigned char r, unsigned char g, unsigned char b, unsigned char life, EulerAngles rotation, short damage, bool sound, bool fadein, int style);
void TriggerShockwaveHitEffect(int x, int y, int z, unsigned char r, unsigned char g, unsigned char b, short rot, int vel);

File diff suppressed because it is too large Load diff

View file

@ -5,11 +5,11 @@
#include "Specific/configuration.h"
#include "Specific/Input/InputAction.h"
struct ItemInfo;
using namespace TEN::Input;
using namespace TEN::Math;
struct ItemInfo;
namespace TEN::Gui
{
enum class InventoryMode
@ -76,20 +76,23 @@ namespace TEN::Gui
LoadGame,
Options,
Display,
Controls,
GeneralActions,
VehicleActions,
QuickActions,
MenuActions,
OtherSettings
};
struct MenuOption
{
MenuType Type;
char const* Text;
MenuType Type = MenuType::None;
std::string Text = {};
};
struct ObjectList
{
short InventoryItem;
EulerAngles Orientation = EulerAngles::Zero;
int InventoryItem = 0;
EulerAngles Orientation = EulerAngles::Zero;
unsigned short Bright;
};
@ -115,7 +118,7 @@ namespace TEN::Gui
private:
// Input inquirers
bool GuiIsPulsed(ActionID actionID) const;
bool GuiIsSelected() const;
bool GuiIsSelected(bool onClicked = true) const;
bool GuiIsDeselected() const;
bool CanSelect() const;
bool CanDeselect() const;
@ -135,9 +138,7 @@ namespace TEN::Gui
bool UseItem;
char SeperateTypeFlag;
char CombineTypeFlag;
InventoryRing PCRing1;
InventoryRing PCRing2;
InventoryRing* Rings[2];
InventoryRing Rings[2];
int CurrentSelectedOption;
bool MenuActive;
char AmmoSelectorFlag;
@ -161,12 +162,13 @@ namespace TEN::Gui
public:
int CompassNeedleAngle;
void Initialize();
bool CallPause();
bool CallInventory(ItemInfo* item, bool resetMode);
InventoryResult TitleOptions(ItemInfo* item);
InventoryResult DoPauseMenu(ItemInfo* item);
void DrawInventory();
void DrawCurrentObjectList(ItemInfo* item, int ringIndex);
void DrawCurrentObjectList(ItemInfo* item, RingTypes ringType);
int IsObjectInInventory(int objectNumber);
int ConvertObjectToInventoryItem(int objectNumber);
int ConvertInventoryItemToObject(int objectNumber);
@ -176,7 +178,7 @@ namespace TEN::Gui
void DrawCompass(ItemInfo* item);
// Getters
InventoryRing* GetRings(int ringIndex);
const InventoryRing& GetRing(RingTypes ringType);
short GetSelectedOption();
Menu GetMenuToDisplay();
InventoryMode GetInventoryMode();
@ -192,6 +194,7 @@ namespace TEN::Gui
void SetInventoryMode(InventoryMode mode);
void SetEnterInventory(int number);
void SetInventoryItemChosen(int number);
void SetLastInventoryItem(int itemNumber);
private:
void HandleDisplaySettingsInput(bool fromPauseMenu);
@ -226,5 +229,9 @@ namespace TEN::Gui
};
extern GuiController g_Gui;
extern const char* ControlStrings[];
extern std::vector<std::string> OptionStrings;
extern std::vector<std::string> GeneralActionStrings;
extern std::vector<std::string> VehicleActionStrings;
extern std::vector<std::string> QuickActionStrings;
extern std::vector<std::string> MenuActionStrings;
}

View file

@ -73,20 +73,20 @@ struct LOTInfo
struct CreatureBiteInfo
{
Vector3i Position = Vector3i::Zero; // TODO: Change back to Vector3.
int BoneID = -1;
Vector3 Position = Vector3::Zero;
int BoneID = -1;
CreatureBiteInfo() {}
CreatureBiteInfo(const Vector3i& pos, int boneID)
CreatureBiteInfo(const Vector3& pos, int boneID)
{
Position = pos;
BoneID = boneID;
}
CreatureBiteInfo(int x, int y, int z, int boneID)
CreatureBiteInfo(float x, float y, float z, int boneID)
{
Position = Vector3i(x, y, z);
Position = Vector3(x, y, z);
BoneID = boneID;
}
};
@ -103,7 +103,7 @@ struct CreatureMuzzleFlashInfo
CreatureMuzzleFlashInfo() {}
CreatureMuzzleFlashInfo(const Vector3i& pos, int boneID, int delay, bool changeToMuzzle2 = false)
CreatureMuzzleFlashInfo(const Vector3& pos, int boneID, int delay, bool changeToMuzzle2 = false)
{
Bite = CreatureBiteInfo(pos, boneID);
Delay = delay;

View file

@ -149,10 +149,23 @@ bool ItemInfo::IsCreature() const
void ItemInfo::ResetModelToDefault()
{
Model.BaseMesh = Objects[ObjectNumber].meshIndex;
if (Objects[ObjectNumber].nmeshes > 0)
{
Model.MeshIndex.resize(Objects[ObjectNumber].nmeshes);
Model.BaseMesh = Objects[ObjectNumber].meshIndex;
for (int i = 0; i < Model.MeshIndex.size(); i++)
Model.MeshIndex[i] = Model.BaseMesh + i;
for (int i = 0; i < Model.MeshIndex.size(); i++)
Model.MeshIndex[i] = Model.BaseMesh + i;
Model.Mutators.resize(Objects[ObjectNumber].nmeshes);
for (auto& mutator : Model.Mutators)
mutator = {};
}
else
{
Model.Mutators.clear();
Model.MeshIndex.clear();
}
}
bool TestState(int refState, const vector<int>& stateList)
@ -239,7 +252,9 @@ void KillItem(short const itemNumber)
if (item == Lara.TargetEntity)
Lara.TargetEntity = nullptr;
if (Objects[item->ObjectNumber].floor != nullptr)
// AI target generation uses a hack with making a dummy item without ObjectNumber.
// Therefore, a check should be done here to prevent access violation.
if (item->ObjectNumber != GAME_OBJECT_ID::ID_NO_OBJECT && Objects[item->ObjectNumber].floor != nullptr)
UpdateBridgeItem(itemNumber, true);
GameScriptHandleKilled(itemNumber, true);
@ -553,20 +568,7 @@ void InitializeItem(short itemNumber)
item->Floor = floor->GetSurfaceHeight(item->Pose.Position.x, item->Pose.Position.z, true);
item->BoxNumber = floor->Box;
if (Objects[item->ObjectNumber].nmeshes > 0)
{
item->Model.MeshIndex.resize(Objects[item->ObjectNumber].nmeshes);
item->ResetModelToDefault();
item->Model.Mutators.resize(Objects[item->ObjectNumber].nmeshes);
for (auto& mutator : item->Model.Mutators)
mutator = {};
}
else
{
item->Model.Mutators.clear();
item->Model.MeshIndex.clear();
}
item->ResetModelToDefault();
if (Objects[item->ObjectNumber].Initialize != nullptr)
Objects[item->ObjectNumber].Initialize(itemNumber);
@ -710,7 +712,7 @@ ItemInfo* FindItem(GAME_OBJECT_ID objectID)
int FindItem(ItemInfo* item)
{
if (item == LaraItem)
return Lara.ItemNumber;
return item->Index;
for (int i = 0; i < g_Level.NumItems; i++)
if (item == &g_Level.Items[i])
@ -729,6 +731,9 @@ void UpdateAllItems()
auto* item = &g_Level.Items[itemNumber];
short nextItem = item->NextActive;
if (!Objects.CheckID(item->ObjectNumber))
continue;
if (item->AfterDeath <= ITEM_DEATH_TIMEOUT)
{
if (Objects[item->ObjectNumber].control)

View file

@ -75,7 +75,9 @@ void ControlMissile(short fxNumber)
else if (fx.objectNumber == ID_PROJ_BOMB)
{
SoundEffect(SFX_TR1_ATLANTEAN_EXPLODE, &fx.pos, soundFXType);
TriggerExplosionSparks(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 0, false, isUnderwater, fx.roomNumber);
TriggerExplosionSparks(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 3, -2, 0, fx.roomNumber);
TriggerExplosionSparks(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 3, -1, 0, fx.roomNumber);
TriggerShockwave(&fx.pos, 48, 304, (GetRandomControl() & 0x1F) + 112, 128, 32, 32, 32, EulerAngles(2048, 0.0f, 0.0f), 0, true, false, (int)ShockwaveStyle::Normal);
}
if (hasHitPlayer)
@ -83,24 +85,20 @@ void ControlMissile(short fxNumber)
if (fx.objectNumber == ID_KNIFETHROWER_KNIFE)
{
DoDamage(LaraItem, KNIFE_DAMAGE);
KillEffect(fxNumber);
}
else if (fx.objectNumber == ID_SCUBA_HARPOON)
{
DoDamage(LaraItem, DIVER_HARPOON_DAMAGE);
KillEffect(fxNumber);
}
else if (fx.objectNumber == ID_PROJ_BOMB)
{
DoDamage(LaraItem, MUTANT_BOMB_DAMAGE);
KillEffect(fxNumber);
}
else if (fx.objectNumber == ID_PROJ_SHARD)
{
TriggerBlood(fx.pos.Position.x, fx.pos.Position.y, fx.pos.Position.z, 0, 10);
SoundEffect(SFX_TR4_BLOOD_LOOP, &fx.pos, soundFXType);
DoDamage(LaraItem, MUTANT_SHARD_DAMAGE);
KillEffect(fxNumber);
}
LaraItem->HitStatus = true;
@ -109,6 +107,8 @@ void ControlMissile(short fxNumber)
fx.frameNumber = 0;
fx.counter = 0;
}
KillEffect(fxNumber);
}
if (pointColl.RoomNumber != fx.roomNumber)
@ -161,14 +161,14 @@ void ControlNatlaGun(short fxNumber)
fxNew.roomNumber = pointColl.RoomNumber;
fxNew.speed = fx.speed;
fxNew.frameNumber = 0;
fxNew.objectNumber = ID_PROJ_NATLA;
fxNew.objectNumber = ID_PROJ_BOMB;
}
}
}
short ShardGun(int x, int y, int z, short velocity, short yRot, short roomNumber)
{
short fxNumber = CreateNewEffect(roomNumber);
int fxNumber = CreateNewEffect(roomNumber);
if (fxNumber != NO_ITEM)
{
auto& fx = EffectList[fxNumber];
@ -188,7 +188,7 @@ short ShardGun(int x, int y, int z, short velocity, short yRot, short roomNumber
short BombGun(int x, int y, int z, short velocity, short yRot, short roomNumber)
{
short fxNumber = CreateNewEffect(roomNumber);
int fxNumber = CreateNewEffect(roomNumber);
if (fxNumber != NO_ITEM)
{
auto& fx = EffectList[fxNumber];
@ -205,23 +205,3 @@ short BombGun(int x, int y, int z, short velocity, short yRot, short roomNumber)
return fxNumber;
}
short NatlaGun(int x, int y, int z, short velocity, short yRot, short roomNumber)
{
short fxNumber = CreateNewEffect(roomNumber);
if (fxNumber != NO_ITEM)
{
auto& fx = EffectList[fxNumber];
fx.pos.Position = Vector3i(x, y, z);
fx.pos.Orientation = EulerAngles(0, yRot, 0);
fx.roomNumber = roomNumber;
fx.speed = velocity;
fx.frameNumber = 0;
fx.objectNumber = ID_PROJ_NATLA;
fx.color = Vector4::One;
ShootAtLara(fx);
}
return fxNumber;
}

View file

@ -7,4 +7,3 @@ void ControlNatlaGun(short fxNumber);
short ShardGun(int x, int y, int z, short velocity, short yRot, short roomNumber);
short BombGun(int x, int y, int z, short velocity, short yRot, short roomNumber);
short NatlaGun(int x, int y, int z, short velocity, short yRot, short roomNumber);

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