mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
Merge branch 'develop' into sezz_x64
This commit is contained in:
commit
54c5e0c70d
504 changed files with 11610 additions and 9032 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,6 +8,7 @@ TombEngine/Legacy Engine Objects
|
||||||
x64/
|
x64/
|
||||||
packages/
|
packages/
|
||||||
.vs/
|
.vs/
|
||||||
|
.vsconfig
|
||||||
*.dll
|
*.dll
|
||||||
*.dmp
|
*.dmp
|
||||||
*.id0
|
*.id0
|
||||||
|
|
|
@ -1,21 +1,61 @@
|
||||||
|
Version 1.0.9
|
||||||
|
=============
|
||||||
|
|
||||||
|
* Fix cold bar triggered in non-water rooms.
|
||||||
|
* Fix spiky wall speed value and change it via OCB number or Lua (Moveable::SetItemFlags[0]).
|
||||||
|
* Fix bats emitter crashing the game if little beetle object does not exist in wad.
|
||||||
|
* Fix gunflash rendering and position for entities.
|
||||||
|
* Fix snowmobile driver crashing the game.
|
||||||
|
* Fix knifethrower not throwing knife.
|
||||||
|
* Fix footprints not being cleared after level change.
|
||||||
|
* Fix thumbstick camera option sometimes producing jerky camera movements during object interaction.
|
||||||
|
* Fix inventory input interference when entering inventory via puzzle.
|
||||||
|
* Fix gamepad still vibrating if Lara was poisoned prior to death.
|
||||||
|
* Add TR1 cowboy.
|
||||||
|
* Add TR3 wall mounted blade.
|
||||||
|
* Add TR3 claw mutant.
|
||||||
|
* Add removable puzzles from puzzle holes and puzzle dones.
|
||||||
|
- Employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done.
|
||||||
|
- Can be mixed with puzzle done and puzzle holes of the same or different type.
|
||||||
|
* Add reusable keys for key holes.
|
||||||
|
- Employed by setting the trigger type as "Switch" for key hole.
|
||||||
|
* Allow key hole animation to be played via OCB number.
|
||||||
|
- Default OCB 0 will play Lara use key animation.
|
||||||
|
- Any positive OCB number will play the animation according to the OCB number.
|
||||||
|
* Add missing gunflash for some entities, also include dynamic light and smoke to all gunflashes.
|
||||||
|
* Add log reports if title level or other levels don't exist.
|
||||||
|
* Add better error handling for missing font, sprites or shaders.
|
||||||
|
* Add "Reset to defaults" entry to controls menu and automatically bind XBOX gamepad profile if connected.
|
||||||
|
|
||||||
|
Lua API changes:
|
||||||
|
* Add class Vec2
|
||||||
|
* Add function String::SetTranslated()
|
||||||
|
* Add function Misc::IsStringDisplaying()
|
||||||
|
* Add the following for use in AddCallback and RemoveCallback:
|
||||||
|
- PRESTART, POSTSTART
|
||||||
|
- PREEND, POSTEND
|
||||||
|
- PRESAVE, POSTSAVE
|
||||||
|
- PRELOAD, POSTLOAD
|
||||||
|
|
||||||
Version 1.0.8
|
Version 1.0.8
|
||||||
=============
|
=============
|
||||||
|
|
||||||
* Fix bubbles phasing through ceilings.
|
* Fix bubbles phasing through ceilings.
|
||||||
* Fix object camera not clearing at level end.
|
* Fix object camera not clearing at level end.
|
||||||
* Fix double breathing sound effect when coming up for air.
|
* Fix double breath sound effect when coming up for air.
|
||||||
* Fix twisting hair bug.
|
* Fix flickering hair.
|
||||||
* Fix harpoon gun triggering water and dry sounds when shooting and reholstering.
|
* Fix harpoon gun triggering water and dry sounds when shooting and reholstering.
|
||||||
* Fix Z-fighting in inventory rendering.
|
* Fix Z-fighting in inventory rendering.
|
||||||
* Fix transparent objects not displaying correctly in the Inventory.
|
* Fix transparent objects not displaying correctly in the Inventory.
|
||||||
* Fix dozy cheat always giving uzi weapons even if not present in WAD.
|
* Fix dozy cheat always giving uzi weapons even if not present in WAD.
|
||||||
* Fix player getting launched when landing close to an edge.
|
* Fix player getting launched when landing close to an edge.
|
||||||
|
* Fix player going through trapdoor/bridge while climbing up a climbable wall.
|
||||||
* Fix TR3 Sophia's charge ring drawing below floor.
|
* Fix TR3 Sophia's charge ring drawing below floor.
|
||||||
* Fix TR5 imp collision handling and animations.
|
* Fix TR5 imp collision handling and animations:
|
||||||
- OCB 1 - Climbs up to Lara when triggered.
|
- OCB 1: Climbs up to player when triggered.
|
||||||
- OCB 2 - Starts of playfully rolling on the floor when triggered.
|
- OCB 2: Starts rolling on the floor when triggered.
|
||||||
- OCB 3 - Will throw stones at Lara.
|
- OCB 3: Will throw stones at player.
|
||||||
- Imp is also scared of Lara if she has a lit torch in her hand.
|
- Imp is also scared of of the player if holding a lit torch.
|
||||||
- Please note you must use the patched version found here: https://github.com/TombEngine/Resources/blob/main/Wad2%20Objects/tr5_Imp.wad2
|
- Please note you must use the patched version found here: https://github.com/TombEngine/Resources/blob/main/Wad2%20Objects/tr5_Imp.wad2
|
||||||
* Fix and improve wraith tails.
|
* Fix and improve wraith tails.
|
||||||
* Add dedicated WRAITH_TRAP object with enhanced effects.
|
* Add dedicated WRAITH_TRAP object with enhanced effects.
|
||||||
|
@ -24,22 +64,23 @@ Version 1.0.8
|
||||||
* Add TR1 slamming doors.
|
* Add TR1 slamming doors.
|
||||||
* Add TR3 mutant wasp (AI_MODIFY object won't allow it to land, the wasp will always fly).
|
* Add TR3 mutant wasp (AI_MODIFY object won't allow it to land, the wasp will always fly).
|
||||||
* Add TR3 Corpse
|
* Add TR3 Corpse
|
||||||
- OCB 0: used for coprses targeted by the compsoganathus dinosaur.
|
- OCB 0: used for coprses targeted by the compsognathus dinosaur.
|
||||||
- OCB 1: used for corpses hung in the air to be used as piranha bait. Will fall when shot.
|
- OCB 1: used for corpses hung in the air to be used as piranha bait. Will fall when shot.
|
||||||
- Please note you must use the patched version found here: https://github.com/TombEngine/Resources/blob/main/Wad2%20Objects/tr3_Compsognathus_Cadavar.wad2
|
- Please note you must use the patched version found here: https://github.com/TombEngine/Resources/blob/main/Wad2%20Objects/tr3_Compsognathus_Cadavar.wad2
|
||||||
* Add cold exposure bar (employed by setting the "cold" flag in water rooms in Tomb Editor).
|
* Add cold exposure bar (employed by setting the "cold" flag in water rooms in Tomb Editor).
|
||||||
* Add water wakes for vehicles.
|
* Add water wakes for vehicles.
|
||||||
* Allow dynamic segment count of hair object.
|
* Restored light effect nullmeshes (color, electrical, pulse, and strobe):
|
||||||
* Restored light effect nullmeshes (color, electrical, pulse and strobe):
|
- Select the light color as object tint in the OCB menu in Tomb Editor.
|
||||||
- Select the color the light should emit as object tint in OCB menu in Tomb editor.
|
|
||||||
- ELECTRICAL_LIGHT:
|
- ELECTRICAL_LIGHT:
|
||||||
- OCB 1: Displays mesh of object.
|
- Can have multiple meshes. Add mesh number to OCB to be renderd with the light.
|
||||||
- OCB -1: Hides mesh of object (used for a neon light effect)
|
- OCB + (mesh number): Light behaves like a neon light.
|
||||||
|
- OCB – (mesh number): Light flickers.
|
||||||
* Restored inventory compass.
|
* Restored inventory compass.
|
||||||
|
* Allow dynamic segment count for hair object.
|
||||||
|
|
||||||
Lua API changes:
|
Lua API changes:
|
||||||
* Add new function Misc::IsSoundPlaying()
|
* Add function Misc::IsSoundPlaying()
|
||||||
|
* Add function DisplayString::SetFlags()
|
||||||
|
|
||||||
Version 1.0.7
|
Version 1.0.7
|
||||||
=============
|
=============
|
||||||
|
|
|
@ -12,7 +12,7 @@ new_type("luautil", "5 Lua utility modules", true)
|
||||||
|
|
||||||
not_luadoc = true
|
not_luadoc = true
|
||||||
|
|
||||||
local version = "1.0.8"
|
local version = "1.0.9"
|
||||||
project = "TombEngine"
|
project = "TombEngine"
|
||||||
title = "TombEngine " .. version .. " Lua API"
|
title = "TombEngine " .. version .. " Lua API"
|
||||||
description = "TombEngine " .. version .. " scripting interface"
|
description = "TombEngine " .. version .. " scripting interface"
|
||||||
|
|
|
@ -128,6 +128,10 @@ when you need to use screen-space coordinates.</p>
|
||||||
<td class="name" ><a href="#DisplayString:GetPosition">DisplayString:GetPosition()</a></td>
|
<td class="name" ><a href="#DisplayString:GetPosition">DisplayString:GetPosition()</a></td>
|
||||||
<td class="summary">Get the position of the string.</td>
|
<td class="summary">Get the position of the string.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" ><a href="#DisplayString:SetFlags">DisplayString:SetFlags(table)</a></td>
|
||||||
|
<td class="summary">Set the display string's flags</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -250,7 +254,7 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
||||||
<h3>Returns:</h3>
|
<h3>Returns:</h3>
|
||||||
<ol>
|
<ol>
|
||||||
|
|
||||||
<span class="types"><span class="type">String</span></span>
|
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
|
||||||
a string
|
a string
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
@ -272,7 +276,7 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
||||||
<h3>Parameters:</h3>
|
<h3>Parameters:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><span class="parameter">string</span>
|
<li><span class="parameter">string</span>
|
||||||
<span class="types"><span class="type">String</span></span>
|
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.4">string</a></span>
|
||||||
the new key for the display string
|
the new key for the display string
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -333,6 +337,38 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "DisplayString:SetFlags"></a>
|
||||||
|
<strong>DisplayString:SetFlags(table)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Set the display string's flags
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">table</span>
|
||||||
|
<span class="types"><a class="type" href="https://www.lua.org/manual/5.4/manual.html#6.6">table</a></span>
|
||||||
|
the new table with display flags options
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Usage:</h3>
|
||||||
|
<ul>
|
||||||
|
<pre class="example"><span class="keyword">local</span> varDisplayString = DisplayString(<span class="string">'example string'</span>, <span class="number">0</span>, <span class="number">0</span>, Color(<span class="number">255</span>, <span class="number">255</span>, <span class="number">255</span>), <span class="keyword">false</span>)
|
||||||
|
varDisplayString:SetFlags({})
|
||||||
|
varDisplayString:SetFlags({ TEN.Strings.DisplayStringOption.SHADOW })
|
||||||
|
varDisplayString:SetFlags({ TEN.Strings.DisplayStringOption.CENTER })
|
||||||
|
varDisplayString:SetFlags({ TEN.Strings.DisplayStringOption.SHADOW, TEN.Strings.DisplayStringOption.CENTER })
|
||||||
|
<span class="comment">-- When passing a table to a function, you can omit the parentheses
|
||||||
|
</span>varDisplayString:SetFlags{ TEN.Strings.DisplayStringOption.CENTER }</pre>
|
||||||
|
</ul>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
@ -341,7 +377,7 @@ TEN.Strings.DisplayStringOption.SHADOW -- will give the text a small shadow
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<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>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-03-31 20:44:31 </i>
|
<i style="float:right;">Last updated 2023-04-11 21:28:36 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
265
Documentation/doc/3 primitive classes/Vec2.html
Normal file
265
Documentation/doc/3 primitive classes/Vec2.html
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
<!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.0.8 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> <here>Vec2</here></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/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>Primitive Class <code>Vec2</code></h1>
|
||||||
|
<p>Represents a 2D vector.</p>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h2><a href="#Members">Members</a></h2>
|
||||||
|
<table class="function_list">
|
||||||
|
<tr>
|
||||||
|
<td class="name" ><a href="#x">x</a></td>
|
||||||
|
<td class="summary">(int) x coordinate</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" ><a href="#y">y</a></td>
|
||||||
|
<td class="summary">(int) y coordinate</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<h2><a href="#Functions">Functions</a></h2>
|
||||||
|
<table class="function_list">
|
||||||
|
<tr>
|
||||||
|
<td class="name" ><a href="#Vec3:GetNormalised">Vec3:GetNormalised(length)</a></td>
|
||||||
|
<td class="summary">Modify this vector so that it becomes close to the requested length.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" ><a href="#Vec2">Vec2(X, Y)</a></td>
|
||||||
|
<td class="summary">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="name" ><a href="#__tostring">__tostring(Vec2)</a></td>
|
||||||
|
<td class="summary">Metafunction; use tostring(myVector)</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 class="section-header "><a name="Members"></a>Members</h2>
|
||||||
|
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a name = "x"></a>
|
||||||
|
<strong>x</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
(int) x coordinate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "y"></a>
|
||||||
|
<strong>y</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
(int) y coordinate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
|
||||||
|
|
||||||
|
<dl class="function">
|
||||||
|
<dt>
|
||||||
|
<a name = "Vec3:GetNormalised"></a>
|
||||||
|
<strong>Vec3:GetNormalised(length)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Modify this vector so that it becomes close to the requested length. </p>
|
||||||
|
|
||||||
|
<p>Note that since the engine uses integers instead of floating-point
|
||||||
|
numbers, this will be less accurate at smaller lengths.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">length</span>
|
||||||
|
<span class="types"><span class="type">int</span></span>
|
||||||
|
the new length to set the vector to.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "Vec2"></a>
|
||||||
|
<strong>Vec2(X, Y)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">X</span>
|
||||||
|
<span class="types"><span class="type">int</span></span>
|
||||||
|
x coordinate
|
||||||
|
</li>
|
||||||
|
<li><span class="parameter">Y</span>
|
||||||
|
<span class="types"><span class="type">int</span></span>
|
||||||
|
y coordinate
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
|
||||||
|
A Vec2 object.
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "__tostring"></a>
|
||||||
|
<strong>__tostring(Vec2)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Metafunction; use tostring(myVector)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">Vec2</span>
|
||||||
|
<span class="types"><a class="type" href="../3 primitive classes/Vec2.html#">Vec2</a></span>
|
||||||
|
this Vec2
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
A string showing the x, y, and z values of the Vec2
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</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-05-02 19:28:45 </i>
|
||||||
|
</div> <!-- id="about" -->
|
||||||
|
</div> <!-- id="container" -->
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -3825,7 +3825,7 @@ __Default: empty__</description>
|
||||||
If false or omitted, this will be the string that's displayed.</description>
|
If false or omitted, this will be the string that's displayed.</description>
|
||||||
<returns>
|
<returns>
|
||||||
<return>
|
<return>
|
||||||
<type>String</type>
|
<type>string</type>
|
||||||
<description>a string</description>
|
<description>a string</description>
|
||||||
</return>
|
</return>
|
||||||
</returns>
|
</returns>
|
||||||
|
@ -3842,7 +3842,7 @@ __Default: empty__</description>
|
||||||
<parameters>
|
<parameters>
|
||||||
<parameter>
|
<parameter>
|
||||||
<name>string</name>
|
<name>string</name>
|
||||||
<type>String</type>
|
<type>string</type>
|
||||||
<description>the new key for the display string</description>
|
<description>the new key for the display string</description>
|
||||||
</parameter>
|
</parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
|
@ -3886,6 +3886,20 @@ __Default: empty__</description>
|
||||||
</returns>
|
</returns>
|
||||||
</function>
|
</function>
|
||||||
|
|
||||||
|
<function>
|
||||||
|
<module>Strings.DisplayString</module>
|
||||||
|
<caller>DisplayString</caller>
|
||||||
|
<name>SetFlags</name>
|
||||||
|
<summary>Set the display string's flags</summary>
|
||||||
|
<parameters>
|
||||||
|
<parameter>
|
||||||
|
<name>table</name>
|
||||||
|
<type>table</type>
|
||||||
|
<description>the new table with display flags options</description>
|
||||||
|
</parameter>
|
||||||
|
</parameters>
|
||||||
|
</function>
|
||||||
|
|
||||||
<function>
|
<function>
|
||||||
<module>Strings</module>
|
<module>Strings</module>
|
||||||
<name>ShowString</name>
|
<name>ShowString</name>
|
||||||
|
|
|
@ -277,7 +277,7 @@ Timer = {
|
||||||
|
|
||||||
--- Get the total time for a timer.
|
--- Get the total time for a timer.
|
||||||
-- This is the amount of time the timer will start with, as well as when starting a new loop
|
-- This is the amount of time the timer will start with, as well as when starting a new loop
|
||||||
-- @function myTimer:GetRemainingTime
|
-- @function myTimer:GetTotalTime
|
||||||
-- @treturn float the timer's total time
|
-- @treturn float the timer's total time
|
||||||
GetTotalTime = function(t)
|
GetTotalTime = function(t)
|
||||||
return LevelVars.Engine.Timer.timers[t.name].totalTime
|
return LevelVars.Engine.Timer.timers[t.name].totalTime
|
||||||
|
|
|
@ -347,8 +347,8 @@ namespace TEN::Gui
|
||||||
if (lara->Control.HandStatus != HandStatus::Free &&
|
if (lara->Control.HandStatus != HandStatus::Free &&
|
||||||
lara->Control.Weapon.GunType == LaraWeaponType::Revolver)
|
lara->Control.Weapon.GunType == LaraWeaponType::Revolver)
|
||||||
{
|
{
|
||||||
UndrawPistolMeshRight(item, LaraWeaponType::Revolver);
|
UndrawPistolMesh(*item, LaraWeaponType::Revolver, true);
|
||||||
DrawPistolMeshes(item, LaraWeaponType::Revolver);
|
DrawPistolMeshes(*item, LaraWeaponType::Revolver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,8 +370,8 @@ namespace TEN::Gui
|
||||||
if (lara->Control.HandStatus != HandStatus::Free &&
|
if (lara->Control.HandStatus != HandStatus::Free &&
|
||||||
lara->Control.Weapon.GunType == LaraWeaponType::Crossbow)
|
lara->Control.Weapon.GunType == LaraWeaponType::Crossbow)
|
||||||
{
|
{
|
||||||
UndrawShotgunMeshes(item, LaraWeaponType::Crossbow);
|
UndrawShotgunMeshes(*item, LaraWeaponType::Crossbow);
|
||||||
DrawShotgunMeshes(item, LaraWeaponType::Crossbow);
|
DrawShotgunMeshes(*item, LaraWeaponType::Crossbow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,8 +393,8 @@ namespace TEN::Gui
|
||||||
if (lara->Control.HandStatus != HandStatus::Free &&
|
if (lara->Control.HandStatus != HandStatus::Free &&
|
||||||
lara->Control.Weapon.GunType == LaraWeaponType::HK)
|
lara->Control.Weapon.GunType == LaraWeaponType::HK)
|
||||||
{
|
{
|
||||||
UndrawShotgunMeshes(item, LaraWeaponType::HK);
|
UndrawShotgunMeshes(*item, LaraWeaponType::HK);
|
||||||
DrawShotgunMeshes(item, LaraWeaponType::HK);
|
DrawShotgunMeshes(*item, LaraWeaponType::HK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,21 @@ namespace TEN::Hud
|
||||||
{
|
{
|
||||||
HudController g_Hud = {};
|
HudController g_Hud = {};
|
||||||
|
|
||||||
void HudController::Update(ItemInfo& item)
|
void HudController::Update(const ItemInfo& item)
|
||||||
{
|
{
|
||||||
this->PickupSummary.Update();
|
PickupSummary.Update();
|
||||||
this->StatusBars.Update(item);
|
StatusBars.Update(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HudController::Draw(ItemInfo& item) const
|
void HudController::Draw(const ItemInfo& item) const
|
||||||
{
|
{
|
||||||
this->PickupSummary.Draw();
|
PickupSummary.Draw();
|
||||||
this->StatusBars.Draw(item);
|
StatusBars.Draw(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HudController::Clear()
|
void HudController::Clear()
|
||||||
{
|
{
|
||||||
this->PickupSummary.Clear();
|
PickupSummary.Clear();
|
||||||
this->StatusBars.Clear();
|
StatusBars.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,13 @@ namespace TEN::Hud
|
||||||
class HudController
|
class HudController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Components
|
// Members
|
||||||
StatusBarsController StatusBars = {};
|
StatusBarsController StatusBars = {};
|
||||||
PickupSummaryController PickupSummary = {};
|
PickupSummaryController PickupSummary = {};
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
void Update(ItemInfo& item);
|
void Update(const ItemInfo& item);
|
||||||
void Draw(ItemInfo& item) const;
|
void Draw(const ItemInfo& item) const;
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,22 +12,50 @@
|
||||||
|
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
|
|
||||||
extern TEN::Renderer::RendererHudBar* g_AirBar;
|
extern RendererHudBar* g_AirBar;
|
||||||
extern TEN::Renderer::RendererHudBar* g_ExposureBar;
|
extern RendererHudBar* g_ExposureBar;
|
||||||
extern TEN::Renderer::RendererHudBar* g_HealthBar;
|
extern RendererHudBar* g_HealthBar;
|
||||||
extern TEN::Renderer::RendererHudBar* g_StaminaBar;
|
extern RendererHudBar* g_StaminaBar;
|
||||||
|
|
||||||
namespace TEN::Hud
|
namespace TEN::Hud
|
||||||
{
|
{
|
||||||
|
void StatusBar::Initialize(float value)
|
||||||
|
{
|
||||||
|
Value =
|
||||||
|
TargetValue = std::clamp(value, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatusBar::Update(float value)
|
||||||
|
{
|
||||||
|
constexpr auto LIFE_START_FADING = 0.2f;
|
||||||
|
constexpr auto LERP_ALPHA = 0.3f;
|
||||||
|
|
||||||
|
// Update life.
|
||||||
|
if (Life > 0.0f)
|
||||||
|
Life -= 1.0f;
|
||||||
|
|
||||||
|
// Update opacity.
|
||||||
|
float alpha = std::clamp(Life, 0.0f, LIFE_START_FADING) / LIFE_START_FADING;
|
||||||
|
Opacity = Lerp(0.0f, 1.0f, alpha);
|
||||||
|
|
||||||
|
// Update target value.
|
||||||
|
TargetValue = std::clamp(value, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// Update value.
|
||||||
|
Value = Lerp(Value, TargetValue, LERP_ALPHA);
|
||||||
|
if (abs(Value - TargetValue) <= EPSILON)
|
||||||
|
Value = TargetValue;
|
||||||
|
}
|
||||||
|
|
||||||
void StatusBarsController::Initialize(const ItemInfo& item)
|
void StatusBarsController::Initialize(const ItemInfo& item)
|
||||||
{
|
{
|
||||||
const auto& player = GetLaraInfo(item);
|
const auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
// Initialize bar values.
|
// Initialize bar values.
|
||||||
InitializeStatusBar(AirBar, player.Status.Air, LARA_AIR_MAX);
|
AirBar.Initialize(player.Status.Air / LARA_AIR_MAX);
|
||||||
InitializeStatusBar(ExposureBar, player.Status.Exposure, LARA_EXPOSURE_MAX);
|
ExposureBar.Initialize(player.Status.Exposure / LARA_EXPOSURE_MAX);
|
||||||
InitializeStatusBar(HealthBar, item.HitPoints, LARA_HEALTH_MAX);
|
HealthBar.Initialize(item.HitPoints / LARA_HEALTH_MAX);
|
||||||
InitializeStatusBar(StaminaBar, player.Status.Stamina, LARA_STAMINA_MAX);
|
StaminaBar.Initialize(player.Status.Stamina / LARA_STAMINA_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBarsController::Update(const ItemInfo& item)
|
void StatusBarsController::Update(const ItemInfo& item)
|
||||||
|
@ -66,52 +94,26 @@ namespace TEN::Hud
|
||||||
*this = {};
|
*this = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusBarsController::InitializeStatusBar(StatusBar& bar, float statusValue, float statusValueMax)
|
|
||||||
{
|
|
||||||
float statusValueNorm = std::clamp(statusValue, 0.0f, statusValueMax);
|
|
||||||
bar.Value = statusValueNorm / statusValueMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBarsController::UpdateStatusBar(StatusBar& bar, float statusValue, float statusValueMax)
|
|
||||||
{
|
|
||||||
// Update life.
|
|
||||||
if (bar.Life > 0.0f)
|
|
||||||
bar.Life -= 1.0f;
|
|
||||||
|
|
||||||
// Update opacity.
|
|
||||||
float alpha = std::clamp(bar.Life, 0.0f, STATUS_BAR_LIFE_START_FADING) / STATUS_BAR_LIFE_START_FADING;
|
|
||||||
bar.Opacity = Lerp(0.0f, 1.0f, alpha);
|
|
||||||
|
|
||||||
// Update target value.
|
|
||||||
float statusValueNorm = std::clamp(statusValue, 0.0f, statusValueMax);
|
|
||||||
bar.TargetValue = statusValueNorm / statusValueMax;
|
|
||||||
|
|
||||||
// Update value.
|
|
||||||
bar.Value = Lerp(bar.Value, bar.TargetValue, STATUS_BAR_VALUE_LERP_ALPHA);
|
|
||||||
if (abs(bar.Value - bar.TargetValue) <= EPSILON)
|
|
||||||
bar.Value = bar.TargetValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StatusBarsController::UpdateAirBar(const ItemInfo& item)
|
void StatusBarsController::UpdateAirBar(const ItemInfo& item)
|
||||||
{
|
{
|
||||||
const auto& player = GetLaraInfo(item);
|
const auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
// Update generic data.
|
// Update generic data.
|
||||||
UpdateStatusBar(AirBar, player.Status.Air, LARA_AIR_MAX);
|
AirBar.Update(player.Status.Air / LARA_AIR_MAX);
|
||||||
|
|
||||||
// Update life.
|
// Update life.
|
||||||
if (AirBar.Value != AirBar.TargetValue ||
|
if (AirBar.Value != AirBar.TargetValue ||
|
||||||
player.Control.WaterStatus == WaterStatus::Underwater)
|
player.Control.WaterStatus == WaterStatus::Underwater)
|
||||||
{
|
{
|
||||||
AirBar.Life = round(STATUS_BAR_LIFE_MAX * FPS);
|
AirBar.Life = round(StatusBar::LIFE_MAX * FPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Special case for UPV as it sets player.Control.WaterStatus to WaterStatus::Dry.
|
// HACK: Special case for UPV as it sets player.Control.WaterStatus to WaterStatus::Dry.
|
||||||
if (player.Vehicle != NO_ITEM)
|
if (player.Context.Vehicle != NO_ITEM)
|
||||||
{
|
{
|
||||||
const auto& vehicleItem = g_Level.Items[player.Vehicle];
|
const auto& vehicleItem = g_Level.Items[player.Context.Vehicle];
|
||||||
if (vehicleItem.ObjectNumber == ID_UPV)
|
if (vehicleItem.ObjectNumber == ID_UPV)
|
||||||
AirBar.Life = round(STATUS_BAR_LIFE_MAX * FPS);
|
AirBar.Life = round(StatusBar::LIFE_MAX * FPS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +122,13 @@ namespace TEN::Hud
|
||||||
const auto& player = GetLaraInfo(item);
|
const auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
// Update generic data.
|
// Update generic data.
|
||||||
UpdateStatusBar(ExposureBar, player.Status.Exposure, LARA_EXPOSURE_MAX);
|
ExposureBar.Update(player.Status.Exposure / LARA_EXPOSURE_MAX);
|
||||||
|
|
||||||
// Update life.
|
// Update life.
|
||||||
if (ExposureBar.Value != ExposureBar.TargetValue ||
|
if (ExposureBar.Value != ExposureBar.TargetValue ||
|
||||||
(TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) && TestEnvironment(ENV_FLAG_COLD, item.RoomNumber)))
|
(TestEnvironment(ENV_FLAG_WATER, item.RoomNumber) && TestEnvironment(ENV_FLAG_COLD, item.RoomNumber)))
|
||||||
{
|
{
|
||||||
ExposureBar.Life = round(STATUS_BAR_LIFE_MAX * FPS);
|
ExposureBar.Life = round(StatusBar::LIFE_MAX * FPS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +137,7 @@ namespace TEN::Hud
|
||||||
const auto& player = GetLaraInfo(item);
|
const auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
// Update generic data.
|
// Update generic data.
|
||||||
UpdateStatusBar(HealthBar, item.HitPoints, LARA_HEALTH_MAX);
|
HealthBar.Update(item.HitPoints / LARA_HEALTH_MAX);
|
||||||
|
|
||||||
// Update life.
|
// Update life.
|
||||||
if (HealthBar.Value != HealthBar.TargetValue ||
|
if (HealthBar.Value != HealthBar.TargetValue ||
|
||||||
|
@ -145,7 +147,7 @@ namespace TEN::Hud
|
||||||
(player.Control.HandStatus == HandStatus::WeaponReady &&
|
(player.Control.HandStatus == HandStatus::WeaponReady &&
|
||||||
player.Control.Weapon.GunType != LaraWeaponType::Torch)) // HACK: Exclude torch.
|
player.Control.Weapon.GunType != LaraWeaponType::Torch)) // HACK: Exclude torch.
|
||||||
{
|
{
|
||||||
HealthBar.Life = round(STATUS_BAR_LIFE_MAX * FPS);
|
HealthBar.Life = round(StatusBar::LIFE_MAX * FPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for weapon undraw.
|
// Special case for weapon undraw.
|
||||||
|
@ -153,7 +155,7 @@ namespace TEN::Hud
|
||||||
item.HitPoints > LARA_HEALTH_CRITICAL && player.Status.Poison == 0 &&
|
item.HitPoints > LARA_HEALTH_CRITICAL && player.Status.Poison == 0 &&
|
||||||
player.Control.HandStatus == HandStatus::WeaponUndraw)
|
player.Control.HandStatus == HandStatus::WeaponUndraw)
|
||||||
{
|
{
|
||||||
HealthBar.Life = 0;// round(STATUS_BAR_LIFE_START_FADING * FPS);
|
HealthBar.Life = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,13 +164,13 @@ namespace TEN::Hud
|
||||||
const auto& player = GetLaraInfo(item);
|
const auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
// Update generic data.
|
// Update generic data.
|
||||||
UpdateStatusBar(StaminaBar, player.Status.Stamina, LARA_STAMINA_MAX);
|
StaminaBar.Update(player.Status.Stamina / LARA_STAMINA_MAX);
|
||||||
|
|
||||||
// Update life.
|
// Update life.
|
||||||
if (StaminaBar.Value != StaminaBar.TargetValue ||
|
if (StaminaBar.Value != StaminaBar.TargetValue ||
|
||||||
StaminaBar.Value != 1.0f)
|
StaminaBar.Value != 1.0f)
|
||||||
{
|
{
|
||||||
StaminaBar.Life = round(STATUS_BAR_LIFE_MAX * FPS);
|
StaminaBar.Life = round(StatusBar::LIFE_MAX * FPS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,30 +2,28 @@
|
||||||
|
|
||||||
enum GAME_OBJECT_ID : short;
|
enum GAME_OBJECT_ID : short;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
namespace TEN::Renderer { struct RendererHudBar; }
|
||||||
|
|
||||||
namespace TEN::Renderer
|
using namespace TEN::Renderer;
|
||||||
{
|
|
||||||
struct RendererHudBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace TEN::Hud
|
namespace TEN::Hud
|
||||||
{
|
{
|
||||||
struct StatusBar
|
struct StatusBar
|
||||||
{
|
{
|
||||||
|
static constexpr auto LIFE_MAX = 0.75f;
|
||||||
|
|
||||||
float Value = 0.0f;
|
float Value = 0.0f;
|
||||||
float TargetValue = 0.0f;
|
float TargetValue = 0.0f;
|
||||||
float Life = 0.0f;
|
float Life = 0.0f;
|
||||||
float Opacity = 0.0f; // TODO: Opacity in renderer.
|
float Opacity = 0.0f; // TODO: Opacity in renderer.
|
||||||
|
|
||||||
|
void Initialize(float value);
|
||||||
|
void Update(float value);
|
||||||
};
|
};
|
||||||
|
|
||||||
class StatusBarsController
|
class StatusBarsController
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// Constants
|
|
||||||
static constexpr auto STATUS_BAR_LIFE_MAX = 0.75f;
|
|
||||||
static constexpr auto STATUS_BAR_LIFE_START_FADING = 0.2f;
|
|
||||||
static constexpr auto STATUS_BAR_VALUE_LERP_ALPHA = 0.3f;
|
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
StatusBar AirBar = {};
|
StatusBar AirBar = {};
|
||||||
StatusBar ExposureBar = {};
|
StatusBar ExposureBar = {};
|
||||||
|
@ -42,18 +40,14 @@ namespace TEN::Hud
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Initializer helpers
|
|
||||||
void InitializeStatusBar(StatusBar& bar, float statusValue, float statusValueMax);
|
|
||||||
|
|
||||||
// Update helpers
|
// Update helpers
|
||||||
void UpdateStatusBar(StatusBar& bar, float statusValue, float statusValueMax);
|
|
||||||
void UpdateAirBar(const ItemInfo& item);
|
void UpdateAirBar(const ItemInfo& item);
|
||||||
void UpdateExposureBar(const ItemInfo& item);
|
void UpdateExposureBar(const ItemInfo& item);
|
||||||
void UpdateHealthBar(const ItemInfo& item);
|
void UpdateHealthBar(const ItemInfo& item);
|
||||||
void UpdateStaminaBar(const ItemInfo& item);
|
void UpdateStaminaBar(const ItemInfo& item);
|
||||||
|
|
||||||
// Draw helpers
|
// Draw helpers
|
||||||
void DrawStatusBar(float value, float criticalValue, const TEN::Renderer::RendererHudBar& rHudBar, GAME_OBJECT_ID textureID, int frame, bool isPoisoned) const;
|
void DrawStatusBar(float value, float criticalValue, const RendererHudBar& rHudBar, GAME_OBJECT_ID textureID, int frame, bool isPoisoned) const;
|
||||||
void DrawAirBar() const;
|
void DrawAirBar() const;
|
||||||
void DrawExposureBar() const;
|
void DrawExposureBar() const;
|
||||||
void DrawHealthBar(bool isPoisoned) const;
|
void DrawHealthBar(bool isPoisoned) const;
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
using namespace TEN::Control::Volumes;
|
using namespace TEN::Control::Volumes;
|
||||||
using namespace TEN::Effects::Hair;
|
using namespace TEN::Effects::Hair;
|
||||||
using namespace TEN::Effects::Items;
|
using namespace TEN::Effects::Items;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
@ -232,6 +232,22 @@ std::function<LaraRoutineFunction> lara_control_routines[NUM_LARA_STATES + 1] =
|
||||||
lara_as_crouch_turn_180,//171
|
lara_as_crouch_turn_180,//171
|
||||||
lara_as_crawl_turn_180,//172
|
lara_as_crawl_turn_180,//172
|
||||||
lara_as_turn_180,//173
|
lara_as_turn_180,//173
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_null,
|
||||||
|
lara_as_use_puzzle,//189
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1] =
|
std::function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1] =
|
||||||
|
@ -410,6 +426,22 @@ std::function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1]
|
||||||
lara_col_crouch_turn_180,//171
|
lara_col_crouch_turn_180,//171
|
||||||
lara_col_crawl_turn_180,//172
|
lara_col_crawl_turn_180,//172
|
||||||
lara_col_turn_180,//173
|
lara_col_turn_180,//173
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_void_func,
|
||||||
|
lara_default_col,//189
|
||||||
};
|
};
|
||||||
|
|
||||||
void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
@ -479,12 +511,12 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
heightFromWater = item->Pose.Position.y - waterHeight;
|
heightFromWater = item->Pose.Position.y - waterHeight;
|
||||||
else
|
else
|
||||||
heightFromWater = NO_HEIGHT;
|
heightFromWater = NO_HEIGHT;
|
||||||
lara->WaterSurfaceDist = -heightFromWater;
|
lara->Context.WaterSurfaceDist = -heightFromWater;
|
||||||
|
|
||||||
if (lara->Vehicle == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM)
|
||||||
WadeSplash(item, waterHeight, waterDepth);
|
WadeSplash(item, waterHeight, waterDepth);
|
||||||
|
|
||||||
if (lara->Vehicle == NO_ITEM && lara->ExtraAnim == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM && lara->ExtraAnim == NO_ITEM)
|
||||||
{
|
{
|
||||||
switch (lara->Control.WaterStatus)
|
switch (lara->Control.WaterStatus)
|
||||||
{
|
{
|
||||||
|
@ -534,7 +566,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
item->Pose.Orientation.x = -ANGLE(45.0f);
|
item->Pose.Orientation.x = -ANGLE(45.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
Splash(item);
|
Splash(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,8 +623,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (waterDepth == NO_HEIGHT || abs(heightFromWater) >= CLICK(1))
|
if (waterDepth == NO_HEIGHT || abs(heightFromWater) >= CLICK(1))
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_FALL_START);
|
SetAnimation(item, LA_FALL_START);
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
item->Animation.IsAirborne = true;
|
item->Animation.IsAirborne = true;
|
||||||
item->Animation.Velocity.z = item->Animation.Velocity.y;
|
item->Animation.Velocity.z = item->Animation.Velocity.y;
|
||||||
item->Animation.Velocity.y = 0.0f;
|
item->Animation.Velocity.y = 0.0f;
|
||||||
|
@ -601,8 +633,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_UNDERWATER_RESURFACE);
|
SetAnimation(item, LA_UNDERWATER_RESURFACE);
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
item->Animation.Velocity.y = 0.0f;
|
item->Animation.Velocity.y = 0.0f;
|
||||||
item->Pose.Position.y = waterHeight;
|
item->Pose.Position.y = waterHeight;
|
||||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||||
|
@ -614,8 +646,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_UNDERWATER_RESURFACE);
|
SetAnimation(item, LA_UNDERWATER_RESURFACE);
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
item->Animation.Velocity.y = 0.0f;
|
item->Animation.Velocity.y = 0.0f;
|
||||||
item->Pose.Position.y = waterHeight + 1;
|
item->Pose.Position.y = waterHeight + 1;
|
||||||
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
lara->Control.WaterStatus = WaterStatus::TreadWater;
|
||||||
|
@ -641,8 +673,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
lara->Control.WaterStatus = WaterStatus::Wade;
|
lara->Control.WaterStatus = WaterStatus::Wade;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
item->Animation.Velocity.y = 0.0f;
|
item->Animation.Velocity.y = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,8 +688,8 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (heightFromWater > SWIM_DEPTH && !isSwamp)
|
if (heightFromWater > SWIM_DEPTH && !isSwamp)
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_ONWATER_IDLE);
|
SetAnimation(item, LA_ONWATER_IDLE);
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
item->Animation.IsAirborne = false;
|
item->Animation.IsAirborne = false;
|
||||||
item->Animation.Velocity.y = 0.0f;
|
item->Animation.Velocity.y = 0.0f;
|
||||||
item->Pose.Position.y += 1 - heightFromWater;
|
item->Pose.Position.y += 1 - heightFromWater;
|
||||||
|
@ -702,7 +734,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
case WaterStatus::Dry:
|
case WaterStatus::Dry:
|
||||||
case WaterStatus::Wade:
|
case WaterStatus::Wade:
|
||||||
if (isSwamp && lara->WaterSurfaceDist < -(LARA_HEIGHT + 8)) // TODO: Find best height. @Sezz 2021.11.10
|
if (isSwamp && lara->Context.WaterSurfaceDist < -(LARA_HEIGHT + 8)) // TODO: Find best height. @Sezz 2021.11.10
|
||||||
{
|
{
|
||||||
if (item->HitPoints >= 0)
|
if (item->HitPoints >= 0)
|
||||||
{
|
{
|
||||||
|
@ -717,7 +749,7 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
else if (lara->Status.Air < LARA_AIR_MAX && item->HitPoints >= 0)
|
else if (lara->Status.Air < LARA_AIR_MAX && item->HitPoints >= 0)
|
||||||
{
|
{
|
||||||
// HACK: Special case for UPV.
|
// HACK: Special case for UPV.
|
||||||
if (lara->Vehicle == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM)
|
||||||
{
|
{
|
||||||
lara->Status.Air += 10;
|
lara->Status.Air += 10;
|
||||||
if (lara->Status.Air > LARA_AIR_MAX)
|
if (lara->Status.Air > LARA_AIR_MAX)
|
||||||
|
@ -730,23 +762,23 @@ void LaraControl(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (lara->Control.WaterStatus == WaterStatus::Dry)
|
if (lara->Control.WaterStatus == WaterStatus::Dry)
|
||||||
{
|
{
|
||||||
// HACK: Special case for UPV.
|
// HACK: Special case for UPV.
|
||||||
if (lara->Vehicle != NO_ITEM)
|
if (lara->Context.Vehicle != NO_ITEM)
|
||||||
{
|
{
|
||||||
auto& vehicleItem = g_Level.Items[lara->Vehicle];
|
auto& vehicleItem = g_Level.Items[lara->Context.Vehicle];
|
||||||
if (vehicleItem.ObjectNumber == ID_UPV)
|
if (vehicleItem.ObjectNumber == ID_UPV)
|
||||||
{
|
{
|
||||||
auto pointColl = GetCollision(item, 0, 0, CLICK(1));
|
auto pointColl = GetCollision(item, 0, 0, CLICK(1));
|
||||||
isCold = isCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCold)
|
isCold = isCold || TestEnvironment(ENV_FLAG_COLD, pointColl.RoomNumber);
|
||||||
{
|
if (isCold)
|
||||||
lara->Status.Exposure--;
|
{
|
||||||
if (lara->Status.Exposure <= 0)
|
lara->Status.Exposure--;
|
||||||
{
|
if (lara->Status.Exposure <= 0)
|
||||||
lara->Status.Exposure = 0;
|
{
|
||||||
item->HitPoints -= 10;
|
lara->Status.Exposure = 0;
|
||||||
|
item->HitPoints -= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -853,6 +885,7 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
|
||||||
coll->Setup.EnableSpasm = true;
|
coll->Setup.EnableSpasm = true;
|
||||||
|
|
||||||
coll->Setup.OldPosition = item->Pose.Position;
|
coll->Setup.OldPosition = item->Pose.Position;
|
||||||
|
coll->Setup.PrevAnimObjectID = item->Animation.AnimObjectID;
|
||||||
coll->Setup.OldAnimNumber = item->Animation.AnimNumber;
|
coll->Setup.OldAnimNumber = item->Animation.AnimNumber;
|
||||||
coll->Setup.OldFrameNumber = item->Animation.FrameNumber;
|
coll->Setup.OldFrameNumber = item->Animation.FrameNumber;
|
||||||
coll->Setup.OldState = item->Animation.ActiveState;
|
coll->Setup.OldState = item->Animation.ActiveState;
|
||||||
|
@ -889,12 +922,12 @@ void LaraAboveWater(ItemInfo* item, CollisionInfo* coll)
|
||||||
DoObjectCollision(item, coll);
|
DoObjectCollision(item, coll);
|
||||||
|
|
||||||
// Handle Lara collision.
|
// Handle Lara collision.
|
||||||
if (lara->Vehicle == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM)
|
||||||
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle weapons.
|
// Handle weapons.
|
||||||
HandleWeapon(item);
|
HandleWeapon(*item);
|
||||||
|
|
||||||
// Handle breath.
|
// Handle breath.
|
||||||
LaraBreath(item);
|
LaraBreath(item);
|
||||||
|
@ -957,9 +990,9 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
// Reset lean.
|
// Reset lean.
|
||||||
if (!lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))
|
if (!lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))
|
||||||
ResetLaraLean(item, 8.0f);
|
ResetPlayerLean(item, 1 / 8.0f);
|
||||||
|
|
||||||
if (lara->WaterCurrentActive && lara->Control.WaterStatus != WaterStatus::FlyCheat)
|
if (lara->Context.WaterCurrentActive && lara->Control.WaterStatus != WaterStatus::FlyCheat)
|
||||||
LaraWaterCurrent(item, coll);
|
LaraWaterCurrent(item, coll);
|
||||||
|
|
||||||
AnimateItem(item);
|
AnimateItem(item);
|
||||||
|
@ -967,12 +1000,12 @@ void LaraWaterSurface(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
DoObjectCollision(item, coll);
|
DoObjectCollision(item, coll);
|
||||||
|
|
||||||
if (lara->Vehicle == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM)
|
||||||
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
||||||
|
|
||||||
UpdateLaraRoom(item, LARA_RADIUS);
|
UpdateLaraRoom(item, LARA_RADIUS);
|
||||||
|
|
||||||
HandleWeapon(item);
|
HandleWeapon(*item);
|
||||||
|
|
||||||
ProcessSectorFlags(item);
|
ProcessSectorFlags(item);
|
||||||
TestTriggers(item, false);
|
TestTriggers(item, false);
|
||||||
|
@ -1026,7 +1059,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
|
||||||
UpdateLaraSubsuitAngles(item);
|
UpdateLaraSubsuitAngles(item);
|
||||||
|
|
||||||
if (!lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))
|
if (!lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))
|
||||||
ResetLaraLean(item, 8.0f, true, false);
|
ResetPlayerLean(item, 1 / 8.0f, true, false);
|
||||||
|
|
||||||
if (item->Pose.Orientation.x < -ANGLE(85.0f))
|
if (item->Pose.Orientation.x < -ANGLE(85.0f))
|
||||||
item->Pose.Orientation.x = -ANGLE(85.0f);
|
item->Pose.Orientation.x = -ANGLE(85.0f);
|
||||||
|
@ -1048,7 +1081,7 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
|
||||||
item->Pose.Orientation.z = -ANGLE(22.0f);
|
item->Pose.Orientation.z = -ANGLE(22.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->WaterCurrentActive && lara->Control.WaterStatus != WaterStatus::FlyCheat)
|
if (lara->Context.WaterCurrentActive && lara->Control.WaterStatus != WaterStatus::FlyCheat)
|
||||||
LaraWaterCurrent(item, coll);
|
LaraWaterCurrent(item, coll);
|
||||||
|
|
||||||
AnimateItem(item);
|
AnimateItem(item);
|
||||||
|
@ -1056,12 +1089,12 @@ void LaraUnderwater(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
DoObjectCollision(item, coll);
|
DoObjectCollision(item, coll);
|
||||||
|
|
||||||
if (/*lara->ExtraAnim == -1 &&*/ lara->Vehicle == NO_ITEM)
|
if (/*lara->ExtraAnim == -1 &&*/ lara->Context.Vehicle == NO_ITEM)
|
||||||
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
lara_collision_routines[item->Animation.ActiveState](item, coll);
|
||||||
|
|
||||||
UpdateLaraRoom(item, 0);
|
UpdateLaraRoom(item, 0);
|
||||||
|
|
||||||
HandleWeapon(item);
|
HandleWeapon(*item);
|
||||||
|
|
||||||
ProcessSectorFlags(item);
|
ProcessSectorFlags(item);
|
||||||
TestTriggers(item, false);
|
TestTriggers(item, false);
|
||||||
|
@ -1082,10 +1115,10 @@ void LaraCheat(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (TrInput & IN_WALK && !(TrInput & IN_LOOK))
|
if (TrInput & IN_WALK && !(TrInput & IN_LOOK))
|
||||||
{
|
{
|
||||||
if (TestEnvironment(ENV_FLAG_WATER, item) || (lara->WaterSurfaceDist > 0 && lara->WaterSurfaceDist != NO_HEIGHT))
|
if (TestEnvironment(ENV_FLAG_WATER, item) || (lara->Context.WaterSurfaceDist > 0 && lara->Context.WaterSurfaceDist != NO_HEIGHT))
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_UNDERWATER_IDLE);
|
SetAnimation(item, LA_UNDERWATER_IDLE);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
lara->Control.WaterStatus = WaterStatus::Underwater;
|
lara->Control.WaterStatus = WaterStatus::Underwater;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1093,11 +1126,11 @@ void LaraCheat(ItemInfo* item, CollisionInfo* coll)
|
||||||
SetAnimation(item, LA_STAND_SOLID);
|
SetAnimation(item, LA_STAND_SOLID);
|
||||||
item->Pose.Orientation.x = 0;
|
item->Pose.Orientation.x = 0;
|
||||||
item->Pose.Orientation.z = 0;
|
item->Pose.Orientation.z = 0;
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
lara->Control.WaterStatus = WaterStatus::Dry;
|
lara->Control.WaterStatus = WaterStatus::Dry;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitialiseLaraMeshes(item);
|
InitializeLaraMeshes(item);
|
||||||
item->HitPoints = LARA_HEALTH_MAX;
|
item->HitPoints = LARA_HEALTH_MAX;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
#include "Game/Lara/lara_monkey.h"
|
#include "Game/Lara/lara_monkey.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/pickup/pickup.h"
|
#include "Game/pickup/pickup.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||||
|
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
|
@ -73,7 +73,7 @@ void lara_as_controlled(ItemInfo* item, CollisionInfo* coll)
|
||||||
coll->Setup.EnableSpasm = false;
|
coll->Setup.EnableSpasm = false;
|
||||||
Camera.flags = CF_FOLLOW_CENTER;
|
Camera.flags = CF_FOLLOW_CENTER;
|
||||||
|
|
||||||
if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd - 1)
|
if (item->Animation.FrameNumber == GetAnimData(*item).frameEnd - 1)
|
||||||
{
|
{
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ void lara_as_vault(ItemInfo* item, CollisionInfo* coll)
|
||||||
coll->Setup.EnableObjectPush = false;
|
coll->Setup.EnableObjectPush = false;
|
||||||
coll->Setup.EnableSpasm = false;
|
coll->Setup.EnableSpasm = false;
|
||||||
|
|
||||||
EaseOutLaraHeight(item, lara->ProjectedFloorHeight - item->Pose.Position.y);
|
EaseOutLaraHeight(item, lara->Context.ProjectedFloorHeight - item->Pose.Position.y);
|
||||||
item->Pose.Orientation.Lerp(lara->TargetOrientation, 0.4f);
|
item->Pose.Orientation.Lerp(lara->Context.TargetOrientation, 0.4f);
|
||||||
|
|
||||||
item->Animation.TargetState = LS_IDLE;
|
item->Animation.TargetState = LS_IDLE;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ void lara_as_auto_jump(ItemInfo* item, CollisionInfo* coll)
|
||||||
coll->Setup.EnableObjectPush = false;
|
coll->Setup.EnableObjectPush = false;
|
||||||
coll->Setup.EnableSpasm = false;
|
coll->Setup.EnableSpasm = false;
|
||||||
|
|
||||||
item->Pose.Orientation.Lerp(lara->TargetOrientation, 0.4f);
|
item->Pose.Orientation.Lerp(lara->Context.TargetOrientation, 0.4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------
|
// ---------------
|
||||||
|
@ -220,7 +220,7 @@ void lara_col_walk_forward(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (LaraDeflectEdge(item, coll))
|
if (LaraDeflectEdge(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_SOFT_SPLAT;
|
item->Animation.TargetState = LS_SOFT_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
||||||
return;
|
return;
|
||||||
|
@ -349,13 +349,13 @@ void lara_col_run_forward(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (LaraDeflectEdge(item, coll))
|
if (LaraDeflectEdge(item, coll))
|
||||||
{
|
{
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
|
|
||||||
if (TestLaraWall(item, OFFSET_RADIUS(coll->Setup.Radius), -CLICK(2.5f)) ||
|
if (TestLaraWall(item, OFFSET_RADIUS(coll->Setup.Radius), -CLICK(2.5f)) ||
|
||||||
coll->HitTallObject)
|
coll->HitTallObject)
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_SPLAT;
|
item->Animation.TargetState = LS_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
Rumble(0.4f, 0.15f);
|
Rumble(0.4f, 0.15f);
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ void lara_col_run_forward(ItemInfo* item, CollisionInfo* coll)
|
||||||
}
|
}
|
||||||
|
|
||||||
item->Animation.TargetState = LS_SOFT_SPLAT;
|
item->Animation.TargetState = LS_SOFT_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
||||||
return;
|
return;
|
||||||
|
@ -1880,7 +1880,7 @@ void lara_col_step_right(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (LaraDeflectEdge(item, coll))
|
if (LaraDeflectEdge(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_SOFT_SPLAT;
|
item->Animation.TargetState = LS_SOFT_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
||||||
return;
|
return;
|
||||||
|
@ -1974,7 +1974,7 @@ void lara_col_step_left(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (LaraDeflectEdge(item, coll))
|
if (LaraDeflectEdge(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_SOFT_SPLAT;
|
item->Animation.TargetState = LS_SOFT_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
||||||
return;
|
return;
|
||||||
|
@ -2227,10 +2227,10 @@ void lara_col_wade_forward(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (LaraDeflectEdge(item, coll))
|
if (LaraDeflectEdge(item, coll))
|
||||||
{
|
{
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
|
|
||||||
item->Animation.TargetState = LS_SOFT_SPLAT;
|
item->Animation.TargetState = LS_SOFT_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
||||||
return;
|
return;
|
||||||
|
@ -2355,13 +2355,13 @@ void lara_col_sprint(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (LaraDeflectEdge(item, coll))
|
if (LaraDeflectEdge(item, coll))
|
||||||
{
|
{
|
||||||
ResetLaraLean(item);
|
ResetPlayerLean(item);
|
||||||
|
|
||||||
if (TestLaraWall(item, OFFSET_RADIUS(coll->Setup.Radius), -CLICK(2.5f)) ||
|
if (TestLaraWall(item, OFFSET_RADIUS(coll->Setup.Radius), -CLICK(2.5f)) ||
|
||||||
coll->HitTallObject)
|
coll->HitTallObject)
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_SPLAT;
|
item->Animation.TargetState = LS_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
Rumble(0.5f, 0.15f);
|
Rumble(0.5f, 0.15f);
|
||||||
|
|
||||||
|
@ -2371,7 +2371,7 @@ void lara_col_sprint(ItemInfo* item, CollisionInfo* coll)
|
||||||
}
|
}
|
||||||
|
|
||||||
item->Animation.TargetState = LS_SOFT_SPLAT;
|
item->Animation.TargetState = LS_SOFT_SPLAT;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
item->Animation.ActiveState = LS_SOFT_SPLAT;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Gui;
|
using namespace TEN::Gui;
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
|
@ -62,7 +62,7 @@ void LaraCheatyBits(ItemInfo* item)
|
||||||
static bool dbFlyCheat = true;
|
static bool dbFlyCheat = true;
|
||||||
if (KeyMap[OIS::KeyCode::KC_O] && dbFlyCheat)
|
if (KeyMap[OIS::KeyCode::KC_O] && dbFlyCheat)
|
||||||
{
|
{
|
||||||
if (lara->Vehicle == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM)
|
||||||
{
|
{
|
||||||
LaraCheatGetStuff(item);
|
LaraCheatGetStuff(item);
|
||||||
DelsGiveLaraItemsCheat(item);
|
DelsGiveLaraItemsCheat(item);
|
||||||
|
@ -77,7 +77,7 @@ void LaraCheatyBits(ItemInfo* item)
|
||||||
item->Pose.Orientation.x = ANGLE(30.0f);
|
item->Pose.Orientation.x = ANGLE(30.0f);
|
||||||
item->HitPoints = LARA_HEALTH_MAX;
|
item->HitPoints = LARA_HEALTH_MAX;
|
||||||
|
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
lara->Control.WaterStatus = WaterStatus::FlyCheat;
|
lara->Control.WaterStatus = WaterStatus::FlyCheat;
|
||||||
lara->Control.Count.Death = 0;
|
lara->Control.Count.Death = 0;
|
||||||
lara->Status.Air = LARA_AIR_MAX;
|
lara->Status.Air = LARA_AIR_MAX;
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/Lara/lara_overhang.h"
|
#include "Game/Lara/lara_overhang.h"
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
#include "Specific/level.h"
|
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
#include "Specific/level.h"
|
||||||
|
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ constexpr auto LADDER_TEST_DISTANCE = CLICK(0.5f) - LADDER_TEST_MARGIN;
|
||||||
constexpr auto LADDER_CLIMB_SHIFT = 70;
|
constexpr auto LADDER_CLIMB_SHIFT = 70;
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// LADDER CLIMB
|
// WALL CLIMB
|
||||||
// Control & Collision Functions
|
// Control & Collision Functions
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
|
||||||
|
@ -40,10 +40,10 @@ void lara_as_climb_end(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
void lara_col_climb_down(ItemInfo* item, CollisionInfo* coll)
|
void lara_col_climb_down(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
if (LaraCheckForLetGo(item, coll) || item->Animation.AnimNumber != LA_LADDER_DOWN)
|
if (LaraCheckForLetGo(item, coll) || !TestAnimNumber(*item, LA_LADDER_DOWN))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int frame = item->Animation.FrameNumber - g_Level.Anims[LA_LADDER_DOWN].frameBase;
|
int frame = item->Animation.FrameNumber - GetAnimData(item->ObjectNumber, LA_LADDER_DOWN).frameBase;
|
||||||
int yShift = 0;
|
int yShift = 0;
|
||||||
|
|
||||||
switch (frame)
|
switch (frame)
|
||||||
|
@ -128,9 +128,9 @@ void lara_as_climb_down(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
void lara_col_climb_up(ItemInfo* item, CollisionInfo* coll)
|
void lara_col_climb_up(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
if (!LaraCheckForLetGo(item, coll) && item->Animation.AnimNumber == LA_LADDER_UP)
|
if (!LaraCheckForLetGo(item, coll) && TestAnimNumber(*item, LA_LADDER_UP))
|
||||||
{
|
{
|
||||||
int frame = item->Animation.FrameNumber - g_Level.Anims[LA_LADDER_UP].frameBase;
|
int frame = item->Animation.FrameNumber - GetAnimData(item->ObjectNumber, LA_LADDER_UP).frameBase;
|
||||||
int yShift;
|
int yShift;
|
||||||
int resultRight, resultLeft;
|
int resultRight, resultLeft;
|
||||||
int shiftRight, shiftLeft;
|
int shiftRight, shiftLeft;
|
||||||
|
@ -304,6 +304,10 @@ void lara_col_climb_idle(ItemInfo* item, CollisionInfo* coll)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Added check to avoid climbing through bridges.
|
||||||
|
if (resultRight == 0 && resultLeft == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (resultRight >= 0 && resultLeft >= 0)
|
if (resultRight >= 0 && resultLeft >= 0)
|
||||||
{
|
{
|
||||||
yShift = shiftLeft;
|
yShift = shiftLeft;
|
||||||
|
@ -321,7 +325,7 @@ void lara_col_climb_idle(ItemInfo* item, CollisionInfo* coll)
|
||||||
yShift = shiftRight;
|
yShift = shiftRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Prevent climbing inside sloped ceilings. Breaks overhang even more, but that shouldn't matter since we'll be doing it over. @Sezz 2022.05.13
|
// HACK: Prevent climbing inside sloped ceilings. Breaks overhang even more, but that shouldn't matter since we'll be doing it over. -- Sezz 2022.05.13
|
||||||
int y = item->Pose.Position.y - (coll->Setup.Height + CLICK(0.5f));
|
int y = item->Pose.Position.y - (coll->Setup.Height + CLICK(0.5f));
|
||||||
auto probe = GetCollision(item, 0, 0, -(coll->Setup.Height + CLICK(0.5f)));
|
auto probe = GetCollision(item, 0, 0, -(coll->Setup.Height + CLICK(0.5f)));
|
||||||
if ((probe.Position.Ceiling - y) < 0)
|
if ((probe.Position.Ceiling - y) < 0)
|
||||||
|
@ -357,6 +361,7 @@ void lara_as_climb_idle(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_LADDER_DISMOUNT_LEFT_START)
|
if (item->Animation.AnimNumber == LA_LADDER_DISMOUNT_LEFT_START)
|
||||||
Camera.targetAngle = -ANGLE(60.0f);
|
Camera.targetAngle = -ANGLE(60.0f);
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_LADDER_DISMOUNT_RIGHT_START)
|
if (item->Animation.AnimNumber == LA_LADDER_DISMOUNT_RIGHT_START)
|
||||||
Camera.targetAngle = ANGLE(60.0f);
|
Camera.targetAngle = ANGLE(60.0f);
|
||||||
|
|
||||||
|
@ -627,10 +632,10 @@ int LaraClimbRightCornerTest(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftExtRightIntTab[angle])
|
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftExtRightIntTab[angle])
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
lara->Context.NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||||
lara->NextCornerPos.Position.z = item->Pose.Position.z = z;
|
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y + ANGLE(90);
|
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y + ANGLE(90);
|
||||||
|
|
||||||
result = LaraTestClimbPos(item, coll->Setup.Radius, coll->Setup.Radius + LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
result = LaraTestClimbPos(item, coll->Setup.Radius, coll->Setup.Radius + LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
||||||
item->ItemFlags[3] = result;
|
item->ItemFlags[3] = result;
|
||||||
|
@ -668,10 +673,10 @@ int LaraClimbRightCornerTest(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftIntRightExtTab[angle])
|
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftIntRightExtTab[angle])
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
lara->Context.NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||||
lara->NextCornerPos.Position.z = item->Pose.Position.z = z;
|
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y - ANGLE(90.0f);
|
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y - ANGLE(90.0f);
|
||||||
|
|
||||||
result = LaraTestClimbPos(item, coll->Setup.Radius, coll->Setup.Radius + LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
result = LaraTestClimbPos(item, coll->Setup.Radius, coll->Setup.Radius + LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
||||||
item->ItemFlags[3] = result;
|
item->ItemFlags[3] = result;
|
||||||
|
@ -716,10 +721,10 @@ int LaraClimbLeftCornerTest(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftIntRightExtTab[angle])
|
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftIntRightExtTab[angle])
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
lara->Context.NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||||
lara->NextCornerPos.Position.z = item->Pose.Position.z = z;
|
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y - ANGLE(90.0f);
|
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y - ANGLE(90.0f);
|
||||||
|
|
||||||
result = LaraTestClimbPos(item, coll->Setup.Radius, -coll->Setup.Radius - LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
result = LaraTestClimbPos(item, coll->Setup.Radius, -coll->Setup.Radius - LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
||||||
item->ItemFlags[3] = result;
|
item->ItemFlags[3] = result;
|
||||||
|
@ -756,10 +761,10 @@ int LaraClimbLeftCornerTest(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftExtRightIntTab[angle])
|
if (GetClimbFlags(x, item->Pose.Position.y, z, item->RoomNumber) & (short)LeftExtRightIntTab[angle])
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Position.x = item->Pose.Position.x = x;
|
lara->Context.NextCornerPos.Position.x = item->Pose.Position.x = x;
|
||||||
lara->NextCornerPos.Position.y = item->Pose.Position.y;
|
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y;
|
||||||
lara->NextCornerPos.Position.z = item->Pose.Position.z = z;
|
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z = z;
|
||||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y + ANGLE(90.0f);
|
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y = lara->Control.MoveAngle = item->Pose.Orientation.y + ANGLE(90.0f);
|
||||||
|
|
||||||
item->ItemFlags[3] = LaraTestClimbPos(item, coll->Setup.Radius, -coll->Setup.Radius - LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
item->ItemFlags[3] = LaraTestClimbPos(item, coll->Setup.Radius, -coll->Setup.Radius - LADDER_TEST_DISTANCE, -CLICK(2), CLICK(2), &shift);
|
||||||
result = item->ItemFlags[3] != 0;
|
result = item->ItemFlags[3] != 0;
|
||||||
|
@ -886,47 +891,22 @@ int LaraTestClimb(ItemInfo* item, int xOffset, int yOffset, int zOffset, int xFr
|
||||||
|
|
||||||
int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* ledge)
|
int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* ledge)
|
||||||
{
|
{
|
||||||
int y = item->Pose.Position.y - 768;
|
auto probePos = Geometry::TranslatePoint(item->Pose.Position, item->Pose.Orientation.y, front, -CLICK(3), right);
|
||||||
|
auto probeOffset = Geometry::TranslatePoint(Vector3i::Zero, item->Pose.Orientation.y, 4.0f);
|
||||||
int x, z;
|
|
||||||
int xFront = 0;
|
|
||||||
int zFront = 0;
|
|
||||||
|
|
||||||
switch (GetQuadrant(item->Pose.Orientation.y))
|
|
||||||
{
|
|
||||||
case NORTH:
|
|
||||||
x = item->Pose.Position.x + right;
|
|
||||||
z = item->Pose.Position.z + front;
|
|
||||||
zFront = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EAST:
|
|
||||||
x = item->Pose.Position.x + front;
|
|
||||||
z = item->Pose.Position.z - right;
|
|
||||||
xFront = 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SOUTH:
|
|
||||||
x = item->Pose.Position.x - right;
|
|
||||||
z = item->Pose.Position.z - front;
|
|
||||||
zFront = -4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
x = item->Pose.Position.x - front;
|
|
||||||
z = item->Pose.Position.z + right;
|
|
||||||
xFront = -4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*shift = 0;
|
*shift = 0;
|
||||||
|
|
||||||
short roomNumber = item->RoomNumber;
|
// Test center.
|
||||||
FloorInfo* floor = GetFloor(x, y, z, &roomNumber);
|
auto pointColl = GetCollision(item);
|
||||||
int ceiling = CLICK(1) - y + GetCeiling(floor, x, y, z);
|
int vPos = item->Pose.Position.y - CLICK(4);
|
||||||
|
if ((pointColl.Position.Ceiling - vPos) > LADDER_CLIMB_SHIFT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
floor = GetFloor(x + xFront, y, z + zFront, &roomNumber);
|
pointColl = GetCollision(probePos.x, probePos.y, probePos.z, item->RoomNumber);
|
||||||
int height = GetFloorHeight(floor, x + xFront, y, z + zFront);
|
int ceiling = (CLICK(1) - probePos.y) + pointColl.Position.Ceiling;
|
||||||
|
|
||||||
|
pointColl = GetCollision(probePos.x + probeOffset.x, probePos.y, probePos.z + probeOffset.z, pointColl.RoomNumber);
|
||||||
|
int height = pointColl.Position.Floor;
|
||||||
|
|
||||||
if (height == NO_HEIGHT)
|
if (height == NO_HEIGHT)
|
||||||
{
|
{
|
||||||
|
@ -934,7 +914,7 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
height -= y;
|
height -= probePos.y;
|
||||||
*ledge = height;
|
*ledge = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,12 +935,13 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
||||||
if (height > 0 && height > *shift)
|
if (height > 0 && height > *shift)
|
||||||
*shift = height;
|
*shift = height;
|
||||||
|
|
||||||
roomNumber = item->RoomNumber;
|
pointColl = GetCollision(probePos.x, probePos.y + CLICK(2), probePos.z, item->RoomNumber);
|
||||||
GetFloor(x, y + CLICK(2), z, &roomNumber);
|
pointColl = GetCollision(probePos.x + probeOffset.x, probePos.y + CLICK(2), probePos.z + probeOffset.z, pointColl.RoomNumber);
|
||||||
floor = GetFloor(x + xFront, y + CLICK(2), z + zFront, &roomNumber);
|
|
||||||
ceiling = GetCeiling(floor, x + xFront, y + CLICK(2), z + zFront) - y;
|
ceiling = pointColl.Position.Ceiling - probePos.y;
|
||||||
if (ceiling <= height)
|
if (ceiling <= height)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (ceiling >= CLICK(2))
|
if (ceiling >= CLICK(2))
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
|
@ -968,13 +949,14 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ceiling = GetCeiling(floor, x + xFront, y, z + zFront) - y;
|
ceiling = GetCollision(probePos.x + probeOffset.x, probePos.y, probePos.z + probeOffset.z, pointColl.RoomNumber).Position.Ceiling - probePos.y;
|
||||||
if (ceiling < CLICK(2))
|
if (ceiling < CLICK(2))
|
||||||
{
|
{
|
||||||
if ((height - ceiling) <= LARA_HEIGHT)
|
if ((height - ceiling) <= LARA_HEIGHT)
|
||||||
{
|
{
|
||||||
if ((height - ceiling) < CLICK(2))
|
if ((height - ceiling) < CLICK(2))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*shift = height;
|
*shift = height;
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
@ -985,7 +967,9 @@ int LaraTestClimbUpPos(ItemInfo* item, int front, int right, int* shift, int* le
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,7 +986,7 @@ bool LaraCheckForLetGo(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TrInput & IN_ACTION && item->HitPoints > 0 || item->Animation.AnimNumber == LA_ONWATER_TO_LADDER) // Can't let go on this anim
|
if (TrInput & IN_ACTION && item->HitPoints > 0 || item->Animation.AnimNumber == LA_ONWATER_TO_LADDER) // Can't let go on this anim
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
|
|
||||||
SetAnimation(item, LA_FALL_START);
|
SetAnimation(item, LA_FALL_START);
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ static ClimbDirectionFlags LeftExtRightIntTab[4] =
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
// LADDER CLIMB
|
// WALL CLIMB
|
||||||
// Control & Collision Functions
|
// Control & Collision Functions
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/Lara/lara_swim.h"
|
#include "Game/Lara/lara_swim.h"
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Objects/Sink.h"
|
#include "Objects/Sink.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||||
#include "ScriptInterfaceLevel.h"
|
#include "ScriptInterfaceLevel.h"
|
||||||
|
|
||||||
|
@ -239,9 +239,10 @@ void LaraCollideStop(ItemInfo* item, CollisionInfo* coll)
|
||||||
case LS_TURN_LEFT_SLOW:
|
case LS_TURN_LEFT_SLOW:
|
||||||
case LS_TURN_RIGHT_FAST:
|
case LS_TURN_RIGHT_FAST:
|
||||||
case LS_TURN_LEFT_FAST:
|
case LS_TURN_LEFT_FAST:
|
||||||
item->Animation.ActiveState = coll->Setup.OldState;
|
item->Animation.AnimObjectID = coll->Setup.PrevAnimObjectID;
|
||||||
item->Animation.AnimNumber = coll->Setup.OldAnimNumber;
|
item->Animation.AnimNumber = coll->Setup.OldAnimNumber;
|
||||||
item->Animation.FrameNumber = coll->Setup.OldFrameNumber;
|
item->Animation.FrameNumber = coll->Setup.OldFrameNumber;
|
||||||
|
item->Animation.ActiveState = coll->Setup.OldState;
|
||||||
|
|
||||||
if (TrInput & IN_LEFT)
|
if (TrInput & IN_LEFT)
|
||||||
{
|
{
|
||||||
|
@ -288,9 +289,10 @@ void LaraCollideStopCrawl(ItemInfo* item, CollisionInfo* coll)
|
||||||
case LS_CRAWL_IDLE:
|
case LS_CRAWL_IDLE:
|
||||||
case LS_CRAWL_TURN_LEFT:
|
case LS_CRAWL_TURN_LEFT:
|
||||||
case LS_CRAWL_TURN_RIGHT:
|
case LS_CRAWL_TURN_RIGHT:
|
||||||
item->Animation.ActiveState = coll->Setup.OldState;
|
item->Animation.AnimObjectID = coll->Setup.PrevAnimObjectID;
|
||||||
item->Animation.AnimNumber = coll->Setup.OldAnimNumber;
|
item->Animation.AnimNumber = coll->Setup.OldAnimNumber;
|
||||||
item->Animation.FrameNumber = coll->Setup.OldFrameNumber;
|
item->Animation.FrameNumber = coll->Setup.OldFrameNumber;
|
||||||
|
item->Animation.ActiveState = coll->Setup.OldState;
|
||||||
|
|
||||||
if (TrInput & IN_LEFT)
|
if (TrInput & IN_LEFT)
|
||||||
item->Animation.TargetState = LS_CRAWL_TURN_LEFT;
|
item->Animation.TargetState = LS_CRAWL_TURN_LEFT;
|
||||||
|
@ -309,7 +311,7 @@ void LaraCollideStopCrawl(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (item->Animation.AnimNumber != LA_CRAWL_IDLE)
|
if (item->Animation.AnimNumber != LA_CRAWL_IDLE)
|
||||||
{
|
{
|
||||||
item->Animation.AnimNumber = LA_CRAWL_IDLE;
|
item->Animation.AnimNumber = LA_CRAWL_IDLE;
|
||||||
item->Animation.FrameNumber = GetFrameNumber(item, 0);
|
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -323,9 +325,10 @@ void LaraCollideStopMonkey(ItemInfo* item, CollisionInfo* coll)
|
||||||
case LS_MONKEY_IDLE:
|
case LS_MONKEY_IDLE:
|
||||||
case LS_MONKEY_TURN_LEFT:
|
case LS_MONKEY_TURN_LEFT:
|
||||||
case LS_MONKEY_TURN_RIGHT:
|
case LS_MONKEY_TURN_RIGHT:
|
||||||
item->Animation.ActiveState = coll->Setup.OldState;
|
item->Animation.AnimObjectID = coll->Setup.PrevAnimObjectID;
|
||||||
item->Animation.AnimNumber = coll->Setup.OldAnimNumber;
|
item->Animation.AnimNumber = coll->Setup.OldAnimNumber;
|
||||||
item->Animation.FrameNumber = coll->Setup.OldFrameNumber;
|
item->Animation.FrameNumber = coll->Setup.OldFrameNumber;
|
||||||
|
item->Animation.ActiveState = coll->Setup.OldState;
|
||||||
|
|
||||||
if (TrInput & IN_LEFT)
|
if (TrInput & IN_LEFT)
|
||||||
item->Animation.TargetState = LS_MONKEY_TURN_LEFT;
|
item->Animation.TargetState = LS_MONKEY_TURN_LEFT;
|
||||||
|
@ -344,7 +347,7 @@ void LaraCollideStopMonkey(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (item->Animation.AnimNumber != LA_MONKEY_IDLE)
|
if (item->Animation.AnimNumber != LA_MONKEY_IDLE)
|
||||||
{
|
{
|
||||||
item->Animation.AnimNumber = LA_MONKEY_IDLE;
|
item->Animation.AnimNumber = LA_MONKEY_IDLE;
|
||||||
item->Animation.FrameNumber = GetFrameNumber(item, 0);
|
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -621,13 +624,13 @@ void LaraWaterCurrent(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
if (lara->WaterCurrentActive)
|
if (lara->Context.WaterCurrentActive)
|
||||||
{
|
{
|
||||||
const auto& sink = g_Level.Sinks[lara->WaterCurrentActive - 1];
|
const auto& sink = g_Level.Sinks[lara->Context.WaterCurrentActive - 1];
|
||||||
|
|
||||||
short headingAngle = Geometry::GetOrientToPoint(item->Pose.Position.ToVector3(), sink.Position).y;
|
short headingAngle = Geometry::GetOrientToPoint(item->Pose.Position.ToVector3(), sink.Position).y;
|
||||||
lara->WaterCurrentPull.x += ((sink.Strength * SECTOR(1) * phd_sin(headingAngle)) - lara->WaterCurrentPull.x) / 16;
|
lara->Context.WaterCurrentPull.x += ((sink.Strength * SECTOR(1) * phd_sin(headingAngle)) - lara->Context.WaterCurrentPull.x) / 16;
|
||||||
lara->WaterCurrentPull.z += ((sink.Strength * SECTOR(1) * phd_cos(headingAngle)) - lara->WaterCurrentPull.z) / 16;
|
lara->Context.WaterCurrentPull.z += ((sink.Strength * SECTOR(1) * phd_cos(headingAngle)) - lara->Context.WaterCurrentPull.z) / 16;
|
||||||
|
|
||||||
item->Pose.Position.y += (sink.Position.y - item->Pose.Position.y) / 16;
|
item->Pose.Position.y += (sink.Position.y - item->Pose.Position.y) / 16;
|
||||||
}
|
}
|
||||||
|
@ -635,31 +638,31 @@ void LaraWaterCurrent(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
|
|
||||||
if (abs(lara->WaterCurrentPull.x) <= 16)
|
if (abs(lara->Context.WaterCurrentPull.x) <= 16)
|
||||||
shift = (abs(lara->WaterCurrentPull.x) > 8) + 2;
|
shift = (abs(lara->Context.WaterCurrentPull.x) > 8) + 2;
|
||||||
else
|
else
|
||||||
shift = 4;
|
shift = 4;
|
||||||
lara->WaterCurrentPull.x -= lara->WaterCurrentPull.x >> shift;
|
lara->Context.WaterCurrentPull.x -= lara->Context.WaterCurrentPull.x >> shift;
|
||||||
|
|
||||||
if (abs(lara->WaterCurrentPull.x) < 4)
|
if (abs(lara->Context.WaterCurrentPull.x) < 4)
|
||||||
lara->WaterCurrentPull.x = 0;
|
lara->Context.WaterCurrentPull.x = 0;
|
||||||
|
|
||||||
if (abs(lara->WaterCurrentPull.z) <= 16)
|
if (abs(lara->Context.WaterCurrentPull.z) <= 16)
|
||||||
shift = (abs(lara->WaterCurrentPull.z) > 8) + 2;
|
shift = (abs(lara->Context.WaterCurrentPull.z) > 8) + 2;
|
||||||
else
|
else
|
||||||
shift = 4;
|
shift = 4;
|
||||||
lara->WaterCurrentPull.z -= lara->WaterCurrentPull.z >> shift;
|
lara->Context.WaterCurrentPull.z -= lara->Context.WaterCurrentPull.z >> shift;
|
||||||
|
|
||||||
if (abs(lara->WaterCurrentPull.z) < 4)
|
if (abs(lara->Context.WaterCurrentPull.z) < 4)
|
||||||
lara->WaterCurrentPull.z = 0;
|
lara->Context.WaterCurrentPull.z = 0;
|
||||||
|
|
||||||
if (!lara->WaterCurrentPull.x && !lara->WaterCurrentPull.z)
|
if (!lara->Context.WaterCurrentPull.x && !lara->Context.WaterCurrentPull.z)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->Pose.Position.x += lara->WaterCurrentPull.x / 256;
|
item->Pose.Position.x += lara->Context.WaterCurrentPull.x / 256;
|
||||||
item->Pose.Position.z += lara->WaterCurrentPull.z / 256;
|
item->Pose.Position.z += lara->Context.WaterCurrentPull.z / 256;
|
||||||
lara->WaterCurrentActive = 0;
|
lara->Context.WaterCurrentActive = 0;
|
||||||
|
|
||||||
coll->Setup.ForwardAngle = phd_atan(item->Pose.Position.z - coll->Setup.OldPosition.z, item->Pose.Position.x - coll->Setup.OldPosition.x);
|
coll->Setup.ForwardAngle = phd_atan(item->Pose.Position.z - coll->Setup.OldPosition.z, item->Pose.Position.x - coll->Setup.OldPosition.x);
|
||||||
coll->Setup.Height = LARA_HEIGHT_CRAWL;
|
coll->Setup.Height = LARA_HEIGHT_CRAWL;
|
||||||
|
|
|
@ -434,7 +434,7 @@ void lara_as_crawl_idle(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = crawlVaultResult.TargetState;
|
item->Animation.TargetState = crawlVaultResult.TargetState;
|
||||||
lara->Control.TurnRate = 0;
|
lara->Control.TurnRate = 0;
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (TestLaraCrawlForward(item, coll)) USE_FEATURE_IF_CPP20([[likely]])
|
else if (TestLaraCrawlForward(item, coll)) USE_FEATURE_IF_CPP20([[likely]])
|
||||||
|
@ -864,7 +864,7 @@ void lara_col_crawl_to_hang(ItemInfo* item, CollisionInfo* coll)
|
||||||
Camera.targetAngle = 0;
|
Camera.targetAngle = 0;
|
||||||
Camera.targetDistance = SECTOR(1);
|
Camera.targetDistance = SECTOR(1);
|
||||||
|
|
||||||
ResetLaraLean(item, 6.0f);
|
ResetPlayerLean(item, 1 / 6.0f);
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_CRAWL_TO_HANG_END)
|
if (item->Animation.AnimNumber == LA_CRAWL_TO_HANG_END)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Game/Lara/lara_two_guns.h"
|
#include "Game/Lara/lara_two_guns.h"
|
||||||
#include "Game/misc.h"
|
#include "Game/misc.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/Generic/Object/burning_torch.h"
|
#include "Objects/Generic/Object/burning_torch.h"
|
||||||
#include "Objects/Generic/Object/objects.h"
|
#include "Objects/Generic/Object/objects.h"
|
||||||
|
@ -28,14 +29,15 @@
|
||||||
#include "Specific/configuration.h"
|
#include "Specific/configuration.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Entities::Generic;
|
using namespace TEN::Entities::Generic;
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
ItemInfo* LastTargets[MAX_TARGETS];
|
constexpr auto TARGET_COUNT_MAX = 8;
|
||||||
ItemInfo* TargetList[MAX_TARGETS];
|
|
||||||
|
std::array<ItemInfo*, TARGET_COUNT_MAX> LastTargets = {};
|
||||||
|
std::array<ItemInfo*, TARGET_COUNT_MAX> TargetList = {};
|
||||||
|
|
||||||
int FlashGrenadeAftershockTimer = 0;
|
int FlashGrenadeAftershockTimer = 0;
|
||||||
|
|
||||||
|
@ -88,7 +90,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
650,
|
650,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
1,
|
1,
|
||||||
9,
|
9,
|
||||||
3,
|
3,
|
||||||
|
@ -105,7 +107,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(4.0f),
|
ANGLE(4.0f),
|
||||||
650,
|
650,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
21,
|
21,
|
||||||
16,
|
16,
|
||||||
3,
|
3,
|
||||||
|
@ -122,7 +124,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
650,
|
650,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
1,
|
1,
|
||||||
3,
|
3,
|
||||||
3,
|
3,
|
||||||
|
@ -139,7 +141,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
0,
|
0,
|
||||||
500,
|
500,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
3,
|
3,
|
||||||
9,
|
9,
|
||||||
3,
|
3,
|
||||||
|
@ -156,7 +158,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(4.0f),
|
ANGLE(4.0f),
|
||||||
500,
|
500,
|
||||||
SECTOR(12),
|
BLOCK(12),
|
||||||
4,
|
4,
|
||||||
0,
|
0,
|
||||||
3,
|
3,
|
||||||
|
@ -173,7 +175,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
500,
|
500,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
5,
|
5,
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
|
@ -199,7 +201,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
|
||||||
// Flare 2
|
// Torch
|
||||||
{
|
{
|
||||||
std::pair(EulerAngles(ANGLE(-55.0f), ANGLE(-30.0f), 0), EulerAngles(ANGLE(55.0f), ANGLE(30.0f), 0)),
|
std::pair(EulerAngles(ANGLE(-55.0f), ANGLE(-30.0f), 0), EulerAngles(ANGLE(55.0f), ANGLE(30.0f), 0)),
|
||||||
std::pair(EulerAngles(ANGLE(-55.0f), ANGLE(-30.0f), 0), EulerAngles(ANGLE(55.0f), ANGLE(30.0f), 0)),
|
std::pair(EulerAngles(ANGLE(-55.0f), ANGLE(-30.0f), 0), EulerAngles(ANGLE(55.0f), ANGLE(30.0f), 0)),
|
||||||
|
@ -207,7 +209,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
400,
|
400,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
3,
|
3,
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
|
@ -224,7 +226,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
500,
|
500,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
20,
|
20,
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
|
@ -241,7 +243,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
500,
|
500,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
|
@ -258,7 +260,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
500,
|
500,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
30,
|
30,
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
|
@ -275,39 +277,39 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
||||||
ANGLE(10.0f),
|
ANGLE(10.0f),
|
||||||
ANGLE(8.0f),
|
ANGLE(8.0f),
|
||||||
400,
|
400,
|
||||||
SECTOR(8),
|
BLOCK(8),
|
||||||
3,
|
3,
|
||||||
0,
|
0,
|
||||||
0,
|
2,
|
||||||
0,
|
0,
|
||||||
SFX_TR4_UZI_FIRE,
|
SFX_TR4_UZI_FIRE,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitialiseNewWeapon(ItemInfo* laraItem)
|
void InitializeNewWeapon(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
lara.LeftArm.FrameNumber = 0;
|
player.TargetEntity = nullptr;
|
||||||
lara.RightArm.FrameNumber = 0;
|
player.LeftArm.FrameNumber =
|
||||||
lara.LeftArm.Orientation = EulerAngles::Zero;
|
player.RightArm.FrameNumber = 0;
|
||||||
lara.RightArm.Orientation = EulerAngles::Zero;
|
player.LeftArm.Orientation =
|
||||||
lara.TargetEntity = nullptr;
|
player.RightArm.Orientation = EulerAngles::Zero;
|
||||||
lara.LeftArm.Locked = false;
|
player.LeftArm.Locked =
|
||||||
lara.RightArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
lara.LeftArm.GunFlash = 0;
|
player.LeftArm.GunFlash =
|
||||||
lara.RightArm.GunFlash = 0;
|
player.RightArm.GunFlash = 0;
|
||||||
|
|
||||||
switch (lara.Control.Weapon.GunType)
|
switch (player.Control.Weapon.GunType)
|
||||||
{
|
{
|
||||||
case LaraWeaponType::Pistol:
|
case LaraWeaponType::Pistol:
|
||||||
case LaraWeaponType::Uzi:
|
case LaraWeaponType::Uzi:
|
||||||
lara.RightArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
player.RightArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
||||||
lara.LeftArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
player.LeftArm.FrameBase = Objects[ID_PISTOLS_ANIM].frameBase;
|
||||||
|
|
||||||
if (lara.Control.HandStatus != HandStatus::Free)
|
if (player.Control.HandStatus != HandStatus::Free)
|
||||||
DrawPistolMeshes(laraItem, lara.Control.Weapon.GunType);
|
DrawPistolMeshes(laraItem, player.Control.Weapon.GunType);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -317,26 +319,26 @@ void InitialiseNewWeapon(ItemInfo* laraItem)
|
||||||
case LaraWeaponType::GrenadeLauncher:
|
case LaraWeaponType::GrenadeLauncher:
|
||||||
case LaraWeaponType::HarpoonGun:
|
case LaraWeaponType::HarpoonGun:
|
||||||
case LaraWeaponType::RocketLauncher:
|
case LaraWeaponType::RocketLauncher:
|
||||||
lara.RightArm.FrameBase = Objects[GetWeaponObjectID(lara.Control.Weapon.GunType)].frameBase;
|
player.RightArm.FrameBase = Objects[GetWeaponObjectID(player.Control.Weapon.GunType)].frameBase;
|
||||||
lara.LeftArm.FrameBase = Objects[GetWeaponObjectID(lara.Control.Weapon.GunType)].frameBase;
|
player.LeftArm.FrameBase = Objects[GetWeaponObjectID(player.Control.Weapon.GunType)].frameBase;
|
||||||
|
|
||||||
if (lara.Control.HandStatus != HandStatus::Free)
|
if (player.Control.HandStatus != HandStatus::Free)
|
||||||
DrawShotgunMeshes(laraItem, lara.Control.Weapon.GunType);
|
DrawShotgunMeshes(laraItem, player.Control.Weapon.GunType);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LaraWeaponType::Flare:
|
case LaraWeaponType::Flare:
|
||||||
lara.RightArm.FrameBase = Objects[ID_FLARE_ANIM].frameBase;
|
player.RightArm.FrameBase = Objects[ID_FLARE_ANIM].frameBase;
|
||||||
lara.LeftArm.FrameBase = Objects[ID_FLARE_ANIM].frameBase;
|
player.LeftArm.FrameBase = Objects[ID_FLARE_ANIM].frameBase;
|
||||||
|
|
||||||
if (lara.Control.HandStatus != HandStatus::Free)
|
if (player.Control.HandStatus != HandStatus::Free)
|
||||||
DrawFlareMeshes(laraItem);
|
DrawFlareMeshes(laraItem);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lara.RightArm.FrameBase = g_Level.Anims[laraItem->Animation.AnimNumber].FramePtr;
|
player.RightArm.FrameBase = g_Level.Anims[laraItem.Animation.AnimNumber].FramePtr;
|
||||||
lara.LeftArm.FrameBase = g_Level.Anims[laraItem->Animation.AnimNumber].FramePtr;
|
player.LeftArm.FrameBase = g_Level.Anims[laraItem.Animation.AnimNumber].FramePtr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,23 +348,23 @@ Ammo& GetAmmo(LaraInfo& lara, LaraWeaponType weaponType)
|
||||||
return lara.Weapons[(int)weaponType].Ammo[(int)lara.Weapons[(int)weaponType].SelectedAmmo];
|
return lara.Weapons[(int)weaponType].Ammo[(int)lara.Weapons[(int)weaponType].SelectedAmmo];
|
||||||
}
|
}
|
||||||
|
|
||||||
GameVector GetTargetPoint(ItemInfo* targetEntity)
|
GameVector GetTargetPoint(ItemInfo& targetEntity)
|
||||||
{
|
{
|
||||||
const auto& bounds = GetBestFrame(*targetEntity).BoundingBox;
|
const auto& bounds = GetBestFrame(targetEntity).BoundingBox;
|
||||||
|
|
||||||
auto center = Vector3i(
|
auto center = Vector3i(
|
||||||
(bounds.X1 + bounds.X2) / 2,
|
(bounds.X1 + bounds.X2) / 2,
|
||||||
bounds.Y1 + (bounds.GetHeight() / 3),
|
bounds.Y1 + (bounds.GetHeight() / 3),
|
||||||
(bounds.Z1 + bounds.Z2) / 2);
|
(bounds.Z1 + bounds.Z2) / 2);
|
||||||
|
|
||||||
float sinY = phd_sin(targetEntity->Pose.Orientation.y);
|
float sinY = phd_sin(targetEntity.Pose.Orientation.y);
|
||||||
float cosY = phd_cos(targetEntity->Pose.Orientation.y);
|
float cosY = phd_cos(targetEntity.Pose.Orientation.y);
|
||||||
|
|
||||||
return GameVector(
|
return GameVector(
|
||||||
targetEntity->Pose.Position.x + ((center.x * cosY) + (center.z * sinY)),
|
targetEntity.Pose.Position.x + ((center.x * cosY) + (center.z * sinY)),
|
||||||
targetEntity->Pose.Position.y + center.y,
|
targetEntity.Pose.Position.y + center.y,
|
||||||
targetEntity->Pose.Position.z + ((center.z * cosY) - (center.x * sinY)),
|
targetEntity.Pose.Position.z + ((center.z * cosY) - (center.x * sinY)),
|
||||||
targetEntity->RoomNumber);
|
targetEntity.RoomNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
HolsterSlot GetWeaponHolsterSlot(LaraWeaponType weaponType)
|
HolsterSlot GetWeaponHolsterSlot(LaraWeaponType weaponType)
|
||||||
|
@ -437,14 +439,14 @@ GAME_OBJECT_ID GetWeaponObjectID(LaraWeaponType weaponType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo* laraItem, LaraWeaponType weaponType)
|
GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
{
|
{
|
||||||
const auto& lara = *GetLaraInfo(laraItem);
|
const auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
switch (weaponType)
|
switch (weaponType)
|
||||||
{
|
{
|
||||||
case LaraWeaponType::Revolver:
|
case LaraWeaponType::Revolver:
|
||||||
return (lara.Weapons[(int)LaraWeaponType::Revolver].HasLasersight ? ID_LARA_REVOLVER_LASER : ID_REVOLVER_ANIM);
|
return (player.Weapons[(int)LaraWeaponType::Revolver].HasLasersight ? ID_LARA_REVOLVER_LASER : ID_REVOLVER_ANIM);
|
||||||
|
|
||||||
case LaraWeaponType::Uzi:
|
case LaraWeaponType::Uzi:
|
||||||
return ID_UZI_ANIM;
|
return ID_UZI_ANIM;
|
||||||
|
@ -456,7 +458,7 @@ GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo* laraItem, LaraWeaponType weaponTy
|
||||||
return ID_HK_ANIM;
|
return ID_HK_ANIM;
|
||||||
|
|
||||||
case LaraWeaponType::Crossbow:
|
case LaraWeaponType::Crossbow:
|
||||||
return (lara.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight ? ID_LARA_CROSSBOW_LASER : ID_CROSSBOW_ANIM);
|
return (player.Weapons[(int)LaraWeaponType::Crossbow].HasLasersight ? ID_LARA_CROSSBOW_LASER : ID_CROSSBOW_ANIM);
|
||||||
|
|
||||||
case LaraWeaponType::GrenadeLauncher:
|
case LaraWeaponType::GrenadeLauncher:
|
||||||
return ID_GRENADE_ANIM;
|
return ID_GRENADE_ANIM;
|
||||||
|
@ -472,139 +474,143 @@ GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo* laraItem, LaraWeaponType weaponTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleWeapon(ItemInfo* laraItem)
|
void HandleWeapon(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
if (lara.LeftArm.GunFlash > 0)
|
if (player.LeftArm.GunFlash > 0)
|
||||||
--lara.LeftArm.GunFlash;
|
--player.LeftArm.GunFlash;
|
||||||
|
|
||||||
if (lara.RightArm.GunFlash > 0)
|
if (player.RightArm.GunFlash > 0)
|
||||||
--lara.RightArm.GunFlash;
|
--player.RightArm.GunFlash;
|
||||||
|
|
||||||
if (lara.RightArm.GunSmoke > 0)
|
if (player.RightArm.GunSmoke > 0)
|
||||||
--lara.RightArm.GunSmoke;
|
--player.RightArm.GunSmoke;
|
||||||
|
|
||||||
if (lara.LeftArm.GunSmoke > 0)
|
if (player.LeftArm.GunSmoke > 0)
|
||||||
--lara.LeftArm.GunSmoke;
|
--player.LeftArm.GunSmoke;
|
||||||
|
|
||||||
if (FlashGrenadeAftershockTimer)
|
if (FlashGrenadeAftershockTimer)
|
||||||
FlashGrenadeAftershockTimer--;
|
FlashGrenadeAftershockTimer--;
|
||||||
|
|
||||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Torch)
|
if (player.Control.Weapon.GunType == LaraWeaponType::Torch)
|
||||||
{
|
{
|
||||||
DoFlameTorch();
|
DoFlameTorch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (laraItem->HitPoints <= 0)
|
if (laraItem.HitPoints <= 0)
|
||||||
{
|
{
|
||||||
lara.Control.HandStatus = HandStatus::Free;
|
player.Control.HandStatus = HandStatus::Free;
|
||||||
}
|
}
|
||||||
else if (lara.Control.HandStatus == HandStatus::Free)
|
else if (player.Control.HandStatus == HandStatus::Free)
|
||||||
{
|
{
|
||||||
// Draw weapon.
|
// Draw weapon.
|
||||||
if (IsHeld(In::DrawWeapon))
|
if (IsHeld(In::DrawWeapon))
|
||||||
{
|
{
|
||||||
// No weapon - no any actions.
|
// No weapon - no any actions.
|
||||||
if (lara.Control.Weapon.LastGunType != LaraWeaponType::None)
|
if (player.Control.Weapon.LastGunType != LaraWeaponType::None)
|
||||||
lara.Control.Weapon.RequestGunType = lara.Control.Weapon.LastGunType;
|
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
|
||||||
}
|
}
|
||||||
// Draw flare.
|
// Draw flare.
|
||||||
else if (IsHeld(In::Flare) && (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() != LaraType::Young))
|
else if (IsHeld(In::Flare) && (g_GameFlow->GetLevel(CurrentLevel)->GetLaraType() != LaraType::Young))
|
||||||
{
|
{
|
||||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Flare)
|
if (player.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||||
{
|
{
|
||||||
if (!lara.LeftArm.FrameNumber)
|
if (!player.LeftArm.FrameNumber)
|
||||||
{
|
{
|
||||||
lara.Control.HandStatus = HandStatus::WeaponUndraw;
|
player.Control.HandStatus = HandStatus::WeaponUndraw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lara.Inventory.TotalFlares)
|
else if (player.Inventory.TotalFlares)
|
||||||
{
|
{
|
||||||
if (lara.Inventory.TotalFlares != -1)
|
if (player.Inventory.TotalFlares != -1)
|
||||||
lara.Inventory.TotalFlares--;
|
player.Inventory.TotalFlares--;
|
||||||
|
|
||||||
lara.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
player.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((IsHeld(In::DrawWeapon) && lara.Control.Weapon.LastGunType != LaraWeaponType::None) ||
|
if ((IsHeld(In::DrawWeapon) && player.Control.Weapon.LastGunType != LaraWeaponType::None) ||
|
||||||
lara.Control.Weapon.RequestGunType != lara.Control.Weapon.GunType)
|
player.Control.Weapon.RequestGunType != player.Control.Weapon.GunType)
|
||||||
{
|
{
|
||||||
if (lara.Control.IsLow &&
|
if (player.Control.IsLow &&
|
||||||
lara.Control.Weapon.RequestGunType >= LaraWeaponType::Shotgun &&
|
player.Control.Weapon.RequestGunType >= LaraWeaponType::Shotgun &&
|
||||||
lara.Control.Weapon.RequestGunType != LaraWeaponType::Flare &&
|
player.Control.Weapon.RequestGunType != LaraWeaponType::Flare &&
|
||||||
lara.Control.Weapon.RequestGunType != LaraWeaponType::Torch)
|
player.Control.Weapon.RequestGunType != LaraWeaponType::Torch)
|
||||||
{
|
{
|
||||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Flare)
|
if (player.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||||
lara.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
player.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||||
}
|
}
|
||||||
else if (lara.Control.Weapon.RequestGunType == LaraWeaponType::Flare ||
|
else if (player.Control.Weapon.RequestGunType == LaraWeaponType::Flare ||
|
||||||
(lara.Vehicle == NO_ITEM &&
|
(player.Context.Vehicle == NO_ITEM &&
|
||||||
(lara.Control.Weapon.RequestGunType == LaraWeaponType::HarpoonGun ||
|
(player.Control.Weapon.RequestGunType == LaraWeaponType::HarpoonGun ||
|
||||||
lara.Control.WaterStatus == WaterStatus::Dry ||
|
player.Control.WaterStatus == WaterStatus::Dry ||
|
||||||
(lara.Control.WaterStatus == WaterStatus::Wade &&
|
(player.Control.WaterStatus == WaterStatus::Wade &&
|
||||||
lara.WaterSurfaceDist > -Weapons[(int)lara.Control.Weapon.GunType].GunHeight))))
|
player.Context.WaterSurfaceDist > -Weapons[(int)player.Control.Weapon.GunType].GunHeight))))
|
||||||
{
|
{
|
||||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Flare)
|
if (player.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||||
{
|
{
|
||||||
CreateFlare(laraItem, ID_FLARE_ITEM, 0);
|
CreateFlare(laraItem, ID_FLARE_ITEM, 0);
|
||||||
UndrawFlareMeshes(laraItem);
|
UndrawFlareMeshes(laraItem);
|
||||||
lara.Flare.ControlLeft = false;
|
player.Flare.ControlLeft = false;
|
||||||
lara.Flare.Life = 0;
|
player.Flare.Life = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.Control.Weapon.GunType = lara.Control.Weapon.RequestGunType;
|
player.Control.Weapon.GunType = player.Control.Weapon.RequestGunType;
|
||||||
InitialiseNewWeapon(laraItem);
|
InitializeNewWeapon(laraItem);
|
||||||
lara.RightArm.FrameNumber = 0;
|
player.RightArm.FrameNumber = 0;
|
||||||
lara.LeftArm.FrameNumber = 0;
|
player.LeftArm.FrameNumber = 0;
|
||||||
lara.Control.HandStatus = HandStatus::WeaponDraw;
|
player.Control.HandStatus = HandStatus::WeaponDraw;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lara.Control.Weapon.LastGunType = lara.Control.Weapon.RequestGunType;
|
player.Control.Weapon.LastGunType = player.Control.Weapon.RequestGunType;
|
||||||
|
|
||||||
if (lara.Control.Weapon.GunType != LaraWeaponType::Flare)
|
if (player.Control.Weapon.GunType != LaraWeaponType::Flare)
|
||||||
lara.Control.Weapon.GunType = lara.Control.Weapon.RequestGunType;
|
{
|
||||||
|
player.Control.Weapon.GunType = player.Control.Weapon.RequestGunType;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
lara.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
{
|
||||||
|
player.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lara.Control.HandStatus == HandStatus::WeaponReady)
|
else if (player.Control.HandStatus == HandStatus::WeaponReady)
|
||||||
{
|
{
|
||||||
if (IsHeld(In::DrawWeapon) ||
|
if (IsHeld(In::DrawWeapon) ||
|
||||||
lara.Control.Weapon.RequestGunType != lara.Control.Weapon.GunType)
|
player.Control.Weapon.RequestGunType != player.Control.Weapon.GunType)
|
||||||
{
|
{
|
||||||
lara.Control.HandStatus = HandStatus::WeaponUndraw;
|
player.Control.HandStatus = HandStatus::WeaponUndraw;
|
||||||
}
|
}
|
||||||
else if (lara.Control.Weapon.GunType != LaraWeaponType::HarpoonGun &&
|
else if (player.Control.Weapon.GunType != LaraWeaponType::HarpoonGun &&
|
||||||
lara.Control.WaterStatus != WaterStatus::Dry &&
|
player.Control.WaterStatus != WaterStatus::Dry &&
|
||||||
(lara.Control.WaterStatus != WaterStatus::Wade ||
|
(player.Control.WaterStatus != WaterStatus::Wade ||
|
||||||
lara.WaterSurfaceDist < -Weapons[(int)lara.Control.Weapon.GunType].GunHeight))
|
player.Context.WaterSurfaceDist < -Weapons[(int)player.Control.Weapon.GunType].GunHeight))
|
||||||
{
|
{
|
||||||
lara.Control.HandStatus = HandStatus::WeaponUndraw;
|
player.Control.HandStatus = HandStatus::WeaponUndraw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsHeld(In::Flare) &&
|
else if (IsHeld(In::Flare) &&
|
||||||
lara.Control.HandStatus == HandStatus::Busy &&
|
player.Control.HandStatus == HandStatus::Busy &&
|
||||||
laraItem->Animation.ActiveState == LS_CRAWL_IDLE &&
|
laraItem.Animation.ActiveState == LS_CRAWL_IDLE &&
|
||||||
laraItem->Animation.AnimNumber == LA_CRAWL_IDLE)
|
laraItem.Animation.AnimNumber == LA_CRAWL_IDLE)
|
||||||
{
|
{
|
||||||
lara.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
player.Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lara.Control.HandStatus)
|
switch (player.Control.HandStatus)
|
||||||
{
|
{
|
||||||
case HandStatus::WeaponDraw:
|
case HandStatus::WeaponDraw:
|
||||||
if (lara.Control.Weapon.GunType != LaraWeaponType::Flare &&
|
if (player.Control.Weapon.GunType != LaraWeaponType::Flare &&
|
||||||
lara.Control.Weapon.GunType != LaraWeaponType::None)
|
player.Control.Weapon.GunType != LaraWeaponType::None)
|
||||||
{
|
{
|
||||||
lara.Control.Weapon.LastGunType = lara.Control.Weapon.GunType;
|
player.Control.Weapon.LastGunType = player.Control.Weapon.GunType;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lara.Control.Weapon.GunType)
|
switch (player.Control.Weapon.GunType)
|
||||||
{
|
{
|
||||||
case LaraWeaponType::Pistol:
|
case LaraWeaponType::Pistol:
|
||||||
case LaraWeaponType::Revolver:
|
case LaraWeaponType::Revolver:
|
||||||
|
@ -612,7 +618,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy)
|
if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy)
|
||||||
Camera.type = CameraType::Combat;
|
Camera.type = CameraType::Combat;
|
||||||
|
|
||||||
DrawPistols(laraItem, lara.Control.Weapon.GunType);
|
DrawPistols(laraItem, player.Control.Weapon.GunType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LaraWeaponType::Shotgun:
|
case LaraWeaponType::Shotgun:
|
||||||
|
@ -624,7 +630,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy)
|
if (Camera.type != CameraType::Look && Camera.type != CameraType::Heavy)
|
||||||
Camera.type = CameraType::Combat;
|
Camera.type = CameraType::Combat;
|
||||||
|
|
||||||
DrawShotgun(laraItem, lara.Control.Weapon.GunType);
|
DrawShotgun(laraItem, player.Control.Weapon.GunType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LaraWeaponType::Flare:
|
case LaraWeaponType::Flare:
|
||||||
|
@ -632,7 +638,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lara.Control.HandStatus = HandStatus::Free;
|
player.Control.HandStatus = HandStatus::Free;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,14 +649,14 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HandStatus::WeaponUndraw:
|
case HandStatus::WeaponUndraw:
|
||||||
laraItem->Model.MeshIndex[LM_HEAD] = laraItem->Model.BaseMesh + LM_HEAD;
|
laraItem.Model.MeshIndex[LM_HEAD] = laraItem.Model.BaseMesh + LM_HEAD;
|
||||||
|
|
||||||
switch (lara.Control.Weapon.GunType)
|
switch (player.Control.Weapon.GunType)
|
||||||
{
|
{
|
||||||
case LaraWeaponType::Pistol:
|
case LaraWeaponType::Pistol:
|
||||||
case LaraWeaponType::Revolver:
|
case LaraWeaponType::Revolver:
|
||||||
case LaraWeaponType::Uzi:
|
case LaraWeaponType::Uzi:
|
||||||
UndrawPistols(laraItem, lara.Control.Weapon.GunType);
|
UndrawPistols(laraItem, player.Control.Weapon.GunType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LaraWeaponType::Shotgun:
|
case LaraWeaponType::Shotgun:
|
||||||
|
@ -659,7 +665,7 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
case LaraWeaponType::GrenadeLauncher:
|
case LaraWeaponType::GrenadeLauncher:
|
||||||
case LaraWeaponType::RocketLauncher:
|
case LaraWeaponType::RocketLauncher:
|
||||||
case LaraWeaponType::HarpoonGun:
|
case LaraWeaponType::HarpoonGun:
|
||||||
UndrawShotgun(laraItem, lara.Control.Weapon.GunType);
|
UndrawShotgun(laraItem, player.Control.Weapon.GunType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LaraWeaponType::Flare:
|
case LaraWeaponType::Flare:
|
||||||
|
@ -674,9 +680,13 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
|
|
||||||
case HandStatus::WeaponReady:
|
case HandStatus::WeaponReady:
|
||||||
if (!IsHeld(In::Action))
|
if (!IsHeld(In::Action))
|
||||||
laraItem->Model.MeshIndex[LM_HEAD] = laraItem->Model.BaseMesh + LM_HEAD;
|
{
|
||||||
|
laraItem.Model.MeshIndex[LM_HEAD] = laraItem.Model.BaseMesh + LM_HEAD;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
laraItem->Model.MeshIndex[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD;
|
{
|
||||||
|
laraItem.Model.MeshIndex[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD;
|
||||||
|
}
|
||||||
|
|
||||||
if (Camera.type != CameraType::Look &&
|
if (Camera.type != CameraType::Look &&
|
||||||
Camera.type != CameraType::Heavy)
|
Camera.type != CameraType::Heavy)
|
||||||
|
@ -686,19 +696,19 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
|
|
||||||
if (IsHeld(In::Action) && !LaserSight)
|
if (IsHeld(In::Action) && !LaserSight)
|
||||||
{
|
{
|
||||||
if (!GetAmmo(lara, lara.Control.Weapon.GunType))
|
if (!GetAmmo(player, player.Control.Weapon.GunType))
|
||||||
{
|
{
|
||||||
bool hasPistols = (lara.Weapons[(int)LaraWeaponType::Pistol].Present && Objects[ID_PISTOLS_ITEM].loaded);
|
bool hasPistols = (player.Weapons[(int)LaraWeaponType::Pistol].Present && Objects[ID_PISTOLS_ITEM].loaded);
|
||||||
lara.Control.Weapon.RequestGunType = hasPistols ? LaraWeaponType::Pistol : LaraWeaponType::None;
|
player.Control.Weapon.RequestGunType = hasPistols ? LaraWeaponType::Pistol : LaraWeaponType::None;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lara.Control.Weapon.GunType)
|
switch (player.Control.Weapon.GunType)
|
||||||
{
|
{
|
||||||
case LaraWeaponType::Pistol:
|
case LaraWeaponType::Pistol:
|
||||||
case LaraWeaponType::Uzi:
|
case LaraWeaponType::Uzi:
|
||||||
PistolHandler(laraItem, lara.Control.Weapon.GunType);
|
HandlePistols(laraItem, player.Control.Weapon.GunType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LaraWeaponType::Shotgun:
|
case LaraWeaponType::Shotgun:
|
||||||
|
@ -708,8 +718,8 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
case LaraWeaponType::RocketLauncher:
|
case LaraWeaponType::RocketLauncher:
|
||||||
case LaraWeaponType::HarpoonGun:
|
case LaraWeaponType::HarpoonGun:
|
||||||
case LaraWeaponType::Revolver:
|
case LaraWeaponType::Revolver:
|
||||||
RifleHandler(laraItem, lara.Control.Weapon.GunType);
|
RifleHandler(laraItem, player.Control.Weapon.GunType);
|
||||||
LasersightWeaponHandler(laraItem, lara.Control.Weapon.GunType);
|
LasersightWeaponHandler(laraItem, player.Control.Weapon.GunType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -719,43 +729,43 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HandStatus::Free:
|
case HandStatus::Free:
|
||||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Flare)
|
if (player.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||||
{
|
{
|
||||||
if (lara.Vehicle != NO_ITEM || TestState(laraItem->Animation.ActiveState, FlarePoseStates))
|
if (player.Context.Vehicle != NO_ITEM || TestState(laraItem.Animation.ActiveState, FlarePoseStates))
|
||||||
{
|
{
|
||||||
if (lara.Flare.ControlLeft)
|
if (player.Flare.ControlLeft)
|
||||||
{
|
{
|
||||||
if (lara.LeftArm.FrameNumber)
|
if (player.LeftArm.FrameNumber)
|
||||||
{
|
{
|
||||||
if (++lara.LeftArm.FrameNumber == 110)
|
if (++player.LeftArm.FrameNumber == 110)
|
||||||
lara.LeftArm.FrameNumber = 0;
|
player.LeftArm.FrameNumber = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lara.LeftArm.FrameNumber = 95;
|
player.LeftArm.FrameNumber = 95;
|
||||||
lara.Flare.ControlLeft = true;
|
player.Flare.ControlLeft = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lara.Flare.ControlLeft = false;
|
player.Flare.ControlLeft = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
SetFlareArm(laraItem, lara.LeftArm.FrameNumber);
|
SetFlareArm(laraItem, player.LeftArm.FrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HandStatus::Busy:
|
case HandStatus::Busy:
|
||||||
if (lara.Control.Weapon.GunType == LaraWeaponType::Flare)
|
if (player.Control.Weapon.GunType == LaraWeaponType::Flare)
|
||||||
{
|
{
|
||||||
if (laraItem->Model.MeshIndex[LM_LHAND] == Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND)
|
if (laraItem.Model.MeshIndex[LM_LHAND] == Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND)
|
||||||
{
|
{
|
||||||
lara.Flare.ControlLeft = (lara.Vehicle != NO_ITEM || TestState(laraItem->Animation.ActiveState, FlarePoseStates));
|
player.Flare.ControlLeft = (player.Context.Vehicle != NO_ITEM || TestState(laraItem.Animation.ActiveState, FlarePoseStates));
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
SetFlareArm(laraItem, lara.LeftArm.FrameNumber);
|
SetFlareArm(laraItem, player.LeftArm.FrameNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,18 +773,19 @@ void HandleWeapon(ItemInfo* laraItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AimWeapon(ItemInfo* laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo)
|
void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo)
|
||||||
{
|
{
|
||||||
const auto& lara = *GetLaraInfo(laraItem);
|
const auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
auto targetArmOrient = arm.Locked ? lara.TargetArmOrient : EulerAngles::Zero;
|
auto targetArmOrient = arm.Locked ? player.TargetArmOrient : EulerAngles::Zero;
|
||||||
arm.Orientation.InterpolateConstant(targetArmOrient, weaponInfo.AimSpeed);
|
arm.Orientation.InterpolateConstant(targetArmOrient, weaponInfo.AimSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, ItemInfo* laraItem, const EulerAngles& armOrient)
|
// TODO: Include snowmobile gun in GetAmmo(), otherwise the player won't be able to shoot while controlling it. -- TokyoSU 2023.04.21
|
||||||
|
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
auto& ammo = GetAmmo(lara, weaponType);
|
auto& ammo = GetAmmo(player, weaponType);
|
||||||
|
|
||||||
if (ammo.GetCount() == 0 && !ammo.HasInfinite())
|
if (ammo.GetCount() == 0 && !ammo.HasInfinite())
|
||||||
return FireWeaponType::NoAmmo;
|
return FireWeaponType::NoAmmo;
|
||||||
|
@ -789,8 +800,8 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, Ite
|
||||||
armOrient.y + (Random::GenerateAngle(0, ANGLE(180.0f)) - ANGLE(90.0f)) * weapon.ShotAccuracy / 65536,
|
armOrient.y + (Random::GenerateAngle(0, ANGLE(180.0f)) - ANGLE(90.0f)) * weapon.ShotAccuracy / 65536,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
auto muzzleOffset = GetJointPosition(laraItem, LM_RHAND);
|
auto muzzleOffset = GetJointPosition(&laraItem, LM_RHAND);
|
||||||
auto pos = Vector3i(laraItem->Pose.Position.x, muzzleOffset.y, laraItem->Pose.Position.z);
|
auto pos = Vector3i(laraItem.Pose.Position.x, muzzleOffset.y, laraItem.Pose.Position.z);
|
||||||
|
|
||||||
// Calculate ray from wobbled orientation.
|
// Calculate ray from wobbled orientation.
|
||||||
auto directionNorm = wobbledArmOrient.ToDirection();
|
auto directionNorm = wobbledArmOrient.ToDirection();
|
||||||
|
@ -798,7 +809,7 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, Ite
|
||||||
auto target = origin + (directionNorm * weapon.TargetDist);
|
auto target = origin + (directionNorm * weapon.TargetDist);
|
||||||
auto ray = Ray(origin, directionNorm);
|
auto ray = Ray(origin, directionNorm);
|
||||||
|
|
||||||
int num = GetSpheres(targetEntity, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity);
|
int num = GetSpheres(&targetEntity, CreatureSpheres, SPHERES_SPACE_WORLD, Matrix::Identity);
|
||||||
int bestJointIndex = NO_JOINT;
|
int bestJointIndex = NO_JOINT;
|
||||||
float bestDistance = INFINITY;
|
float bestDistance = INFINITY;
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
|
@ -815,11 +826,11 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, Ite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.Control.Weapon.HasFired = true;
|
player.Control.Weapon.HasFired = true;
|
||||||
lara.Control.Weapon.Fired = true;
|
player.Control.Weapon.Fired = true;
|
||||||
|
|
||||||
auto vOrigin = GameVector(pos);
|
auto vOrigin = GameVector(pos);
|
||||||
short roomNumber = laraItem->RoomNumber;
|
short roomNumber = laraItem.RoomNumber;
|
||||||
GetFloor(pos.x, pos.y, pos.z, &roomNumber);
|
GetFloor(pos.x, pos.y, pos.z, &roomNumber);
|
||||||
vOrigin.RoomNumber = roomNumber;
|
vOrigin.RoomNumber = roomNumber;
|
||||||
|
|
||||||
|
@ -838,46 +849,47 @@ FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, Ite
|
||||||
// NOTE: It seems that entities hit by the player in the normal way must have GetTargetOnLOS return false.
|
// NOTE: It seems that entities hit by the player in the normal way must have GetTargetOnLOS return false.
|
||||||
// It's strange, but this replicates original behaviour until we fully understand what is happening.
|
// It's strange, but this replicates original behaviour until we fully understand what is happening.
|
||||||
if (!GetTargetOnLOS(&vOrigin, &vTarget, false, true))
|
if (!GetTargetOnLOS(&vOrigin, &vTarget, false, true))
|
||||||
HitTarget(laraItem, targetEntity, &vTarget, weapon.Damage, false, bestJointIndex);
|
HitTarget(&laraItem, &targetEntity, &vTarget, weapon.Damage, false, bestJointIndex);
|
||||||
|
|
||||||
return FireWeaponType::PossibleHit;
|
return FireWeaponType::PossibleHit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo)
|
||||||
{
|
{
|
||||||
if (!g_Configuration.AutoTarget)
|
if (!g_Configuration.AutoTarget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
if (BinocularRange)
|
if (BinocularRange)
|
||||||
{
|
{
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto origin = GameVector(
|
auto origin = GameVector(
|
||||||
laraItem->Pose.Position.x,
|
laraItem.Pose.Position.x,
|
||||||
GetJointPosition(laraItem, LM_RHAND).y, // Muzzle offset.
|
GetJointPosition(&laraItem, LM_RHAND).y, // Muzzle offset.
|
||||||
laraItem->Pose.Position.z,
|
laraItem.Pose.Position.z,
|
||||||
laraItem->RoomNumber);
|
laraItem.RoomNumber);
|
||||||
|
|
||||||
ItemInfo* bestEntity = nullptr;
|
ItemInfo* closestEntityPtr = nullptr;
|
||||||
float bestDistance = INFINITY;
|
|
||||||
short bestYOrient = MAXSHORT;
|
float closestDistance = INFINITY;
|
||||||
unsigned int numTargets = 0;
|
short closestHeadingAngle = MAXSHORT;
|
||||||
|
unsigned int targetCount = 0;
|
||||||
float maxDistance = weaponInfo.TargetDist;
|
float maxDistance = weaponInfo.TargetDist;
|
||||||
|
|
||||||
for (auto* activeCreature : ActiveCreatures)
|
for (auto* creaturePtr : ActiveCreatures)
|
||||||
{
|
{
|
||||||
// Continue loop if no item.
|
// Continue loop if no item.
|
||||||
if (activeCreature->ItemNumber == NO_ITEM)
|
if (creaturePtr->ItemNumber == NO_ITEM)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto& item = g_Level.Items[activeCreature->ItemNumber];
|
auto& item = g_Level.Items[creaturePtr->ItemNumber];
|
||||||
|
|
||||||
// Check whether creature is alive.
|
// Check if creature is alive.
|
||||||
if (item.HitPoints <= 0)
|
if (item.HitPoints <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -887,64 +899,64 @@ void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Assess line of sight.
|
// Assess line of sight.
|
||||||
auto target = GetTargetPoint(&item);
|
auto target = GetTargetPoint(item);
|
||||||
if (!LOS(&origin, &target))
|
if (!LOS(&origin, &target))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Assess whether relative orientation falls within weapon's lock constraints.
|
// Assess whether relative orientation falls within weapon's lock constraints.
|
||||||
auto orient = Geometry::GetOrientToPoint(origin.ToVector3(), target.ToVector3()) - (laraItem->Pose.Orientation + lara.ExtraTorsoRot);
|
auto orient = Geometry::GetOrientToPoint(origin.ToVector3(), target.ToVector3()) - (laraItem.Pose.Orientation + player.ExtraTorsoRot);
|
||||||
if (orient.x >= weaponInfo.LockOrientConstraint.first.x &&
|
if (orient.x >= weaponInfo.LockOrientConstraint.first.x &&
|
||||||
orient.y >= weaponInfo.LockOrientConstraint.first.y &&
|
orient.y >= weaponInfo.LockOrientConstraint.first.y &&
|
||||||
orient.x <= weaponInfo.LockOrientConstraint.second.x &&
|
orient.x <= weaponInfo.LockOrientConstraint.second.x &&
|
||||||
orient.y <= weaponInfo.LockOrientConstraint.second.y)
|
orient.y <= weaponInfo.LockOrientConstraint.second.y)
|
||||||
{
|
{
|
||||||
TargetList[numTargets] = &item;
|
TargetList[targetCount] = &item;
|
||||||
++numTargets;
|
++targetCount;
|
||||||
|
|
||||||
if (distance < bestDistance &&
|
if (distance < closestDistance &&
|
||||||
abs(orient.y) < (bestYOrient + ANGLE(15.0f)))
|
abs(orient.y) < (closestHeadingAngle + ANGLE(15.0f)))
|
||||||
{
|
{
|
||||||
bestEntity = &item;
|
closestEntityPtr = &item;
|
||||||
bestDistance = distance;
|
closestDistance = distance;
|
||||||
bestYOrient = abs(orient.y);
|
closestHeadingAngle = abs(orient.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetList[numTargets] = nullptr;
|
TargetList[targetCount] = nullptr;
|
||||||
if (!TargetList[0])
|
if (TargetList[0] == nullptr)
|
||||||
{
|
{
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int slot = 0; slot < MAX_TARGETS; ++slot)
|
for (const auto* targetPtr : TargetList)
|
||||||
{
|
{
|
||||||
if (!TargetList[slot])
|
if (targetPtr == nullptr)
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
|
|
||||||
if (TargetList[slot] == lara.TargetEntity)
|
if (targetPtr == player.TargetEntity)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara.Control.HandStatus != HandStatus::Free || IsClicked(In::SwitchTarget))
|
if (IsClicked(In::SwitchTarget) || player.Control.HandStatus != HandStatus::Free)
|
||||||
{
|
{
|
||||||
if (lara.TargetEntity == nullptr)
|
if (player.TargetEntity == nullptr)
|
||||||
{
|
{
|
||||||
lara.TargetEntity = bestEntity;
|
player.TargetEntity = closestEntityPtr;
|
||||||
LastTargets[0] = nullptr;
|
LastTargets[0] = nullptr;
|
||||||
}
|
}
|
||||||
else if (IsClicked(In::SwitchTarget))
|
else if (IsClicked(In::SwitchTarget))
|
||||||
{
|
{
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
|
|
||||||
for (int match = 0; match < MAX_TARGETS && TargetList[match]; ++match)
|
for (const auto& targetPtr : TargetList)
|
||||||
{
|
{
|
||||||
bool doLoop = false;
|
bool doLoop = false;
|
||||||
for (int slot = 0; slot < MAX_TARGETS && LastTargets[slot]; ++slot)
|
for (const auto* lastTargetPtr : LastTargets)
|
||||||
{
|
{
|
||||||
if (LastTargets[slot] == TargetList[match])
|
if (lastTargetPtr == targetPtr)
|
||||||
{
|
{
|
||||||
doLoop = true;
|
doLoop = true;
|
||||||
break;
|
break;
|
||||||
|
@ -953,8 +965,8 @@ void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
||||||
|
|
||||||
if (!doLoop)
|
if (!doLoop)
|
||||||
{
|
{
|
||||||
lara.TargetEntity = TargetList[match];
|
player.TargetEntity = targetPtr;
|
||||||
if (lara.TargetEntity)
|
if (player.TargetEntity)
|
||||||
flag = false;
|
flag = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -963,44 +975,44 @@ void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
lara.TargetEntity = bestEntity;
|
player.TargetEntity = closestEntityPtr;
|
||||||
LastTargets[0] = nullptr;
|
LastTargets[0] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara.TargetEntity != LastTargets[0])
|
if (player.TargetEntity != LastTargets[0])
|
||||||
{
|
{
|
||||||
for (int slot = 7; slot > 0; --slot)
|
for (int slot = TARGET_COUNT_MAX - 1; slot > 0; --slot)
|
||||||
LastTargets[slot] = LastTargets[slot - 1];
|
LastTargets[slot] = LastTargets[slot - 1];
|
||||||
|
|
||||||
LastTargets[0] = lara.TargetEntity;
|
LastTargets[0] = player.TargetEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
LaraTargetInfo(laraItem, weaponInfo);
|
LaraTargetInfo(laraItem, weaponInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaraTargetInfo(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
void LaraTargetInfo(ItemInfo& laraItem, const WeaponInfo& weaponInfo)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
if (lara.TargetEntity == nullptr)
|
if (player.TargetEntity == nullptr)
|
||||||
{
|
{
|
||||||
lara.RightArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
lara.LeftArm.Locked = false;
|
player.LeftArm.Locked = false;
|
||||||
lara.TargetArmOrient = EulerAngles::Zero;
|
player.TargetArmOrient = EulerAngles::Zero;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto origin = GameVector(
|
auto origin = GameVector(
|
||||||
laraItem->Pose.Position.x,
|
laraItem.Pose.Position.x,
|
||||||
GetJointPosition(laraItem, LM_RHAND).y, // Muzzle offset.
|
GetJointPosition(&laraItem, LM_RHAND).y, // Muzzle offset.
|
||||||
laraItem->Pose.Position.z,
|
laraItem.Pose.Position.z,
|
||||||
laraItem->RoomNumber);
|
laraItem.RoomNumber);
|
||||||
auto target = GetTargetPoint(lara.TargetEntity);
|
auto target = GetTargetPoint(*player.TargetEntity);
|
||||||
|
|
||||||
auto orient = Geometry::GetOrientToPoint(origin.ToVector3(), target.ToVector3()) - laraItem->Pose.Orientation;
|
auto orient = Geometry::GetOrientToPoint(origin.ToVector3(), target.ToVector3()) - laraItem.Pose.Orientation;
|
||||||
|
|
||||||
if (LOS(&origin, &target))
|
if (LOS(&origin, &target))
|
||||||
{
|
{
|
||||||
|
@ -1009,41 +1021,41 @@ void LaraTargetInfo(ItemInfo* laraItem, const WeaponInfo& weaponInfo)
|
||||||
orient.x <= weaponInfo.LockOrientConstraint.second.x &&
|
orient.x <= weaponInfo.LockOrientConstraint.second.x &&
|
||||||
orient.y <= weaponInfo.LockOrientConstraint.second.y)
|
orient.y <= weaponInfo.LockOrientConstraint.second.y)
|
||||||
{
|
{
|
||||||
lara.RightArm.Locked = true;
|
player.RightArm.Locked = true;
|
||||||
lara.LeftArm.Locked = true;
|
player.LeftArm.Locked = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lara.LeftArm.Locked)
|
if (player.LeftArm.Locked)
|
||||||
{
|
{
|
||||||
if (orient.x < weaponInfo.LeftOrientConstraint.first.x ||
|
if (orient.x < weaponInfo.LeftOrientConstraint.first.x ||
|
||||||
orient.y < weaponInfo.LeftOrientConstraint.first.y ||
|
orient.y < weaponInfo.LeftOrientConstraint.first.y ||
|
||||||
orient.x > weaponInfo.LeftOrientConstraint.second.x ||
|
orient.x > weaponInfo.LeftOrientConstraint.second.x ||
|
||||||
orient.y > weaponInfo.LeftOrientConstraint.second.y)
|
orient.y > weaponInfo.LeftOrientConstraint.second.y)
|
||||||
{
|
{
|
||||||
lara.LeftArm.Locked = false;
|
player.LeftArm.Locked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara.RightArm.Locked)
|
if (player.RightArm.Locked)
|
||||||
{
|
{
|
||||||
if (orient.x < weaponInfo.RightOrientConstraint.first.x ||
|
if (orient.x < weaponInfo.RightOrientConstraint.first.x ||
|
||||||
orient.y < weaponInfo.RightOrientConstraint.first.y ||
|
orient.y < weaponInfo.RightOrientConstraint.first.y ||
|
||||||
orient.x > weaponInfo.RightOrientConstraint.second.x ||
|
orient.x > weaponInfo.RightOrientConstraint.second.x ||
|
||||||
orient.y > weaponInfo.RightOrientConstraint.second.y)
|
orient.y > weaponInfo.RightOrientConstraint.second.y)
|
||||||
{
|
{
|
||||||
lara.RightArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lara.RightArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
lara.LeftArm.Locked = false;
|
player.LeftArm.Locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.TargetArmOrient = orient;
|
player.TargetArmOrient = orient;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, int damage, bool isExplosive, int bestJointIndex)
|
void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, int damage, bool isExplosive, int bestJointIndex)
|
||||||
|
|
|
@ -5,8 +5,6 @@ class EulerAngles;
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
|
||||||
constexpr auto MAX_TARGETS = 8;
|
|
||||||
|
|
||||||
enum class FireWeaponType
|
enum class FireWeaponType
|
||||||
{
|
{
|
||||||
Miss = -1,
|
Miss = -1,
|
||||||
|
@ -48,20 +46,20 @@ struct WeaponInfo
|
||||||
extern int FlashGrenadeAftershockTimer;
|
extern int FlashGrenadeAftershockTimer;
|
||||||
extern WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons];
|
extern WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons];
|
||||||
|
|
||||||
void InitialiseNewWeapon(ItemInfo* laraItem);
|
void InitializeNewWeapon(ItemInfo& laraItem);
|
||||||
|
|
||||||
Ammo& GetAmmo(LaraInfo& lara, LaraWeaponType weaponType);
|
Ammo& GetAmmo(LaraInfo& lara, LaraWeaponType weaponType);
|
||||||
GameVector GetTargetPoint(ItemInfo* targetEntity);
|
GameVector GetTargetPoint(ItemInfo& targetEntity);
|
||||||
HolsterSlot GetWeaponHolsterSlot(LaraWeaponType weaponType);
|
HolsterSlot GetWeaponHolsterSlot(LaraWeaponType weaponType);
|
||||||
GAME_OBJECT_ID GetWeaponObjectID(LaraWeaponType weaponType);
|
GAME_OBJECT_ID GetWeaponObjectID(LaraWeaponType weaponType);
|
||||||
GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo* laraItem, LaraWeaponType weaponType);
|
GAME_OBJECT_ID GetWeaponObjectMeshID(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
|
|
||||||
void HandleWeapon(ItemInfo* laraItem);
|
void HandleWeapon(ItemInfo& laraItem);
|
||||||
void AimWeapon(ItemInfo* laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo);
|
void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo);
|
||||||
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo* targetEntity, ItemInfo* laraItem, const EulerAngles& armOrient);
|
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient);
|
||||||
|
|
||||||
void FindNewTarget(ItemInfo* laraItem, const WeaponInfo& weaponInfo);
|
void FindNewTarget(ItemInfo& laraItem, const WeaponInfo& weaponInfo);
|
||||||
void LaraTargetInfo(ItemInfo* laraItem, const WeaponInfo& weaponInfo);
|
void LaraTargetInfo(ItemInfo& laraItem, const WeaponInfo& weaponInfo);
|
||||||
void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, int damage, bool isExplosive, int bestJointIndex = NO_JOINT);
|
void HitTarget(ItemInfo* laraItem, ItemInfo* targetEntity, GameVector* hitPos, int damage, bool isExplosive, int bestJointIndex = NO_JOINT);
|
||||||
|
|
||||||
void SmashItem(short itemNumber);
|
void SmashItem(short itemNumber);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "Game/animation.h"
|
#include "Game/animation.h"
|
||||||
#include "Game/camera.h"
|
#include "Game/camera.h"
|
||||||
#include "Game/collision/collide_item.h"
|
#include "Game/collision/collide_item.h"
|
||||||
|
#include "Game/control/control.h"
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/effects/chaffFX.h"
|
#include "Game/effects/chaffFX.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
|
@ -11,16 +12,16 @@
|
||||||
#include "Game/Lara/lara_fire.h"
|
#include "Game/Lara/lara_fire.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
constexpr auto FLARE_LIFE_MAX = 60 * FPS;
|
constexpr auto FLARE_LIFE_MAX = 60.0f * FPS;
|
||||||
constexpr auto FLARE_LIGHT_COLOR = Vector3(0.8f, 0.42947f, 0.2921f);
|
constexpr auto FLARE_LIGHT_COLOR = Vector3(0.8f, 0.43f, 0.3f);
|
||||||
|
|
||||||
void FlareControl(short itemNumber)
|
void FlareControl(short itemNumber)
|
||||||
{
|
{
|
||||||
|
@ -43,13 +44,13 @@ void FlareControl(short itemNumber)
|
||||||
flareItem.Pose.Orientation.z = 0;
|
flareItem.Pose.Orientation.z = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto velocity = Vector3i(
|
auto vel = Vector3i(
|
||||||
flareItem.Animation.Velocity.z * phd_sin(flareItem.Pose.Orientation.y),
|
flareItem.Animation.Velocity.z * phd_sin(flareItem.Pose.Orientation.y),
|
||||||
flareItem.Animation.Velocity.y,
|
flareItem.Animation.Velocity.y,
|
||||||
flareItem.Animation.Velocity.z * phd_cos(flareItem.Pose.Orientation.y));
|
flareItem.Animation.Velocity.z * phd_cos(flareItem.Pose.Orientation.y));
|
||||||
|
|
||||||
auto prevPos = flareItem.Pose.Position;
|
auto prevPos = flareItem.Pose.Position;
|
||||||
flareItem.Pose.Position += Vector3i(velocity.x, 0, velocity.z);
|
flareItem.Pose.Position += Vector3i(vel.x, 0, vel.z);
|
||||||
|
|
||||||
if (TestEnvironment(ENV_FLAG_WATER, &flareItem) ||
|
if (TestEnvironment(ENV_FLAG_WATER, &flareItem) ||
|
||||||
TestEnvironment(ENV_FLAG_SWAMP, &flareItem))
|
TestEnvironment(ENV_FLAG_SWAMP, &flareItem))
|
||||||
|
@ -63,13 +64,14 @@ void FlareControl(short itemNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
flareItem.Pose.Position.y += flareItem.Animation.Velocity.y;
|
flareItem.Pose.Position.y += flareItem.Animation.Velocity.y;
|
||||||
DoProjectileDynamics(itemNumber, prevPos.x, prevPos.y, prevPos.z, velocity.x, velocity.y, velocity.z);
|
DoProjectileDynamics(itemNumber, prevPos.x, prevPos.y, prevPos.z, vel.x, vel.y, vel.z);
|
||||||
|
|
||||||
int& life = flareItem.Data;
|
int& life = flareItem.Data;
|
||||||
life &= 0x7FFF;
|
life &= 0x7FFF;
|
||||||
if (life >= FLARE_LIFE_MAX)
|
if (life >= FLARE_LIFE_MAX)
|
||||||
{
|
{
|
||||||
if (!flareItem.Animation.Velocity.y && !flareItem.Animation.Velocity.z)
|
if (flareItem.Animation.Velocity.y == 0.0f &&
|
||||||
|
flareItem.Animation.Velocity.z == 0.0f)
|
||||||
{
|
{
|
||||||
KillItem(itemNumber);
|
KillItem(itemNumber);
|
||||||
return;
|
return;
|
||||||
|
@ -83,91 +85,89 @@ void FlareControl(short itemNumber)
|
||||||
if (DoFlareLight(flareItem.Pose.Position, life))
|
if (DoFlareLight(flareItem.Pose.Position, life))
|
||||||
{
|
{
|
||||||
TriggerChaffEffects(flareItem, life);
|
TriggerChaffEffects(flareItem, life);
|
||||||
/* Hardcoded code */
|
|
||||||
|
|
||||||
life |= 0x8000;
|
life |= 0x8000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadyFlare(ItemInfo* laraItem)
|
void ReadyFlare(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
lara.Control.HandStatus = HandStatus::Free;
|
player.Control.HandStatus = HandStatus::Free;
|
||||||
lara.LeftArm.Orientation = EulerAngles::Zero;
|
player.LeftArm.Orientation =
|
||||||
lara.RightArm.Orientation = EulerAngles::Zero;
|
player.RightArm.Orientation = EulerAngles::Zero;
|
||||||
lara.LeftArm.Locked = false;
|
player.LeftArm.Locked =
|
||||||
lara.RightArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UndrawFlareMeshes(ItemInfo* laraItem)
|
void UndrawFlareMeshes(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND;
|
laraItem.Model.MeshIndex[LM_LHAND] = laraItem.Model.BaseMesh + LM_LHAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawFlareMeshes(ItemInfo* laraItem)
|
void DrawFlareMeshes(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
laraItem->Model.MeshIndex[LM_LHAND] = Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND;
|
laraItem.Model.MeshIndex[LM_LHAND] = Objects[ID_FLARE_ANIM].meshIndex + LM_LHAND;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UndrawFlare(ItemInfo* laraItem)
|
void UndrawFlare(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
int flareFrame = lara.Flare.Frame;
|
int flareFrame = player.Flare.Frame;
|
||||||
int armFrame = lara.LeftArm.FrameNumber;
|
int armFrame = player.LeftArm.FrameNumber;
|
||||||
|
|
||||||
lara.Flare.ControlLeft = true;
|
player.Flare.ControlLeft = true;
|
||||||
|
|
||||||
if (laraItem->Animation.TargetState == LS_IDLE &&
|
if (laraItem.Animation.TargetState == LS_IDLE &&
|
||||||
lara.Vehicle == NO_ITEM)
|
player.Context.Vehicle == NO_ITEM)
|
||||||
{
|
{
|
||||||
if (laraItem->Animation.AnimNumber == LA_STAND_IDLE)
|
if (laraItem.Animation.AnimNumber == LA_STAND_IDLE)
|
||||||
{
|
{
|
||||||
laraItem->Animation.AnimNumber = LA_DISCARD_FLARE;
|
laraItem.Animation.AnimNumber = LA_DISCARD_FLARE;
|
||||||
flareFrame = armFrame + g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
flareFrame = armFrame + g_Level.Anims[laraItem.Animation.AnimNumber].frameBase;
|
||||||
laraItem->Animation.FrameNumber = flareFrame;
|
laraItem.Animation.FrameNumber = flareFrame;
|
||||||
lara.Flare.Frame = flareFrame;
|
player.Flare.Frame = flareFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (laraItem->Animation.AnimNumber == LA_DISCARD_FLARE)
|
if (laraItem.Animation.AnimNumber == LA_DISCARD_FLARE)
|
||||||
{
|
{
|
||||||
lara.Flare.ControlLeft = false;
|
player.Flare.ControlLeft = false;
|
||||||
|
|
||||||
if (flareFrame >= (g_Level.Anims[laraItem->Animation.AnimNumber].frameBase + 31)) // 31 = Last frame.
|
if (flareFrame >= (g_Level.Anims[laraItem.Animation.AnimNumber].frameBase + 31)) // 31 = Last frame.
|
||||||
{
|
{
|
||||||
lara.Control.Weapon.RequestGunType = lara.Control.Weapon.LastGunType;
|
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
|
||||||
lara.Control.Weapon.GunType = lara.Control.Weapon.LastGunType;
|
player.Control.Weapon.GunType = player.Control.Weapon.LastGunType;
|
||||||
lara.Control.HandStatus = HandStatus::Free;
|
player.Control.HandStatus = HandStatus::Free;
|
||||||
|
|
||||||
InitialiseNewWeapon(laraItem);
|
InitializeNewWeapon(laraItem);
|
||||||
|
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
lara.RightArm.Locked = false;
|
player.LeftArm.Locked =
|
||||||
lara.LeftArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
SetAnimation(laraItem, LA_STAND_IDLE);
|
SetAnimation(&laraItem, LA_STAND_IDLE);
|
||||||
lara.Flare.Frame = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
player.Flare.Frame = g_Level.Anims[laraItem.Animation.AnimNumber].frameBase;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.Flare.Frame++;
|
player.Flare.Frame++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (laraItem->Animation.AnimNumber == LA_DISCARD_FLARE)
|
else if (laraItem.Animation.AnimNumber == LA_DISCARD_FLARE)
|
||||||
{
|
{
|
||||||
SetAnimation(laraItem, LA_STAND_IDLE);
|
SetAnimation(&laraItem, LA_STAND_IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (armFrame >= 33 && armFrame < 72)
|
if (armFrame >= 33 && armFrame < 72)
|
||||||
{
|
{
|
||||||
armFrame = 2;
|
armFrame = 2;
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
else if (!armFrame)
|
else if (!armFrame)
|
||||||
{
|
{
|
||||||
armFrame = 1;
|
armFrame = 1;
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
else if (armFrame >= 72 && armFrame < 95)
|
else if (armFrame >= 72 && armFrame < 95)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +176,7 @@ void UndrawFlare(ItemInfo* laraItem)
|
||||||
if (armFrame == 94)
|
if (armFrame == 94)
|
||||||
{
|
{
|
||||||
armFrame = 1;
|
armFrame = 1;
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (armFrame >= 1 && armFrame < 33)
|
else if (armFrame >= 1 && armFrame < 33)
|
||||||
|
@ -187,27 +187,27 @@ void UndrawFlare(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
CreateFlare(laraItem, ID_FLARE_ITEM, true);
|
CreateFlare(laraItem, ID_FLARE_ITEM, true);
|
||||||
UndrawFlareMeshes(laraItem);
|
UndrawFlareMeshes(laraItem);
|
||||||
lara.Flare.Life = 0;
|
player.Flare.Life = 0;
|
||||||
}
|
}
|
||||||
else if (armFrame == 33)
|
else if (armFrame == 33)
|
||||||
{
|
{
|
||||||
armFrame = 0;
|
armFrame = 0;
|
||||||
|
|
||||||
lara.Control.Weapon.RequestGunType = lara.Control.Weapon.LastGunType;
|
player.Control.Weapon.RequestGunType = player.Control.Weapon.LastGunType;
|
||||||
lara.Control.Weapon.GunType = lara.Control.Weapon.LastGunType;
|
player.Control.Weapon.GunType = player.Control.Weapon.LastGunType;
|
||||||
lara.Control.HandStatus = HandStatus::Free;
|
player.Control.HandStatus = HandStatus::Free;
|
||||||
|
|
||||||
InitialiseNewWeapon(laraItem);
|
InitializeNewWeapon(laraItem);
|
||||||
|
|
||||||
lara.TargetEntity = nullptr;
|
player.TargetEntity = nullptr;
|
||||||
lara.LeftArm.Locked = false;
|
player.LeftArm.Locked =
|
||||||
lara.RightArm.Locked = false;
|
player.RightArm.Locked = false;
|
||||||
lara.Flare.ControlLeft = false;
|
player.Flare.ControlLeft = false;
|
||||||
lara.Flare.Frame = 0;
|
player.Flare.Frame = 0;
|
||||||
}
|
}
|
||||||
else if (armFrame < 21)
|
else if (armFrame < 21)
|
||||||
{
|
{
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (armFrame >= 95 && armFrame < 110)
|
else if (armFrame >= 95 && armFrame < 110)
|
||||||
|
@ -217,30 +217,30 @@ void UndrawFlare(ItemInfo* laraItem)
|
||||||
if (armFrame == 110)
|
if (armFrame == 110)
|
||||||
{
|
{
|
||||||
armFrame = 1;
|
armFrame = 1;
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.LeftArm.FrameNumber = armFrame;
|
player.LeftArm.FrameNumber = armFrame;
|
||||||
SetFlareArm(laraItem, lara.LeftArm.FrameNumber);
|
SetFlareArm(laraItem, player.LeftArm.FrameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawFlare(ItemInfo* laraItem)
|
void DrawFlare(ItemInfo& laraItem)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
if (laraItem->Animation.ActiveState == LS_PICKUP_FLARE ||
|
if (laraItem.Animation.ActiveState == LS_PICKUP_FLARE ||
|
||||||
laraItem->Animation.ActiveState == LS_PICKUP)
|
laraItem.Animation.ActiveState == LS_PICKUP)
|
||||||
{
|
{
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
lara.Flare.ControlLeft = false;
|
player.Flare.ControlLeft = false;
|
||||||
lara.LeftArm.FrameNumber = 93;
|
player.LeftArm.FrameNumber = 93;
|
||||||
SetFlareArm(laraItem, 93);
|
SetFlareArm(laraItem, 93);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int armFrame = lara.LeftArm.FrameNumber + 1;
|
int armFrame = player.LeftArm.FrameNumber + 1;
|
||||||
lara.Flare.ControlLeft = true;
|
player.Flare.ControlLeft = true;
|
||||||
|
|
||||||
if (armFrame < 33 || armFrame > 94)
|
if (armFrame < 33 || armFrame > 94)
|
||||||
{
|
{
|
||||||
|
@ -254,11 +254,14 @@ void DrawFlare(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
if (armFrame == 72)
|
if (armFrame == 72)
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_FLARE_IGNITE_DRY, &laraItem->Pose, TestEnvironment(ENV_FLAG_WATER, laraItem) ? SoundEnvironment::Water : SoundEnvironment::Land);
|
player.Flare.Life = 1;
|
||||||
lara.Flare.Life = 1;
|
SoundEffect(
|
||||||
|
SFX_TR4_FLARE_IGNITE_DRY,
|
||||||
|
&laraItem.Pose,
|
||||||
|
TestEnvironment(ENV_FLAG_WATER, &laraItem) ? SoundEnvironment::Water : SoundEnvironment::Land);
|
||||||
}
|
}
|
||||||
|
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -266,18 +269,18 @@ void DrawFlare(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
ReadyFlare(laraItem);
|
ReadyFlare(laraItem);
|
||||||
armFrame = 0;
|
armFrame = 0;
|
||||||
DoFlareInHand(laraItem, lara.Flare.Life);
|
DoFlareInHand(laraItem, player.Flare.Life);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.LeftArm.FrameNumber = armFrame;
|
player.LeftArm.FrameNumber = armFrame;
|
||||||
SetFlareArm(laraItem, armFrame);
|
SetFlareArm(laraItem, armFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFlareArm(ItemInfo* laraItem, int armFrame)
|
void SetFlareArm(ItemInfo& laraItem, int armFrame)
|
||||||
{
|
{
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
auto& player = *GetLaraInfo(&laraItem);
|
||||||
int flareAnimNum = Objects[ID_FLARE_ANIM].animIndex;
|
int flareAnimNum = Objects[ID_FLARE_ANIM].animIndex;
|
||||||
|
|
||||||
if (armFrame >= 95)
|
if (armFrame >= 95)
|
||||||
|
@ -297,13 +300,13 @@ void SetFlareArm(ItemInfo* laraItem, int armFrame)
|
||||||
flareAnimNum += 1;
|
flareAnimNum += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara.LeftArm.AnimNumber = flareAnimNum;
|
player.LeftArm.AnimNumber = flareAnimNum;
|
||||||
lara.LeftArm.FrameBase = g_Level.Anims[flareAnimNum].FramePtr;
|
player.LeftArm.FrameBase = g_Level.Anims[flareAnimNum].FramePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
void CreateFlare(ItemInfo& laraItem, GAME_OBJECT_ID objectID, bool isThrown)
|
||||||
{
|
{
|
||||||
const auto& lara = *GetLaraInfo(laraItem);
|
const auto& lara = *GetLaraInfo(&laraItem);
|
||||||
|
|
||||||
auto itemNumber = CreateItem();
|
auto itemNumber = CreateItem();
|
||||||
if (itemNumber == NO_ITEM)
|
if (itemNumber == NO_ITEM)
|
||||||
|
@ -311,36 +314,40 @@ void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
||||||
|
|
||||||
auto& flareItem = g_Level.Items[itemNumber];
|
auto& flareItem = g_Level.Items[itemNumber];
|
||||||
|
|
||||||
flareItem.ObjectNumber = objectNumber;
|
flareItem.ObjectNumber = objectID;
|
||||||
flareItem.RoomNumber = laraItem->RoomNumber;
|
flareItem.RoomNumber = laraItem.RoomNumber;
|
||||||
|
|
||||||
auto pos = GetJointPosition(laraItem, LM_LHAND, Vector3i(-16, 32, 42));
|
auto pos = GetJointPosition(&laraItem, LM_LHAND, Vector3i(-16, 32, 42));
|
||||||
|
|
||||||
flareItem.Pose.Position = pos;
|
flareItem.Pose.Position = pos;
|
||||||
|
|
||||||
int floorHeight = GetCollision(pos.x, pos.y, pos.z, laraItem->RoomNumber).Position.Floor;
|
int floorHeight = GetCollision(pos.x, pos.y, pos.z, laraItem.RoomNumber).Position.Floor;
|
||||||
auto hasCollided = GetCollidedObjects(&flareItem, 0, true, CollidedItems, CollidedMeshes, true);
|
auto hasCollided = GetCollidedObjects(&flareItem, 0, true, CollidedItems, CollidedMeshes, true);
|
||||||
bool hasLanded = false;
|
bool hasLanded = false;
|
||||||
|
|
||||||
if (floorHeight < pos.y || hasCollided)
|
if (floorHeight < pos.y || hasCollided)
|
||||||
{
|
{
|
||||||
hasLanded = true;
|
hasLanded = true;
|
||||||
flareItem.Pose.Position.x = laraItem->Pose.Position.x + 320 * phd_sin(flareItem.Pose.Orientation.y);
|
flareItem.Pose.Position.x = laraItem.Pose.Position.x + 320 * phd_sin(flareItem.Pose.Orientation.y);
|
||||||
flareItem.Pose.Position.z = laraItem->Pose.Position.z + 320 * phd_cos(flareItem.Pose.Orientation.y);
|
flareItem.Pose.Position.z = laraItem.Pose.Position.z + 320 * phd_cos(flareItem.Pose.Orientation.y);
|
||||||
flareItem.Pose.Orientation.y = laraItem->Pose.Orientation.y + ANGLE(180.0f);
|
flareItem.Pose.Orientation.y = laraItem.Pose.Orientation.y + ANGLE(180.0f);
|
||||||
flareItem.RoomNumber = laraItem->RoomNumber;
|
flareItem.RoomNumber = laraItem.RoomNumber;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isThrown)
|
if (isThrown)
|
||||||
flareItem.Pose.Orientation.y = laraItem->Pose.Orientation.y;
|
{
|
||||||
|
flareItem.Pose.Orientation.y = laraItem.Pose.Orientation.y;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
flareItem.Pose.Orientation.y = laraItem->Pose.Orientation.y - ANGLE(45.0f);
|
{
|
||||||
|
flareItem.Pose.Orientation.y = laraItem.Pose.Orientation.y - ANGLE(45.0f);
|
||||||
|
}
|
||||||
|
|
||||||
flareItem.RoomNumber = laraItem->RoomNumber;
|
flareItem.RoomNumber = laraItem.RoomNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitialiseItem(itemNumber);
|
InitializeItem(itemNumber);
|
||||||
|
|
||||||
flareItem.Pose.Orientation.x = 0;
|
flareItem.Pose.Orientation.x = 0;
|
||||||
flareItem.Pose.Orientation.z = 0;
|
flareItem.Pose.Orientation.z = 0;
|
||||||
|
@ -348,19 +355,19 @@ void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
||||||
|
|
||||||
if (isThrown)
|
if (isThrown)
|
||||||
{
|
{
|
||||||
flareItem.Animation.Velocity.z = laraItem->Animation.Velocity.z + 50;
|
flareItem.Animation.Velocity.z = laraItem.Animation.Velocity.z + 50;
|
||||||
flareItem.Animation.Velocity.y = laraItem->Animation.Velocity.y - 50;
|
flareItem.Animation.Velocity.y = laraItem.Animation.Velocity.y - 50;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flareItem.Animation.Velocity.z = laraItem->Animation.Velocity.z + 10;
|
flareItem.Animation.Velocity.z = laraItem.Animation.Velocity.z + 10;
|
||||||
flareItem.Animation.Velocity.y = laraItem->Animation.Velocity.y + 50;
|
flareItem.Animation.Velocity.y = laraItem.Animation.Velocity.y + 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasLanded)
|
if (hasLanded)
|
||||||
flareItem.Animation.Velocity.z /= 2;
|
flareItem.Animation.Velocity.z /= 2;
|
||||||
|
|
||||||
if (objectNumber == ID_FLARE_ITEM)
|
if (objectID == ID_FLARE_ITEM)
|
||||||
{
|
{
|
||||||
flareItem.Data = (int)0;
|
flareItem.Data = (int)0;
|
||||||
int& life = flareItem.Data;
|
int& life = flareItem.Data;
|
||||||
|
@ -379,28 +386,21 @@ void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown)
|
||||||
flareItem.Status = ITEM_ACTIVE;
|
flareItem.Status = ITEM_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawFlareInAir(ItemInfo* flareItem)
|
void DoFlareInHand(ItemInfo& laraItem, int flareLife)
|
||||||
{
|
{
|
||||||
TENLog("DrawFlareInAir() not implemented!", LogLevel::Warning);
|
auto& lara = *GetLaraInfo(&laraItem);
|
||||||
}
|
|
||||||
|
|
||||||
void DoFlareInHand(ItemInfo* laraItem, int flareLife)
|
auto pos = GetJointPosition(&laraItem, LM_LHAND, Vector3i(11, 32, 41));
|
||||||
{
|
|
||||||
auto& lara = *GetLaraInfo(laraItem);
|
|
||||||
|
|
||||||
auto pos = GetJointPosition(laraItem, LM_LHAND, Vector3i(11, 32, 41));
|
|
||||||
|
|
||||||
if (DoFlareLight(pos, flareLife))
|
if (DoFlareLight(pos, flareLife))
|
||||||
TriggerChaffEffects(BinocularOn ? 0 : flareLife);
|
TriggerChaffEffects(BinocularOn ? 0 : flareLife);
|
||||||
|
|
||||||
/* Hardcoded code */
|
|
||||||
|
|
||||||
if (lara.Flare.Life >= FLARE_LIFE_MAX)
|
if (lara.Flare.Life >= FLARE_LIFE_MAX)
|
||||||
{
|
{
|
||||||
// Prevent Lara from intercepting reach/jump states with flare throws.
|
// Prevent player from intercepting reach/jump states with flare throws.
|
||||||
if (laraItem->Animation.IsAirborne ||
|
if (laraItem.Animation.IsAirborne ||
|
||||||
laraItem->Animation.TargetState == LS_JUMP_PREPARE ||
|
laraItem.Animation.TargetState == LS_JUMP_PREPARE ||
|
||||||
laraItem->Animation.TargetState == LS_JUMP_FORWARD)
|
laraItem.Animation.TargetState == LS_JUMP_FORWARD)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -419,53 +419,39 @@ bool DoFlareLight(const Vector3i& pos, int flareLife)
|
||||||
if (flareLife >= FLARE_LIFE_MAX || flareLife == 0)
|
if (flareLife >= FLARE_LIFE_MAX || flareLife == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float randomFloat = Random::GenerateFloat();
|
auto sphere = BoundingSphere(pos.ToVector3() - Vector3(0, BLOCK(1 / 8.0f), 0), BLOCK(1 / 16.0f));
|
||||||
|
auto lightPos = Random::GeneratePointInSphere(sphere);
|
||||||
|
|
||||||
auto lightPos = pos + Vector3i(
|
bool spawnChaff = false;
|
||||||
randomFloat * 120,
|
|
||||||
(randomFloat * 120) - CLICK(1),
|
|
||||||
randomFloat * 120);
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
bool isEnding = (flareLife > (FLARE_LIFE_MAX - 90));
|
bool isEnding = (flareLife > (FLARE_LIFE_MAX - 90));
|
||||||
bool isDying = (flareLife > (FLARE_LIFE_MAX - 5));
|
bool isDying = (flareLife > (FLARE_LIFE_MAX - 5));
|
||||||
|
|
||||||
if (isDying)
|
if (isDying)
|
||||||
{
|
{
|
||||||
int falloff = 6 * (1.0f - (flareLife / FLARE_LIFE_MAX));
|
int falloff = (1.0f - (flareLife / FLARE_LIFE_MAX)) * 6;
|
||||||
|
auto color = FLARE_LIGHT_COLOR * 255;
|
||||||
|
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, falloff, color.x, color.y, color.z);
|
||||||
|
|
||||||
int r = FLARE_LIGHT_COLOR.x * 255;
|
spawnChaff = Random::TestProbability(9 / 10.0f);
|
||||||
int g = FLARE_LIGHT_COLOR.y * 255;
|
|
||||||
int b = FLARE_LIGHT_COLOR.z * 255;
|
|
||||||
|
|
||||||
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, falloff, r, g, b);
|
|
||||||
|
|
||||||
result = (randomFloat < 0.9f);
|
|
||||||
}
|
}
|
||||||
else if (isEnding)
|
else if (isEnding)
|
||||||
{
|
{
|
||||||
float multiplier = Random::GenerateFloat(0.05f, 1.0f);
|
float multiplier = Random::GenerateFloat(0.05f, 1.0f);
|
||||||
int falloff = 8 * multiplier;
|
int falloff = multiplier * 8;
|
||||||
|
auto color = (FLARE_LIGHT_COLOR * multiplier) * 255;
|
||||||
|
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, falloff, color.x, color.y, color.z);
|
||||||
|
|
||||||
int r = FLARE_LIGHT_COLOR.x * 255 * multiplier;
|
spawnChaff = Random::TestProbability(2 / 5.0f);
|
||||||
int g = FLARE_LIGHT_COLOR.y * 255 * multiplier;
|
|
||||||
int b = FLARE_LIGHT_COLOR.z * 255 * multiplier;
|
|
||||||
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, falloff, r, g, b);
|
|
||||||
|
|
||||||
result = (randomFloat < 0.4f);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float multiplier = Random::GenerateFloat(0.6f, 0.8f);
|
float multiplier = Random::GenerateFloat(0.6f, 0.8f);
|
||||||
int falloff = 8 * (1.0f - (flareLife / FLARE_LIFE_MAX));
|
int falloff = (1.0f - (flareLife / FLARE_LIFE_MAX)) * 8;
|
||||||
|
auto color = (FLARE_LIGHT_COLOR * multiplier) * 255;
|
||||||
|
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, falloff, color.x, color.y, color.z);
|
||||||
|
|
||||||
int r = FLARE_LIGHT_COLOR.x * 255 * multiplier;
|
spawnChaff = Random::TestProbability(3 / 10.0f);
|
||||||
int g = FLARE_LIGHT_COLOR.y * 255 * multiplier;
|
|
||||||
int b = FLARE_LIGHT_COLOR.z * 255 * multiplier;
|
|
||||||
TriggerDynamicLight(lightPos.x, lightPos.y, lightPos.z, falloff, r, g, b);
|
|
||||||
|
|
||||||
result = (randomFloat < 0.3f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((isDying || isEnding) ? result : true);
|
return ((isDying || isEnding) ? spawnChaff : true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Game/control/control.h"
|
|
||||||
|
|
||||||
|
enum GAME_OBJECT_ID : short;
|
||||||
|
class Vector3i;
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
class Vector3i;
|
|
||||||
enum GAME_OBJECT_ID : short;
|
|
||||||
|
|
||||||
void FlareControl(short itemNumber);
|
void FlareControl(short itemNumber);
|
||||||
void ReadyFlare(ItemInfo* laraItem);
|
void ReadyFlare(ItemInfo& laraItem);
|
||||||
void UndrawFlareMeshes(ItemInfo* laraItem);
|
|
||||||
void DrawFlareMeshes(ItemInfo* laraItem);
|
void UndrawFlareMeshes(ItemInfo& laraItem);
|
||||||
void UndrawFlare(ItemInfo* laraItem);
|
void DrawFlareMeshes(ItemInfo& laraItem);
|
||||||
void DrawFlare(ItemInfo* laraItem);
|
|
||||||
void SetFlareArm(ItemInfo* laraItem, int armFrame);
|
void UndrawFlare(ItemInfo& laraItem);
|
||||||
void CreateFlare(ItemInfo* laraItem, GAME_OBJECT_ID objectNumber, bool isThrown);
|
void DrawFlare(ItemInfo& laraItem);
|
||||||
void DrawFlareInAir(ItemInfo* flareItem);
|
|
||||||
void DoFlareInHand(ItemInfo* laraItem, int flareLife);
|
void SetFlareArm(ItemInfo& laraItem, int armFrame);
|
||||||
|
void CreateFlare(ItemInfo& laraItem, GAME_OBJECT_ID objectID, bool isThrown);
|
||||||
|
|
||||||
|
void DoFlareInHand(ItemInfo& laraItem, int flareLife);
|
||||||
bool DoFlareLight(const Vector3i& pos, int flareLife);
|
bool DoFlareLight(const Vector3i& pos, int flareLife);
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
#include "Game/Lara/lara_collide.h"
|
#include "Game/Lara/lara_collide.h"
|
||||||
#include "Game/Lara/lara_fire.h"
|
#include "Game/Lara/lara_fire.h"
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Scripting/Include/ScriptInterfaceLevel.h"
|
#include "Scripting/Include/ScriptInterfaceLevel.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
#include "Objects/TR2/Vehicles/skidoo.h"
|
#include "Objects/TR2/Vehicles/skidoo.h"
|
||||||
#include "Objects/TR3/Vehicles/big_gun.h"
|
#include "Objects/TR3/Vehicles/big_gun.h"
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
using namespace TEN::Control::Volumes;
|
using namespace TEN::Control::Volumes;
|
||||||
using namespace TEN::Effects::Bubble;
|
using namespace TEN::Effects::Bubble;
|
||||||
using namespace TEN::Effects::Drip;
|
using namespace TEN::Effects::Drip;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
|
@ -71,14 +71,14 @@ void HandleLaraMovementParameters(ItemInfo* item, CollisionInfo* coll)
|
||||||
if ((!lara->Control.IsMoving || (lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))) &&
|
if ((!lara->Control.IsMoving || (lara->Control.IsMoving && !(TrInput & (IN_LEFT | IN_RIGHT)))) &&
|
||||||
(!lara->Control.IsLow && item->Animation.ActiveState != LS_DEATH)) // HACK: Don't interfere with surface alignment in crouch, crawl, and death states.
|
(!lara->Control.IsLow && item->Animation.ActiveState != LS_DEATH)) // HACK: Don't interfere with surface alignment in crouch, crawl, and death states.
|
||||||
{
|
{
|
||||||
ResetLaraLean(item, 6.0f);
|
ResetPlayerLean(item, 1 / 6.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset crawl flex.
|
// Reset crawl flex.
|
||||||
if (!(TrInput & IN_LOOK) && coll->Setup.Height > LARA_HEIGHT - LARA_HEADROOM && // HACK
|
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 && !(TrInput & (IN_LEFT | IN_RIGHT)))))
|
||||||
{
|
{
|
||||||
ResetLaraFlex(item, 12.0f);
|
ResetPlayerFlex(item, 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply and reset turn rate.
|
// Apply and reset turn rate.
|
||||||
|
@ -94,20 +94,20 @@ bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
if (lara->Vehicle == NO_ITEM)
|
if (lara->Context.Vehicle == NO_ITEM)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!g_Level.Items[lara->Vehicle].Active)
|
if (!g_Level.Items[lara->Context.Vehicle].Active)
|
||||||
{
|
{
|
||||||
lara->Vehicle = NO_ITEM;
|
lara->Context.Vehicle = NO_ITEM;
|
||||||
item->Animation.IsAirborne = true;
|
item->Animation.IsAirborne = true;
|
||||||
SetAnimation(item, LA_FALL_START);
|
SetAnimation(item, LA_FALL_START);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestVolumes(lara->Vehicle);
|
TestVolumes(lara->Context.Vehicle);
|
||||||
|
|
||||||
switch (g_Level.Items[lara->Vehicle].ObjectNumber)
|
switch (g_Level.Items[lara->Context.Vehicle].ObjectNumber)
|
||||||
{
|
{
|
||||||
case ID_QUAD:
|
case ID_QUAD:
|
||||||
QuadBikeControl(item, coll);
|
QuadBikeControl(item, coll);
|
||||||
|
@ -143,7 +143,7 @@ bool HandleLaraVehicle(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
// Boats are processed like normal items in loop.
|
// Boats are processed like normal items in loop.
|
||||||
default:
|
default:
|
||||||
HandleWeapon(item);
|
HandleWeapon(*item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -289,7 +289,7 @@ void DoLaraStep(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TestLaraStepUp(item, coll))
|
if (TestLaraStepUp(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_STEP_UP;
|
item->Animation.TargetState = LS_STEP_UP;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Pose.Position.y += coll->Middle.Floor;
|
item->Pose.Position.y += coll->Middle.Floor;
|
||||||
return;
|
return;
|
||||||
|
@ -298,7 +298,7 @@ void DoLaraStep(ItemInfo* item, CollisionInfo* coll)
|
||||||
else if (TestLaraStepDown(item, coll))
|
else if (TestLaraStepDown(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_STEP_DOWN;
|
item->Animation.TargetState = LS_STEP_DOWN;
|
||||||
if (GetStateDispatch(item, g_Level.Anims[item->Animation.AnimNumber]))
|
if (GetStateDispatch(item, GetAnimData(*item)))
|
||||||
{
|
{
|
||||||
item->Pose.Position.y += coll->Middle.Floor;
|
item->Pose.Position.y += coll->Middle.Floor;
|
||||||
return;
|
return;
|
||||||
|
@ -755,29 +755,30 @@ void SetLaraVault(ItemInfo* item, CollisionInfo* coll, VaultTestResult vaultResu
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
lara->ProjectedFloorHeight = vaultResult.Height;
|
lara->Context.ProjectedFloorHeight = vaultResult.Height;
|
||||||
lara->Control.HandStatus = vaultResult.SetBusyHands ? HandStatus::Busy : lara->Control.HandStatus;
|
lara->Control.HandStatus = vaultResult.SetBusyHands ? HandStatus::Busy : lara->Control.HandStatus;
|
||||||
lara->Control.TurnRate = 0;
|
lara->Control.TurnRate = 0;
|
||||||
|
|
||||||
if (vaultResult.SnapToLedge)
|
if (vaultResult.SnapToLedge)
|
||||||
{
|
{
|
||||||
SnapItemToLedge(item, coll, 0.2f, false);
|
SnapItemToLedge(item, coll, 0.2f, false);
|
||||||
lara->TargetOrientation = EulerAngles(0, coll->NearestLedgeAngle, 0);
|
lara->Context.TargetOrientation = EulerAngles(0, coll->NearestLedgeAngle, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lara->TargetOrientation = EulerAngles(0, item->Pose.Orientation.y, 0);
|
lara->Context.TargetOrientation = EulerAngles(0, item->Pose.Orientation.y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vaultResult.SetJumpVelocity)
|
if (vaultResult.SetJumpVelocity)
|
||||||
{
|
{
|
||||||
int height = lara->ProjectedFloorHeight - item->Pose.Position.y;
|
int height = lara->Context.ProjectedFloorHeight - item->Pose.Position.y;
|
||||||
if (height > -CLICK(3.5f))
|
if (height > -CLICK(3.5f))
|
||||||
height = -CLICK(3.5f);
|
height = -CLICK(3.5f);
|
||||||
else if (height < -CLICK(7.5f))
|
else if (height < -CLICK(7.5f))
|
||||||
height = -CLICK(7.5f);
|
height = -CLICK(7.5f);
|
||||||
|
|
||||||
lara->Control.CalculatedJumpVelocity = -3 - sqrt(-9600 - 12 * height); // TODO: Find a better formula for this that won't require the above block.
|
// TODO: Find a better formula for this that won't require the above block.
|
||||||
|
lara->Context.CalcJumpVelocity = -3 - sqrt(-9600 - 12 * (height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,7 +924,7 @@ void SetLaraCornerAnimation(ItemInfo* item, CollisionInfo* coll, bool flip)
|
||||||
item->Animation.Velocity.z = 2;
|
item->Animation.Velocity.z = 2;
|
||||||
item->Animation.Velocity.y = 1;
|
item->Animation.Velocity.y = 1;
|
||||||
item->Pose.Position.y += CLICK(1);
|
item->Pose.Position.y += CLICK(1);
|
||||||
item->Pose.Orientation.y += lara->NextCornerPos.Orientation.y / 2;
|
item->Pose.Orientation.y += lara->Context.NextCornerPos.Orientation.y / 2;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -935,9 +936,9 @@ void SetLaraCornerAnimation(ItemInfo* item, CollisionInfo* coll, bool flip)
|
||||||
else
|
else
|
||||||
SetAnimation(item, LA_HANG_IDLE);
|
SetAnimation(item, LA_HANG_IDLE);
|
||||||
|
|
||||||
item->Pose.Position = lara->NextCornerPos.Position;
|
item->Pose.Position = lara->Context.NextCornerPos.Position;
|
||||||
item->Pose.Orientation.y = lara->NextCornerPos.Orientation.y;
|
item->Pose.Orientation.y = lara->Context.NextCornerPos.Orientation.y;
|
||||||
coll->Setup.OldPosition = lara->NextCornerPos.Position;
|
coll->Setup.OldPosition = lara->Context.NextCornerPos.Position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -958,98 +959,49 @@ void SetLaraVehicle(ItemInfo* item, ItemInfo* vehicle)
|
||||||
|
|
||||||
if (vehicle == nullptr)
|
if (vehicle == nullptr)
|
||||||
{
|
{
|
||||||
if (lara->Vehicle != NO_ITEM)
|
if (lara->Context.Vehicle != NO_ITEM)
|
||||||
g_Level.Items[lara->Vehicle].Active = false;
|
g_Level.Items[lara->Context.Vehicle].Active = false;
|
||||||
|
|
||||||
lara->Vehicle = NO_ITEM;
|
lara->Context.Vehicle = NO_ITEM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_Level.Items[vehicle->Index].Active = true;
|
g_Level.Items[vehicle->Index].Active = true;
|
||||||
lara->Vehicle = vehicle->Index;
|
lara->Context.Vehicle = vehicle->Index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetLaraLean(ItemInfo* item, float rate, bool resetRoll, bool resetPitch)
|
void ResetPlayerLean(ItemInfo* item, float alpha, bool resetRoll, bool resetPitch)
|
||||||
{
|
{
|
||||||
if (!rate)
|
if (resetRoll)
|
||||||
{
|
item->Pose.Orientation.Lerp(EulerAngles(item->Pose.Orientation.x, item->Pose.Orientation.y, 0), alpha);
|
||||||
TENLog(std::string("ResetLaraLean() attempted division by zero!"), LogLevel::Warning);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rate = abs(rate);
|
|
||||||
|
|
||||||
if (resetPitch)
|
if (resetPitch)
|
||||||
{
|
item->Pose.Orientation.Lerp(EulerAngles(0, item->Pose.Orientation.y, item->Pose.Orientation.z), alpha);
|
||||||
if (abs(item->Pose.Orientation.x) > ANGLE(0.1f))
|
|
||||||
item->Pose.Orientation.x += item->Pose.Orientation.x / -rate;
|
|
||||||
else
|
|
||||||
item->Pose.Orientation.x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resetRoll)
|
|
||||||
{
|
|
||||||
if (abs(item->Pose.Orientation.z) > ANGLE(0.1f))
|
|
||||||
item->Pose.Orientation.z += item->Pose.Orientation.z / -rate;
|
|
||||||
else
|
|
||||||
item->Pose.Orientation.z = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetLaraFlex(ItemInfo* item, float rate)
|
void ResetPlayerFlex(ItemInfo* item, float alpha)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto& player = GetLaraInfo(*item);
|
||||||
|
|
||||||
if (!rate)
|
player.ExtraHeadRot.Lerp(EulerAngles::Zero, alpha);
|
||||||
{
|
player.ExtraTorsoRot.Lerp(EulerAngles::Zero, alpha);
|
||||||
TENLog(std::string("ResetLaraFlex() attempted division by zero."), LogLevel::Warning);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rate = abs(rate);
|
|
||||||
|
|
||||||
// Reset head.
|
|
||||||
if (abs(lara->ExtraHeadRot.x) > ANGLE(0.1f))
|
|
||||||
lara->ExtraHeadRot.x += lara->ExtraHeadRot.x / -rate;
|
|
||||||
else
|
|
||||||
lara->ExtraHeadRot.x = 0;
|
|
||||||
|
|
||||||
if (abs(lara->ExtraHeadRot.y) > ANGLE(0.1f))
|
|
||||||
lara->ExtraHeadRot.y += lara->ExtraHeadRot.y / -rate;
|
|
||||||
else
|
|
||||||
lara->ExtraHeadRot.y = 0;
|
|
||||||
|
|
||||||
if (abs(lara->ExtraHeadRot.z) > ANGLE(0.1f))
|
|
||||||
lara->ExtraHeadRot.z += lara->ExtraHeadRot.z / -rate;
|
|
||||||
else
|
|
||||||
lara->ExtraHeadRot.z = 0;
|
|
||||||
|
|
||||||
// Reset torso.
|
|
||||||
if (abs(lara->ExtraTorsoRot.x) > ANGLE(0.1f))
|
|
||||||
lara->ExtraTorsoRot.x += lara->ExtraTorsoRot.x / -rate;
|
|
||||||
else
|
|
||||||
lara->ExtraTorsoRot.x = 0;
|
|
||||||
|
|
||||||
if (abs(lara->ExtraTorsoRot.y) > ANGLE(0.1f))
|
|
||||||
lara->ExtraTorsoRot.y += lara->ExtraTorsoRot.y / -rate;
|
|
||||||
else
|
|
||||||
lara->ExtraTorsoRot.y = 0;
|
|
||||||
|
|
||||||
if (abs(lara->ExtraTorsoRot.z) > ANGLE(0.1f))
|
|
||||||
lara->ExtraTorsoRot.z += lara->ExtraTorsoRot.z / -rate;
|
|
||||||
else
|
|
||||||
lara->ExtraTorsoRot.z = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RumbleLaraHealthCondition(ItemInfo* item)
|
void RumbleLaraHealthCondition(ItemInfo* item)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
constexpr auto POWER = 0.2f;
|
||||||
|
constexpr auto DELAY = 0.1f;
|
||||||
|
|
||||||
if (item->HitPoints > LARA_HEALTH_CRITICAL && lara->Status.Poison == 0)
|
const auto& player = GetLaraInfo(*item);
|
||||||
|
|
||||||
|
if (item->HitPoints > LARA_HEALTH_CRITICAL && player.Status.Poison == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool doPulse = (GlobalCounter & 0x0F) % 0x0F == 1;
|
if (item->HitPoints == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool doPulse = ((GlobalCounter & 0x0F) % 0x0F == 1);
|
||||||
if (doPulse)
|
if (doPulse)
|
||||||
Rumble(0.2f, 0.1f);
|
Rumble(POWER, DELAY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ void SetLaraCornerAnimation(ItemInfo* item, CollisionInfo* coll, bool flip);
|
||||||
void SetLaraSwimDiveAnimation(ItemInfo* item);
|
void SetLaraSwimDiveAnimation(ItemInfo* item);
|
||||||
void SetLaraVehicle(ItemInfo* item, ItemInfo* vehicle = nullptr);
|
void SetLaraVehicle(ItemInfo* item, ItemInfo* vehicle = nullptr);
|
||||||
|
|
||||||
void ResetLaraLean(ItemInfo* item, float rate = 1.0f, bool resetRoll = true, bool resetPitch = true);
|
void ResetPlayerLean(ItemInfo* item, float alpha = 1.0f, bool resetRoll = true, bool resetPitch = true);
|
||||||
void ResetLaraFlex(ItemInfo* item, float rate = 1.0f);
|
void ResetPlayerFlex(ItemInfo* item, float alpha = 1.0f);
|
||||||
|
|
||||||
void RumbleLaraHealthCondition(ItemInfo* item);
|
void RumbleLaraHealthCondition(ItemInfo* item);
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
#include "Game/Lara/lara_flare.h"
|
#include "Game/Lara/lara_flare.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Hud;
|
using namespace TEN::Hud;
|
||||||
|
|
||||||
void InitialiseLara(bool restore)
|
void InitializeLara(bool restore)
|
||||||
{
|
{
|
||||||
if (Lara.ItemNumber == NO_ITEM)
|
if (Lara.ItemNumber == NO_ITEM)
|
||||||
return;
|
return;
|
||||||
|
@ -39,10 +39,10 @@ void InitialiseLara(bool restore)
|
||||||
Lara.ItemNumber = itemNumber;
|
Lara.ItemNumber = itemNumber;
|
||||||
Lara.HitDirection = -1;
|
Lara.HitDirection = -1;
|
||||||
Lara.Control.Weapon.WeaponItem = NO_ITEM;
|
Lara.Control.Weapon.WeaponItem = NO_ITEM;
|
||||||
Lara.WaterSurfaceDist = 100;
|
Lara.Context.WaterSurfaceDist = 100;
|
||||||
|
|
||||||
Lara.ExtraAnim = NO_ITEM;
|
Lara.ExtraAnim = NO_ITEM;
|
||||||
Lara.Vehicle = NO_ITEM;
|
Lara.Context.Vehicle = NO_ITEM;
|
||||||
Lara.Location = -1;
|
Lara.Location = -1;
|
||||||
Lara.HighestLocation = -1;
|
Lara.HighestLocation = -1;
|
||||||
Lara.Control.Rope.Ptr = -1;
|
Lara.Control.Rope.Ptr = -1;
|
||||||
|
@ -50,17 +50,17 @@ void InitialiseLara(bool restore)
|
||||||
Lara.Control.HandStatus = HandStatus::Free;
|
Lara.Control.HandStatus = HandStatus::Free;
|
||||||
|
|
||||||
if (restore)
|
if (restore)
|
||||||
InitialiseLaraLevelJump(itemNumber, &lBackup);
|
InitializeLaraLevelJump(itemNumber, &lBackup);
|
||||||
else
|
else
|
||||||
InitialiseLaraDefaultInventory();
|
InitializeLaraDefaultInventory();
|
||||||
|
|
||||||
InitialiseLaraMeshes(LaraItem);
|
InitializeLaraMeshes(LaraItem);
|
||||||
InitialiseLaraAnims(LaraItem);
|
InitializeLaraAnims(LaraItem);
|
||||||
|
|
||||||
g_Hud.StatusBars.Initialize(*LaraItem);
|
g_Hud.StatusBars.Initialize(*LaraItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseLaraMeshes(ItemInfo* item)
|
void InitializeLaraMeshes(ItemInfo* item)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ void InitialiseLaraMeshes(ItemInfo* item)
|
||||||
lara->RightArm.Locked = false;
|
lara->RightArm.Locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseLaraAnims(ItemInfo* item)
|
void InitializeLaraAnims(ItemInfo* item)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
|
@ -143,13 +143,13 @@ void InitialiseLaraAnims(ItemInfo* item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseLaraLoad(short itemNum)
|
void InitializeLaraLoad(short itemNum)
|
||||||
{
|
{
|
||||||
Lara.ItemNumber = itemNum;
|
Lara.ItemNumber = itemNum;
|
||||||
LaraItem = &g_Level.Items[itemNum];
|
LaraItem = &g_Level.Items[itemNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseLaraLevelJump(short itemNum, LaraInfo* lBackup)
|
void InitializeLaraLevelJump(short itemNum, LaraInfo* lBackup)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNum];
|
auto* item = &g_Level.Items[itemNum];
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
@ -169,10 +169,10 @@ void InitialiseLaraLevelJump(short itemNum, LaraInfo* lBackup)
|
||||||
lara->Control.HandStatus = lBackup->Control.HandStatus;
|
lara->Control.HandStatus = lBackup->Control.HandStatus;
|
||||||
lara->Control.Weapon = lBackup->Control.Weapon;
|
lara->Control.Weapon = lBackup->Control.Weapon;
|
||||||
lara->Flare = lBackup->Flare;
|
lara->Flare = lBackup->Flare;
|
||||||
DrawFlareMeshes(item);
|
DrawFlareMeshes(*item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseLaraDefaultInventory()
|
void InitializeLaraDefaultInventory()
|
||||||
{
|
{
|
||||||
if (Objects[ID_FLARE_INV_ITEM].loaded)
|
if (Objects[ID_FLARE_INV_ITEM].loaded)
|
||||||
Lara.Inventory.TotalFlares = 3;
|
Lara.Inventory.TotalFlares = 3;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Game/Lara/lara_struct.h"
|
#include "Game/Lara/lara_struct.h"
|
||||||
|
|
||||||
void InitialiseLara(bool restore);
|
void InitializeLara(bool restore);
|
||||||
void InitialiseLaraMeshes(ItemInfo* item);
|
void InitializeLaraMeshes(ItemInfo* item);
|
||||||
void InitialiseLaraAnims(ItemInfo* item);
|
void InitializeLaraAnims(ItemInfo* item);
|
||||||
void InitialiseLaraLoad(short itemNumber);
|
void InitializeLaraLoad(short itemNumber);
|
||||||
void InitialiseLaraLevelJump(short itemNum, LaraInfo* lBackup);
|
void InitializeLaraLevelJump(short itemNum, LaraInfo* lBackup);
|
||||||
void InitialiseLaraDefaultInventory();
|
void InitializeLaraDefaultInventory();
|
|
@ -10,11 +10,11 @@
|
||||||
#include "Game/Lara/lara_basic.h"
|
#include "Game/Lara/lara_basic.h"
|
||||||
#include "Game/Lara/lara_overhang.h"
|
#include "Game/Lara/lara_overhang.h"
|
||||||
#include "Game/Lara/lara_slide.h"
|
#include "Game/Lara/lara_slide.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
#include "Flow/ScriptInterfaceFlowHandler.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ void lara_col_jump_forward(ItemInfo* item, CollisionInfo* coll)
|
||||||
// Collision: lara_col_freefall()
|
// Collision: lara_col_freefall()
|
||||||
void lara_as_freefall(ItemInfo* item, CollisionInfo* coll)
|
void lara_as_freefall(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
item->Animation.Velocity.z = item->Animation.Velocity.z * 0.95f;
|
item->Animation.Velocity.z *= 0.95f;
|
||||||
|
|
||||||
ModulateLaraTurnRateY(item, 0, 0, 0);
|
ModulateLaraTurnRateY(item, 0, 0, 0);
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ void lara_as_pickup_flare(ItemInfo* item, CollisionInfo* coll)
|
||||||
Camera.targetElevation = -ANGLE(15.0f);
|
Camera.targetElevation = -ANGLE(15.0f);
|
||||||
Camera.targetDistance = SECTOR(1);
|
Camera.targetDistance = SECTOR(1);
|
||||||
|
|
||||||
if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd - 1)
|
if (item->Animation.FrameNumber == (GetAnimData(*item).frameEnd - 1))
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,16 +102,14 @@ void lara_col_turn_switch(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
if (item->Animation.AnimNumber == LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_CONTINUE)
|
if (item->Animation.AnimNumber == LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_CONTINUE)
|
||||||
{
|
{
|
||||||
|
SetAnimation(item, LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END);
|
||||||
item->Pose.Orientation.y -= ANGLE(90.0f);
|
item->Pose.Orientation.y -= ANGLE(90.0f);
|
||||||
item->Animation.AnimNumber = LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END;
|
|
||||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_CONTINUE)
|
if (item->Animation.AnimNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_CONTINUE)
|
||||||
{
|
{
|
||||||
|
SetAnimation(item, LA_TURNSWITCH_PUSH_CLOCKWISE_END);
|
||||||
item->Pose.Orientation.y += ANGLE(90.0f);
|
item->Pose.Orientation.y += ANGLE(90.0f);
|
||||||
item->Animation.AnimNumber = LA_TURNSWITCH_PUSH_CLOCKWISE_END;
|
|
||||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +149,7 @@ void lara_as_use_puzzle(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = LS_MISC_CONTROL;
|
item->Animation.ActiveState = LS_MISC_CONTROL;
|
||||||
item->Animation.AnimNumber = item->ItemFlags[0];
|
item->Animation.AnimNumber = item->ItemFlags[0];
|
||||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
item->Animation.FrameNumber = GetAnimData(*item).frameBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +206,7 @@ void lara_as_pushable_grab(ItemInfo* item, CollisionInfo* coll)
|
||||||
void lara_as_pulley(ItemInfo* item, CollisionInfo* coll)
|
void lara_as_pulley(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
auto* pulleyItem = &g_Level.Items[lara->InteractedItem];
|
auto* pulleyItem = &g_Level.Items[lara->Context.InteractedItem];
|
||||||
|
|
||||||
lara->Control.CanLook = false;
|
lara->Control.CanLook = false;
|
||||||
coll->Setup.EnableSpasm = false;
|
coll->Setup.EnableSpasm = false;
|
||||||
|
@ -220,7 +218,7 @@ void lara_as_pulley(ItemInfo* item, CollisionInfo* coll)
|
||||||
item->Animation.TargetState = LS_IDLE;
|
item->Animation.TargetState = LS_IDLE;
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_PULLEY_PULL &&
|
if (item->Animation.AnimNumber == LA_PULLEY_PULL &&
|
||||||
item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase + 44)
|
item->Animation.FrameNumber == GetAnimData(*item).frameBase + 44)
|
||||||
{
|
{
|
||||||
if (pulleyItem->TriggerFlags)
|
if (pulleyItem->TriggerFlags)
|
||||||
{
|
{
|
||||||
|
@ -250,7 +248,7 @@ void lara_as_pulley(ItemInfo* item, CollisionInfo* coll)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_PULLEY_RELEASE &&
|
if (item->Animation.AnimNumber == LA_PULLEY_RELEASE &&
|
||||||
item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd - 1)
|
item->Animation.FrameNumber == GetAnimData(*item).frameEnd - 1)
|
||||||
{
|
{
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
}
|
}
|
||||||
|
@ -284,11 +282,11 @@ void lara_as_horizontal_bar_swing(ItemInfo* item, CollisionInfo* coll)
|
||||||
void lara_as_horizontal_bar_leap(ItemInfo* item, CollisionInfo* coll)
|
void lara_as_horizontal_bar_leap(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
const auto& barItem = g_Level.Items[lara->InteractedItem];
|
const auto& barItem = g_Level.Items[lara->Context.InteractedItem];
|
||||||
|
|
||||||
item->Animation.IsAirborne = true;
|
item->Animation.IsAirborne = true;
|
||||||
|
|
||||||
if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase)
|
if (item->Animation.FrameNumber == GetAnimData(*item).frameBase)
|
||||||
{
|
{
|
||||||
int distance = 0;
|
int distance = 0;
|
||||||
if (item->Pose.Orientation.y == barItem.Pose.Orientation.y)
|
if (item->Pose.Orientation.y == barItem.Pose.Orientation.y)
|
||||||
|
@ -613,7 +611,7 @@ void lara_col_rope_idle(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TrInput & IN_SPRINT)
|
if (TrInput & IN_SPRINT)
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_ROPE_SWING;
|
item->Animation.TargetState = LS_ROPE_SWING;
|
||||||
lara->Control.Rope.DFrame = (g_Level.Anims[LA_ROPE_SWING].frameBase + 32) << 8;
|
lara->Control.Rope.DFrame = (GetAnimData(LA_ROPE_SWING).frameBase + 32) << 8;
|
||||||
lara->Control.Rope.Frame = lara->Control.Rope.DFrame;
|
lara->Control.Rope.Frame = lara->Control.Rope.DFrame;
|
||||||
}
|
}
|
||||||
else if (TrInput & IN_FORWARD && lara->Control.Rope.Segment > 4)
|
else if (TrInput & IN_FORWARD && lara->Control.Rope.Segment > 4)
|
||||||
|
@ -677,7 +675,7 @@ void lara_col_rope_swing(ItemInfo* item, CollisionInfo* coll)
|
||||||
item->Animation.FrameNumber = lara->Control.Rope.Frame >> 8;
|
item->Animation.FrameNumber = lara->Control.Rope.Frame >> 8;
|
||||||
|
|
||||||
if (!(TrInput & IN_SPRINT) &&
|
if (!(TrInput & IN_SPRINT) &&
|
||||||
item->Animation.FrameNumber == g_Level.Anims[LA_ROPE_SWING].frameBase + 32 &&
|
item->Animation.FrameNumber == GetAnimData(LA_ROPE_SWING).frameBase + 32 &&
|
||||||
lara->Control.Rope.MaxXBackward < 6750 &&
|
lara->Control.Rope.MaxXBackward < 6750 &&
|
||||||
lara->Control.Rope.MaxXForward < 6750)
|
lara->Control.Rope.MaxXForward < 6750)
|
||||||
{
|
{
|
||||||
|
@ -690,7 +688,7 @@ void lara_col_rope_swing(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TrInput & IN_JUMP)
|
if (TrInput & IN_JUMP)
|
||||||
JumpOffRope(item);
|
JumpOffRope(item);
|
||||||
}
|
}
|
||||||
else if (item->Animation.FrameNumber == g_Level.Anims[LA_ROPE_IDLE_TO_SWING].frameBase + 15)
|
else if (item->Animation.FrameNumber == GetAnimData(LA_ROPE_IDLE_TO_SWING).frameBase + 15)
|
||||||
ApplyVelocityToRope(lara->Control.Rope.Segment, item->Pose.Orientation.y, 128);
|
ApplyVelocityToRope(lara->Control.Rope.Segment, item->Pose.Orientation.y, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,9 +704,9 @@ void lara_as_rope_up(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
Camera.targetAngle = ANGLE(30.0f);
|
Camera.targetAngle = ANGLE(30.0f);
|
||||||
|
|
||||||
if (g_Level.Anims[item->Animation.AnimNumber].frameEnd == item->Animation.FrameNumber)
|
if (GetAnimData(*item).frameEnd == item->Animation.FrameNumber)
|
||||||
{
|
{
|
||||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
item->Animation.FrameNumber = GetAnimData(*item).frameBase;
|
||||||
lara->Control.Rope.Segment -= 2;
|
lara->Control.Rope.Segment -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Game/control/control.h"
|
|
||||||
#include "Math/Math.h"
|
|
||||||
#include "Specific/clock.h"
|
|
||||||
|
|
||||||
enum class LaraWeaponType;
|
enum class LaraWeaponType;
|
||||||
|
class GameVector;
|
||||||
|
class Pose;
|
||||||
|
class Vector3i;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
|
||||||
enum class GrenadeType
|
enum class GrenadeType
|
||||||
|
@ -26,28 +26,28 @@ enum class ProjectileType
|
||||||
FlashGrenade
|
FlashGrenade
|
||||||
};
|
};
|
||||||
|
|
||||||
void AnimateShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void AnimateShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void ReadyShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void ReadyShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void FireShotgun(ItemInfo* laraItem);
|
void FireShotgun(ItemInfo& laraItem);
|
||||||
void DrawShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void DrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void UndrawShotgun(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void UndrawShotgun(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void DrawShotgunMeshes(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void DrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void UndrawShotgunMeshes(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void UndrawShotgunMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
|
|
||||||
ItemInfo* FireHarpoon(ItemInfo* laraItem);
|
ItemInfo* FireHarpoon(ItemInfo& laraItem);
|
||||||
void HarpoonBoltControl(short itemNumber);
|
void HarpoonBoltControl(short itemNumber);
|
||||||
void FireGrenade(ItemInfo* laraItem);
|
void FireGrenade(ItemInfo& laraItem);
|
||||||
void GrenadeControl(short itemNumber);
|
void GrenadeControl(short itemNumber);
|
||||||
void FireRocket(ItemInfo* laraItem);
|
void FireRocket(ItemInfo& laraItem);
|
||||||
void RocketControl(short itemNumber);
|
void RocketControl(short itemNumber);
|
||||||
void FireCrossbow(ItemInfo* laraItem, Pose* pos);
|
void FireCrossbow(ItemInfo& laraItem, Pose* pos);
|
||||||
|
void FireCrossBowFromLaserSight(ItemInfo& laraItem, GameVector* origin, GameVector* target);
|
||||||
void CrossbowBoltControl(short itemNumber);
|
void CrossbowBoltControl(short itemNumber);
|
||||||
void FireCrossBowFromLaserSight(ItemInfo* laraItem, GameVector* origin, GameVector* target);
|
|
||||||
|
|
||||||
void FireHK(ItemInfo* laraItem, int mode);
|
void FireHK(ItemInfo& laraItem, int mode);
|
||||||
void RifleHandler(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void RifleHandler(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void LasersightWeaponHandler(ItemInfo* item, LaraWeaponType weaponType);
|
void LasersightWeaponHandler(ItemInfo& item, LaraWeaponType weaponType);
|
||||||
|
|
||||||
void DoExplosiveDamage(ItemInfo& emitter, ItemInfo& target, ItemInfo& projectile, int damage);
|
void DoExplosiveDamage(ItemInfo& emitter, ItemInfo& target, ItemInfo& projectile, int damage);
|
||||||
void HandleProjectile(ItemInfo& item, ItemInfo& emitter, const Vector3i& prevPos, ProjectileType type, int damage);
|
void HandleProjectile(ItemInfo& projectile, ItemInfo& emitter, const Vector3i& prevPos, ProjectileType type, int damage);
|
||||||
void SomeSparkEffect(int x, int y, int z, int count);
|
void SomeSparkEffect(int x, int y, int z, int count);
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
|
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Flow/ScriptInterfaceFlowHandler.h"
|
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
|
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
|
@ -336,7 +336,7 @@ void lara_col_slopeclimb(ItemInfo* item, CollisionInfo* coll)
|
||||||
// Engage shimmy mode if LEFT/LSTEP or RIGHT/RSTEP are pressed.
|
// Engage shimmy mode if LEFT/LSTEP or RIGHT/RSTEP are pressed.
|
||||||
if (TrInput & IN_LEFT || TrInput & IN_RIGHT)
|
if (TrInput & IN_LEFT || TrInput & IN_RIGHT)
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Orientation.z = (item->Animation.AnimNumber == LA_OVERHANG_IDLE_LEFT) ? true : false; // HACK.
|
lara->Context.NextCornerPos.Orientation.z = (item->Animation.AnimNumber == LA_OVERHANG_IDLE_LEFT) ? true : false; // HACK.
|
||||||
SetAnimation(item, item->Animation.AnimNumber == LA_OVERHANG_IDLE_LEFT ? LA_OVERHANG_IDLE_2_HANG_LEFT : LA_OVERHANG_IDLE_2_HANG_RIGHT);
|
SetAnimation(item, item->Animation.AnimNumber == LA_OVERHANG_IDLE_LEFT ? LA_OVERHANG_IDLE_2_HANG_LEFT : LA_OVERHANG_IDLE_2_HANG_RIGHT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ void lara_col_slopehang(ItemInfo* item, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
// Return to climbing mode.
|
// Return to climbing mode.
|
||||||
if (TrInput & IN_FORWARD || TrInput & IN_BACK)
|
if (TrInput & IN_FORWARD || TrInput & IN_BACK)
|
||||||
SetAnimation(item, lara->NextCornerPos.Orientation.z ? LA_OVERHANG_HANG_2_IDLE_LEFT : LA_OVERHANG_HANG_2_IDLE_RIGHT); // HACK.
|
SetAnimation(item, lara->Context.NextCornerPos.Orientation.z ? LA_OVERHANG_HANG_2_IDLE_LEFT : LA_OVERHANG_HANG_2_IDLE_RIGHT); // HACK.
|
||||||
|
|
||||||
// Shimmy control.
|
// Shimmy control.
|
||||||
if (TrInput & IN_LEFT || TrInput & IN_RIGHT)
|
if (TrInput & IN_LEFT || TrInput & IN_RIGHT)
|
||||||
|
@ -641,7 +641,7 @@ void lara_as_slopeclimbup(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (!(TrInput & IN_ACTION))
|
if (!(TrInput & IN_ACTION))
|
||||||
{
|
{
|
||||||
int frame = GetCurrentRelativeFrameNumber(item);
|
int frame = GetFrameNumber(item);
|
||||||
int length = GetFrameCount(item->Animation.AnimNumber);
|
int length = GetFrameCount(item->Animation.AnimNumber);
|
||||||
int dPos = CLICK(1) - (frame * CLICK(1) / length);
|
int dPos = CLICK(1) - (frame * CLICK(1) / length);
|
||||||
|
|
||||||
|
@ -671,7 +671,7 @@ void lara_as_slopeclimbdown(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (!(TrInput & IN_ACTION))
|
if (!(TrInput & IN_ACTION))
|
||||||
{
|
{
|
||||||
int frame = GetCurrentRelativeFrameNumber(item);
|
int frame = GetFrameNumber(item);
|
||||||
int length = GetFrameCount(item->Animation.AnimNumber);
|
int length = GetFrameCount(item->Animation.AnimNumber);
|
||||||
int dPos = frame * CLICK(1) / length;
|
int dPos = frame * CLICK(1) / length;
|
||||||
|
|
||||||
|
@ -688,7 +688,7 @@ void lara_as_sclimbstart(ItemInfo* item, CollisionInfo* coll)
|
||||||
// Rotating camera effect during monkey to overhead slope transition.
|
// Rotating camera effect during monkey to overhead slope transition.
|
||||||
if (item->Animation.AnimNumber == LA_OVERHANG_MONKEY_SLOPE_CONVEX)
|
if (item->Animation.AnimNumber == LA_OVERHANG_MONKEY_SLOPE_CONVEX)
|
||||||
{
|
{
|
||||||
int frame = GetCurrentRelativeFrameNumber(item);
|
int frame = GetFrameNumber(item);
|
||||||
int numFrames = GetFrameCount(item->Animation.AnimNumber);
|
int numFrames = GetFrameCount(item->Animation.AnimNumber);
|
||||||
|
|
||||||
float frac = (frame * 1.5f) / (float)(numFrames);
|
float frac = (frame * 1.5f) / (float)(numFrames);
|
||||||
|
@ -744,7 +744,7 @@ void lara_as_sclimbstop(ItemInfo* item, CollisionInfo* coll)
|
||||||
// Rotating camera effect during concave slope to monkey transition.
|
// Rotating camera effect during concave slope to monkey transition.
|
||||||
else if (item->Animation.AnimNumber == LA_OVERHANG_SLOPE_MONKEY_CONCAVE)
|
else if (item->Animation.AnimNumber == LA_OVERHANG_SLOPE_MONKEY_CONCAVE)
|
||||||
{
|
{
|
||||||
int frame = GetCurrentRelativeFrameNumber(item);
|
int frame = GetFrameNumber(item);
|
||||||
int numFrames = GetFrameCount(item->Animation.AnimNumber);
|
int numFrames = GetFrameCount(item->Animation.AnimNumber);
|
||||||
|
|
||||||
float frac = (frame * 1.25f) / (float)(numFrames);
|
float frac = (frame * 1.25f) / (float)(numFrames);
|
||||||
|
@ -810,7 +810,7 @@ void lara_as_sclimbend(ItemInfo* item, CollisionInfo* coll)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetLaraInfo(item)->NextCornerPos.Orientation.z = 0;
|
GetLaraInfo(item)->Context.NextCornerPos.Orientation.z = 0;
|
||||||
item->Pose.Orientation.x = 0;
|
item->Pose.Orientation.x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,7 +1050,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll)
|
||||||
auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber);
|
auto probeNow = GetCollision(now.x, now.y, now.z, item->RoomNumber);
|
||||||
auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber);
|
auto probeDown = GetCollision(down.x, down.y, down.z, item->RoomNumber);
|
||||||
|
|
||||||
if (item->Animation.AnimNumber == LA_REACH_TO_MONKEY && !GetFrameNumber(item, 0)) // Manage proper grabbing of monkey slope on forward jump.
|
if (item->Animation.AnimNumber == LA_REACH_TO_MONKEY && !GetFrameIndex(item, 0)) // Manage proper grabbing of monkey slope on forward jump.
|
||||||
{
|
{
|
||||||
int ceilDist = item->Pose.Position.y - probeNow.Position.Ceiling;
|
int ceilDist = item->Pose.Position.y - probeNow.Position.Ceiling;
|
||||||
|
|
||||||
|
@ -1064,7 +1064,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll)
|
||||||
|
|
||||||
if (SlopeCheck(probeNow.CeilingTilt, slopeData.Goal) || bridge >= 0)
|
if (SlopeCheck(probeNow.CeilingTilt, slopeData.Goal) || bridge >= 0)
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Orientation.z = AlignToGrab(item);
|
lara->Context.NextCornerPos.Orientation.z = AlignToGrab(item);
|
||||||
|
|
||||||
int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).Position.Ceiling;
|
int ceiling = GetCollision(probeNow.Block, item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z).Position.Ceiling;
|
||||||
item->Pose.Position.y = ceiling + HEIGHT_ADJUST;
|
item->Pose.Position.y = ceiling + HEIGHT_ADJUST;
|
||||||
|
@ -1077,7 +1077,7 @@ void SlopeMonkeyExtra(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TrInput & IN_FORWARD) // Monkey to slope transitions.
|
if (TrInput & IN_FORWARD) // Monkey to slope transitions.
|
||||||
{
|
{
|
||||||
if (probeNow.BottomBlock->Flags.Monkeyswing &&
|
if (probeNow.BottomBlock->Flags.Monkeyswing &&
|
||||||
((item->Animation.AnimNumber == LA_REACH_TO_MONKEY && GetFrameNumber(item, 0) >= 54) || item->Animation.AnimNumber == LA_MONKEY_IDLE))
|
((item->Animation.AnimNumber == LA_REACH_TO_MONKEY && GetFrameIndex(item, 0) >= 54) || item->Animation.AnimNumber == LA_MONKEY_IDLE))
|
||||||
{
|
{
|
||||||
if (abs(OrientDelta(slopeData.GoalOrient, item->Pose.Orientation.y)) <= ANGLE(30.0f) &&
|
if (abs(OrientDelta(slopeData.GoalOrient, item->Pose.Orientation.y)) <= ANGLE(30.0f) &&
|
||||||
InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, 0, CLICK(0.5f)))
|
InStrip(item->Pose.Position.x, item->Pose.Position.z, item->Pose.Orientation.y, 0, CLICK(0.5f)))
|
||||||
|
|
|
@ -134,7 +134,7 @@ void lara_as_slide_back(ItemInfo* item, CollisionInfo* coll)
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
Camera.targetElevation = -ANGLE(45.0f);
|
Camera.targetElevation = -ANGLE(45.0f);
|
||||||
Camera.targetAngle = ANGLE(135.0f);
|
//Camera.targetAngle = ANGLE(135.0f); // TODO: Player setting to swivel camera around. -- Sezz 2023.04.09
|
||||||
|
|
||||||
if (item->HitPoints <= 0)
|
if (item->HitPoints <= 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,14 +4,10 @@
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
namespace TEN::Renderer
|
|
||||||
{
|
|
||||||
struct RendererMesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CreatureInfo;
|
struct CreatureInfo;
|
||||||
struct FX_INFO;
|
struct FX_INFO;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
namespace TEN::Renderer { struct RendererMesh; };
|
||||||
|
|
||||||
// Inventory object constants
|
// Inventory object constants
|
||||||
constexpr int NUM_PUZZLES = ID_PUZZLE_ITEM16 - ID_PUZZLE_ITEM1 + 1;
|
constexpr int NUM_PUZZLES = ID_PUZZLE_ITEM16 - ID_PUZZLE_ITEM1 + 1;
|
||||||
|
@ -212,6 +208,10 @@ enum LaraState
|
||||||
LS_CRAWL_TURN_180 = 172,
|
LS_CRAWL_TURN_180 = 172,
|
||||||
LS_TURN_180 = 173,
|
LS_TURN_180 = 173,
|
||||||
|
|
||||||
|
// 174-188 reserved for "true" ladders. -- Sezz 2023.04.16
|
||||||
|
|
||||||
|
LS_REMOVE_PUZZLE = 189,
|
||||||
|
|
||||||
NUM_LARA_STATES
|
NUM_LARA_STATES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -508,7 +508,7 @@ enum LaraAnim
|
||||||
LA_CRAWL_IDLE_TO_CRAWL_BACK = 275, // Crawl > crawl back
|
LA_CRAWL_IDLE_TO_CRAWL_BACK = 275, // Crawl > crawl back
|
||||||
LA_CRAWL_BACK = 276, // Crawl back (looped)
|
LA_CRAWL_BACK = 276, // Crawl back (looped)
|
||||||
LA_CRAWL_BACK_TO_IDLE_RIGHT = 277, // Crawl back > crawl idle, right foot first
|
LA_CRAWL_BACK_TO_IDLE_RIGHT = 277, // Crawl back > crawl idle, right foot first
|
||||||
LA_CRAWL_BACK_TO_IDLE_RIGHT_END = 278, // Unused.
|
LA_REMOVE_PUZZLE = 278, // Remove puzzle item > idle
|
||||||
LA_CRAWL_BACK_TO_IDLE_LEFT = 279, // Crawl back > crawl idle, left foot first
|
LA_CRAWL_BACK_TO_IDLE_LEFT = 279, // Crawl back > crawl idle, left foot first
|
||||||
LA_CRAWL_BACK_TO_IDLE_LEFT_END = 280, // Unused.
|
LA_CRAWL_BACK_TO_IDLE_LEFT_END = 280, // Unused.
|
||||||
LA_CRAWL_TURN_LEFT_TO_IDLE_EARLY = 281, // Crawl rotate left > crawl idle, early opportunity
|
LA_CRAWL_TURN_LEFT_TO_IDLE_EARLY = 281, // Crawl rotate left > crawl idle, early opportunity
|
||||||
|
@ -815,11 +815,12 @@ enum LaraAnim
|
||||||
LA_LEDGE_JUMP_BACK_START = 567,
|
LA_LEDGE_JUMP_BACK_START = 567,
|
||||||
LA_LEDGE_JUMP_BACK_END = 568,
|
LA_LEDGE_JUMP_BACK_END = 568,
|
||||||
|
|
||||||
|
// 569-598 reserved for "true" ladders. -- Sezz 2023.04.16
|
||||||
|
|
||||||
NUM_LARA_ANIMS
|
NUM_LARA_ANIMS
|
||||||
|
|
||||||
// TRASHED ANIMS (please reuse slots before going any higher and remove entries from this list as you go):
|
// TRASHED ANIMS (please reuse slots before going any higher and remove entries from this list as you go):
|
||||||
// 102
|
// 280,
|
||||||
// 273, 274, 278, 280,
|
|
||||||
// 343, 345,
|
// 343, 345,
|
||||||
// 364, 366, 368, 370,
|
// 364, 366, 368, 370,
|
||||||
};
|
};
|
||||||
|
@ -865,6 +866,18 @@ enum LARA_MESHES
|
||||||
NUM_LARA_MESHES
|
NUM_LARA_MESHES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LaraWeaponTypeCarried
|
||||||
|
{
|
||||||
|
WTYPE_MISSING = 0,
|
||||||
|
WTYPE_PRESENT = (1 << 0),
|
||||||
|
WTYPE_SILENCER = (1 << 1),
|
||||||
|
WTYPE_LASERSIGHT = (1 << 2),
|
||||||
|
WTYPE_AMMO_1 = (1 << 3),
|
||||||
|
WTYPE_AMMO_2 = (1 << 4),
|
||||||
|
WTYPE_AMMO_3 = (1 << 5),
|
||||||
|
WTYPE_MASK_AMMO = WTYPE_AMMO_1 | WTYPE_AMMO_2 | WTYPE_AMMO_3,
|
||||||
|
};
|
||||||
|
|
||||||
enum class WeaponAmmoType
|
enum class WeaponAmmoType
|
||||||
{
|
{
|
||||||
Ammo1,
|
Ammo1,
|
||||||
|
@ -893,18 +906,6 @@ enum class LaraWeaponType
|
||||||
NumWeapons
|
NumWeapons
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LaraWeaponTypeCarried
|
|
||||||
{
|
|
||||||
WTYPE_MISSING = 0,
|
|
||||||
WTYPE_PRESENT = (1 << 0),
|
|
||||||
WTYPE_SILENCER = (1 << 1),
|
|
||||||
WTYPE_LASERSIGHT = (1 << 2),
|
|
||||||
WTYPE_AMMO_1 = (1 << 3),
|
|
||||||
WTYPE_AMMO_2 = (1 << 4),
|
|
||||||
WTYPE_AMMO_3 = (1 << 5),
|
|
||||||
WTYPE_MASK_AMMO = WTYPE_AMMO_1 | WTYPE_AMMO_2 | WTYPE_AMMO_3,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class HolsterSlot
|
enum class HolsterSlot
|
||||||
{
|
{
|
||||||
Empty = ID_LARA_HOLSTERS,
|
Empty = ID_LARA_HOLSTERS,
|
||||||
|
@ -919,14 +920,6 @@ enum class HolsterSlot
|
||||||
RocketLauncher = ID_ROCKET_ANIM
|
RocketLauncher = ID_ROCKET_ANIM
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Unused.
|
|
||||||
enum class ClothType
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Dry,
|
|
||||||
Wet
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class WaterStatus
|
enum class WaterStatus
|
||||||
{
|
{
|
||||||
Dry,
|
Dry,
|
||||||
|
@ -969,8 +962,8 @@ struct Ammo
|
||||||
using CountType = int;
|
using CountType = int;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CountType Count;
|
CountType Count = 0;
|
||||||
bool IsInfinite;
|
bool IsInfinite = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CountType Clamp(int value)
|
static CountType Clamp(int value)
|
||||||
|
@ -988,15 +981,15 @@ public:
|
||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetInfinite(bool infinite)
|
void SetInfinite(bool isInfinite)
|
||||||
{
|
{
|
||||||
this->IsInfinite = infinite;
|
IsInfinite = isInfinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ammo& operator --()
|
Ammo& operator --()
|
||||||
{
|
{
|
||||||
assertion(this->Count > 0, "Ammo count is already 0!");
|
assertion(Count > 0, "Ammo count is already 0.");
|
||||||
--this->Count;
|
--Count;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1009,7 +1002,7 @@ public:
|
||||||
|
|
||||||
Ammo& operator ++()
|
Ammo& operator ++()
|
||||||
{
|
{
|
||||||
++this->Count;
|
++Count;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1022,7 +1015,7 @@ public:
|
||||||
|
|
||||||
Ammo& operator =(int value)
|
Ammo& operator =(int value)
|
||||||
{
|
{
|
||||||
this->Count = Clamp(value);
|
Count = Clamp(value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,10 +1024,10 @@ public:
|
||||||
return (Count == Clamp(value));
|
return (Count == Clamp(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ammo& operator =(Ammo& rhs)
|
Ammo& operator =(Ammo& ammo)
|
||||||
{
|
{
|
||||||
this->Count = rhs.Count;
|
Count = ammo.Count;
|
||||||
this->IsInfinite = rhs.Count;
|
IsInfinite = ammo.Count;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,20 +1048,20 @@ public:
|
||||||
Ammo& operator +=(int value)
|
Ammo& operator +=(int value)
|
||||||
{
|
{
|
||||||
int temp = Count + value;
|
int temp = Count + value;
|
||||||
this->Count = Clamp(temp);
|
Count = Clamp(temp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ammo& operator -=(int value)
|
Ammo& operator -=(int value)
|
||||||
{
|
{
|
||||||
int temp = Count - value;
|
int temp = Count - value;
|
||||||
this->Count = Clamp(temp);
|
Count = Clamp(temp);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
return (IsInfinite || Count > 0);
|
return (IsInfinite || (Count > 0));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1085,22 +1078,22 @@ struct CarriedWeaponInfo
|
||||||
bool HasLasersight = false; // TODO: Duplicated in LaraInventoryData.
|
bool HasLasersight = false; // TODO: Duplicated in LaraInventoryData.
|
||||||
bool HasSilencer = false; // TODO: Unused and duplicated in LaraInventoryData.
|
bool HasSilencer = false; // TODO: Unused and duplicated in LaraInventoryData.
|
||||||
|
|
||||||
Ammo Ammo[(int)WeaponAmmoType::NumAmmoTypes] = {};
|
Ammo Ammo[(int)WeaponAmmoType::NumAmmoTypes] = {};
|
||||||
WeaponAmmoType SelectedAmmo = WeaponAmmoType::Ammo1; // WeaponAmmoType_enum
|
WeaponAmmoType SelectedAmmo = WeaponAmmoType::Ammo1; // WeaponAmmoType_enum
|
||||||
LaraWeaponTypeCarried WeaponMode = LaraWeaponTypeCarried::WTYPE_MISSING;
|
LaraWeaponTypeCarried WeaponMode = LaraWeaponTypeCarried::WTYPE_MISSING;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArmInfo
|
struct ArmInfo
|
||||||
{
|
{
|
||||||
int AnimNumber;
|
int AnimNumber = 0;
|
||||||
int FrameNumber;
|
int FrameNumber = 0;
|
||||||
int FrameBase;
|
int FrameBase = 0;
|
||||||
|
|
||||||
EulerAngles Orientation;
|
EulerAngles Orientation = EulerAngles::Zero;
|
||||||
|
bool Locked = false;
|
||||||
|
|
||||||
bool Locked;
|
int GunFlash = 0;
|
||||||
int GunFlash;
|
int GunSmoke = 0;
|
||||||
int GunSmoke;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FlareData
|
struct FlareData
|
||||||
|
@ -1122,29 +1115,29 @@ constexpr int MAX_DIARY_STRINGS_PER_PAGE = 8;
|
||||||
|
|
||||||
struct DiaryString
|
struct DiaryString
|
||||||
{
|
{
|
||||||
Vector2i Position;
|
Vector2i Position = Vector2i::Zero;
|
||||||
int StringID;
|
int StringID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DiaryPage
|
struct DiaryPage
|
||||||
{
|
{
|
||||||
DiaryString Strings[MAX_DIARY_STRINGS_PER_PAGE];
|
DiaryString Strings[MAX_DIARY_STRINGS_PER_PAGE] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DiaryInfo
|
struct DiaryInfo
|
||||||
{
|
{
|
||||||
bool Present;
|
bool Present = false;
|
||||||
DiaryPage Pages[MAX_DIARY_PAGES];
|
DiaryPage Pages[MAX_DIARY_PAGES] = {};
|
||||||
unsigned int NumPages;
|
unsigned int NumPages = 0;
|
||||||
unsigned int CurrentPage;
|
unsigned int CurrentPage = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LaraInventoryData
|
struct LaraInventoryData
|
||||||
{
|
{
|
||||||
bool IsBusy;
|
bool IsBusy = false;
|
||||||
bool OldBusy;
|
bool OldBusy = false;
|
||||||
|
|
||||||
DiaryInfo Diary;
|
DiaryInfo Diary = {};
|
||||||
|
|
||||||
byte BeetleLife;
|
byte BeetleLife;
|
||||||
int BeetleComponents; // BeetleComponentFlags enum
|
int BeetleComponents; // BeetleComponentFlags enum
|
||||||
|
@ -1157,29 +1150,29 @@ struct LaraInventoryData
|
||||||
int TotalFlares;
|
int TotalFlares;
|
||||||
unsigned int TotalSecrets;
|
unsigned int TotalSecrets;
|
||||||
|
|
||||||
bool HasBinoculars;
|
bool HasBinoculars = false;
|
||||||
bool HasCrowbar;
|
bool HasCrowbar = false;
|
||||||
bool HasTorch;
|
bool HasTorch = false;
|
||||||
bool HasLasersight;
|
bool HasLasersight = false;
|
||||||
bool HasSilencer; // TODO: Unused.
|
bool HasSilencer = false; // TODO: Unused.
|
||||||
|
|
||||||
// TODO: Convert to bools.
|
// TODO: Convert to bools.
|
||||||
int Puzzles[NUM_PUZZLES];
|
int Puzzles[NUM_PUZZLES] = {};
|
||||||
int Keys[NUM_KEYS];
|
int Keys[NUM_KEYS] = {};
|
||||||
int Pickups[NUM_PICKUPS];
|
int Pickups[NUM_PICKUPS] = {};
|
||||||
int Examines[NUM_EXAMINES];
|
int Examines[NUM_EXAMINES] = {};
|
||||||
int PuzzlesCombo[NUM_PUZZLES * 2];
|
int PuzzlesCombo[NUM_PUZZLES * 2] = {};
|
||||||
int KeysCombo[NUM_KEYS * 2];
|
int KeysCombo[NUM_KEYS * 2] = {};
|
||||||
int PickupsCombo[NUM_PICKUPS * 2];
|
int PickupsCombo[NUM_PICKUPS * 2] = {};
|
||||||
int ExaminesCombo[NUM_EXAMINES * 2];
|
int ExaminesCombo[NUM_EXAMINES * 2] = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LaraCountData
|
struct LaraCountData
|
||||||
{
|
{
|
||||||
unsigned int Pose;
|
unsigned int Pose = 0;
|
||||||
unsigned int PositionAdjust;
|
unsigned int PositionAdjust = 0;
|
||||||
unsigned int Run;
|
unsigned int Run = 0;
|
||||||
unsigned int Death;
|
unsigned int Death = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WeaponControlData
|
struct WeaponControlData
|
||||||
|
@ -1204,31 +1197,37 @@ struct WeaponControlData
|
||||||
|
|
||||||
struct RopeControlData
|
struct RopeControlData
|
||||||
{
|
{
|
||||||
byte Segment;
|
byte Segment = 0;
|
||||||
byte Direction;
|
byte Direction = 0;
|
||||||
short ArcFront;
|
|
||||||
short ArcBack;
|
short ArcFront = 0;
|
||||||
short LastX;
|
short ArcBack = 0;
|
||||||
short MaxXForward;
|
|
||||||
short MaxXBackward;
|
short LastX = 0;
|
||||||
int DFrame;
|
short MaxXForward = 0;
|
||||||
int Frame;
|
short MaxXBackward = 0;
|
||||||
unsigned short FrameRate;
|
|
||||||
unsigned short Y;
|
int DFrame = 0;
|
||||||
int Ptr;
|
int Frame = 0;
|
||||||
int Offset;
|
unsigned short FrameRate = 0;
|
||||||
int DownVel;
|
|
||||||
byte Flag;
|
unsigned short Y = 0;
|
||||||
int Count;
|
int Ptr = 0;
|
||||||
|
int Offset = 0;
|
||||||
|
int DownVel = 0;
|
||||||
|
byte Flag = 0;
|
||||||
|
int Count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Give tightrope a property for difficulty?
|
||||||
|
// TODO: Remove old tightrope functionality.
|
||||||
struct TightropeControlData
|
struct TightropeControlData
|
||||||
{
|
{
|
||||||
#if NEW_TIGHTROPE
|
#if NEW_TIGHTROPE
|
||||||
float Balance;
|
short TightropeItem = 0;
|
||||||
unsigned int TimeOnTightrope;
|
bool CanDismount = false;
|
||||||
bool CanDismount;
|
float Balance = 0.0f;
|
||||||
short TightropeItem; // TODO: Give tightrope a property for difficulty?
|
unsigned int TimeOnTightrope = 0;
|
||||||
#else // !NEW_TIGHTROPE
|
#else // !NEW_TIGHTROPE
|
||||||
unsigned int OnCount;
|
unsigned int OnCount;
|
||||||
byte Off;
|
byte Off;
|
||||||
|
@ -1238,25 +1237,24 @@ struct TightropeControlData
|
||||||
|
|
||||||
struct SubsuitControlData
|
struct SubsuitControlData
|
||||||
{
|
{
|
||||||
short XRot;
|
short XRot = 0;
|
||||||
short DXRot;
|
short DXRot = 0;
|
||||||
int Velocity[2];
|
int Velocity[2] = {};
|
||||||
int VerticalVelocity;
|
int VerticalVelocity = 0;
|
||||||
|
|
||||||
// TODO: These appear to be unused.
|
// TODO: These appear to be unused.
|
||||||
short XRotVel;
|
short XRotVel = 0;
|
||||||
unsigned short HitCount;
|
unsigned short HitCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LaraControlData
|
struct LaraControlData
|
||||||
{
|
{
|
||||||
short MoveAngle = 0;
|
short MoveAngle = 0;
|
||||||
short TurnRate = 0;
|
short TurnRate = 0;
|
||||||
int CalculatedJumpVelocity = 0;
|
|
||||||
|
|
||||||
JumpDirection JumpDirection = {};
|
|
||||||
HandStatus HandStatus = {};
|
HandStatus HandStatus = {};
|
||||||
WaterStatus WaterStatus = {};
|
WaterStatus WaterStatus = {};
|
||||||
|
JumpDirection JumpDirection = {};
|
||||||
LaraCountData Count = {};
|
LaraCountData Count = {};
|
||||||
|
|
||||||
RopeControlData Rope = {};
|
RopeControlData Rope = {};
|
||||||
|
@ -1265,25 +1263,19 @@ struct LaraControlData
|
||||||
WeaponControlData Weapon = {};
|
WeaponControlData Weapon = {};
|
||||||
|
|
||||||
bool IsClimbingLadder = false;
|
bool IsClimbingLadder = false;
|
||||||
bool Locked = false;
|
bool Locked = false; // IsLocked
|
||||||
bool IsLow = false;
|
bool IsLow = false;
|
||||||
bool IsMonkeySwinging = false;
|
bool IsMonkeySwinging = false;
|
||||||
bool IsMoving = false;
|
bool IsMoving = false;
|
||||||
bool RunJumpQueued = false;
|
bool RunJumpQueued = false; // IsRunJumpQueued
|
||||||
bool KeepLow = false;
|
bool KeepLow = false; // IsInLowSpace
|
||||||
|
|
||||||
bool CanClimbLadder = false;
|
bool CanClimbLadder = false;
|
||||||
bool CanLook = false;
|
bool CanLook = false;
|
||||||
bool CanMonkeySwing = false;
|
bool CanMonkeySwing = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayerEffectData
|
// TODO: Refactor status handling to use floats.
|
||||||
{
|
|
||||||
std::array<float, NUM_LARA_MESHES> DripNodes = {};
|
|
||||||
std::array<float, NUM_LARA_MESHES> BubbleNodes = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Make these floats.
|
|
||||||
struct PlayerStatusData
|
struct PlayerStatusData
|
||||||
{
|
{
|
||||||
int Air = 0;
|
int Air = 0;
|
||||||
|
@ -1292,40 +1284,54 @@ struct PlayerStatusData
|
||||||
int Stamina = 0;
|
int Stamina = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlayerContextData
|
||||||
|
{
|
||||||
|
int ProjectedFloorHeight = 0;
|
||||||
|
float CalcJumpVelocity = 0;
|
||||||
|
Pose NextCornerPos = Pose::Zero;
|
||||||
|
EulerAngles TargetOrientation = EulerAngles::Zero;
|
||||||
|
|
||||||
|
int WaterSurfaceDist = 0;
|
||||||
|
short WaterCurrentActive = 0; // Sink number? Often used as bool.
|
||||||
|
Vector3i WaterCurrentPull = Vector3i::Zero;
|
||||||
|
|
||||||
|
int InteractedItem = 0; // Item number.
|
||||||
|
int Vehicle = 0; // Item number.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlayerEffectData
|
||||||
|
{
|
||||||
|
std::array<float, NUM_LARA_MESHES> DripNodes = {};
|
||||||
|
std::array<float, NUM_LARA_MESHES> BubbleNodes = {};
|
||||||
|
};
|
||||||
|
|
||||||
struct LaraInfo
|
struct LaraInfo
|
||||||
{
|
{
|
||||||
int ItemNumber = 0; // TODO: Remove. No longer necessary since ItemInfo already has this.
|
int ItemNumber = 0; // TODO: Remove. No longer necessary since ItemInfo already has it. -- Sezz 2023.04.09
|
||||||
|
|
||||||
PlayerStatusData Status = {};
|
LaraControlData Control = {};
|
||||||
LaraControlData Control = {};
|
PlayerContextData Context = {};
|
||||||
LaraInventoryData Inventory;
|
PlayerStatusData Status = {};
|
||||||
CarriedWeaponInfo Weapons[(int)LaraWeaponType::NumWeapons];
|
PlayerEffectData Effect = {};
|
||||||
FlareData Flare = {};
|
LaraInventoryData Inventory = {};
|
||||||
TorchData Torch = {};
|
|
||||||
|
|
||||||
EulerAngles ExtraHeadRot = {};
|
FlareData Flare = {};
|
||||||
EulerAngles ExtraTorsoRot = {};
|
TorchData Torch = {};
|
||||||
short WaterCurrentActive = 0;
|
CarriedWeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] = {};
|
||||||
Vector3i WaterCurrentPull = Vector3i::Zero;
|
|
||||||
|
|
||||||
|
EulerAngles ExtraHeadRot = {};
|
||||||
|
EulerAngles ExtraTorsoRot = {};
|
||||||
ArmInfo LeftArm = {};
|
ArmInfo LeftArm = {};
|
||||||
ArmInfo RightArm = {};
|
ArmInfo RightArm = {};
|
||||||
EulerAngles TargetArmOrient = EulerAngles::Zero;
|
EulerAngles TargetArmOrient = EulerAngles::Zero;
|
||||||
ItemInfo* TargetEntity = nullptr;
|
ItemInfo* TargetEntity = nullptr; // TargetEntityPtr. Should use item number instead?
|
||||||
|
|
||||||
int Vehicle;
|
// TODO: Rewrite and restore spasm effect. Also move to PlayerEffectData?
|
||||||
int ExtraAnim;
|
int HitFrame = 0; // Frame index.
|
||||||
int HitFrame;
|
int HitDirection = 0; // Cardinal direction.
|
||||||
int HitDirection;
|
FX_INFO* SpasmEffect = nullptr; // Not saved.
|
||||||
FX_INFO* SpasmEffect; // Not saved. TODO: Restore this effect.
|
|
||||||
|
|
||||||
short InteractedItem;
|
int ExtraAnim = 0; // Item number? Only ever set to NO_ITEM or 1.
|
||||||
int ProjectedFloorHeight;
|
|
||||||
EulerAngles TargetOrientation;
|
|
||||||
int WaterSurfaceDist;
|
|
||||||
Pose NextCornerPos;
|
|
||||||
|
|
||||||
PlayerEffectData Effect = {};
|
|
||||||
|
|
||||||
signed char Location = 0;
|
signed char Location = 0;
|
||||||
signed char HighestLocation = 0;
|
signed char HighestLocation = 0;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
// -----------------------------
|
// -----------------------------
|
||||||
|
@ -170,7 +170,7 @@ bool TestLaraHang(ItemInfo* item, CollisionInfo* coll)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (((item->Animation.AnimNumber == LA_REACH_TO_HANG && item->Animation.FrameNumber == GetFrameNumber(item, 21)) || item->Animation.AnimNumber == LA_HANG_IDLE) &&
|
if (((item->Animation.AnimNumber == LA_REACH_TO_HANG && item->Animation.FrameNumber == GetFrameIndex(item, 21)) || item->Animation.AnimNumber == LA_HANG_IDLE) &&
|
||||||
TestLaraClimbIdle(item, coll))
|
TestLaraClimbIdle(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.TargetState = LS_LADDER_IDLE;
|
item->Animation.TargetState = LS_LADDER_IDLE;
|
||||||
|
@ -273,7 +273,7 @@ bool TestLaraHangJump(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TestLaraMonkeyGrab(item, coll))
|
if (TestLaraMonkeyGrab(item, coll))
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_REACH_TO_MONKEY);
|
SetAnimation(item, LA_REACH_TO_MONKEY);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
item->Animation.Velocity.z = 0;
|
item->Animation.Velocity.z = 0;
|
||||||
item->Animation.Velocity.y = 0;
|
item->Animation.Velocity.y = 0;
|
||||||
item->Animation.IsAirborne = false;
|
item->Animation.IsAirborne = false;
|
||||||
|
@ -300,7 +300,7 @@ bool TestLaraHangJump(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (TestHangSwingIn(item, coll))
|
if (TestHangSwingIn(item, coll))
|
||||||
{
|
{
|
||||||
SetAnimation(item, LA_REACH_TO_HANG_OSCILLATE);
|
SetAnimation(item, LA_REACH_TO_HANG_OSCILLATE);
|
||||||
ResetLaraFlex(item);
|
ResetPlayerFlex(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SetAnimation(item, LA_REACH_TO_HANG);
|
SetAnimation(item, LA_REACH_TO_HANG);
|
||||||
|
@ -575,12 +575,12 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
||||||
|
|
||||||
// Store next position
|
// Store next position
|
||||||
item->Pose = cornerResult.RealPositionResult;
|
item->Pose = cornerResult.RealPositionResult;
|
||||||
lara->NextCornerPos.Position = Vector3i(
|
lara->Context.NextCornerPos.Position = Vector3i(
|
||||||
item->Pose.Position.x,
|
item->Pose.Position.x,
|
||||||
GetCollision(item, item->Pose.Orientation.y, coll->Setup.Radius + 16, -(coll->Setup.Height + CLICK(0.5f))).Position.Floor + abs(bounds.Y1),
|
GetCollision(item, item->Pose.Orientation.y, coll->Setup.Radius + 16, -(coll->Setup.Height + CLICK(0.5f))).Position.Floor + abs(bounds.Y1),
|
||||||
item->Pose.Position.z
|
item->Pose.Position.z
|
||||||
);
|
);
|
||||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y;
|
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y;
|
||||||
lara->Control.MoveAngle = item->Pose.Orientation.y;
|
lara->Control.MoveAngle = item->Pose.Orientation.y;
|
||||||
|
|
||||||
item->Pose = cornerResult.ProbeResult;
|
item->Pose = cornerResult.ProbeResult;
|
||||||
|
@ -596,9 +596,9 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
||||||
if (lara->Control.CanClimbLadder)
|
if (lara->Control.CanClimbLadder)
|
||||||
{
|
{
|
||||||
auto& angleSet = testAngle > 0 ? LeftExtRightIntTab : LeftIntRightExtTab;
|
auto& angleSet = testAngle > 0 ? LeftExtRightIntTab : LeftIntRightExtTab;
|
||||||
if (GetClimbFlags(lara->NextCornerPos.Position.x, item->Pose.Position.y, lara->NextCornerPos.Position.z, item->RoomNumber) & (short)angleSet[GetQuadrant(item->Pose.Orientation.y)])
|
if (GetClimbFlags(lara->Context.NextCornerPos.Position.x, item->Pose.Position.y, lara->Context.NextCornerPos.Position.z, item->RoomNumber) & (short)angleSet[GetQuadrant(item->Pose.Orientation.y)])
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Position.y = item->Pose.Position.y; // Restore original Y pos for ladder tests because we don't snap to ledge height in such case.
|
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y; // Restore original Y pos for ladder tests because we don't snap to ledge height in such case.
|
||||||
return CornerType::Inner;
|
return CornerType::Inner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -634,10 +634,10 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
||||||
|
|
||||||
// Store next position
|
// Store next position
|
||||||
item->Pose = cornerResult.RealPositionResult;
|
item->Pose = cornerResult.RealPositionResult;
|
||||||
lara->NextCornerPos.Position.x = item->Pose.Position.x;
|
lara->Context.NextCornerPos.Position.x = item->Pose.Position.x;
|
||||||
lara->NextCornerPos.Position.y = GetCollision(item, item->Pose.Orientation.y, coll->Setup.Radius * 1.25f, -(abs(bounds.Y1) + LARA_HEADROOM)).Position.Floor + abs(bounds.Y1);
|
lara->Context.NextCornerPos.Position.y = GetCollision(item, item->Pose.Orientation.y, coll->Setup.Radius * 1.25f, -(abs(bounds.Y1) + LARA_HEADROOM)).Position.Floor + abs(bounds.Y1);
|
||||||
lara->NextCornerPos.Position.z = item->Pose.Position.z;
|
lara->Context.NextCornerPos.Position.z = item->Pose.Position.z;
|
||||||
lara->NextCornerPos.Orientation.y = item->Pose.Orientation.y;
|
lara->Context.NextCornerPos.Orientation.y = item->Pose.Orientation.y;
|
||||||
lara->Control.MoveAngle = item->Pose.Orientation.y;
|
lara->Control.MoveAngle = item->Pose.Orientation.y;
|
||||||
|
|
||||||
item->Pose = cornerResult.ProbeResult;
|
item->Pose = cornerResult.ProbeResult;
|
||||||
|
@ -653,9 +653,9 @@ CornerType TestLaraHangCorner(ItemInfo* item, CollisionInfo* coll, float testAng
|
||||||
if (lara->Control.CanClimbLadder)
|
if (lara->Control.CanClimbLadder)
|
||||||
{
|
{
|
||||||
auto& angleSet = testAngle > 0 ? LeftIntRightExtTab : LeftExtRightIntTab;
|
auto& angleSet = testAngle > 0 ? LeftIntRightExtTab : LeftExtRightIntTab;
|
||||||
if (GetClimbFlags(lara->NextCornerPos.Position.x, item->Pose.Position.y, lara->NextCornerPos.Position.z, item->RoomNumber) & (short)angleSet[GetQuadrant(item->Pose.Orientation.y)])
|
if (GetClimbFlags(lara->Context.NextCornerPos.Position.x, item->Pose.Position.y, lara->Context.NextCornerPos.Position.z, item->RoomNumber) & (short)angleSet[GetQuadrant(item->Pose.Orientation.y)])
|
||||||
{
|
{
|
||||||
lara->NextCornerPos.Position.y = item->Pose.Position.y; // Restore original Y pos for ladder tests because we don't snap to ledge height in such case.
|
lara->Context.NextCornerPos.Position.y = item->Pose.Position.y; // Restore original Y pos for ladder tests because we don't snap to ledge height in such case.
|
||||||
return CornerType::Outer;
|
return CornerType::Outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1219,7 +1219,7 @@ bool TestLaraPose(ItemInfo* item, CollisionInfo* coll)
|
||||||
lara->Control.HandStatus == HandStatus::Free && // Hands are free.
|
lara->Control.HandStatus == HandStatus::Free && // Hands are free.
|
||||||
(lara->Control.Weapon.GunType != LaraWeaponType::Flare || // Flare is not being handled.
|
(lara->Control.Weapon.GunType != LaraWeaponType::Flare || // Flare is not being handled.
|
||||||
lara->Flare.Life) &&
|
lara->Flare.Life) &&
|
||||||
lara->Vehicle == NO_ITEM) // Not in a vehicle.
|
lara->Context.Vehicle == NO_ITEM) // Not in a vehicle.
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1645,7 +1645,7 @@ bool TestLaraCrouchRoll(ItemInfo* item, CollisionInfo* coll)
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
// Assess water depth.
|
// Assess water depth.
|
||||||
if (lara->WaterSurfaceDist < -CLICK(1))
|
if (lara->Context.WaterSurfaceDist < -CLICK(1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Assess continuity of path.
|
// Assess continuity of path.
|
||||||
|
@ -1830,7 +1830,7 @@ VaultTestResult TestLaraVaultTolerance(ItemInfo* item, CollisionInfo* coll, Vaul
|
||||||
auto probeMiddle = GetCollision(item);
|
auto probeMiddle = GetCollision(item);
|
||||||
|
|
||||||
bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, item);
|
bool isSwamp = TestEnvironment(ENV_FLAG_SWAMP, item);
|
||||||
bool swampTooDeep = testSetup.CheckSwampDepth ? (isSwamp && lara->WaterSurfaceDist < -CLICK(3)) : isSwamp;
|
bool swampTooDeep = testSetup.CheckSwampDepth ? (isSwamp && lara->Context.WaterSurfaceDist < -CLICK(3)) : isSwamp;
|
||||||
int y = isSwamp ? item->Pose.Position.y : probeMiddle.Position.Floor; // HACK: Avoid cheese when in the midst of performing a step. Can be done better. @Sezz 2022.04.08
|
int y = isSwamp ? item->Pose.Position.y : probeMiddle.Position.Floor; // HACK: Avoid cheese when in the midst of performing a step. Can be done better. @Sezz 2022.04.08
|
||||||
|
|
||||||
// Check swamp depth (if applicable).
|
// Check swamp depth (if applicable).
|
||||||
|
@ -2065,7 +2065,7 @@ VaultTestResult TestLaraVault(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (!(TrInput & IN_ACTION) || lara->Control.HandStatus != HandStatus::Free)
|
if (!(TrInput & IN_ACTION) || lara->Control.HandStatus != HandStatus::Free)
|
||||||
return VaultTestResult{ false };
|
return VaultTestResult{ false };
|
||||||
|
|
||||||
if (TestEnvironment(ENV_FLAG_SWAMP, item) && lara->WaterSurfaceDist < -CLICK(3))
|
if (TestEnvironment(ENV_FLAG_SWAMP, item) && lara->Context.WaterSurfaceDist < -CLICK(3))
|
||||||
return VaultTestResult{ false };
|
return VaultTestResult{ false };
|
||||||
|
|
||||||
VaultTestResult vaultResult;
|
VaultTestResult vaultResult;
|
||||||
|
@ -2154,24 +2154,24 @@ bool TestAndDoLaraLadderClimb(ItemInfo* item, CollisionInfo* coll)
|
||||||
if (!(TrInput & IN_ACTION) || !(TrInput & IN_FORWARD) || lara->Control.HandStatus != HandStatus::Free)
|
if (!(TrInput & IN_ACTION) || !(TrInput & IN_FORWARD) || lara->Control.HandStatus != HandStatus::Free)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (TestEnvironment(ENV_FLAG_SWAMP, item) && lara->WaterSurfaceDist < -CLICK(3))
|
if (TestEnvironment(ENV_FLAG_SWAMP, item) && lara->Context.WaterSurfaceDist < -CLICK(3))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Auto jump to ladder.
|
// Auto jump to ladder.
|
||||||
auto vaultResult = TestLaraLadderAutoJump(item, coll);
|
auto vaultResult = TestLaraLadderAutoJump(item, coll);
|
||||||
if (vaultResult.Success)
|
if (vaultResult.Success)
|
||||||
{
|
{
|
||||||
// TODO: Somehow harmonise CalculatedJumpVelocity to work for both ledge and ladder auto jumps, because otherwise there will be a need for an odd workaround in the future.
|
// TODO: Somehow harmonise Context.CalcJumpVelocity to work for both ledge and ladder auto jumps, because otherwise there will be a need for an odd workaround in the future.
|
||||||
lara->Control.CalculatedJumpVelocity = -3 - sqrt(-9600 - 12 * std::max((vaultResult.Height - item->Pose.Position.y + CLICK(0.2f)), -CLICK(7.1f)));
|
lara->Context.CalcJumpVelocity = -3 - sqrt(-9600 - 12 * std::max((vaultResult.Height - item->Pose.Position.y + CLICK(0.2f)), -CLICK(7.1f)));
|
||||||
item->Animation.AnimNumber = LA_STAND_SOLID;
|
item->Animation.AnimNumber = LA_STAND_SOLID;
|
||||||
item->Animation.FrameNumber = GetFrameNumber(item, 0);
|
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||||
item->Animation.TargetState = LS_JUMP_UP;
|
item->Animation.TargetState = LS_JUMP_UP;
|
||||||
item->Animation.ActiveState = LS_IDLE;
|
item->Animation.ActiveState = LS_IDLE;
|
||||||
lara->Control.TurnRate = 0;
|
lara->Control.TurnRate = 0;
|
||||||
|
|
||||||
ShiftItem(item, coll);
|
ShiftItem(item, coll);
|
||||||
SnapItemToGrid(item, coll); // HACK: until fragile ladder code is refactored, we must exactly snap to grid.
|
SnapItemToGrid(item, coll); // HACK: until fragile ladder code is refactored, we must exactly snap to grid.
|
||||||
lara->TargetOrientation = EulerAngles(0, item->Pose.Orientation.y, 0);
|
lara->Context.TargetOrientation = EulerAngles(0, item->Pose.Orientation.y, 0);
|
||||||
AnimateItem(item);
|
AnimateItem(item);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2183,7 +2183,7 @@ bool TestAndDoLaraLadderClimb(ItemInfo* item, CollisionInfo* coll)
|
||||||
TestLaraClimbIdle(item, coll))
|
TestLaraClimbIdle(item, coll))
|
||||||
{
|
{
|
||||||
item->Animation.AnimNumber = LA_STAND_SOLID;
|
item->Animation.AnimNumber = LA_STAND_SOLID;
|
||||||
item->Animation.FrameNumber = GetFrameNumber(item, 0);
|
item->Animation.FrameNumber = GetFrameIndex(item, 0);
|
||||||
item->Animation.TargetState = LS_LADDER_IDLE;
|
item->Animation.TargetState = LS_LADDER_IDLE;
|
||||||
item->Animation.ActiveState = LS_IDLE;
|
item->Animation.ActiveState = LS_IDLE;
|
||||||
lara->Control.HandStatus = HandStatus::Busy;
|
lara->Control.HandStatus = HandStatus::Busy;
|
||||||
|
|
|
@ -9,504 +9,417 @@
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_fire.h"
|
#include "Game/Lara/lara_fire.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
|
#include "Game/Lara/lara_struct.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
#include "Math/Random.h"
|
#include "Game/Setup.h"
|
||||||
|
#include "Math/Math.h"
|
||||||
|
#include "Objects/game_object_ids.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/level.h"
|
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
|
#include "Specific/level.h"
|
||||||
|
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math::Random;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
struct PistolDef
|
struct WeaponAnimData
|
||||||
{
|
{
|
||||||
short ObjectNumber;
|
GAME_OBJECT_ID ObjectID = GAME_OBJECT_ID::ID_NO_OBJECT;
|
||||||
int Draw1Anim2;
|
|
||||||
int Draw1Anim;
|
int Draw1Anim2 = 0;
|
||||||
int Draw2Anim;
|
int Draw1Anim = 0;
|
||||||
int RecoilAnim;
|
int Draw2Anim = 0;
|
||||||
|
int RecoilAnim = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
PistolDef PistolsTable[4] =
|
static WeaponAnimData GetWeaponAnimData(LaraWeaponType weaponType)
|
||||||
{
|
{
|
||||||
{ ID_LARA, 0, 0, 0, 0 },
|
static const auto DEFAULT_WEAPON_ANIM_DATA = WeaponAnimData{ ID_LARA, 0, 0, 0, 0 };
|
||||||
{ ID_PISTOLS_ANIM, 4, 5, 13, 24 },
|
static const auto ANIM_DATA_MAP = std::unordered_map<LaraWeaponType, WeaponAnimData>
|
||||||
{ ID_REVOLVER_ANIM , 7, 8, 15, 29 },
|
|
||||||
{ ID_UZI_ANIM, 4, 5, 13, 24 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void AnimatePistols(ItemInfo* laraItem, LaraWeaponType weaponType)
|
|
||||||
{
|
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
|
||||||
auto* weapon = &Weapons[(int)weaponType];
|
|
||||||
auto* p = &PistolsTable[(int)lara->Control.Weapon.GunType];
|
|
||||||
|
|
||||||
int fired = false;
|
|
||||||
|
|
||||||
if (laraItem->MeshBits.TestAny())
|
|
||||||
{
|
{
|
||||||
if (lara->LeftArm.GunSmoke)
|
{ LaraWeaponType::None, WeaponAnimData{ ID_LARA, 0, 0, 0, 0 } },
|
||||||
{
|
{ LaraWeaponType::Pistol, WeaponAnimData{ ID_PISTOLS_ANIM, 4, 5, 13, 24 } },
|
||||||
auto offset = Vector3i::Zero;
|
{ LaraWeaponType::Revolver, WeaponAnimData{ ID_REVOLVER_ANIM , 7, 8, 15, 29 } },
|
||||||
switch (weaponType)
|
{ LaraWeaponType::Uzi, WeaponAnimData{ ID_UZI_ANIM, 4, 5, 13, 24 } }
|
||||||
{
|
};
|
||||||
case LaraWeaponType::Pistol:
|
|
||||||
offset = Vector3i(4, 128, 40);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LaraWeaponType::Revolver:
|
auto it = ANIM_DATA_MAP.find(weaponType);
|
||||||
offset = Vector3i(16, 160, 56);
|
return ((it != ANIM_DATA_MAP.end()) ? it->second : DEFAULT_WEAPON_ANIM_DATA);
|
||||||
break;
|
|
||||||
|
|
||||||
case LaraWeaponType::Uzi:
|
|
||||||
offset = Vector3i(8, 140, 48);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pos = GetJointPosition(laraItem, LM_LHAND, offset);
|
|
||||||
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, weaponType, lara->LeftArm.GunSmoke);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lara->RightArm.GunSmoke)
|
|
||||||
{
|
|
||||||
auto offset = Vector3i::Zero;
|
|
||||||
switch (weaponType)
|
|
||||||
{
|
|
||||||
case LaraWeaponType::Pistol:
|
|
||||||
offset = Vector3i(-16, 128, 40);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LaraWeaponType::Revolver:
|
|
||||||
offset = Vector3i(-32, 160, 56);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LaraWeaponType::Uzi:
|
|
||||||
offset = Vector3i(-16, 140, 48);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pos = GetJointPosition(laraItem, LM_RHAND, offset);
|
|
||||||
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, weaponType, lara->RightArm.GunSmoke);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shooting action for right arm.
|
|
||||||
int frameRight = lara->RightArm.FrameNumber; // frame number of DRAW_END?
|
|
||||||
if ((TrInput & IN_ACTION && !lara->TargetEntity) || lara->RightArm.Locked)
|
|
||||||
{
|
|
||||||
// POINT ARMS FORWARD
|
|
||||||
// at or beyond (2) DRAW_END start frame AND before (0) SHOOT_START end frame...
|
|
||||||
if ((frameRight >= 0) && (frameRight < p->Draw1Anim2))
|
|
||||||
{
|
|
||||||
// ...increment toward (0) SHOOT_START end frame
|
|
||||||
frameRight++;
|
|
||||||
}
|
|
||||||
// at (0) SHOOT_START end frame
|
|
||||||
else if (frameRight == p->Draw1Anim2)
|
|
||||||
{
|
|
||||||
// actually shoot, bang bang
|
|
||||||
if (TrInput & IN_ACTION)
|
|
||||||
{
|
|
||||||
if (weaponType != LaraWeaponType::Revolver)
|
|
||||||
{
|
|
||||||
auto rightArmOrient = EulerAngles(
|
|
||||||
lara->RightArm.Orientation.x,
|
|
||||||
lara->RightArm.Orientation.y + laraItem->Pose.Orientation.y,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (FireWeapon(weaponType, lara->TargetEntity, laraItem, rightArmOrient) != FireWeaponType::NoAmmo)
|
|
||||||
{
|
|
||||||
lara->RightArm.GunSmoke = 28;
|
|
||||||
|
|
||||||
TriggerGunShell(1, ID_GUNSHELL, weaponType); // Right Hand
|
|
||||||
|
|
||||||
lara->RightArm.GunFlash = weapon->FlashTime;
|
|
||||||
|
|
||||||
SoundEffect(SFX_TR4_EXPLOSION1, &laraItem->Pose, SoundEnvironment::Land, 0.9f, 0.3f);
|
|
||||||
SoundEffect(weapon->SampleNum, &laraItem->Pose);
|
|
||||||
fired = true;
|
|
||||||
|
|
||||||
if (weaponType == LaraWeaponType::Uzi)
|
|
||||||
lara->Control.Weapon.UziRight = true;
|
|
||||||
|
|
||||||
Statistics.Game.AmmoUsed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// go to (3) SHOOT_CONTINUE start frame
|
|
||||||
frameRight = p->RecoilAnim;
|
|
||||||
}
|
|
||||||
else if (lara->Control.Weapon.UziRight)
|
|
||||||
{
|
|
||||||
SoundEffect(weapon->SampleNum + 1, &laraItem->Pose);
|
|
||||||
lara->Control.Weapon.UziRight = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// at or beyond (3) SHOOT_CONTINUE start frame
|
|
||||||
else if (frameRight >= p->RecoilAnim)
|
|
||||||
{
|
|
||||||
if (weaponType == LaraWeaponType::Uzi)
|
|
||||||
{
|
|
||||||
SoundEffect(weapon->SampleNum, &laraItem->Pose);
|
|
||||||
lara->Control.Weapon.UziRight = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment toward (3) SHOOT_CONTINUE end frame (finish recoil before allowing to shoot again)
|
|
||||||
frameRight++;
|
|
||||||
|
|
||||||
// at (3) SHOOT_CONTINUE end frame, go to (0) START_SHOOT end frame
|
|
||||||
if (frameRight == (p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameRight = p->Draw1Anim2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// HAS LET GO OF ACTION
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// let (3) SHOOT_CONTINUE finish
|
|
||||||
if ((frameRight >= p->RecoilAnim) && (frameRight < p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameRight++;
|
|
||||||
// at (3) SHOOT_CONTINUE end frame, go to (0) START_SHOOT end frame
|
|
||||||
if (frameRight == (p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameRight = p->Draw1Anim2;
|
|
||||||
// go back to ready stance
|
|
||||||
else if ((frameRight > 0) && (frameRight <= p->Draw1Anim2))
|
|
||||||
frameRight--;
|
|
||||||
|
|
||||||
if (lara->Control.Weapon.UziRight)
|
|
||||||
{
|
|
||||||
SoundEffect(weapon->SampleNum + 1, &laraItem->Pose);
|
|
||||||
lara->Control.Weapon.UziRight = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetArmInfo(laraItem, lara->RightArm, frameRight);
|
|
||||||
|
|
||||||
// Shooting for left arm.
|
|
||||||
int frameLeft = lara->LeftArm.FrameNumber;
|
|
||||||
if ((TrInput & IN_ACTION && !lara->TargetEntity) || lara->LeftArm.Locked)
|
|
||||||
{
|
|
||||||
if ((frameLeft >= 0) && (frameLeft < p->Draw1Anim2))
|
|
||||||
frameLeft++;
|
|
||||||
else if (frameLeft == p->Draw1Anim2)
|
|
||||||
{
|
|
||||||
if (TrInput & IN_ACTION)
|
|
||||||
{
|
|
||||||
auto leftArmOrient = EulerAngles(
|
|
||||||
lara->LeftArm.Orientation.x,
|
|
||||||
lara->LeftArm.Orientation.y + laraItem->Pose.Orientation.y,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (FireWeapon(weaponType, lara->TargetEntity, laraItem, leftArmOrient) != FireWeaponType::NoAmmo)
|
|
||||||
{
|
|
||||||
if (weaponType == LaraWeaponType::Revolver)
|
|
||||||
{
|
|
||||||
lara->RightArm.GunSmoke = 28;
|
|
||||||
lara->RightArm.GunFlash = weapon->FlashTime;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lara->LeftArm.GunSmoke = 28;
|
|
||||||
TriggerGunShell(0, ID_GUNSHELL, weaponType); // Left hand
|
|
||||||
lara->LeftArm.GunFlash = weapon->FlashTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fired)
|
|
||||||
{
|
|
||||||
SoundEffect(SFX_TR4_EXPLOSION1, &laraItem->Pose, SoundEnvironment::Land, 0.9f, 0.3f);
|
|
||||||
SoundEffect(weapon->SampleNum, &laraItem->Pose);
|
|
||||||
fired = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weaponType == LaraWeaponType::Uzi)
|
|
||||||
lara->Control.Weapon.UziLeft = true;
|
|
||||||
|
|
||||||
Statistics.Game.AmmoUsed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
frameLeft = p->RecoilAnim;
|
|
||||||
}
|
|
||||||
else if (lara->Control.Weapon.UziLeft)
|
|
||||||
{
|
|
||||||
SoundEffect(weapon->SampleNum + 1, &laraItem->Pose);
|
|
||||||
lara->Control.Weapon.UziLeft = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (frameLeft >= p->RecoilAnim)
|
|
||||||
{
|
|
||||||
if (weaponType == LaraWeaponType::Uzi)
|
|
||||||
{
|
|
||||||
SoundEffect(weapon->SampleNum, &laraItem->Pose);
|
|
||||||
lara->Control.Weapon.UziLeft = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
frameLeft++;
|
|
||||||
|
|
||||||
if (frameLeft == (p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameLeft = p->Draw1Anim2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Havent GOT a LOCK ON..
|
|
||||||
{
|
|
||||||
if ((frameLeft >= p->RecoilAnim) && (frameLeft < p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameLeft++;
|
|
||||||
if (frameLeft == (p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameLeft = p->Draw1Anim2;
|
|
||||||
else if ((frameLeft > 0) && (frameLeft <= p->Draw1Anim2))
|
|
||||||
frameLeft--;
|
|
||||||
|
|
||||||
if (lara->Control.Weapon.UziLeft)
|
|
||||||
{
|
|
||||||
SoundEffect(weapon->SampleNum + 1, &laraItem->Pose);
|
|
||||||
lara->Control.Weapon.UziLeft = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fired) // Rumble gamepad only once if any of the hands fired.
|
|
||||||
{
|
|
||||||
float power = weaponType == LaraWeaponType::Uzi ? GenerateFloat(0.1f, 0.3f) : 1.0f;
|
|
||||||
Rumble(power, 0.1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetArmInfo(laraItem, lara->LeftArm, frameLeft);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PistolHandler(ItemInfo* laraItem, LaraWeaponType weaponType)
|
static Vector3i GetWeaponSmokeRelOffset(LaraWeaponType weaponType, bool isRightWeapon)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
switch (weaponType)
|
||||||
auto& weapon = Weapons[(int)weaponType];
|
|
||||||
|
|
||||||
FindNewTarget(laraItem, weapon);
|
|
||||||
if (TrInput & IN_ACTION)
|
|
||||||
LaraTargetInfo(laraItem, weapon);
|
|
||||||
|
|
||||||
AimWeapon(laraItem, lara->LeftArm, weapon);
|
|
||||||
AimWeapon(laraItem, lara->RightArm, weapon);
|
|
||||||
|
|
||||||
if (lara->LeftArm.Locked && !lara->RightArm.Locked)
|
|
||||||
{
|
{
|
||||||
lara->ExtraTorsoRot.x = lara->LeftArm.Orientation.x / 2;
|
case LaraWeaponType::Pistol:
|
||||||
lara->ExtraTorsoRot.y = lara->LeftArm.Orientation.y / 2;
|
return Vector3i(isRightWeapon ? -16 : 4, 128, 40);
|
||||||
|
|
||||||
if (Camera.oldType != CameraType::Look)
|
case LaraWeaponType::Revolver:
|
||||||
lara->ExtraHeadRot = lara->ExtraTorsoRot;
|
return Vector3i(isRightWeapon ? -32 : 16, 160, 56);
|
||||||
}
|
|
||||||
else if (!lara->LeftArm.Locked && lara->RightArm.Locked)
|
|
||||||
{
|
|
||||||
lara->ExtraTorsoRot.x = lara->RightArm.Orientation.x / 2;
|
|
||||||
lara->ExtraTorsoRot.y = lara->RightArm.Orientation.y / 2;
|
|
||||||
|
|
||||||
if (Camera.oldType != CameraType::Look)
|
case LaraWeaponType::Uzi:
|
||||||
lara->ExtraHeadRot = lara->ExtraTorsoRot;
|
return Vector3i(isRightWeapon ? -16 : 8, 140, 48);
|
||||||
}
|
|
||||||
else if (lara->LeftArm.Locked && lara->RightArm.Locked)
|
|
||||||
{
|
|
||||||
lara->ExtraTorsoRot.x = (lara->LeftArm.Orientation.x + lara->RightArm.Orientation.x) / 4;
|
|
||||||
lara->ExtraTorsoRot.y = (lara->LeftArm.Orientation.y + lara->RightArm.Orientation.y) / 4;
|
|
||||||
|
|
||||||
if (Camera.oldType != CameraType::Look)
|
default:
|
||||||
lara->ExtraHeadRot = lara->ExtraTorsoRot;
|
return Vector3i::Zero;
|
||||||
}
|
|
||||||
|
|
||||||
AnimatePistols(laraItem, weaponType);
|
|
||||||
|
|
||||||
if (lara->LeftArm.GunFlash || lara->RightArm.GunFlash)
|
|
||||||
{
|
|
||||||
auto pos = GetJointPosition(laraItem,
|
|
||||||
(lara->LeftArm.GunFlash != 0) ? LM_LHAND : LM_RHAND,
|
|
||||||
Vector3i(
|
|
||||||
(byte)GetRandomControl() - 128,
|
|
||||||
(GetRandomControl() & 0x7F) - 63,
|
|
||||||
(byte)GetRandomControl() - 128
|
|
||||||
));
|
|
||||||
TriggerDynamicLight(pos.x+GenerateFloat(-128,128), pos.y + GenerateFloat(-128, 128), pos.z + GenerateFloat(-128, 128), GenerateFloat(8,11), (GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 128, GetRandomControl() & 0x3F);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadyPistols(ItemInfo* laraItem, LaraWeaponType weaponType)
|
static void SetArmInfo(const ItemInfo& laraItem, ArmInfo& arm, int frame)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
const auto& player = GetLaraInfo(laraItem);
|
||||||
|
const auto& weaponAnimData = GetWeaponAnimData(player.Control.Weapon.GunType);
|
||||||
|
|
||||||
lara->Control.HandStatus = HandStatus::WeaponReady;
|
int animBase = Objects[(int)weaponAnimData.ObjectID].animIndex;
|
||||||
lara->LeftArm.Orientation = EulerAngles::Zero;
|
|
||||||
lara->RightArm.Orientation = EulerAngles::Zero;
|
|
||||||
lara->LeftArm.FrameNumber = 0;
|
|
||||||
lara->RightArm.FrameNumber = 0;
|
|
||||||
lara->TargetEntity = nullptr;
|
|
||||||
lara->LeftArm.Locked = false;
|
|
||||||
lara->RightArm.Locked = false;
|
|
||||||
lara->LeftArm.FrameBase = Objects[GetWeaponObjectID(weaponType)].frameBase;
|
|
||||||
lara->RightArm.FrameBase = Objects[GetWeaponObjectID(weaponType)].frameBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType)
|
if (frame < weaponAnimData.Draw1Anim)
|
||||||
{
|
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
|
||||||
auto* p = &PistolsTable[(int)lara->Control.Weapon.GunType];
|
|
||||||
|
|
||||||
int frame = lara->LeftArm.FrameNumber + 1;
|
|
||||||
|
|
||||||
if (frame < p->Draw1Anim || frame > p->RecoilAnim - 1)
|
|
||||||
frame = p->Draw1Anim;
|
|
||||||
else if (frame == p->Draw2Anim)
|
|
||||||
{
|
{
|
||||||
DrawPistolMeshes(laraItem, weaponType);
|
|
||||||
SoundEffect(SFX_TR4_LARA_DRAW, &laraItem->Pose);
|
|
||||||
}
|
|
||||||
else if (frame == p->RecoilAnim - 1)
|
|
||||||
{
|
|
||||||
ReadyPistols(laraItem, weaponType);
|
|
||||||
frame = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetArmInfo(laraItem, lara->RightArm, frame);
|
|
||||||
SetArmInfo(laraItem, lara->LeftArm, frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UndrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType)
|
|
||||||
{
|
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
|
||||||
auto* weapon = &Weapons[(int)weaponType];
|
|
||||||
auto* p = &PistolsTable[(int)lara->Control.Weapon.GunType];
|
|
||||||
|
|
||||||
int frameLeft = lara->LeftArm.FrameNumber;
|
|
||||||
|
|
||||||
// Finish recoil anim before reholstering weapon.
|
|
||||||
if ((frameLeft >= p->RecoilAnim) && (frameLeft < p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameLeft++;
|
|
||||||
|
|
||||||
if (frameLeft == (p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameLeft = p->Draw1Anim2;
|
|
||||||
else if (frameLeft > 0 && frameLeft < p->Draw1Anim)
|
|
||||||
{
|
|
||||||
lara->LeftArm.Orientation.x -= lara->LeftArm.Orientation.x / frameLeft;
|
|
||||||
lara->LeftArm.Orientation.y -= lara->LeftArm.Orientation.y / frameLeft;
|
|
||||||
frameLeft--;
|
|
||||||
}
|
|
||||||
else if (frameLeft == 0)
|
|
||||||
{
|
|
||||||
lara->LeftArm.Orientation = EulerAngles::Zero;
|
|
||||||
frameLeft = p->RecoilAnim - 1;
|
|
||||||
}
|
|
||||||
else if (frameLeft > p->Draw1Anim && (frameLeft < p->RecoilAnim))
|
|
||||||
{
|
|
||||||
frameLeft--;
|
|
||||||
|
|
||||||
if (frameLeft == p->Draw2Anim - 1)
|
|
||||||
{
|
|
||||||
UndrawPistolMeshLeft(laraItem, weaponType);
|
|
||||||
SoundEffect(SFX_TR4_LARA_HOLSTER, &laraItem->Pose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetArmInfo(laraItem, lara->LeftArm, frameLeft);
|
|
||||||
|
|
||||||
int frameRight = lara->RightArm.FrameNumber;
|
|
||||||
|
|
||||||
if ((frameRight >= p->RecoilAnim) && (frameRight < p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameRight++;
|
|
||||||
|
|
||||||
if (frameRight == (p->RecoilAnim + weapon->RecoilFrame))
|
|
||||||
frameRight = p->Draw1Anim2;
|
|
||||||
else if (frameRight > 0 && frameRight < p->Draw1Anim)
|
|
||||||
{
|
|
||||||
lara->RightArm.Orientation.x -= lara->RightArm.Orientation.x / frameRight;
|
|
||||||
lara->RightArm.Orientation.y -= lara->RightArm.Orientation.y / frameRight;
|
|
||||||
frameRight--;
|
|
||||||
}
|
|
||||||
else if (frameRight == 0)
|
|
||||||
{
|
|
||||||
lara->RightArm.Orientation = EulerAngles::Zero;
|
|
||||||
frameRight = p->RecoilAnim - 1;
|
|
||||||
}
|
|
||||||
else if (frameRight > p->Draw1Anim && (frameRight < p->RecoilAnim))
|
|
||||||
{
|
|
||||||
frameRight--;
|
|
||||||
|
|
||||||
if (frameRight == p->Draw2Anim - 1)
|
|
||||||
{
|
|
||||||
UndrawPistolMeshRight(laraItem, weaponType);
|
|
||||||
SoundEffect(SFX_TR4_LARA_HOLSTER, &laraItem->Pose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetArmInfo(laraItem, lara->RightArm, frameRight);
|
|
||||||
|
|
||||||
if (frameLeft == p->Draw1Anim && frameRight == p->Draw1Anim)
|
|
||||||
{
|
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
|
||||||
lara->LeftArm.FrameNumber = 0;
|
|
||||||
lara->RightArm.FrameNumber = 0;
|
|
||||||
lara->TargetEntity = nullptr;
|
|
||||||
lara->RightArm.Locked = false;
|
|
||||||
lara->LeftArm.Locked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(TrInput & IN_LOOK))
|
|
||||||
{
|
|
||||||
lara->ExtraHeadRot = (lara->LeftArm.Orientation + lara->RightArm.Orientation) / 4;
|
|
||||||
lara->ExtraTorsoRot = (lara->LeftArm.Orientation + lara->RightArm.Orientation) / 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetArmInfo(ItemInfo* laraItem, ArmInfo& arm, int frame)
|
|
||||||
{
|
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
|
||||||
const auto& pistols = PistolsTable[(int)lara->Control.Weapon.GunType];
|
|
||||||
|
|
||||||
int animBase = Objects[(int)pistols.ObjectNumber].animIndex;
|
|
||||||
|
|
||||||
if (frame < pistols.Draw1Anim)
|
|
||||||
arm.AnimNumber = animBase;
|
arm.AnimNumber = animBase;
|
||||||
else if (frame < pistols.Draw2Anim)
|
}
|
||||||
|
else if (frame < weaponAnimData.Draw2Anim)
|
||||||
|
{
|
||||||
arm.AnimNumber = animBase + 1;
|
arm.AnimNumber = animBase + 1;
|
||||||
else if (frame < pistols.RecoilAnim)
|
}
|
||||||
|
else if (frame < weaponAnimData.RecoilAnim)
|
||||||
|
{
|
||||||
arm.AnimNumber = animBase + 2;
|
arm.AnimNumber = animBase + 2;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
arm.AnimNumber = animBase + 3;
|
arm.AnimNumber = animBase + 3;
|
||||||
|
}
|
||||||
|
|
||||||
arm.FrameNumber = frame;
|
arm.FrameNumber = frame;
|
||||||
arm.FrameBase = g_Level.Anims[arm.AnimNumber].FramePtr;
|
arm.FrameBase = g_Level.Anims[arm.AnimNumber].FramePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawPistolMeshes(ItemInfo* laraItem, LaraWeaponType weaponType)
|
static void ReadyPistols(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
|
||||||
if (weaponType != LaraWeaponType::Revolver)
|
player.Control.HandStatus = HandStatus::WeaponReady;
|
||||||
lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
player.TargetEntity = nullptr;
|
||||||
|
player.LeftArm.FrameBase =
|
||||||
lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty;
|
player.RightArm.FrameBase = Objects[GetWeaponObjectID(weaponType)].frameBase;
|
||||||
|
player.LeftArm.FrameNumber =
|
||||||
laraItem->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_RHAND;
|
player.RightArm.FrameNumber = 0;
|
||||||
if (weaponType != LaraWeaponType::Revolver)
|
player.LeftArm.Orientation =
|
||||||
laraItem->Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_LHAND;
|
player.RightArm.Orientation = EulerAngles::Zero;
|
||||||
|
player.LeftArm.Locked =
|
||||||
|
player.RightArm.Locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UndrawPistolMeshRight(ItemInfo* laraItem, LaraWeaponType weaponType)
|
static void AnimateWeapon(ItemInfo& laraItem, LaraWeaponType weaponType, bool& hasFired, bool isRightWeapon)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
auto& arm = isRightWeapon ? player.RightArm : player.LeftArm;
|
||||||
|
auto& uziBool = isRightWeapon ? player.Control.Weapon.UziRight : player.Control.Weapon.UziLeft;
|
||||||
|
const auto& weapon = Weapons[(int)weaponType];
|
||||||
|
const auto& weaponAnimData = GetWeaponAnimData(player.Control.Weapon.GunType);
|
||||||
|
|
||||||
laraItem->Model.MeshIndex[LM_RHAND] = laraItem->Model.BaseMesh + LM_RHAND;
|
// Spawn weapon smoke.
|
||||||
if (lara->Weapons[(int)weaponType].Present)
|
if (laraItem.MeshBits.TestAny() && arm.GunSmoke)
|
||||||
lara->Control.Weapon.HolsterInfo.RightHolster = GetWeaponHolsterSlot(weaponType);
|
|
||||||
else
|
|
||||||
lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UndrawPistolMeshLeft(ItemInfo* laraItem, LaraWeaponType weaponType)
|
|
||||||
{
|
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
|
||||||
|
|
||||||
if (weaponType != LaraWeaponType::Revolver)
|
|
||||||
{
|
{
|
||||||
laraItem->Model.MeshIndex[LM_LHAND] = laraItem->Model.BaseMesh + LM_LHAND;
|
auto relOffset = GetWeaponSmokeRelOffset(weaponType, isRightWeapon);
|
||||||
|
auto pos = GetJointPosition(&laraItem, isRightWeapon ? LM_RHAND : LM_LHAND, relOffset);
|
||||||
|
TriggerGunSmoke(pos.x, pos.y, pos.z, 0, 0, 0, 0, weaponType, arm.GunSmoke);
|
||||||
|
}
|
||||||
|
|
||||||
if (lara->Weapons[(int)weaponType].Present)
|
int frame = arm.FrameNumber;
|
||||||
lara->Control.Weapon.HolsterInfo.LeftHolster = GetWeaponHolsterSlot(weaponType);
|
|
||||||
else
|
// Wind animation forward.
|
||||||
lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
if ((IsHeld(In::Action) && !player.TargetEntity) || arm.Locked)
|
||||||
|
{
|
||||||
|
// At or beyond DRAW_END (2) start frame AND before SHOOT_START (0) end frame; increment toward SHOOT_START (0) end frame.
|
||||||
|
if (frame >= 0 && frame < weaponAnimData.Draw1Anim2)
|
||||||
|
{
|
||||||
|
frame++;
|
||||||
|
}
|
||||||
|
// At SHOOT_START (0) end frame.
|
||||||
|
else if (frame == weaponAnimData.Draw1Anim2)
|
||||||
|
{
|
||||||
|
// Shoot weapon.
|
||||||
|
if (IsHeld(In::Action))
|
||||||
|
{
|
||||||
|
// HACK: Special case for revolver.
|
||||||
|
bool canShoot = (weaponType == LaraWeaponType::Revolver) ? isRightWeapon : true;
|
||||||
|
if (canShoot)
|
||||||
|
{
|
||||||
|
// HACK: Revolver, a right weapon, uses the left arm's orientation.
|
||||||
|
auto armOrient = (weaponType == LaraWeaponType::Revolver) ?
|
||||||
|
EulerAngles(
|
||||||
|
player.LeftArm.Orientation.x,
|
||||||
|
player.LeftArm.Orientation.y + laraItem.Pose.Orientation.y,
|
||||||
|
0) :
|
||||||
|
EulerAngles(
|
||||||
|
arm.Orientation.x,
|
||||||
|
arm.Orientation.y + laraItem.Pose.Orientation.y,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (FireWeapon(weaponType, *player.TargetEntity, laraItem, armOrient) != FireWeaponType::NoAmmo)
|
||||||
|
{
|
||||||
|
arm.GunSmoke = 28;
|
||||||
|
TriggerGunShell(isRightWeapon ? true : false, ID_GUNSHELL, weaponType);
|
||||||
|
arm.GunFlash = weapon.FlashTime;
|
||||||
|
|
||||||
|
if (weaponType == LaraWeaponType::Uzi)
|
||||||
|
uziBool = true;
|
||||||
|
|
||||||
|
if (!hasFired)
|
||||||
|
{
|
||||||
|
SoundEffect(SFX_TR4_EXPLOSION1, &laraItem.Pose, SoundEnvironment::Land, 0.9f, 0.3f);
|
||||||
|
SoundEffect(weapon.SampleNum, &laraItem.Pose);
|
||||||
|
hasFired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Statistics.Game.AmmoUsed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to SHOOT_CONTINUE (3) start frame.
|
||||||
|
frame = weaponAnimData.RecoilAnim;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (uziBool)
|
||||||
|
{
|
||||||
|
SoundEffect(weapon.SampleNum + 1, &laraItem.Pose);
|
||||||
|
uziBool = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// At or beyond SHOOT_CONTINUE (3) start frame; increment toward SHOOT_CONTINUE (3) end frame to finish recoil before allowing to shoot again.
|
||||||
|
else if (frame >= weaponAnimData.RecoilAnim)
|
||||||
|
{
|
||||||
|
if (weaponType == LaraWeaponType::Uzi)
|
||||||
|
{
|
||||||
|
SoundEffect(weapon.SampleNum, &laraItem.Pose);
|
||||||
|
uziBool = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame++;
|
||||||
|
|
||||||
|
// At SHOOT_CONTINUE (3) end frame; go to START_SHOOT (0) end frame.
|
||||||
|
if (frame == (weaponAnimData.RecoilAnim + weapon.RecoilFrame))
|
||||||
|
frame = weaponAnimData.Draw1Anim2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wind animation backward.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Let SHOOT_CONTINUE (3) finish.
|
||||||
|
if (frame >= weaponAnimData.RecoilAnim && frame < (weaponAnimData.RecoilAnim + weapon.RecoilFrame))
|
||||||
|
frame++;
|
||||||
|
|
||||||
|
// At SHOOT_CONTINUE (3) end frame; go to START_SHOOT (0) end frame.
|
||||||
|
if (frame == (weaponAnimData.RecoilAnim + weapon.RecoilFrame))
|
||||||
|
{
|
||||||
|
frame = weaponAnimData.Draw1Anim2;
|
||||||
|
}
|
||||||
|
// Go back to "ready" stance.
|
||||||
|
else if ((frame > 0) && (frame <= weaponAnimData.Draw1Anim2))
|
||||||
|
{
|
||||||
|
frame--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uziBool)
|
||||||
|
{
|
||||||
|
SoundEffect(weapon.SampleNum + 1, &laraItem.Pose);
|
||||||
|
uziBool = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetArmInfo(laraItem, arm, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int AnimateWeaponUndraw(ItemInfo& laraItem, LaraWeaponType weaponType, bool isRightWeapon)
|
||||||
|
{
|
||||||
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
auto& arm = isRightWeapon ? player.RightArm : player.LeftArm;
|
||||||
|
const auto& weapon = Weapons[(int)weaponType];
|
||||||
|
const auto& weaponAnimData = GetWeaponAnimData(player.Control.Weapon.GunType);
|
||||||
|
|
||||||
|
int frame = arm.FrameNumber;
|
||||||
|
|
||||||
|
// Finish recoil anim before reholstering weapon.
|
||||||
|
if (frame >= weaponAnimData.RecoilAnim && frame < (weaponAnimData.RecoilAnim + weapon.RecoilFrame))
|
||||||
|
frame++;
|
||||||
|
|
||||||
|
if (frame == (weaponAnimData.RecoilAnim + weapon.RecoilFrame))
|
||||||
|
{
|
||||||
|
frame = weaponAnimData.Draw1Anim2;
|
||||||
|
}
|
||||||
|
else if (frame > 0 && frame < weaponAnimData.Draw1Anim)
|
||||||
|
{
|
||||||
|
arm.Orientation -= arm.Orientation / frame;
|
||||||
|
frame--;
|
||||||
|
}
|
||||||
|
else if (frame == 0)
|
||||||
|
{
|
||||||
|
arm.Orientation = EulerAngles::Zero;
|
||||||
|
frame = weaponAnimData.RecoilAnim - 1;
|
||||||
|
}
|
||||||
|
else if (frame > weaponAnimData.Draw1Anim && frame < weaponAnimData.RecoilAnim)
|
||||||
|
{
|
||||||
|
frame--;
|
||||||
|
|
||||||
|
if (frame == (weaponAnimData.Draw2Anim - 1))
|
||||||
|
{
|
||||||
|
UndrawPistolMesh(laraItem, weaponType, isRightWeapon);
|
||||||
|
SoundEffect(SFX_TR4_LARA_HOLSTER, &laraItem.Pose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetArmInfo(laraItem, arm, frame);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandlePistols(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
|
{
|
||||||
|
auto& lara = *GetLaraInfo(&laraItem);
|
||||||
|
auto& weapon = Weapons[(int)weaponType];
|
||||||
|
|
||||||
|
FindNewTarget(laraItem, weapon);
|
||||||
|
if (IsHeld(In::Action))
|
||||||
|
LaraTargetInfo(laraItem, weapon);
|
||||||
|
|
||||||
|
AimWeapon(laraItem, lara.LeftArm, weapon);
|
||||||
|
AimWeapon(laraItem, lara.RightArm, weapon);
|
||||||
|
|
||||||
|
if (lara.LeftArm.Locked && !lara.RightArm.Locked)
|
||||||
|
{
|
||||||
|
lara.ExtraTorsoRot = lara.LeftArm.Orientation / 2;
|
||||||
|
|
||||||
|
if (Camera.oldType != CameraType::Look)
|
||||||
|
lara.ExtraHeadRot = lara.ExtraTorsoRot;
|
||||||
|
}
|
||||||
|
else if (!lara.LeftArm.Locked && lara.RightArm.Locked)
|
||||||
|
{
|
||||||
|
lara.ExtraTorsoRot = lara.RightArm.Orientation / 2;
|
||||||
|
|
||||||
|
if (Camera.oldType != CameraType::Look)
|
||||||
|
lara.ExtraHeadRot = lara.ExtraTorsoRot;
|
||||||
|
}
|
||||||
|
else if (lara.LeftArm.Locked && lara.RightArm.Locked)
|
||||||
|
{
|
||||||
|
lara.ExtraTorsoRot = (lara.LeftArm.Orientation + lara.RightArm.Orientation) / 4;
|
||||||
|
|
||||||
|
if (Camera.oldType != CameraType::Look)
|
||||||
|
lara.ExtraHeadRot = lara.ExtraTorsoRot;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatePistols(laraItem, weaponType);
|
||||||
|
|
||||||
|
if (lara.LeftArm.GunFlash || lara.RightArm.GunFlash)
|
||||||
|
{
|
||||||
|
auto basePos = GetJointPosition(&laraItem, (lara.LeftArm.GunFlash != 0) ? LM_LHAND : LM_RHAND).ToVector3();
|
||||||
|
auto sphere = BoundingSphere(basePos, BLOCK(1 / 8.0f));
|
||||||
|
auto lightPos = Random::GeneratePointInSphere(sphere);
|
||||||
|
|
||||||
|
TriggerDynamicLight(
|
||||||
|
lightPos.x, lightPos.y, lightPos.z,
|
||||||
|
Random::GenerateFloat(8.0f, 11.0f),
|
||||||
|
(GetRandomControl() & 0x3F) + 192, (GetRandomControl() & 0x1F) + 128, GetRandomControl() & 0x3F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimatePistols(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
|
{
|
||||||
|
bool hasFired = false;
|
||||||
|
AnimateWeapon(laraItem, weaponType, hasFired, true);
|
||||||
|
AnimateWeapon(laraItem, weaponType, hasFired, false);
|
||||||
|
|
||||||
|
// If either weapon has fired, rumble gamepad.
|
||||||
|
if (hasFired)
|
||||||
|
{
|
||||||
|
float power = (weaponType == LaraWeaponType::Uzi) ? Random::GenerateFloat(0.1f, 0.3f) : 1.0f;
|
||||||
|
Rumble(power, 0.1f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPistols(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
|
{
|
||||||
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
const auto& weaponAnimData = GetWeaponAnimData(player.Control.Weapon.GunType);
|
||||||
|
|
||||||
|
int frame = player.LeftArm.FrameNumber + 1;
|
||||||
|
|
||||||
|
if (frame < weaponAnimData.Draw1Anim || frame > (weaponAnimData.RecoilAnim - 1))
|
||||||
|
{
|
||||||
|
frame = weaponAnimData.Draw1Anim;
|
||||||
|
}
|
||||||
|
else if (frame == weaponAnimData.Draw2Anim)
|
||||||
|
{
|
||||||
|
DrawPistolMeshes(laraItem, weaponType);
|
||||||
|
SoundEffect(SFX_TR4_LARA_DRAW, &laraItem.Pose);
|
||||||
|
}
|
||||||
|
else if (frame == (weaponAnimData.RecoilAnim - 1))
|
||||||
|
{
|
||||||
|
ReadyPistols(laraItem, weaponType);
|
||||||
|
frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetArmInfo(laraItem, player.RightArm, frame);
|
||||||
|
SetArmInfo(laraItem, player.LeftArm, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UndrawPistols(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
|
{
|
||||||
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
const auto& weaponAnimData = GetWeaponAnimData(player.Control.Weapon.GunType);
|
||||||
|
|
||||||
|
int frameLeft = AnimateWeaponUndraw(laraItem, weaponType, false);
|
||||||
|
int frameRight = AnimateWeaponUndraw(laraItem, weaponType, true);
|
||||||
|
|
||||||
|
if (frameLeft == weaponAnimData.Draw1Anim &&
|
||||||
|
frameRight == weaponAnimData.Draw1Anim)
|
||||||
|
{
|
||||||
|
player.Control.HandStatus = HandStatus::Free;
|
||||||
|
player.TargetEntity = nullptr;
|
||||||
|
player.LeftArm.FrameNumber =
|
||||||
|
player.RightArm.FrameNumber = 0;
|
||||||
|
player.LeftArm.Locked =
|
||||||
|
player.RightArm.Locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsHeld(In::Look))
|
||||||
|
{
|
||||||
|
player.ExtraHeadRot = (player.LeftArm.Orientation + player.RightArm.Orientation) / 4;
|
||||||
|
player.ExtraTorsoRot = (player.LeftArm.Orientation + player.RightArm.Orientation) / 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPistolMeshes(ItemInfo& laraItem, LaraWeaponType weaponType)
|
||||||
|
{
|
||||||
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
|
||||||
|
if (weaponType != LaraWeaponType::Revolver)
|
||||||
|
player.Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
||||||
|
|
||||||
|
player.Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty;
|
||||||
|
|
||||||
|
laraItem.Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_RHAND;
|
||||||
|
if (weaponType != LaraWeaponType::Revolver)
|
||||||
|
laraItem.Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(laraItem, weaponType)].meshIndex + LM_LHAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UndrawPistolMesh(ItemInfo& laraItem, LaraWeaponType weaponType, bool isRightWeapon)
|
||||||
|
{
|
||||||
|
auto& player = GetLaraInfo(laraItem);
|
||||||
|
auto& holster = isRightWeapon ? player.Control.Weapon.HolsterInfo.RightHolster : player.Control.Weapon.HolsterInfo.LeftHolster;
|
||||||
|
|
||||||
|
// HACK: Special case for revolver.
|
||||||
|
if (!isRightWeapon && weaponType == LaraWeaponType::Revolver)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int jointIndex = isRightWeapon ? LM_RHAND : LM_LHAND;
|
||||||
|
laraItem.Model.MeshIndex[jointIndex] = laraItem.Model.BaseMesh + jointIndex;
|
||||||
|
|
||||||
|
if (player.Weapons[(int)weaponType].Present)
|
||||||
|
{
|
||||||
|
holster = GetWeaponHolsterSlot(weaponType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
holster = HolsterSlot::Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Game/Lara/lara_struct.h"
|
|
||||||
|
|
||||||
void AnimatePistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
enum class LaraWeaponType;
|
||||||
void PistolHandler(ItemInfo* laraItem, LaraWeaponType weaponType);
|
struct ItemInfo;
|
||||||
void ReadyPistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
|
||||||
void DrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void HandlePistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void UndrawPistols(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void AnimatePistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void SetArmInfo(ItemInfo* laraItem, ArmInfo& arm, int frame);
|
|
||||||
void DrawPistolMeshes(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void DrawPistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void UndrawPistolMeshRight(ItemInfo* laraItem, LaraWeaponType weaponType);
|
void DrawPistolMeshes(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
void UndrawPistolMeshLeft(ItemInfo* laraItem, LaraWeaponType weaponType);
|
|
||||||
|
void UndrawPistols(ItemInfo& laraItem, LaraWeaponType weaponType);
|
||||||
|
void UndrawPistolMesh(ItemInfo& laraItem, LaraWeaponType weaponType, bool isRightWeapon);
|
||||||
|
|
139
TombEngine/Game/Setup.cpp
Normal file
139
TombEngine/Game/Setup.cpp
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#include "framework.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
|
|
||||||
|
#include "Game/animation.h"
|
||||||
|
#include "Game/camera.h"
|
||||||
|
#include "Game/collision/collide_item.h"
|
||||||
|
#include "Game/control/flipeffect.h"
|
||||||
|
#include "Game/effects/effects.h"
|
||||||
|
#include "Game/effects/Hair.h"
|
||||||
|
#include "Game/effects/tomb4fx.h"
|
||||||
|
#include "Game/itemdata/creature_info.h"
|
||||||
|
#include "Game/pickup/pickup.h"
|
||||||
|
#include "Game/room.h"
|
||||||
|
#include "Objects/Effects/effect_objects.h"
|
||||||
|
#include "Objects/Generic/generic_objects.h"
|
||||||
|
#include "Objects/Generic/Object/objects.h"
|
||||||
|
#include "Objects/Generic/Object/rope.h"
|
||||||
|
#include "Objects/Generic/Switches/fullblock_switch.h"
|
||||||
|
#include "Objects/Generic/Switches/switch.h"
|
||||||
|
#include "Objects/Generic/Traps/falling_block.h"
|
||||||
|
#include "Objects/TR1/tr1_objects.h"
|
||||||
|
#include "Objects/TR2/tr2_objects.h"
|
||||||
|
#include "Objects/TR3/tr3_objects.h"
|
||||||
|
#include "Objects/TR4/tr4_objects.h"
|
||||||
|
#include "Objects/TR5/tr5_objects.h"
|
||||||
|
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||||
|
#include "Objects/Utils/object_helper.h"
|
||||||
|
#include "Specific/level.h"
|
||||||
|
|
||||||
|
using namespace TEN::Effects::Hair;
|
||||||
|
using namespace TEN::Entities;
|
||||||
|
using namespace TEN::Entities::Switches;
|
||||||
|
|
||||||
|
ObjectInfo Objects[ID_NUMBER_OBJECTS];
|
||||||
|
STATIC_INFO StaticObjects[MAX_STATICS];
|
||||||
|
|
||||||
|
void InitializeGameFlags()
|
||||||
|
{
|
||||||
|
ZeroMemory(FlipMap, MAX_FLIPMAP * sizeof(int));
|
||||||
|
ZeroMemory(FlipStats, MAX_FLIPMAP * sizeof(int));
|
||||||
|
|
||||||
|
FlipEffect = -1;
|
||||||
|
FlipStatus = 0;
|
||||||
|
Camera.underwater = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
memset(&Particles, 0, MAX_PARTICLES * sizeof(Particle));
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_PARTICLES; i++)
|
||||||
|
{
|
||||||
|
Particles[i].on = false;
|
||||||
|
Particles[i].dynamic = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NextFireSpark = 1;
|
||||||
|
NextSmokeSpark = 0;
|
||||||
|
NextGunShell = 0;
|
||||||
|
NextBlood = 0;
|
||||||
|
|
||||||
|
TEN::Entities::TR4::ClearBeetleSwarm();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomObjects()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeObjects()
|
||||||
|
{
|
||||||
|
AllocTR4Objects();
|
||||||
|
AllocTR5Objects();
|
||||||
|
|
||||||
|
ObjectInfo* obj;
|
||||||
|
|
||||||
|
for (int i = 0; i < ID_NUMBER_OBJECTS; i++)
|
||||||
|
{
|
||||||
|
obj = &Objects[i];
|
||||||
|
obj->Initialize = nullptr;
|
||||||
|
obj->collision = nullptr;
|
||||||
|
obj->control = nullptr;
|
||||||
|
obj->floor = nullptr;
|
||||||
|
obj->ceiling = nullptr;
|
||||||
|
obj->drawRoutine = DrawAnimatingItem;
|
||||||
|
obj->HitRoutine = DefaultItemHit;
|
||||||
|
obj->pivotLength = 0;
|
||||||
|
obj->radius = DEFAULT_RADIUS;
|
||||||
|
obj->shadowType = ShadowMode::None;
|
||||||
|
obj->HitPoints = NOT_TARGETABLE;
|
||||||
|
obj->hitEffect = HitEffect::None;
|
||||||
|
obj->explodableMeshbits = 0;
|
||||||
|
obj->intelligent = false;
|
||||||
|
obj->waterCreature = false;
|
||||||
|
obj->nonLot = false;
|
||||||
|
obj->usingDrawAnimatingItem = true;
|
||||||
|
obj->undead = false;
|
||||||
|
obj->LotType = LotType::Basic;
|
||||||
|
obj->meshSwapSlot = NO_ITEM;
|
||||||
|
obj->isPickup = false;
|
||||||
|
obj->isPuzzleHole = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeEffectsObjects();
|
||||||
|
InitializeGenericObjects(); // Generic objects
|
||||||
|
InitializeTR1Objects(); // Standard TR1 objects
|
||||||
|
InitializeTR2Objects(); // Standard TR2 objects
|
||||||
|
InitializeTR3Objects(); // Standard TR3 objects
|
||||||
|
InitializeTR4Objects(); // Standard TR4 objects
|
||||||
|
InitializeTR5Objects(); // Standard TR5 objects
|
||||||
|
|
||||||
|
// User defined objects
|
||||||
|
CustomObjects();
|
||||||
|
|
||||||
|
HairEffect.Initialize();
|
||||||
|
InitializeSpecialEffects();
|
||||||
|
|
||||||
|
NumRPickups = 0;
|
||||||
|
CurrentSequence = 0;
|
||||||
|
SequenceResults[0][1][2] = 0;
|
||||||
|
SequenceResults[0][2][1] = 1;
|
||||||
|
SequenceResults[1][0][2] = 2;
|
||||||
|
SequenceResults[1][2][0] = 3;
|
||||||
|
SequenceResults[2][0][1] = 4;
|
||||||
|
SequenceResults[2][1][0] = 5;
|
||||||
|
SequenceUsed[0] = 0;
|
||||||
|
SequenceUsed[1] = 0;
|
||||||
|
SequenceUsed[2] = 0;
|
||||||
|
SequenceUsed[3] = 0;
|
||||||
|
SequenceUsed[4] = 0;
|
||||||
|
SequenceUsed[5] = 0;
|
||||||
|
}
|
|
@ -1,16 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Objects/objectslist.h"
|
#include "Objects/objectslist.h"
|
||||||
|
#include "Game/control/box.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Renderer/Renderer11Enums.h"
|
#include "Renderer/Renderer11Enums.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
|
|
||||||
enum class ZoneType;
|
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
|
||||||
constexpr auto DEFAULT_RADIUS = 10;
|
constexpr auto DEFAULT_RADIUS = 10;
|
||||||
|
|
||||||
// Custom LOT definition for Creature. Used in InitialiseSlot() in lot.cpp.
|
// Custom LOT definition for Creature. Used in InitializeSlot() in lot.cpp.
|
||||||
enum class LotType
|
enum class LotType
|
||||||
{
|
{
|
||||||
Skeleton,
|
Skeleton,
|
||||||
|
@ -23,7 +23,8 @@ enum class LotType
|
||||||
Flyer,
|
Flyer,
|
||||||
Blockable, // For large creatures such as trex and shiva.
|
Blockable, // For large creatures such as trex and shiva.
|
||||||
Spider, // Only 2 block vault allowed.
|
Spider, // Only 2 block vault allowed.
|
||||||
Ape // Only 2 block vault allowed.
|
Ape, // Only 2 block vault allowed.
|
||||||
|
SnowmobileGun // Only 1 block vault allowed and 4 block drop max.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum JointRotationFlags
|
enum JointRotationFlags
|
||||||
|
@ -52,53 +53,59 @@ enum ShatterType
|
||||||
|
|
||||||
struct ObjectInfo
|
struct ObjectInfo
|
||||||
{
|
{
|
||||||
int nmeshes;
|
bool loaded = false; // IsLoaded
|
||||||
int meshIndex;
|
|
||||||
int boneIndex;
|
int nmeshes; // BoneCount
|
||||||
int frameBase;
|
int meshIndex; // Base index in g_Level.Meshes.
|
||||||
|
int boneIndex; // Base index in g_Level.Bones.
|
||||||
|
int animIndex; // Base index in g_Level.Anims.
|
||||||
|
int frameBase; // Base index in g_Level.Frames.
|
||||||
|
|
||||||
LotType LotType;
|
LotType LotType;
|
||||||
int animIndex;
|
|
||||||
short HitPoints;
|
|
||||||
short pivotLength;
|
|
||||||
short radius;
|
|
||||||
ShadowMode shadowType;
|
|
||||||
short biteOffset;
|
|
||||||
bool loaded;
|
|
||||||
bool intelligent;
|
|
||||||
bool nonLot;
|
|
||||||
bool waterCreature;
|
|
||||||
bool usingDrawAnimatingItem;
|
|
||||||
HitEffect hitEffect;
|
HitEffect hitEffect;
|
||||||
bool undead;
|
ShadowMode shadowType;
|
||||||
bool isPickup;
|
|
||||||
bool isPuzzleHole;
|
|
||||||
int meshSwapSlot;
|
int meshSwapSlot;
|
||||||
|
int pivotLength;
|
||||||
|
int radius;
|
||||||
|
|
||||||
|
int HitPoints;
|
||||||
|
bool intelligent; // IsIntelligent
|
||||||
|
bool waterCreature; // IsWaterCreature
|
||||||
|
bool undead; // IsUndead
|
||||||
|
bool nonLot; // IsNonLot
|
||||||
|
bool isPickup; // IsPickup
|
||||||
|
bool isPuzzleHole; // IsReceptacle
|
||||||
|
bool usingDrawAnimatingItem;
|
||||||
|
|
||||||
DWORD explodableMeshbits;
|
DWORD explodableMeshbits;
|
||||||
|
|
||||||
std::function<void(short itemNumber)> initialise;
|
std::function<void(short itemNumber)> Initialize;
|
||||||
std::function<void(short itemNumber)> control;
|
std::function<void(short itemNumber)> control;
|
||||||
|
std::function<void(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)> collision;
|
||||||
|
|
||||||
|
std::function<void(ItemInfo& target, ItemInfo& source, std::optional<GameVector> pos, int damage, bool isExplosive, int jointIndex)> HitRoutine;
|
||||||
|
std::function<void(ItemInfo* item)> drawRoutine;
|
||||||
|
|
||||||
std::function<std::optional<int>(int itemNumber, int x, int y, int z)> floor;
|
std::function<std::optional<int>(int itemNumber, int x, int y, int z)> floor;
|
||||||
std::function<std::optional<int>(int itemNumber, int x, int y, int z)> ceiling;
|
std::function<std::optional<int>(int itemNumber, int x, int y, int z)> ceiling;
|
||||||
std::function<int(short itemNumber)> floorBorder;
|
std::function<int(short itemNumber)> floorBorder;
|
||||||
std::function<int(short itemNumber)> ceilingBorder;
|
std::function<int(short itemNumber)> ceilingBorder;
|
||||||
std::function<void(ItemInfo* item)> drawRoutine;
|
|
||||||
std::function<void(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)> collision;
|
|
||||||
std::function<void(ItemInfo& target, ItemInfo& source, std::optional<GameVector> pos, int damage, bool isExplosive, int jointIndex)> HitRoutine;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use ROT_X/Y/Z to allow bones to be rotated with CreatureJoint().
|
/// ROT_X/Y/Z allows bones to be rotated with CreatureJoint().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="boneID">the mesh id - 1</param>
|
/// <param name="boneNumber:">Mesh number - 1.</param>
|
||||||
/// <param name="flags">can be ROT_X, ROT_Y, ROT_Z or all.</param>
|
/// <param name="flags:">JointRotationFlags enum.</param>
|
||||||
void SetBoneRotationFlags(int boneID, int flags)
|
void SetBoneRotationFlags(int boneNumber, int flags)
|
||||||
{
|
{
|
||||||
g_Level.Bones[boneIndex + boneID * 4] |= flags;
|
g_Level.Bones[boneIndex + (boneNumber * 4)] |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use this to set up a hit effect for the slot based on its value.
|
/// Set up hit effect for object based on its value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="isAlive">Use this if the object is alive but not intelligent to set up blood effects.</param>
|
/// <param name="isAlive:">Use if object is alive but not intelligent to set up blood effects.</param>
|
||||||
void SetupHitEffect(bool isSolid = false, bool isAlive = false)
|
void SetupHitEffect(bool isSolid = false, bool isAlive = false)
|
||||||
{
|
{
|
||||||
// Avoid some objects such as ID_SAS_DYING having None.
|
// Avoid some objects such as ID_SAS_DYING having None.
|
||||||
|
@ -153,6 +160,6 @@ constexpr auto SWAMP_GRAVITY = GRAVITY / 3.0f;
|
||||||
extern ObjectInfo Objects[ID_NUMBER_OBJECTS];
|
extern ObjectInfo Objects[ID_NUMBER_OBJECTS];
|
||||||
extern STATIC_INFO StaticObjects[MAX_STATICS];
|
extern STATIC_INFO StaticObjects[MAX_STATICS];
|
||||||
|
|
||||||
void InitialiseGameFlags();
|
void InitializeGameFlags();
|
||||||
void InitialiseSpecialEffects();
|
void InitializeSpecialEffects();
|
||||||
void InitialiseObjects();
|
void InitializeObjects();
|
|
@ -8,12 +8,12 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/Generic/Object/rope.h"
|
#include "Objects/Generic/Object/rope.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Entities::Generic;
|
using namespace TEN::Entities::Generic;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
@ -74,10 +74,10 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased)
|
||||||
{
|
{
|
||||||
auto& player = GetLaraInfo(item);
|
auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
if (player.Control.CalculatedJumpVelocity != 0)
|
if (player.Context.CalcJumpVelocity != 0)
|
||||||
{
|
{
|
||||||
item.Animation.Velocity.y = player.Control.CalculatedJumpVelocity;
|
item.Animation.Velocity.y = player.Context.CalcJumpVelocity;
|
||||||
player.Control.CalculatedJumpVelocity = 0;
|
player.Context.CalcJumpVelocity = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,8 +121,8 @@ static void PerformAnimCommands(ItemInfo& item, bool isFrameBased)
|
||||||
auto& player = GetLaraInfo(item);
|
auto& player = GetLaraInfo(item);
|
||||||
|
|
||||||
if (playAlways ||
|
if (playAlways ||
|
||||||
(playOnLand && (player.WaterSurfaceDist >= -SHALLOW_WATER_DEPTH || player.WaterSurfaceDist == NO_HEIGHT)) ||
|
(playOnLand && (player.Context.WaterSurfaceDist >= -SHALLOW_WATER_DEPTH || player.Context.WaterSurfaceDist == NO_HEIGHT)) ||
|
||||||
(playInWater && player.WaterSurfaceDist < -SHALLOW_WATER_DEPTH && player.WaterSurfaceDist != NO_HEIGHT && !TestEnvironment(ENV_FLAG_SWAMP, &item)))
|
(playInWater && player.Context.WaterSurfaceDist < -SHALLOW_WATER_DEPTH && player.Context.WaterSurfaceDist != NO_HEIGHT && !TestEnvironment(ENV_FLAG_SWAMP, &item)))
|
||||||
{
|
{
|
||||||
SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, SoundEnvironment::Always);
|
SoundEffect(commandDataPtr[1] & 0x3FFF, &item.Pose, SoundEnvironment::Always);
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,19 @@ void AnimateItem(ItemInfo* item)
|
||||||
{
|
{
|
||||||
item->Animation.ActiveState = animPtr->ActiveState;
|
item->Animation.ActiveState = animPtr->ActiveState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Theoretically this is better than above block, but it must be checked. -- Sezz 2023.03.31
|
||||||
|
/*if (item->Animation.ActiveState != animPtr->ActiveState)
|
||||||
|
{
|
||||||
|
item->Animation.ActiveState =
|
||||||
|
item->Animation.TargetState = animPtr->ActiveState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!item->IsLara())
|
||||||
|
{
|
||||||
|
if (item->Animation.RequiredState == item->Animation.ActiveState)
|
||||||
|
item->Animation.RequiredState = NO_STATE;
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int frameCount = GetNonZeroFrameCount(*animPtr);
|
unsigned int frameCount = GetNonZeroFrameCount(*animPtr);
|
||||||
|
@ -336,19 +349,23 @@ bool HasStateDispatch(ItemInfo* item, int targetState)
|
||||||
|
|
||||||
bool TestAnimNumber(const ItemInfo& item, int animNumber)
|
bool TestAnimNumber(const ItemInfo& item, int animNumber)
|
||||||
{
|
{
|
||||||
const auto& object = Objects[item.ObjectNumber];
|
const auto& object = Objects[item.Animation.AnimObjectID];
|
||||||
return (item.Animation.AnimNumber == (object.animIndex + animNumber));
|
return (item.Animation.AnimNumber == (object.animIndex + animNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestLastFrame(ItemInfo* item, int animNumber)
|
bool TestLastFrame(ItemInfo* item, int animNumber)
|
||||||
{
|
{
|
||||||
if (animNumber == NO_ANIM)
|
const auto& object = Objects[item->Animation.AnimObjectID];
|
||||||
animNumber = item->Animation.AnimNumber;
|
|
||||||
|
|
||||||
if (item->Animation.AnimNumber != animNumber)
|
if (animNumber == NO_ANIM)
|
||||||
|
animNumber = item->Animation.AnimNumber - object.animIndex;
|
||||||
|
|
||||||
|
// Animation to test doesn't match; return early.
|
||||||
|
int animIndex = object.animIndex + animNumber;
|
||||||
|
if (item->Animation.AnimNumber != animIndex)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto& anim = GetAnimData(*item, animNumber);
|
const auto& anim = GetAnimData(object, animNumber);
|
||||||
return (item->Animation.FrameNumber >= anim.frameEnd);
|
return (item->Animation.FrameNumber >= anim.frameEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,32 +397,49 @@ void TranslateItem(ItemInfo* item, const Vector3& direction, float distance)
|
||||||
item->Pose.Translate(direction, distance);
|
item->Pose.Translate(direction, distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAnimation(ItemInfo* item, int animNumber, int frameNumber)
|
void SetAnimation(ItemInfo& item, GAME_OBJECT_ID animObjectID, int animNumber, int frameNumber)
|
||||||
{
|
{
|
||||||
const auto& object = Objects[item->ObjectNumber];
|
const auto& animObject = Objects[animObjectID];
|
||||||
int animIndex = object.animIndex + animNumber;
|
int animIndex = animObject.animIndex + animNumber;
|
||||||
|
|
||||||
// Animation already set; return early.
|
// Animation is missing; return early.
|
||||||
if (item->Animation.AnimNumber == animIndex)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Animation doesn't exist; return early.
|
|
||||||
if (animIndex < 0 || animIndex >= g_Level.Anims.size())
|
if (animIndex < 0 || animIndex >= g_Level.Anims.size())
|
||||||
{
|
{
|
||||||
TENLog(
|
TENLog(
|
||||||
std::string("Attempted to set nonexistent animation ") + std::to_string(animNumber) +
|
std::string("Attempted to set missing animation ") + std::to_string(animNumber) +
|
||||||
std::string(" for object ") + std::to_string(item->ObjectNumber),
|
(animObjectID == item.ObjectNumber ? std::string() : std::string(" from object ") + GetObjectName(animObjectID)) +
|
||||||
|
std::string(" for object ") + GetObjectName(item.ObjectNumber),
|
||||||
LogLevel::Warning);
|
LogLevel::Warning);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& anim = GetAnimData(*item, animNumber);
|
const auto& anim = GetAnimData(animObject, animNumber);
|
||||||
|
int frameIndex = anim.frameBase + frameNumber;
|
||||||
item->Animation.AnimNumber = animIndex;
|
|
||||||
item->Animation.FrameNumber = anim.frameBase + frameNumber;
|
// Animation already set; return early.
|
||||||
item->Animation.ActiveState =
|
if (item.Animation.AnimObjectID == animObjectID &&
|
||||||
item->Animation.TargetState = anim.ActiveState;
|
item.Animation.AnimNumber == animIndex &&
|
||||||
|
item.Animation.FrameNumber == frameIndex)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Animation.AnimObjectID = animObjectID;
|
||||||
|
item.Animation.AnimNumber = animIndex;
|
||||||
|
item.Animation.FrameNumber = frameIndex;
|
||||||
|
item.Animation.ActiveState =
|
||||||
|
item.Animation.TargetState = anim.ActiveState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAnimation(ItemInfo& item, int animNumber, int frameNumber)
|
||||||
|
{
|
||||||
|
SetAnimation(item, item.ObjectNumber, animNumber, frameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAnimation(ItemInfo* item, int animNumber, int frameNumber)
|
||||||
|
{
|
||||||
|
SetAnimation(*item, item->ObjectNumber, animNumber, frameNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimData& GetAnimData(int animIndex)
|
AnimData& GetAnimData(int animIndex)
|
||||||
|
@ -413,6 +447,12 @@ AnimData& GetAnimData(int animIndex)
|
||||||
return g_Level.Anims[animIndex];
|
return g_Level.Anims[animIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimData& GetAnimData(GAME_OBJECT_ID objectID, int animNumber)
|
||||||
|
{
|
||||||
|
const auto& object = Objects[objectID];
|
||||||
|
return GetAnimData(object, animNumber);
|
||||||
|
}
|
||||||
|
|
||||||
AnimData& GetAnimData(const ObjectInfo& object, int animNumber)
|
AnimData& GetAnimData(const ObjectInfo& object, int animNumber)
|
||||||
{
|
{
|
||||||
return g_Level.Anims[object.animIndex + animNumber];
|
return g_Level.Anims[object.animIndex + animNumber];
|
||||||
|
@ -421,12 +461,140 @@ AnimData& GetAnimData(const ObjectInfo& object, int animNumber)
|
||||||
AnimData& GetAnimData(const ItemInfo& item, int animNumber)
|
AnimData& GetAnimData(const ItemInfo& item, int animNumber)
|
||||||
{
|
{
|
||||||
if (animNumber == NO_ANIM)
|
if (animNumber == NO_ANIM)
|
||||||
return g_Level.Anims[item.Animation.AnimNumber];
|
return GetAnimData(item.Animation.AnimNumber);
|
||||||
|
|
||||||
const auto& object = Objects[item.ObjectNumber];
|
const auto& object = Objects[item.Animation.AnimObjectID];
|
||||||
return GetAnimData(object, animNumber);
|
return GetAnimData(object, animNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimFrameInterpData GetFrameInterpData(const ItemInfo& item)
|
||||||
|
{
|
||||||
|
const auto& anim = GetAnimData(item);
|
||||||
|
|
||||||
|
// Normalize animation's current frame number into keyframe range.
|
||||||
|
int frameNumber = GetFrameNumber(item);
|
||||||
|
float frameNumberNorm = frameNumber / (float)anim.Interpolation;
|
||||||
|
|
||||||
|
// Calculate keyframe numbers defining interpolated frame and get pointers to them.
|
||||||
|
int frame0 = (int)floor(frameNumberNorm);
|
||||||
|
int frame1 = (int)ceil(frameNumberNorm);
|
||||||
|
auto* framePtr0 = &g_Level.Frames[anim.FramePtr + frame0];
|
||||||
|
auto* framePtr1 = &g_Level.Frames[anim.FramePtr + frame1];
|
||||||
|
|
||||||
|
// Calculate interpolation alpha between keyframes.
|
||||||
|
float alpha = (1.0f / anim.Interpolation) * (frameNumber % anim.Interpolation);
|
||||||
|
|
||||||
|
// Return frame interpolation data.
|
||||||
|
return AnimFrameInterpData{ framePtr0, framePtr1, alpha };
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimFrame& GetAnimFrame(const ItemInfo& item, int animNumber, int frameNumber)
|
||||||
|
{
|
||||||
|
return *GetFrame(item.ObjectNumber, animNumber, frameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimFrame* GetFrame(GAME_OBJECT_ID objectID, int animNumber, int frameNumber)
|
||||||
|
{
|
||||||
|
const auto& object = Objects[objectID];
|
||||||
|
|
||||||
|
int animIndex = object.animIndex + animNumber;
|
||||||
|
assertion(animIndex < g_Level.Anims.size(), "GetFrame() attempted to access missing animation.");
|
||||||
|
|
||||||
|
const auto& anim = GetAnimData(object, animNumber);
|
||||||
|
|
||||||
|
// Get and clamp frame count.
|
||||||
|
unsigned int frameCount = anim.frameEnd - anim.frameBase;
|
||||||
|
if (frameNumber > frameCount)
|
||||||
|
frameNumber = frameCount;
|
||||||
|
|
||||||
|
// Interpolate and return frame pointer.
|
||||||
|
auto* framePtr = &g_Level.Frames[anim.FramePtr];
|
||||||
|
framePtr += frameNumber / anim.Interpolation;
|
||||||
|
return framePtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimFrame* GetFirstFrame(GAME_OBJECT_ID objectID, int animNumber)
|
||||||
|
{
|
||||||
|
return GetFrame(objectID, animNumber, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimFrame* GetLastFrame(GAME_OBJECT_ID objectID, int animNumber)
|
||||||
|
{
|
||||||
|
return GetFrame(objectID, animNumber, INT_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimFrame& GetBestFrame(const ItemInfo& item)
|
||||||
|
{
|
||||||
|
auto frameData = GetFrameInterpData(item);
|
||||||
|
if (frameData.Alpha <= 0.5f)
|
||||||
|
return *frameData.FramePtr0;
|
||||||
|
else
|
||||||
|
return *frameData.FramePtr1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetFrameNumber(const ItemInfo& item)
|
||||||
|
{
|
||||||
|
const auto& anim = GetAnimData(item);
|
||||||
|
return (item.Animation.FrameNumber - anim.frameBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetFrameNumber(ItemInfo* item)
|
||||||
|
{
|
||||||
|
return GetFrameNumber(*item);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetAnimNumber(const ItemInfo& item)
|
||||||
|
{
|
||||||
|
const auto& object = Objects[item.Animation.AnimObjectID];
|
||||||
|
return (item.Animation.AnimNumber - object.animIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetAnimIndex(const ItemInfo& item, int animNumber)
|
||||||
|
{
|
||||||
|
const auto& object = Objects[item.Animation.AnimObjectID];
|
||||||
|
return (object.animIndex + animNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetFrameIndex(ItemInfo* item, int frameNumber)
|
||||||
|
{
|
||||||
|
int animNumber = item->Animation.AnimNumber - Objects[item->Animation.AnimObjectID].animIndex;
|
||||||
|
return GetFrameIndex(item->Animation.AnimObjectID, animNumber, frameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetFrameIndex(GAME_OBJECT_ID objectID, int animNumber, int frameNumber)
|
||||||
|
{
|
||||||
|
const auto& object = Objects[objectID];
|
||||||
|
const auto& anim = GetAnimData(object, animNumber);
|
||||||
|
|
||||||
|
return (anim.frameBase + frameNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetFrameCount(int animIndex)
|
||||||
|
{
|
||||||
|
if (animIndex < 0 || g_Level.Anims.size() <= animIndex)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const auto& anim = GetAnimData(animIndex);
|
||||||
|
|
||||||
|
int end = anim.frameEnd;
|
||||||
|
int base = anim.frameBase;
|
||||||
|
return (end - base);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetNextAnimState(ItemInfo* item)
|
||||||
|
{
|
||||||
|
return GetNextAnimState(item->Animation.AnimObjectID, item->Animation.AnimNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetNextAnimState(int objectID, int animNumber)
|
||||||
|
{
|
||||||
|
const auto& object = Objects[objectID];
|
||||||
|
const auto& anim = GetAnimData(object, animNumber);
|
||||||
|
|
||||||
|
const auto& nextAnim = GetAnimData(anim.JumpAnimNum);
|
||||||
|
return nextAnim.ActiveState;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetStateDispatch(ItemInfo* item, const AnimData& anim)
|
bool GetStateDispatch(ItemInfo* item, const AnimData& anim)
|
||||||
{
|
{
|
||||||
// Active and target states already match; return early.
|
// Active and target states already match; return early.
|
||||||
|
@ -464,123 +632,6 @@ bool GetStateDispatch(ItemInfo* item, const AnimData& anim)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimFrameInterpData GetFrameInterpData(const ItemInfo& item)
|
|
||||||
{
|
|
||||||
const auto& anim = GetAnimData(item);
|
|
||||||
|
|
||||||
// Normalize animation's current frame number into keyframe range.
|
|
||||||
int frameNumber = item.Animation.FrameNumber - anim.frameBase;
|
|
||||||
float frameNumberNorm = frameNumber / (float)anim.Interpolation;
|
|
||||||
|
|
||||||
// Calculate keyframe numbers defining interpolated frame and get pointers to them.
|
|
||||||
int frame0 = (int)floor(frameNumberNorm);
|
|
||||||
int frame1 = (int)ceil(frameNumberNorm);
|
|
||||||
auto* framePtr0 = &g_Level.Frames[anim.FramePtr + frame0];
|
|
||||||
auto* framePtr1 = &g_Level.Frames[anim.FramePtr + frame1];
|
|
||||||
|
|
||||||
// Calculate interpolation alpha between keyframes.
|
|
||||||
float alpha = (1.0f / anim.Interpolation) * (frameNumber % anim.Interpolation);
|
|
||||||
|
|
||||||
// Return frame interpolation data.
|
|
||||||
return AnimFrameInterpData{ framePtr0, framePtr1, alpha };
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimFrame& GetAnimFrame(const ItemInfo& item, int animNumber, int frameNumber)
|
|
||||||
{
|
|
||||||
return *GetFrame(item.ObjectNumber, animNumber, frameNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimFrame* GetFrame(GAME_OBJECT_ID objectID, int animNumber, int frameNumber)
|
|
||||||
{
|
|
||||||
const auto& object = Objects[objectID];
|
|
||||||
|
|
||||||
int animIndex = object.animIndex + animNumber;
|
|
||||||
assertion(animIndex < g_Level.Anims.size(), "GetFrame() attempted to access nonexistent animation.");
|
|
||||||
|
|
||||||
const auto& anim = GetAnimData(object, animNumber);
|
|
||||||
|
|
||||||
// Get and clamp frame count.
|
|
||||||
unsigned int frameCount = anim.frameEnd - anim.frameBase;
|
|
||||||
if (frameNumber > frameCount)
|
|
||||||
frameNumber = frameCount;
|
|
||||||
|
|
||||||
// Interpolate and return frame pointer.
|
|
||||||
auto* framePtr = &g_Level.Frames[anim.FramePtr];
|
|
||||||
framePtr += frameNumber / anim.Interpolation;
|
|
||||||
return framePtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimFrame* GetFirstFrame(GAME_OBJECT_ID objectID, int animNumber)
|
|
||||||
{
|
|
||||||
return GetFrame(objectID, animNumber, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimFrame* GetLastFrame(GAME_OBJECT_ID objectID, int animNumber)
|
|
||||||
{
|
|
||||||
return GetFrame(objectID, animNumber, INT_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimFrame& GetBestFrame(const ItemInfo& item)
|
|
||||||
{
|
|
||||||
auto frameData = GetFrameInterpData(item);
|
|
||||||
if (frameData.Alpha <= 0.5f)
|
|
||||||
return *frameData.FramePtr0;
|
|
||||||
else
|
|
||||||
return *frameData.FramePtr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetCurrentRelativeFrameNumber(ItemInfo* item)
|
|
||||||
{
|
|
||||||
return (item->Animation.FrameNumber - GetFrameNumber(item, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Returns g_Level.Anims index.
|
|
||||||
int GetAnimNumber(ItemInfo& item, int animNumber)
|
|
||||||
{
|
|
||||||
const auto& object = Objects[item.ObjectNumber];
|
|
||||||
return (object.animIndex + animNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetFrameNumber(ItemInfo* item, int frameToStart)
|
|
||||||
{
|
|
||||||
int animNumber = item->Animation.AnimNumber - Objects[item->ObjectNumber].animIndex;
|
|
||||||
return GetFrameNumber(item->ObjectNumber, animNumber, frameToStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetFrameNumber(int objectID, int animNumber, int frameToStart)
|
|
||||||
{
|
|
||||||
const auto& object = Objects[objectID];
|
|
||||||
const auto& anim = GetAnimData(object, animNumber);
|
|
||||||
|
|
||||||
return (anim.frameBase + frameToStart);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetFrameCount(int animIndex)
|
|
||||||
{
|
|
||||||
if (animIndex < 0 || g_Level.Anims.size() <= animIndex)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const auto& anim = GetAnimData(animIndex);
|
|
||||||
|
|
||||||
int end = anim.frameEnd;
|
|
||||||
int base = anim.frameBase;
|
|
||||||
return (end - base);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetNextAnimState(ItemInfo* item)
|
|
||||||
{
|
|
||||||
return GetNextAnimState(item->ObjectNumber, item->Animation.AnimNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
int GetNextAnimState(int objectID, int animNumber)
|
|
||||||
{
|
|
||||||
const auto& object = Objects[objectID];
|
|
||||||
const auto& anim = GetAnimData(object, animNumber);
|
|
||||||
|
|
||||||
const auto& nextAnim = GetAnimData(anim.JumpAnimNum);
|
|
||||||
return nextAnim.ActiveState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawAnimatingItem(ItemInfo* item)
|
void DrawAnimatingItem(ItemInfo* item)
|
||||||
{
|
{
|
||||||
// TODO: to refactor
|
// TODO: to refactor
|
||||||
|
@ -613,6 +664,16 @@ Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOff
|
||||||
return GetJointPosition(*item, jointIndex, relOffset);
|
return GetJointPosition(*item, jointIndex, relOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3i GetJointPosition(ItemInfo* item, const CreatureBiteInfo& bite)
|
||||||
|
{
|
||||||
|
return GetJointPosition(item, bite.BoneID, bite.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite)
|
||||||
|
{
|
||||||
|
return GetJointPosition(item, bite.BoneID, bite.Position);
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex)
|
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex)
|
||||||
{
|
{
|
||||||
const auto& object = Objects[objectID];
|
const auto& object = Objects[objectID];
|
||||||
|
|
|
@ -4,13 +4,16 @@
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
enum GAME_OBJECT_ID : short;
|
||||||
class EulerAngles;
|
class EulerAngles;
|
||||||
class Pose;
|
class Pose;
|
||||||
class Vector3i;
|
class Vector3i;
|
||||||
|
struct CreatureBiteInfo;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
struct ObjectInfo;
|
||||||
|
|
||||||
// NOTES:
|
// NOTES:
|
||||||
// animNumber: Relative entity animation ID.
|
// animNumber: Relative animation number.
|
||||||
// animIndex: Index of animation in giant g_Level.Anims vector.
|
// animIndex: Index of animation in giant g_Level.Anims vector.
|
||||||
|
|
||||||
constexpr auto NO_STATE = -1;
|
constexpr auto NO_STATE = -1;
|
||||||
|
@ -107,20 +110,29 @@ void TranslateItem(ItemInfo* item, const EulerAngles& orient, float distance);
|
||||||
void TranslateItem(ItemInfo* item, const Vector3& direction, float distance);
|
void TranslateItem(ItemInfo* item, const Vector3& direction, float distance);
|
||||||
|
|
||||||
// Setters
|
// Setters
|
||||||
void SetAnimation(ItemInfo* item, int animNumber, int frameNumber = 0);
|
void SetAnimation(ItemInfo& item, GAME_OBJECT_ID animObjectID, int animNumber, int frameNumber = 0);
|
||||||
|
void SetAnimation(ItemInfo& item, int animNumber, int frameNumber = 0);
|
||||||
|
void SetAnimation(ItemInfo* item, int animNumber, int frameNumber = 0); // Deprecated.
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
AnimData& GetAnimData(int animIndex);
|
AnimData& GetAnimData(int animIndex); // Deprecated.
|
||||||
|
AnimData& GetAnimData(GAME_OBJECT_ID objectID, int animNumber);
|
||||||
AnimData& GetAnimData(const ObjectInfo& object, int animNumber);
|
AnimData& GetAnimData(const ObjectInfo& object, int animNumber);
|
||||||
AnimData& GetAnimData(const ItemInfo& item, int animNumber = NO_ANIM);
|
AnimData& GetAnimData(const ItemInfo& item, int animNumber = NO_ANIM);
|
||||||
int GetCurrentRelativeFrameNumber(ItemInfo* item);
|
|
||||||
int GetAnimNumber(ItemInfo& item, int animNumber);
|
int GetAnimNumber(const ItemInfo& item);
|
||||||
int GetFrameNumber(ItemInfo* item, int frameToStart);
|
int GetAnimIndex(const ItemInfo& item, int animNumber);
|
||||||
int GetFrameNumber(int objectID, int animNumber, int frameToStart);
|
|
||||||
int GetFrameCount(int animIndex);
|
int GetFrameNumber(const ItemInfo& item);
|
||||||
int GetNextAnimState(ItemInfo* item);
|
int GetFrameNumber(ItemInfo* item); // Deprecated.
|
||||||
int GetNextAnimState(int objectID, int animNumber);
|
int GetFrameIndex(ItemInfo* item, int frameNumber);
|
||||||
bool GetStateDispatch(ItemInfo* item, const AnimData& anim);
|
int GetFrameIndex(GAME_OBJECT_ID objectID, int animNumber, int frameNumber);
|
||||||
|
|
||||||
|
int GetFrameCount(int animIndex);
|
||||||
|
|
||||||
|
int GetNextAnimState(ItemInfo* item);
|
||||||
|
int GetNextAnimState(int objectID, int animNumber);
|
||||||
|
bool GetStateDispatch(ItemInfo* item, const AnimData& anim);
|
||||||
|
|
||||||
AnimFrameInterpData GetFrameInterpData(const ItemInfo& item);
|
AnimFrameInterpData GetFrameInterpData(const ItemInfo& item);
|
||||||
AnimFrame& GetAnimFrame(const ItemInfo& item, int animNumber, int frameNumber);
|
AnimFrame& GetAnimFrame(const ItemInfo& item, int animNumber, int frameNumber);
|
||||||
|
@ -134,6 +146,9 @@ void DrawAnimatingItem(ItemInfo* item);
|
||||||
|
|
||||||
Vector3i GetJointPosition(const ItemInfo& item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero);
|
Vector3i GetJointPosition(const ItemInfo& item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero);
|
||||||
Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero);
|
Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero);
|
||||||
|
Vector3i GetJointPosition(ItemInfo* item, const CreatureBiteInfo& bite);
|
||||||
|
Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite);
|
||||||
|
|
||||||
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex);
|
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex);
|
||||||
Quaternion GetBoneOrientation(const ItemInfo& item, int boneIndex);
|
Quaternion GetBoneOrientation(const ItemInfo& item, int boneIndex);
|
||||||
float GetBoneLength(GAME_OBJECT_ID objectID, int boneIndex);
|
float GetBoneLength(GAME_OBJECT_ID objectID, int boneIndex);
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Game/spotcam.h"
|
#include "Game/spotcam.h"
|
||||||
#include "Objects/Generic/Object/burning_torch.h"
|
#include "Objects/Generic/Object/burning_torch.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using TEN::Renderer::g_Renderer;
|
using TEN::Renderer::g_Renderer;
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ inline void RumbleFromBounce()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InitialiseCamera()
|
void InitializeCamera()
|
||||||
{
|
{
|
||||||
Camera.shift = LaraItem->Pose.Position.y - SECTOR(1);
|
Camera.shift = LaraItem->Pose.Position.y - SECTOR(1);
|
||||||
|
|
||||||
|
@ -545,8 +545,11 @@ void DoThumbstickCamera()
|
||||||
Camera.target.y == OldCam.target.y &&
|
Camera.target.y == OldCam.target.y &&
|
||||||
Camera.target.z == OldCam.target.z))
|
Camera.target.z == OldCam.target.z))
|
||||||
{
|
{
|
||||||
Camera.targetAngle = ANGLE(THUMBCAM_VERTICAL_CONSTRAINT_ANGLE * AxisMap[InputAxis::CameraHorizontal]);
|
if (abs(AxisMap[InputAxis::CameraHorizontal]) > EPSILON && abs(Camera.targetAngle) == 0)
|
||||||
Camera.targetElevation = ANGLE(-10.0f + (THUMBCAM_HORIZONTAL_CONSTRAINT_ANGLE * AxisMap[InputAxis::CameraVertical]));
|
Camera.targetAngle = ANGLE(THUMBCAM_VERTICAL_CONSTRAINT_ANGLE * AxisMap[InputAxis::CameraHorizontal]);
|
||||||
|
|
||||||
|
if (abs(AxisMap[InputAxis::CameraVertical]) > EPSILON)
|
||||||
|
Camera.targetElevation = ANGLE(-10.0f + (THUMBCAM_HORIZONTAL_CONSTRAINT_ANGLE * AxisMap[InputAxis::CameraVertical]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1563,7 +1566,7 @@ void LookLeftRight(ItemInfo* item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->Control.HandStatus != HandStatus::Busy &&
|
if (lara->Control.HandStatus != HandStatus::Busy &&
|
||||||
lara->Vehicle == NO_ITEM &&
|
lara->Context.Vehicle == NO_ITEM &&
|
||||||
!lara->LeftArm.Locked &&
|
!lara->LeftArm.Locked &&
|
||||||
!lara->RightArm.Locked)
|
!lara->RightArm.Locked)
|
||||||
{
|
{
|
||||||
|
@ -1602,7 +1605,7 @@ void LookUpDown(ItemInfo* item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->Control.HandStatus != HandStatus::Busy &&
|
if (lara->Control.HandStatus != HandStatus::Busy &&
|
||||||
lara->Vehicle == NO_ITEM &&
|
lara->Context.Vehicle == NO_ITEM &&
|
||||||
!lara->LeftArm.Locked &&
|
!lara->LeftArm.Locked &&
|
||||||
!lara->RightArm.Locked)
|
!lara->RightArm.Locked)
|
||||||
{
|
{
|
||||||
|
@ -1634,7 +1637,7 @@ void ResetLook(ItemInfo* item)
|
||||||
if (lara->Control.HandStatus != HandStatus::Busy &&
|
if (lara->Control.HandStatus != HandStatus::Busy &&
|
||||||
!lara->LeftArm.Locked &&
|
!lara->LeftArm.Locked &&
|
||||||
!lara->RightArm.Locked &&
|
!lara->RightArm.Locked &&
|
||||||
lara->Vehicle == NO_ITEM)
|
lara->Context.Vehicle == NO_ITEM)
|
||||||
{
|
{
|
||||||
lara->ExtraTorsoRot = lara->ExtraHeadRot;
|
lara->ExtraTorsoRot = lara->ExtraHeadRot;
|
||||||
}
|
}
|
||||||
|
@ -2074,7 +2077,7 @@ void HandleOptics(ItemInfo* item)
|
||||||
AlterFOV(LastFOV);
|
AlterFOV(LastFOV);
|
||||||
|
|
||||||
Lara.Inventory.IsBusy = false;
|
Lara.Inventory.IsBusy = false;
|
||||||
ResetLaraFlex(LaraItem);
|
ResetPlayerFlex(LaraItem);
|
||||||
|
|
||||||
TrInput &= ~IN_LOOK;
|
TrInput &= ~IN_LOOK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ extern float CinematicBarsSpeed;
|
||||||
void LookAt(CAMERA_INFO* cam, short roll);
|
void LookAt(CAMERA_INFO* cam, short roll);
|
||||||
void AlterFOV(short value, bool store = true);
|
void AlterFOV(short value, bool store = true);
|
||||||
short GetCurrentFOV();
|
short GetCurrentFOV();
|
||||||
void InitialiseCamera();
|
void InitializeCamera();
|
||||||
void MoveCamera(GameVector* ideal, int speed);
|
void MoveCamera(GameVector* ideal, int speed);
|
||||||
void ChaseCamera(ItemInfo* item);
|
void ChaseCamera(ItemInfo* item);
|
||||||
void UpdateCameraElevation();
|
void UpdateCameraElevation();
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/pickup/pickup.h"
|
#include "Game/pickup/pickup.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "ScriptInterfaceGame.h"
|
#include "ScriptInterfaceGame.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
|
@ -51,6 +51,7 @@ void GenericSphereBoxCollision(short itemNumber, ItemInfo* laraItem, CollisionIn
|
||||||
|
|
||||||
if (item->ItemFlags[2] != 0)
|
if (item->ItemFlags[2] != 0)
|
||||||
collidedBits &= ~1;
|
collidedBits &= ~1;
|
||||||
|
coll->Setup.EnableObjectPush = item->ItemFlags[4] == 0;
|
||||||
|
|
||||||
while (collidedBits)
|
while (collidedBits)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
|
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
int xFront, zFront, xRight, zRight, xLeft, zLeft;
|
int xFront, zFront, xRight, zRight, xLeft, zLeft;
|
||||||
|
|
||||||
// Get nearest 90-degree snapped angle (quadrant).
|
// Get nearest 90-degree snapped angle (quadrant).
|
||||||
auto quadrant = GetQuadrant(coll->Setup.ForwardAngle);
|
int quadrant = GetQuadrant(coll->Setup.ForwardAngle);
|
||||||
|
|
||||||
// Get side probe offsets depending on quadrant.
|
// Get side probe offsets depending on quadrant.
|
||||||
// If unconstrained mode is specified, don't use quadrant.
|
// If unconstrained mode is specified, don't use quadrant.
|
||||||
|
@ -322,7 +322,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
// TEST 2: CENTERPOINT PROBE
|
// TEST 2: CENTERPOINT PROBE
|
||||||
|
|
||||||
collResult = GetCollision(probePos.x, probePos.y, probePos.z, realRoomNumber);
|
collResult = GetCollision(probePos.x, probePos.y, probePos.z, realRoomNumber);
|
||||||
auto topRoomNumber = collResult.RoomNumber; // Keep top room number as we need it to re-probe from origin room.
|
int topRoomNumber = collResult.RoomNumber; // Keep top room number as we need it to re-probe from origin room.
|
||||||
|
|
||||||
if (doPlayerCollision)
|
if (doPlayerCollision)
|
||||||
{
|
{
|
||||||
|
@ -394,7 +394,9 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
height = GetFloorHeight(tfLocation, probePos.x + xFront, probePos.z + zFront).value_or(NO_HEIGHT);
|
height = GetFloorHeight(tfLocation, probePos.x + xFront, probePos.z + zFront).value_or(NO_HEIGHT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
height = GetCollision(probePos.x + xFront, probePos.y, probePos.z + zFront, topRoomNumber).Position.Floor;
|
height = GetCollision(probePos.x + xFront, probePos.y, probePos.z + zFront, topRoomNumber).Position.Floor;
|
||||||
|
}
|
||||||
|
|
||||||
if (height != NO_HEIGHT)
|
if (height != NO_HEIGHT)
|
||||||
height -= (doPlayerCollision ? entityPos.y : probePos.y);
|
height -= (doPlayerCollision ? entityPos.y : probePos.y);
|
||||||
|
@ -408,19 +410,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
coll->Front.Floor = MAX_HEIGHT;
|
coll->Front.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||||
coll->Front.FloorSlope &&
|
coll->Front.FloorSlope &&
|
||||||
coll->Front.Floor > coll->Middle.Floor)
|
coll->Front.Floor > coll->Middle.Floor)
|
||||||
{
|
{
|
||||||
coll->Front.Floor = STOP_SIZE;
|
coll->Front.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockCeilingSlope &&
|
else if (coll->Setup.BlockCeilingSlope &&
|
||||||
coll->Front.CeilingSlope)
|
coll->Front.CeilingSlope)
|
||||||
{
|
{
|
||||||
coll->Front.Floor = MAX_HEIGHT;
|
coll->Front.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockDeathFloorDown &&
|
else if (coll->Setup.BlockDeathFloorDown &&
|
||||||
coll->Front.Floor >= CLICK(0.5f) &&
|
coll->Front.Floor >= CLICK(0.5f) &&
|
||||||
collResult.BottomBlock->Flags.Death)
|
collResult.BottomBlock->Flags.Death)
|
||||||
{
|
{
|
||||||
coll->Front.Floor = STOP_SIZE;
|
coll->Front.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -471,19 +473,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
coll->MiddleLeft.Floor = MAX_HEIGHT;
|
coll->MiddleLeft.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||||
coll->MiddleLeft.FloorSlope &&
|
coll->MiddleLeft.FloorSlope &&
|
||||||
coll->MiddleLeft.Floor > 0)
|
coll->MiddleLeft.Floor > 0)
|
||||||
{
|
{
|
||||||
coll->MiddleLeft.Floor = STOP_SIZE;
|
coll->MiddleLeft.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockCeilingSlope &&
|
else if (coll->Setup.BlockCeilingSlope &&
|
||||||
coll->MiddleLeft.CeilingSlope)
|
coll->MiddleLeft.CeilingSlope)
|
||||||
{
|
{
|
||||||
coll->MiddleLeft.Floor = MAX_HEIGHT;
|
coll->MiddleLeft.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockDeathFloorDown &&
|
else if (coll->Setup.BlockDeathFloorDown &&
|
||||||
coll->MiddleLeft.Floor >= CLICK(0.5f) &&
|
coll->MiddleLeft.Floor >= CLICK(0.5f) &&
|
||||||
collResult.BottomBlock->Flags.Death)
|
collResult.BottomBlock->Flags.Death)
|
||||||
{
|
{
|
||||||
coll->MiddleLeft.Floor = STOP_SIZE;
|
coll->MiddleLeft.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -528,19 +530,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
coll->FrontLeft.Floor = MAX_HEIGHT;
|
coll->FrontLeft.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||||
coll->FrontLeft.FloorSlope &&
|
coll->FrontLeft.FloorSlope &&
|
||||||
coll->FrontLeft.Floor > 0)
|
coll->FrontLeft.Floor > 0)
|
||||||
{
|
{
|
||||||
coll->FrontLeft.Floor = STOP_SIZE;
|
coll->FrontLeft.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockCeilingSlope &&
|
else if (coll->Setup.BlockCeilingSlope &&
|
||||||
coll->FrontLeft.CeilingSlope)
|
coll->FrontLeft.CeilingSlope)
|
||||||
{
|
{
|
||||||
coll->FrontLeft.Floor = MAX_HEIGHT;
|
coll->FrontLeft.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockDeathFloorDown &&
|
else if (coll->Setup.BlockDeathFloorDown &&
|
||||||
coll->FrontLeft.Floor >= CLICK(0.5f) &&
|
coll->FrontLeft.Floor >= CLICK(0.5f) &&
|
||||||
collResult.BottomBlock->Flags.Death)
|
collResult.BottomBlock->Flags.Death)
|
||||||
{
|
{
|
||||||
coll->FrontLeft.Floor = STOP_SIZE;
|
coll->FrontLeft.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -590,19 +592,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
coll->MiddleRight.Floor = MAX_HEIGHT;
|
coll->MiddleRight.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||||
coll->MiddleRight.FloorSlope &&
|
coll->MiddleRight.FloorSlope &&
|
||||||
coll->MiddleRight.Floor > 0)
|
coll->MiddleRight.Floor > 0)
|
||||||
{
|
{
|
||||||
coll->MiddleRight.Floor = STOP_SIZE;
|
coll->MiddleRight.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockCeilingSlope &&
|
else if (coll->Setup.BlockCeilingSlope &&
|
||||||
coll->MiddleRight.CeilingSlope)
|
coll->MiddleRight.CeilingSlope)
|
||||||
{
|
{
|
||||||
coll->MiddleRight.Floor = MAX_HEIGHT;
|
coll->MiddleRight.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockDeathFloorDown &&
|
else if (coll->Setup.BlockDeathFloorDown &&
|
||||||
coll->MiddleRight.Floor >= CLICK(0.5f) &&
|
coll->MiddleRight.Floor >= CLICK(0.5f) &&
|
||||||
collResult.BottomBlock->Flags.Death)
|
collResult.BottomBlock->Flags.Death)
|
||||||
{
|
{
|
||||||
coll->MiddleRight.Floor = STOP_SIZE;
|
coll->MiddleRight.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -647,19 +649,19 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
coll->FrontRight.Floor = MAX_HEIGHT;
|
coll->FrontRight.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockFloorSlopeDown &&
|
else if (coll->Setup.BlockFloorSlopeDown &&
|
||||||
coll->FrontRight.FloorSlope &&
|
coll->FrontRight.FloorSlope &&
|
||||||
coll->FrontRight.Floor > 0)
|
coll->FrontRight.Floor > 0)
|
||||||
{
|
{
|
||||||
coll->FrontRight.Floor = STOP_SIZE;
|
coll->FrontRight.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockCeilingSlope &&
|
else if (coll->Setup.BlockCeilingSlope &&
|
||||||
coll->FrontRight.CeilingSlope)
|
coll->FrontRight.CeilingSlope)
|
||||||
{
|
{
|
||||||
coll->FrontRight.Floor = MAX_HEIGHT;
|
coll->FrontRight.Floor = MAX_HEIGHT;
|
||||||
}
|
}
|
||||||
else if (coll->Setup.BlockDeathFloorDown &&
|
else if (coll->Setup.BlockDeathFloorDown &&
|
||||||
coll->FrontRight.Floor >= CLICK(0.5f) &&
|
coll->FrontRight.Floor >= CLICK(0.5f) &&
|
||||||
collResult.BottomBlock->Flags.Death)
|
collResult.BottomBlock->Flags.Death)
|
||||||
{
|
{
|
||||||
coll->FrontRight.Floor = STOP_SIZE;
|
coll->FrontRight.Floor = STOP_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -725,7 +727,7 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coll->CollisionType = ((coll->CollisionType == CT_TOP) ? CT_TOP_FRONT : CT_FRONT);
|
coll->CollisionType = (coll->CollisionType == CT_TOP) ? CT_TOP_FRONT : CT_FRONT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,12 +775,20 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
quarter %= 2;
|
quarter %= 2;
|
||||||
|
|
||||||
if (coll->MiddleLeft.HasFlippedDiagonalSplit())
|
if (coll->MiddleLeft.HasFlippedDiagonalSplit())
|
||||||
if (quarter) coll->CollisionType = CT_LEFT;
|
{
|
||||||
|
if (quarter)
|
||||||
|
coll->CollisionType = CT_LEFT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (!quarter) coll->CollisionType = CT_LEFT;
|
{
|
||||||
|
if (!quarter)
|
||||||
|
coll->CollisionType = CT_LEFT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
coll->CollisionType = CT_LEFT;
|
coll->CollisionType = CT_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -815,16 +825,24 @@ void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offse
|
||||||
|
|
||||||
if (coll->DiagonalStepAtRight())
|
if (coll->DiagonalStepAtRight())
|
||||||
{
|
{
|
||||||
int quarter = (unsigned short)(coll->Setup.ForwardAngle) / ANGLE(90.0f); // NOTE: Different from quadrant!
|
int quarter = unsigned short(coll->Setup.ForwardAngle) / ANGLE(90.0f); // NOTE: Different from quadrant!
|
||||||
quarter %= 2;
|
quarter %= 2;
|
||||||
|
|
||||||
if (coll->MiddleRight.HasFlippedDiagonalSplit())
|
if (coll->MiddleRight.HasFlippedDiagonalSplit())
|
||||||
if (quarter) coll->CollisionType = CT_RIGHT;
|
{
|
||||||
|
if (quarter)
|
||||||
|
coll->CollisionType = CT_RIGHT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (!quarter) coll->CollisionType = CT_RIGHT;
|
{
|
||||||
|
if (!quarter)
|
||||||
|
coll->CollisionType = CT_RIGHT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
coll->CollisionType = CT_RIGHT;
|
coll->CollisionType = CT_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Math/Math.h"
|
#include "Objects/game_object_ids.h"
|
||||||
|
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
|
@ -87,10 +87,11 @@ struct CollisionSetup
|
||||||
bool EnableSpasm; // Convulse when pushed
|
bool EnableSpasm; // Convulse when pushed
|
||||||
|
|
||||||
// Preserve old parameters to restore later
|
// Preserve old parameters to restore later
|
||||||
Vector3i OldPosition;
|
Vector3i OldPosition = Vector3i::Zero;
|
||||||
int OldAnimNumber;
|
GAME_OBJECT_ID PrevAnimObjectID = ID_NO_OBJECT;
|
||||||
int OldFrameNumber;
|
int OldAnimNumber = 0;
|
||||||
int OldState;
|
int OldFrameNumber = 0;
|
||||||
|
int OldState = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CollisionInfo
|
struct CollisionInfo
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
|
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
int FloorInfo::GetSurfacePlaneIndex(int x, int z, bool isFloor) const
|
int FloorInfo::GetSurfacePlaneIndex(int x, int z, bool isFloor) const
|
||||||
|
@ -313,7 +313,7 @@ void FloorInfo::RemoveBridge(int itemNumber)
|
||||||
BridgeItemNumbers.erase(itemNumber);
|
BridgeItemNumbers.erase(itemNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace TEN::Floordata
|
namespace TEN::Collision::Floordata
|
||||||
{
|
{
|
||||||
Vector3 GetSurfaceNormal(const Vector2& tilt, bool isFloor)
|
Vector3 GetSurfaceNormal(const Vector2& tilt, bool isFloor)
|
||||||
{
|
{
|
||||||
|
@ -756,26 +756,32 @@ namespace TEN::Floordata
|
||||||
auto floor = &GetFloorSide(item.RoomNumber, x, z);
|
auto floor = &GetFloorSide(item.RoomNumber, x, z);
|
||||||
floor->AddBridge(itemNumber);
|
floor->AddBridge(itemNumber);
|
||||||
|
|
||||||
const auto floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
if (Objects[item.ObjectNumber].floorBorder != nullptr)
|
||||||
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
|
||||||
{
|
{
|
||||||
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
int floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
||||||
if (!roomAbove)
|
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
||||||
break;
|
{
|
||||||
|
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
||||||
|
if (!roomAbove.has_value())
|
||||||
|
break;
|
||||||
|
|
||||||
floor = &GetFloorSide(*roomAbove, x, z);
|
floor = &GetFloorSide(*roomAbove, x, z);
|
||||||
floor->AddBridge(itemNumber);
|
floor->AddBridge(itemNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
if (Objects[item.ObjectNumber].ceilingBorder != nullptr)
|
||||||
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
|
||||||
{
|
{
|
||||||
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
int ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
||||||
if (!roomBelow)
|
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
||||||
break;
|
{
|
||||||
|
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
||||||
|
if (!roomBelow.has_value())
|
||||||
|
break;
|
||||||
|
|
||||||
floor = &GetFloorSide(*roomBelow, x, z);
|
floor = &GetFloorSide(*roomBelow, x, z);
|
||||||
floor->AddBridge(itemNumber);
|
floor->AddBridge(itemNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,29 +791,35 @@ namespace TEN::Floordata
|
||||||
x += item.Pose.Position.x;
|
x += item.Pose.Position.x;
|
||||||
z += item.Pose.Position.z;
|
z += item.Pose.Position.z;
|
||||||
|
|
||||||
auto floor = &GetFloorSide(item.RoomNumber, x, z);
|
auto* floor = &GetFloorSide(item.RoomNumber, x, z);
|
||||||
floor->RemoveBridge(itemNumber);
|
floor->RemoveBridge(itemNumber);
|
||||||
|
|
||||||
const auto floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
if (Objects[item.ObjectNumber].floorBorder != nullptr)
|
||||||
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
|
||||||
{
|
{
|
||||||
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
int floorBorder = Objects[item.ObjectNumber].floorBorder(itemNumber);
|
||||||
if (!roomAbove)
|
while (floorBorder <= floor->GetSurfaceHeight(x, z, false))
|
||||||
break;
|
{
|
||||||
|
const auto roomAbove = floor->GetRoomNumberAbove(x, z);
|
||||||
|
if (!roomAbove.has_value())
|
||||||
|
break;
|
||||||
|
|
||||||
floor = &GetFloorSide(*roomAbove, x, z);
|
floor = &GetFloorSide(*roomAbove, x, z);
|
||||||
floor->RemoveBridge(itemNumber);
|
floor->RemoveBridge(itemNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
if (Objects[item.ObjectNumber].ceilingBorder != nullptr)
|
||||||
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
|
||||||
{
|
{
|
||||||
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
int ceilingBorder = Objects[item.ObjectNumber].ceilingBorder(itemNumber);
|
||||||
if (!roomBelow)
|
while (ceilingBorder >= floor->GetSurfaceHeight(x, z, true))
|
||||||
break;
|
{
|
||||||
|
const auto roomBelow = floor->GetRoomNumberBelow(x, z);
|
||||||
|
if (!roomBelow.has_value())
|
||||||
|
break;
|
||||||
|
|
||||||
floor = &GetFloorSide(*roomBelow, x, z);
|
floor = &GetFloorSide(*roomBelow, x, z);
|
||||||
floor->RemoveBridge(itemNumber);
|
floor->RemoveBridge(itemNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,17 +836,20 @@ namespace TEN::Floordata
|
||||||
auto bounds = GameBoundingBox(item);
|
auto bounds = GameBoundingBox(item);
|
||||||
auto dxBounds = bounds.ToBoundingOrientedBox(item->Pose);
|
auto dxBounds = bounds.ToBoundingOrientedBox(item->Pose);
|
||||||
|
|
||||||
Vector3 pos = Vector3(x, y + (bottom ? 4 : -4), z); // Introduce slight vertical margin just in case
|
auto pos = Vector3(x, y + (bottom ? 4 : -4), z); // Introduce slight vertical margin just in case.
|
||||||
|
|
||||||
static float distance;
|
float distance = 0.0f;
|
||||||
if (dxBounds.Intersects(pos, (bottom ? -Vector3::UnitY : Vector3::UnitY), distance))
|
if (dxBounds.Intersects(pos, (bottom ? -Vector3::UnitY : Vector3::UnitY), distance))
|
||||||
|
{
|
||||||
return std::optional{ item->Pose.Position.y + (bottom ? bounds.Y2 : bounds.Y1) };
|
return std::optional{ item->Pose.Position.y + (bottom ? bounds.Y2 : bounds.Y1) };
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets bridge min or max height regardless of actual X/Z world position
|
// Gets bridge min or max height regardless of actual X/Z world position.
|
||||||
|
|
||||||
int GetBridgeBorder(int itemNumber, bool bottom)
|
int GetBridgeBorder(int itemNumber, bool bottom)
|
||||||
{
|
{
|
||||||
auto item = &g_Level.Items[itemNumber];
|
auto item = &g_Level.Items[itemNumber];
|
||||||
|
@ -847,6 +862,7 @@ namespace TEN::Floordata
|
||||||
void UpdateBridgeItem(int itemNumber, bool forceRemoval)
|
void UpdateBridgeItem(int itemNumber, bool forceRemoval)
|
||||||
{
|
{
|
||||||
auto item = &g_Level.Items[itemNumber];
|
auto item = &g_Level.Items[itemNumber];
|
||||||
|
if (!Objects[item->ObjectNumber].loaded) return;
|
||||||
|
|
||||||
// Force removal if object was killed
|
// Force removal if object was killed
|
||||||
if (item->Flags & IFLAG_KILLED)
|
if (item->Flags & IFLAG_KILLED)
|
||||||
|
@ -873,10 +889,10 @@ namespace TEN::Floordata
|
||||||
{
|
{
|
||||||
for (int z = 0; z < room->zSize; z++)
|
for (int z = 0; z < room->zSize; z++)
|
||||||
{
|
{
|
||||||
auto pX = room->x + (x * BLOCK(1)) + BLOCK(0.5f);
|
float pX = room->x + (x * BLOCK(1)) + BLOCK(0.5f);
|
||||||
auto pZ = room->z + (z * BLOCK(1)) + BLOCK(0.5f);
|
float pZ = room->z + (z * BLOCK(1)) + BLOCK(0.5f);
|
||||||
auto offX = pX - item->Pose.Position.x;
|
float offX = pX - item->Pose.Position.x;
|
||||||
auto offZ = pZ - item->Pose.Position.z;
|
float offZ = pZ - item->Pose.Position.z;
|
||||||
|
|
||||||
// Clean previous bridge state
|
// Clean previous bridge state
|
||||||
RemoveBridge(itemNumber, offX, offZ);
|
RemoveBridge(itemNumber, offX, offZ);
|
||||||
|
@ -897,4 +913,15 @@ namespace TEN::Floordata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TestMaterial(MaterialType refMaterial, const std::vector<MaterialType>& materialList)
|
||||||
|
{
|
||||||
|
for (const auto& material : materialList)
|
||||||
|
{
|
||||||
|
if (material == refMaterial)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,16 @@ using namespace TEN::Math;
|
||||||
// Ceiling: Upper surface of a collision block.
|
// Ceiling: Upper surface of a collision block.
|
||||||
// Floor: Lower surface of a collision block.
|
// Floor: Lower surface of a collision block.
|
||||||
// Floordata: Name of the engine's level geometry collision system consisting of rooms and their divisions within a grid.
|
// Floordata: Name of the engine's level geometry collision system consisting of rooms and their divisions within a grid.
|
||||||
// Plane: One of two surface triangles. CHECK: If it's a Vector3, isn't that simply the surface normal?
|
// Plane: One of two surface triangles.
|
||||||
// Portal: Link from one room to another allowing traversal.
|
// Portal: Link from one room to another allowing traversal.
|
||||||
// Room number: Unique numeric index of a room.
|
// Room number: Unique numeric index of a room.
|
||||||
// Surface: Floor or ceiling.
|
// Surface: Floor or ceiling.
|
||||||
// Wall: Inferred from a floor or ceiling with max height. Note that true "walls" do not exist.
|
// Wall: Inferred from a floor or ceiling with max height. Note that true "walls" do not exist.
|
||||||
|
|
||||||
|
// Planes are non-standard. Instead of 4 components storing a normal and a distance, floordata uses a Vector3:
|
||||||
|
// x and y store the 2D direction vector in the xz plane (not normalized).
|
||||||
|
// z stores the distance.
|
||||||
|
|
||||||
constexpr auto WALL_PLANE = Vector3(0, 0, -CLICK(127));
|
constexpr auto WALL_PLANE = Vector3(0, 0, -CLICK(127));
|
||||||
|
|
||||||
enum class MaterialType
|
enum class MaterialType
|
||||||
|
@ -154,7 +158,7 @@ class FloorInfo
|
||||||
void RemoveBridge(int itemNumber);
|
void RemoveBridge(int itemNumber);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace TEN::Floordata
|
namespace TEN::Collision::Floordata
|
||||||
{
|
{
|
||||||
// TODO: Use normals natively.
|
// TODO: Use normals natively.
|
||||||
Vector3 GetSurfaceNormal(const Vector2& tilt, bool isFloor);
|
Vector3 GetSurfaceNormal(const Vector2& tilt, bool isFloor);
|
||||||
|
@ -183,4 +187,6 @@ namespace TEN::Floordata
|
||||||
std::optional<int> GetBridgeItemIntersect(int itemNumber, int x, int y, int z, bool bottom);
|
std::optional<int> GetBridgeItemIntersect(int itemNumber, int x, int y, int z, bool bottom);
|
||||||
int GetBridgeBorder(int itemNumber, bool bottom);
|
int GetBridgeBorder(int itemNumber, bool bottom);
|
||||||
void UpdateBridgeItem(int itemNumber, bool forceRemoval = false);
|
void UpdateBridgeItem(int itemNumber, bool forceRemoval = false);
|
||||||
|
|
||||||
|
bool TestMaterial(MaterialType refMaterial, const std::vector<MaterialType>& materialList);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "Game/collision/collide_room.h"
|
#include "Game/collision/collide_room.h"
|
||||||
#include "Game/control/control.h"
|
#include "Game/control/control.h"
|
||||||
#include "Game/control/lot.h"
|
#include "Game/control/lot.h"
|
||||||
|
#include "Game/effects/smoke.h"
|
||||||
#include "Game/effects/tomb4fx.h"
|
#include "Game/effects/tomb4fx.h"
|
||||||
#include "Game/itemdata/creature_info.h"
|
#include "Game/itemdata/creature_info.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
|
@ -15,12 +16,14 @@
|
||||||
#include "Game/misc.h"
|
#include "Game/misc.h"
|
||||||
#include "Game/pickup/pickup.h"
|
#include "Game/pickup/pickup.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
#include "Specific/setup.h"
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/objectslist.h"
|
#include "Objects/objectslist.h"
|
||||||
#include "Objects/TR5/Object/tr5_pushableblock.h"
|
#include "Objects/TR5/Object/tr5_pushableblock.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
|
|
||||||
|
using namespace TEN::Effects::Smoke;
|
||||||
|
|
||||||
constexpr auto ESCAPE_DIST = SECTOR(5);
|
constexpr auto ESCAPE_DIST = SECTOR(5);
|
||||||
constexpr auto STALK_DIST = SECTOR(3);
|
constexpr auto STALK_DIST = SECTOR(3);
|
||||||
constexpr auto REACHED_GOAL_RADIUS = 640;
|
constexpr auto REACHED_GOAL_RADIUS = 640;
|
||||||
|
@ -33,6 +36,8 @@ constexpr auto FEELER_ANGLE = ANGLE(45.0f);
|
||||||
constexpr auto CREATURE_AI_ROTATION_MAX = ANGLE(90.0f);
|
constexpr auto CREATURE_AI_ROTATION_MAX = ANGLE(90.0f);
|
||||||
constexpr auto CREATURE_JOINT_ROTATION_MAX = ANGLE(70.0f);
|
constexpr auto CREATURE_JOINT_ROTATION_MAX = ANGLE(70.0f);
|
||||||
|
|
||||||
|
constexpr auto CREATURE_GUN_EFFECT_VERTICAL_OFFSET = 75;
|
||||||
|
|
||||||
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
||||||
constexpr int HIGH_PRIO_RANGE = 8;
|
constexpr int HIGH_PRIO_RANGE = 8;
|
||||||
constexpr int MEDIUM_PRIO_RANGE = HIGH_PRIO_RANGE + HIGH_PRIO_RANGE * (HIGH_PRIO_RANGE / 6.0f);
|
constexpr int MEDIUM_PRIO_RANGE = HIGH_PRIO_RANGE + HIGH_PRIO_RANGE * (HIGH_PRIO_RANGE / 6.0f);
|
||||||
|
@ -548,57 +553,44 @@ bool CreaturePathfind(ItemInfo* item, Vector3i prevPos, short angle, short tilt)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureKill(ItemInfo* item, int entityKillAnim, int laraExtraKillAnim, int entityKillState, int laraKillState)
|
void CreatureKill(ItemInfo* creatureItem, int creatureAnimNumber, int playerAnimNumber, int creatureState, int playerState)
|
||||||
{
|
{
|
||||||
item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex + entityKillAnim;
|
auto& playerItem = *LaraItem;
|
||||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
auto& player = GetLaraInfo(playerItem);
|
||||||
item->Animation.ActiveState = entityKillState;
|
|
||||||
|
|
||||||
LaraItem->Animation.AnimNumber = Objects[ID_LARA_EXTRA_ANIMS].animIndex + laraExtraKillAnim;
|
SetAnimation(*creatureItem, creatureAnimNumber);
|
||||||
LaraItem->Animation.FrameNumber = g_Level.Anims[LaraItem->Animation.AnimNumber].frameBase;
|
SetAnimation(playerItem, ID_LARA_EXTRA_ANIMS, playerAnimNumber);
|
||||||
LaraItem->Animation.ActiveState = 0;
|
|
||||||
LaraItem->Animation.TargetState = laraKillState;
|
|
||||||
|
|
||||||
LaraItem->Pose = item->Pose;
|
playerItem.Pose = creatureItem->Pose;
|
||||||
LaraItem->Animation.IsAirborne = false;
|
playerItem.Animation.IsAirborne = false;
|
||||||
LaraItem->Animation.Velocity.z = 0;
|
playerItem.Animation.Velocity = Vector3::Zero;
|
||||||
LaraItem->Animation.Velocity.y = 0;
|
|
||||||
|
|
||||||
if (item->RoomNumber != LaraItem->RoomNumber)
|
if (creatureItem->RoomNumber != playerItem.RoomNumber)
|
||||||
ItemNewRoom(Lara.ItemNumber, item->RoomNumber);
|
ItemNewRoom(player.ItemNumber, creatureItem->RoomNumber);
|
||||||
|
|
||||||
AnimateItem(LaraItem);
|
AnimateItem(&playerItem);
|
||||||
|
|
||||||
Lara.ExtraAnim = 1;
|
player.ExtraAnim = 1;
|
||||||
Lara.Control.HandStatus = HandStatus::Busy;
|
player.Control.HandStatus = HandStatus::Busy;
|
||||||
Lara.Control.Weapon.GunType = LaraWeaponType::None;
|
player.Control.Weapon.GunType = LaraWeaponType::None;
|
||||||
Lara.HitDirection = -1;
|
player.HitDirection = -1;
|
||||||
|
|
||||||
Camera.pos.RoomNumber = LaraItem->RoomNumber;
|
Camera.pos.RoomNumber = playerItem.RoomNumber;
|
||||||
Camera.type = CameraType::Chase;
|
Camera.type = CameraType::Chase;
|
||||||
Camera.flags = CF_FOLLOW_CENTER;
|
Camera.flags = CF_FOLLOW_CENTER;
|
||||||
Camera.targetAngle = ANGLE(170.0f);
|
Camera.targetAngle = ANGLE(170.0f);
|
||||||
Camera.targetElevation = -ANGLE(25.0f);
|
Camera.targetElevation = -ANGLE(25.0f);
|
||||||
|
|
||||||
// TODO: exist in TR5 but just commented in case.
|
|
||||||
/*
|
|
||||||
ForcedFixedCamera.x = item->pos.Position.x + (phd_sin(item->pos.Orientation.y) << 13) >> W2V_SHIFT;
|
|
||||||
ForcedFixedCamera.y = item->pos.Position.y - WALL_SIZE;
|
|
||||||
ForcedFixedCamera.z = item->pos.Position.z + (phd_cos(item->pos.Orientation.y) << 13) >> W2V_SHIFT;
|
|
||||||
ForcedFixedCamera.roomNumber = item->roomNumber;
|
|
||||||
UseForcedFixedCamera = true;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
short CreatureEffect2(ItemInfo* item, BiteInfo bite, short velocity, short angle, std::function<CreatureEffectFunction> func)
|
short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function<CreatureEffectFunction> func)
|
||||||
{
|
{
|
||||||
auto pos = GetJointPosition(item, bite.meshNum, Vector3i(bite.Position));
|
auto pos = GetJointPosition(item, bite);
|
||||||
return func(pos.x, pos.y, pos.z, velocity, angle, item->RoomNumber);
|
return func(pos.x, pos.y, pos.z, velocity, angle, item->RoomNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
short CreatureEffect(ItemInfo* item, BiteInfo bite, std::function<CreatureEffectFunction> func)
|
short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function<CreatureEffectFunction> func)
|
||||||
{
|
{
|
||||||
auto pos = GetJointPosition(item, bite.meshNum, Vector3i(bite.Position));
|
auto pos = GetJointPosition(item, bite);
|
||||||
return func(pos.x, pos.y, pos.z, item->Animation.Velocity.z, item->Pose.Orientation.y, item->RoomNumber);
|
return func(pos.x, pos.y, pos.z, item->Animation.Velocity.z, item->Pose.Orientation.y, item->RoomNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +652,7 @@ void CreatureFloat(short itemNumber)
|
||||||
|
|
||||||
if (item->Pose.Position.y <= waterLevel)
|
if (item->Pose.Position.y <= waterLevel)
|
||||||
{
|
{
|
||||||
if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameBase)
|
if (item->Animation.FrameNumber == GetAnimData(*item).frameBase)
|
||||||
{
|
{
|
||||||
item->Pose.Position.y = waterLevel;
|
item->Pose.Position.y = waterLevel;
|
||||||
item->Collidable = false;
|
item->Collidable = false;
|
||||||
|
@ -735,26 +727,47 @@ short CreatureTurn(ItemInfo* item, short maxTurn)
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreatureAnimation(short itemNumber, short angle, short tilt)
|
static void SpawnCreatureGunEffect(const ItemInfo& item, const CreatureMuzzleFlashInfo& muzzleFlash)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
if (muzzleFlash.Delay == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!item->IsCreature())
|
auto muzzlePos = muzzleFlash.Bite;
|
||||||
|
auto pos = GetJointPosition(item, muzzlePos);
|
||||||
|
TriggerDynamicLight(pos.x, pos.y, pos.z, 15, 128, 64, 16);
|
||||||
|
|
||||||
|
if (muzzleFlash.UseSmoke)
|
||||||
|
{
|
||||||
|
muzzlePos.Position.y -= CREATURE_GUN_EFFECT_VERTICAL_OFFSET;
|
||||||
|
auto smokePos = GetJointPosition(item, muzzlePos);
|
||||||
|
SpawnGunSmokeParticles(smokePos.ToVector3(), Vector3::Zero, item.RoomNumber, 1, LaraWeaponType::Pistol, 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreatureAnimation(short itemNumber, short headingAngle, short tiltAngle)
|
||||||
|
{
|
||||||
|
auto& item = g_Level.Items[itemNumber];
|
||||||
|
if (!item.IsCreature())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto prevPos = item->Pose.Position;
|
auto& creature = *GetCreatureInfo(&item);
|
||||||
|
|
||||||
AnimateItem(item);
|
SpawnCreatureGunEffect(item, creature.MuzzleFlash[0]);
|
||||||
ProcessSectorFlags(item);
|
SpawnCreatureGunEffect(item, creature.MuzzleFlash[1]);
|
||||||
CreatureHealth(item);
|
|
||||||
|
|
||||||
if (item->Status == ITEM_DEACTIVATED)
|
auto prevPos = item.Pose.Position;
|
||||||
|
|
||||||
|
AnimateItem(&item);
|
||||||
|
ProcessSectorFlags(&item);
|
||||||
|
CreatureHealth(&item);
|
||||||
|
|
||||||
|
if (item.Status == ITEM_DEACTIVATED)
|
||||||
{
|
{
|
||||||
CreatureDie(itemNumber, false);
|
CreatureDie(itemNumber, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreaturePathfind(item, prevPos, angle, tilt);
|
return CreaturePathfind(&item, prevPos, headingAngle, tiltAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureHealth(ItemInfo* item)
|
void CreatureHealth(ItemInfo* item)
|
||||||
|
@ -1088,7 +1101,7 @@ bool CreatureActive(short itemNumber)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseCreature(short itemNumber)
|
void InitializeCreature(short itemNumber)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
|
|
||||||
|
@ -2097,7 +2110,7 @@ void AdjustStopperFlag(ItemInfo* item, int direction)
|
||||||
floor->Stopper = !floor->Stopper;
|
floor->Stopper = !floor->Stopper;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseItemBoxData()
|
void InitializeItemBoxData()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < g_Level.Items.size(); i++)
|
for (int i = 0; i < g_Level.Items.size(); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
|
|
||||||
struct BiteInfo;
|
struct CreatureBiteInfo;
|
||||||
struct CreatureInfo;
|
struct CreatureInfo;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
struct LOTInfo;
|
struct LOTInfo;
|
||||||
|
@ -20,55 +20,6 @@ enum TARGET_TYPE
|
||||||
SECONDARY_TARGET
|
SECONDARY_TARGET
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OBJECT_BONES
|
|
||||||
{
|
|
||||||
short bone0;
|
|
||||||
short bone1;
|
|
||||||
short bone2;
|
|
||||||
short bone3;
|
|
||||||
|
|
||||||
OBJECT_BONES()
|
|
||||||
{
|
|
||||||
this->bone0 = 0;
|
|
||||||
this->bone1 = 0;
|
|
||||||
this->bone2 = 0;
|
|
||||||
this->bone3 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
OBJECT_BONES(short all)
|
|
||||||
{
|
|
||||||
this->bone0 = all;
|
|
||||||
this->bone1 = all;
|
|
||||||
this->bone2 = all;
|
|
||||||
this->bone3 = all;
|
|
||||||
}
|
|
||||||
|
|
||||||
OBJECT_BONES(short angleY, short angleX)
|
|
||||||
{
|
|
||||||
this->bone0 = angleY;
|
|
||||||
this->bone1 = angleX;
|
|
||||||
this->bone2 = angleY;
|
|
||||||
this->bone3 = angleX;
|
|
||||||
}
|
|
||||||
|
|
||||||
OBJECT_BONES(short angleY, short angleX, bool total)
|
|
||||||
{
|
|
||||||
this->bone0 = angleY;
|
|
||||||
this->bone1 = angleX;
|
|
||||||
|
|
||||||
if (total)
|
|
||||||
{
|
|
||||||
this->bone2 = angleY;
|
|
||||||
this->bone3 = angleX;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->bone2 = 0;
|
|
||||||
this->bone3 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AI_INFO
|
struct AI_INFO
|
||||||
{
|
{
|
||||||
int zoneNumber;
|
int zoneNumber;
|
||||||
|
@ -99,30 +50,6 @@ struct OVERLAP
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BiteInfo
|
|
||||||
{
|
|
||||||
Vector3 Position = Vector3::Zero;
|
|
||||||
int meshNum = 0;
|
|
||||||
|
|
||||||
BiteInfo()
|
|
||||||
{
|
|
||||||
this->Position = Vector3::Zero;
|
|
||||||
this->meshNum = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BiteInfo(const Vector3& pos, int meshNumber)
|
|
||||||
{
|
|
||||||
this->Position = pos;
|
|
||||||
this->meshNum = meshNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
BiteInfo(float xPos, float yPos, float zPos, int meshNumber)
|
|
||||||
{
|
|
||||||
this->Position = Vector3(xPos, yPos, zPos);
|
|
||||||
this->meshNum = meshNumber;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber)
|
#define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber)
|
||||||
|
|
||||||
constexpr auto BOX_BLOCKED = (1 << 14); // unpassable for other enemies, always set for movable blocks & closed doors
|
constexpr auto BOX_BLOCKED = (1 << 14); // unpassable for other enemies, always set for movable blocks & closed doors
|
||||||
|
@ -164,8 +91,8 @@ short AIGuard(CreatureInfo* creature);
|
||||||
void AlertNearbyGuards(ItemInfo* item);
|
void AlertNearbyGuards(ItemInfo* item);
|
||||||
void AlertAllGuards(short itemNumber);
|
void AlertAllGuards(short itemNumber);
|
||||||
void CreatureKill(ItemInfo* item, int entityKillAnim, int laraExtraKillAnim, int entityKillState, int laraKillState);
|
void CreatureKill(ItemInfo* item, int entityKillAnim, int laraExtraKillAnim, int entityKillState, int laraKillState);
|
||||||
short CreatureEffect2(ItemInfo* item, BiteInfo bite, short velocity, short angle, std::function<CreatureEffectFunction> func);
|
short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function<CreatureEffectFunction> func);
|
||||||
short CreatureEffect(ItemInfo* item, BiteInfo bite, std::function<CreatureEffectFunction> func);
|
short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function<CreatureEffectFunction> func);
|
||||||
void CreatureUnderwater(ItemInfo* item, int depth);
|
void CreatureUnderwater(ItemInfo* item, int depth);
|
||||||
void CreatureFloat(short itemNumber);
|
void CreatureFloat(short itemNumber);
|
||||||
void CreatureJoint(ItemInfo* item, short joint, short required, short maxAngle = ANGLE(70.0f));
|
void CreatureJoint(ItemInfo* item, short joint, short required, short maxAngle = ANGLE(70.0f));
|
||||||
|
@ -180,14 +107,14 @@ void TargetBox(LOTInfo* LOT, int boxNumber);
|
||||||
bool UpdateLOT(LOTInfo* LOT, int expansion);
|
bool UpdateLOT(LOTInfo* LOT, int expansion);
|
||||||
bool SearchLOT(LOTInfo* LOT, int expansion);
|
bool SearchLOT(LOTInfo* LOT, int expansion);
|
||||||
bool CreatureActive(short itemNumber);
|
bool CreatureActive(short itemNumber);
|
||||||
void InitialiseCreature(short itemNumber);
|
void InitializeCreature(short itemNumber);
|
||||||
bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber);
|
bool StalkBox(ItemInfo* item, ItemInfo* enemy, int boxNumber);
|
||||||
void CreatureAIInfo(ItemInfo* item, AI_INFO* AI);
|
void CreatureAIInfo(ItemInfo* item, AI_INFO* AI);
|
||||||
TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT);
|
TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT);
|
||||||
bool CreatureAnimation(short itemNumber, short angle, short tilt);
|
bool CreatureAnimation(short itemNumber, short headingAngle, short tiltAngle);
|
||||||
void CreatureHealth(ItemInfo* item);
|
void CreatureHealth(ItemInfo* item);
|
||||||
void AdjustStopperFlag(ItemInfo* item, int direction);
|
void AdjustStopperFlag(ItemInfo* item, int direction);
|
||||||
void InitialiseItemBoxData();
|
void InitializeItemBoxData();
|
||||||
|
|
||||||
bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType);
|
bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/effects/Electricity.h"
|
#include "Game/effects/Electricity.h"
|
||||||
#include "Game/effects/explosion.h"
|
#include "Game/effects/explosion.h"
|
||||||
#include "Game/effects/footprint.h"
|
#include "Game/effects/Footprint.h"
|
||||||
#include "Game/effects/Hair.h"
|
#include "Game/effects/Hair.h"
|
||||||
#include "Game/effects/Ripple.h"
|
#include "Game/effects/Ripple.h"
|
||||||
#include "Game/effects/simple_particle.h"
|
#include "Game/effects/simple_particle.h"
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
#include "Game/pickup/pickup.h"
|
#include "Game/pickup/pickup.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Game/spotcam.h"
|
#include "Game/spotcam.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/Effects/tr4_locusts.h"
|
#include "Objects/Effects/tr4_locusts.h"
|
||||||
|
@ -54,7 +55,6 @@
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Specific/winmain.h"
|
#include "Specific/winmain.h"
|
||||||
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
@ -65,7 +65,7 @@ using namespace TEN::Effects::Drip;
|
||||||
using namespace TEN::Effects::Electricity;
|
using namespace TEN::Effects::Electricity;
|
||||||
using namespace TEN::Effects::Environment;
|
using namespace TEN::Effects::Environment;
|
||||||
using namespace TEN::Effects::Explosion;
|
using namespace TEN::Effects::Explosion;
|
||||||
using namespace TEN::Effects::Footprints;
|
using namespace TEN::Effects::Footprint;
|
||||||
using namespace TEN::Effects::Hair;
|
using namespace TEN::Effects::Hair;
|
||||||
using namespace TEN::Effects::Ripple;
|
using namespace TEN::Effects::Ripple;
|
||||||
using namespace TEN::Effects::Smoke;
|
using namespace TEN::Effects::Smoke;
|
||||||
|
@ -74,7 +74,7 @@ using namespace TEN::Effects::Streamer;
|
||||||
using namespace TEN::Entities::Generic;
|
using namespace TEN::Entities::Generic;
|
||||||
using namespace TEN::Entities::Switches;
|
using namespace TEN::Entities::Switches;
|
||||||
using namespace TEN::Entities::TR4;
|
using namespace TEN::Entities::TR4;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Hud;
|
using namespace TEN::Hud;
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
@ -84,7 +84,7 @@ int GameTimer = 0;
|
||||||
int GlobalCounter = 0;
|
int GlobalCounter = 0;
|
||||||
int Wibble = 0;
|
int Wibble = 0;
|
||||||
|
|
||||||
bool InitialiseGame;
|
bool InitializeGame;
|
||||||
bool DoTheGame;
|
bool DoTheGame;
|
||||||
bool JustLoaded;
|
bool JustLoaded;
|
||||||
bool ThreadEnded;
|
bool ThreadEnded;
|
||||||
|
@ -124,7 +124,6 @@ GameStatus ControlPhase(int numFrames)
|
||||||
{
|
{
|
||||||
auto time1 = std::chrono::high_resolution_clock::now();
|
auto time1 = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
auto* level = g_GameFlow->GetLevel(CurrentLevel);
|
|
||||||
bool isTitle = (CurrentLevel == 0);
|
bool isTitle = (CurrentLevel == 0);
|
||||||
|
|
||||||
RegeneratePickups();
|
RegeneratePickups();
|
||||||
|
@ -271,7 +270,6 @@ unsigned CALLBACK GameMain(void *)
|
||||||
else
|
else
|
||||||
g_Renderer.RenderTitleImage();
|
g_Renderer.RenderTitleImage();
|
||||||
|
|
||||||
|
|
||||||
// Execute the Lua gameflow and play the game.
|
// Execute the Lua gameflow and play the game.
|
||||||
g_GameFlow->DoFlow();
|
g_GameFlow->DoFlow();
|
||||||
|
|
||||||
|
@ -296,17 +294,17 @@ GameStatus DoLevel(int levelIndex, bool loadGame)
|
||||||
|
|
||||||
// Initialize items, effects, lots, and cameras.
|
// Initialize items, effects, lots, and cameras.
|
||||||
HairEffect.Initialize();
|
HairEffect.Initialize();
|
||||||
InitialiseFXArray(true);
|
InitializeFXArray(true);
|
||||||
InitialiseCamera();
|
InitializeCamera();
|
||||||
InitialiseSpotCamSequences(isTitle);
|
InitializeSpotCamSequences(isTitle);
|
||||||
InitialiseItemBoxData();
|
InitializeItemBoxData();
|
||||||
|
|
||||||
// Initialize scripting.
|
// Initialize scripting.
|
||||||
InitialiseScripting(levelIndex, loadGame);
|
InitializeScripting(levelIndex, loadGame);
|
||||||
InitialiseNodeScripts();
|
InitializeNodeScripts();
|
||||||
|
|
||||||
// Initialize game variables and optionally load game.
|
// Initialize game variables and optionally load game.
|
||||||
InitialiseOrLoadGame(loadGame);
|
InitializeOrLoadGame(loadGame);
|
||||||
|
|
||||||
// Prepare title menu, if necessary.
|
// Prepare title menu, if necessary.
|
||||||
if (isTitle)
|
if (isTitle)
|
||||||
|
@ -416,6 +414,7 @@ void CleanUp()
|
||||||
StreamerEffect.Clear();
|
StreamerEffect.Clear();
|
||||||
ClearUnderwaterBloodParticles();
|
ClearUnderwaterBloodParticles();
|
||||||
ClearBubbles();
|
ClearBubbles();
|
||||||
|
ClearFootprints();
|
||||||
ClearDrips();
|
ClearDrips();
|
||||||
ClearRipples();
|
ClearRipples();
|
||||||
DisableSmokeParticles();
|
DisableSmokeParticles();
|
||||||
|
@ -438,7 +437,7 @@ void CleanUp()
|
||||||
ClearObjCamera();
|
ClearObjCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseScripting(int levelIndex, bool loadGame)
|
void InitializeScripting(int levelIndex, bool loadGame)
|
||||||
{
|
{
|
||||||
TENLog("Loading level script...", LogLevel::Info);
|
TENLog("Loading level script...", LogLevel::Info);
|
||||||
|
|
||||||
|
@ -465,9 +464,9 @@ void InitialiseScripting(int levelIndex, bool loadGame)
|
||||||
PlaySoundTrack(level->GetAmbientTrack(), SoundTrackType::BGM);
|
PlaySoundTrack(level->GetAmbientTrack(), SoundTrackType::BGM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeInitialiseScripting(int levelIndex)
|
void DeInitializeScripting(int levelIndex, GameStatus reason)
|
||||||
{
|
{
|
||||||
g_GameScript->OnEnd();
|
g_GameScript->OnEnd(reason);
|
||||||
g_GameScript->FreeLevelScripts();
|
g_GameScript->FreeLevelScripts();
|
||||||
g_GameScriptEntities->FreeEntities();
|
g_GameScriptEntities->FreeEntities();
|
||||||
|
|
||||||
|
@ -475,7 +474,7 @@ void DeInitialiseScripting(int levelIndex)
|
||||||
g_GameScript->ResetScripts(true);
|
g_GameScript->ResetScripts(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseOrLoadGame(bool loadGame)
|
void InitializeOrLoadGame(bool loadGame)
|
||||||
{
|
{
|
||||||
RequiredStartPos = false;
|
RequiredStartPos = false;
|
||||||
|
|
||||||
|
@ -495,7 +494,7 @@ void InitialiseOrLoadGame(bool loadGame)
|
||||||
Camera.target.y = LaraItem->Pose.Position.y;
|
Camera.target.y = LaraItem->Pose.Position.y;
|
||||||
Camera.target.z = LaraItem->Pose.Position.z;
|
Camera.target.z = LaraItem->Pose.Position.z;
|
||||||
|
|
||||||
InitialiseGame = false;
|
InitializeGame = false;
|
||||||
|
|
||||||
g_GameFlow->SelectedSaveGame = 0;
|
g_GameFlow->SelectedSaveGame = 0;
|
||||||
g_GameScript->OnLoad();
|
g_GameScript->OnLoad();
|
||||||
|
@ -505,12 +504,12 @@ void InitialiseOrLoadGame(bool loadGame)
|
||||||
// If not loading a savegame, clear all info.
|
// If not loading a savegame, clear all info.
|
||||||
Statistics.Level = {};
|
Statistics.Level = {};
|
||||||
|
|
||||||
if (InitialiseGame)
|
if (InitializeGame)
|
||||||
{
|
{
|
||||||
// Clear all game info as well.
|
// Clear all game info as well.
|
||||||
Statistics.Game = {};
|
Statistics.Game = {};
|
||||||
GameTimer = 0;
|
GameTimer = 0;
|
||||||
InitialiseGame = false;
|
InitializeGame = false;
|
||||||
|
|
||||||
TENLog("Starting new game.", LogLevel::Info);
|
TENLog("Starting new game.", LogLevel::Info);
|
||||||
}
|
}
|
||||||
|
@ -563,6 +562,7 @@ GameStatus DoGameLoop(int levelIndex)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (result == GameStatus::ExitToTitle ||
|
if (result == GameStatus::ExitToTitle ||
|
||||||
|
result == GameStatus::LaraDead ||
|
||||||
result == GameStatus::LoadGame ||
|
result == GameStatus::LoadGame ||
|
||||||
result == GameStatus::LevelComplete)
|
result == GameStatus::LevelComplete)
|
||||||
{
|
{
|
||||||
|
@ -574,13 +574,13 @@ GameStatus DoGameLoop(int levelIndex)
|
||||||
Sound_UpdateScene();
|
Sound_UpdateScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
EndGameLoop(levelIndex);
|
EndGameLoop(levelIndex, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndGameLoop(int levelIndex)
|
void EndGameLoop(int levelIndex, GameStatus reason)
|
||||||
{
|
{
|
||||||
DeInitialiseScripting(levelIndex);
|
DeInitializeScripting(levelIndex, reason);
|
||||||
|
|
||||||
StopAllSounds();
|
StopAllSounds();
|
||||||
StopSoundTracks();
|
StopSoundTracks();
|
||||||
|
@ -678,7 +678,7 @@ GameStatus HandleGlobalInputEvents(bool isTitle)
|
||||||
if (Lara.Control.Count.Death > DEATH_NO_INPUT_TIMEOUT ||
|
if (Lara.Control.Count.Death > DEATH_NO_INPUT_TIMEOUT ||
|
||||||
Lara.Control.Count.Death > DEATH_INPUT_TIMEOUT && !NoAction())
|
Lara.Control.Count.Death > DEATH_INPUT_TIMEOUT && !NoAction())
|
||||||
{
|
{
|
||||||
return GameStatus::ExitToTitle; // Maybe do game over menu like some PSX versions have??
|
return GameStatus::LaraDead; // Maybe do game over menu like some PSX versions have??
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has level been completed?
|
// Has level been completed?
|
||||||
|
|
|
@ -50,7 +50,7 @@ extern int RumbleTimer;
|
||||||
extern int GlobalCounter;
|
extern int GlobalCounter;
|
||||||
extern int Wibble;
|
extern int Wibble;
|
||||||
|
|
||||||
extern bool InitialiseGame;
|
extern bool InitializeGame;
|
||||||
extern bool DoTheGame;
|
extern bool DoTheGame;
|
||||||
extern bool JustLoaded;
|
extern bool JustLoaded;
|
||||||
extern bool ThreadEnded;
|
extern bool ThreadEnded;
|
||||||
|
@ -77,7 +77,7 @@ int DrawPhase(bool isTitle);
|
||||||
GameStatus ControlPhase(int numFrames);
|
GameStatus ControlPhase(int numFrames);
|
||||||
GameStatus DoLevel(int levelIndex, bool loadGame = false);
|
GameStatus DoLevel(int levelIndex, bool loadGame = false);
|
||||||
GameStatus DoGameLoop(int levelIndex);
|
GameStatus DoGameLoop(int levelIndex);
|
||||||
void EndGameLoop(int levelIndex);
|
void EndGameLoop(int levelIndex, GameStatus reason);
|
||||||
|
|
||||||
GameStatus HandleMenuCalls(bool isTitle);
|
GameStatus HandleMenuCalls(bool isTitle);
|
||||||
GameStatus HandleGlobalInputEvents(bool isTitle);
|
GameStatus HandleGlobalInputEvents(bool isTitle);
|
||||||
|
@ -92,8 +92,8 @@ void UpdateShatters();
|
||||||
|
|
||||||
void CleanUp();
|
void CleanUp();
|
||||||
|
|
||||||
void InitialiseOrLoadGame(bool loadGame);
|
void InitializeOrLoadGame(bool loadGame);
|
||||||
void InitialiseScripting(int levelIndex, bool loadGame);
|
void InitializeScripting(int levelIndex, bool loadGame);
|
||||||
void DeInitialiseScripting(int levelIndex);
|
void DeInitializeScripting(int levelIndex);
|
||||||
|
|
||||||
unsigned CALLBACK GameMain(void*);
|
unsigned CALLBACK GameMain(void*);
|
||||||
|
|
|
@ -7,16 +7,16 @@
|
||||||
#include "Game/effects/Hair.h"
|
#include "Game/effects/Hair.h"
|
||||||
#include "Game/effects/tomb4fx.h"
|
#include "Game/effects/tomb4fx.h"
|
||||||
#include "Game/effects/weather.h"
|
#include "Game/effects/weather.h"
|
||||||
#include "Game/effects/footprint.h"
|
#include "Game/effects/Footprint.h"
|
||||||
#include "Game/effects/debris.h"
|
#include "Game/effects/debris.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_fire.h"
|
#include "Game/Lara/lara_fire.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/pickup/pickup.h"
|
#include "Game/pickup/pickup.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Objects/Generic/puzzles_keys.h"
|
#include "Objects/Generic/puzzles_keys.h"
|
||||||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||||
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
|
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
#include "Objects/Effects/tr4_locusts.h"
|
#include "Objects/Effects/tr4_locusts.h"
|
||||||
|
|
||||||
using namespace TEN::Effects::Environment;
|
using namespace TEN::Effects::Environment;
|
||||||
using namespace TEN::Effects::Footprints;
|
using namespace TEN::Effects::Footprint;
|
||||||
using namespace TEN::Effects::Hair;
|
using namespace TEN::Effects::Hair;
|
||||||
|
|
||||||
int FlipEffect;
|
int FlipEffect;
|
||||||
|
@ -121,12 +121,12 @@ void Puzzle(ItemInfo* item)
|
||||||
|
|
||||||
void AddLeftFootprint(ItemInfo* item)
|
void AddLeftFootprint(ItemInfo* item)
|
||||||
{
|
{
|
||||||
AddFootprint(item, false);
|
SpawnFootprint(*item, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddRightFootprint(ItemInfo* item)
|
void AddRightFootprint(ItemInfo* item)
|
||||||
{
|
{
|
||||||
AddFootprint(item, true);
|
SpawnFootprint(*item, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetHair(ItemInfo* item)
|
void ResetHair(ItemInfo* item)
|
||||||
|
@ -155,7 +155,7 @@ void DrawLeftPistol(ItemInfo* item)
|
||||||
|
|
||||||
if (item->Model.MeshIndex[LM_LHAND] == item->Model.BaseMesh + LM_LHAND)
|
if (item->Model.MeshIndex[LM_LHAND] == item->Model.BaseMesh + LM_LHAND)
|
||||||
{
|
{
|
||||||
item->Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(item, LaraWeaponType::Pistol)].meshIndex + LM_LHAND;
|
item->Model.MeshIndex[LM_LHAND] = Objects[GetWeaponObjectMeshID(*item, LaraWeaponType::Pistol)].meshIndex + LM_LHAND;
|
||||||
lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
lara->Control.Weapon.HolsterInfo.LeftHolster = HolsterSlot::Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -171,7 +171,7 @@ void DrawRightPistol(ItemInfo* item)
|
||||||
|
|
||||||
if (item->Model.MeshIndex[LM_RHAND] == item->Model.BaseMesh + LM_RHAND)
|
if (item->Model.MeshIndex[LM_RHAND] == item->Model.BaseMesh + LM_RHAND)
|
||||||
{
|
{
|
||||||
item->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(item, LaraWeaponType::Pistol)].meshIndex + LM_RHAND;
|
item->Model.MeshIndex[LM_RHAND] = Objects[GetWeaponObjectMeshID(*item, LaraWeaponType::Pistol)].meshIndex + LM_RHAND;
|
||||||
lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty;
|
lara->Control.Weapon.HolsterInfo.RightHolster = HolsterSlot::Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara_fire.h"
|
#include "Game/Lara/lara_fire.h"
|
||||||
#include "Game/Lara/lara_one_gun.h"
|
#include "Game/Lara/lara_one_gun.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Objects/Generic/Object/objects.h"
|
#include "Objects/Generic/Object/objects.h"
|
||||||
#include "Objects/Generic/Switches/switch.h"
|
#include "Objects/Generic/Switches/switch.h"
|
||||||
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
||||||
#include "ScriptInterfaceGame.h"
|
#include "ScriptInterfaceGame.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
int NumberLosRooms;
|
int NumberLosRooms;
|
||||||
short LosRooms[20];
|
short LosRooms[20];
|
||||||
|
@ -252,7 +252,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (LaserSight && isFiring)
|
if (LaserSight && isFiring)
|
||||||
FireCrossBowFromLaserSight(LaraItem, origin, &target2);
|
FireCrossBowFromLaserSight(*LaraItem, origin, &target2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +263,7 @@ bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, boo
|
||||||
if (Lara.Control.Weapon.GunType == LaraWeaponType::Crossbow)
|
if (Lara.Control.Weapon.GunType == LaraWeaponType::Crossbow)
|
||||||
{
|
{
|
||||||
if (isFiring && LaserSight)
|
if (isFiring && LaserSight)
|
||||||
FireCrossBowFromLaserSight(LaraItem, origin, &target2);
|
FireCrossBowFromLaserSight(*LaraItem, origin, &target2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/misc.h"
|
#include "Game/misc.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
#define DEFAULT_FLY_UPDOWN_SPEED 16
|
#define DEFAULT_FLY_UPDOWN_SPEED 16
|
||||||
#define DEFAULT_SWIM_UPDOWN_SPEED 32
|
#define DEFAULT_SWIM_UPDOWN_SPEED 32
|
||||||
|
@ -16,15 +16,15 @@
|
||||||
int SlotsUsed;
|
int SlotsUsed;
|
||||||
std::vector<CreatureInfo*> ActiveCreatures;
|
std::vector<CreatureInfo*> ActiveCreatures;
|
||||||
|
|
||||||
void InitialiseLOTarray(int itemNumber)
|
void InitializeLOTarray(int itemNumber)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
auto* creature = GetCreatureInfo(item);
|
auto* creature = GetCreatureInfo(item);
|
||||||
|
|
||||||
if (!creature->LOT.Initialised)
|
if (!creature->LOT.Initialized)
|
||||||
{
|
{
|
||||||
creature->LOT.Node = std::vector<BoxNode>(g_Level.Boxes.size(), BoxNode{});
|
creature->LOT.Node = std::vector<BoxNode>(g_Level.Boxes.size(), BoxNode{});
|
||||||
creature->LOT.Initialised = true;
|
creature->LOT.Initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ bool EnableEntityAI(short itemNum, bool always, bool makeTarget)
|
||||||
if (item->IsCreature())
|
if (item->IsCreature())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
InitialiseSlot(itemNum, makeTarget);
|
InitializeSlot(itemNum, makeTarget);
|
||||||
ActiveCreatures.push_back(item->Data);
|
ActiveCreatures.push_back(item->Data);
|
||||||
|
|
||||||
return item->IsCreature();
|
return item->IsCreature();
|
||||||
|
@ -55,14 +55,14 @@ void DisableEntityAI(short itemNumber)
|
||||||
item->Data = nullptr;
|
item->Data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseSlot(short itemNumber, bool makeTarget)
|
void InitializeSlot(short itemNumber, bool makeTarget)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
auto* object = &Objects[item->ObjectNumber];
|
auto* object = &Objects[item->ObjectNumber];
|
||||||
item->Data = CreatureInfo();
|
item->Data = CreatureInfo();
|
||||||
auto* creature = GetCreatureInfo(item);
|
auto* creature = GetCreatureInfo(item);
|
||||||
|
|
||||||
InitialiseLOTarray(itemNumber);
|
InitializeLOTarray(itemNumber);
|
||||||
creature->ItemNumber = itemNumber;
|
creature->ItemNumber = itemNumber;
|
||||||
creature->Mood = MoodType::Bored;
|
creature->Mood = MoodType::Bored;
|
||||||
creature->JointRotation[0] = 0;
|
creature->JointRotation[0] = 0;
|
||||||
|
@ -146,6 +146,12 @@ void InitialiseSlot(short itemNumber, bool makeTarget)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LotType::SnowmobileGun:
|
||||||
|
creature->LOT.Step = CLICK(1);
|
||||||
|
creature->LOT.Drop = -BLOCK(1);
|
||||||
|
creature->LOT.Zone = ZoneType::Human;
|
||||||
|
break;
|
||||||
|
|
||||||
// Can climb.
|
// Can climb.
|
||||||
case LotType::Human:
|
case LotType::Human:
|
||||||
creature->LOT.Step = BLOCK(1);
|
creature->LOT.Step = BLOCK(1);
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
extern std::vector<CreatureInfo*> ActiveCreatures;
|
extern std::vector<CreatureInfo*> ActiveCreatures;
|
||||||
|
|
||||||
void InitialiseLOTarray(int allocMem);
|
void InitializeLOTarray(int allocMem);
|
||||||
bool EnableEntityAI(short itemNum, bool always, bool makeTarget = true);
|
bool EnableEntityAI(short itemNum, bool always, bool makeTarget = true);
|
||||||
void InitialiseSlot(short itemNum, bool makeTarget);
|
void InitializeSlot(short itemNum, bool makeTarget);
|
||||||
void SetEntityTarget(short itemNum, short target);
|
void SetEntityTarget(short itemNum, short target);
|
||||||
void DisableEntityAI(short itemNumber);
|
void DisableEntityAI(short itemNumber);
|
||||||
void ClearLOT(LOTInfo* LOT);
|
void ClearLOT(LOTInfo* LOT);
|
||||||
|
|
|
@ -15,13 +15,14 @@
|
||||||
#include "Game/Lara/lara_tests.h"
|
#include "Game/Lara/lara_tests.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Game/spotcam.h"
|
#include "Game/spotcam.h"
|
||||||
#include "Objects/Generic/Switches/generic_switch.h"
|
#include "Objects/Generic/Switches/generic_switch.h"
|
||||||
|
#include "Objects/Generic/puzzles_keys.h"
|
||||||
#include "Objects/objectslist.h"
|
#include "Objects/objectslist.h"
|
||||||
#include "Objects/TR3/Vehicles/kayak.h"
|
#include "Objects/TR3/Vehicles/kayak.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Items;
|
using namespace TEN::Effects::Items;
|
||||||
using namespace TEN::Entities::Switches;
|
using namespace TEN::Entities::Switches;
|
||||||
|
@ -82,7 +83,8 @@ bool GetKeyTrigger(ItemInfo* item)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
// NOTE: attatchedToSwitch parameter unused.
|
||||||
|
int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch)
|
||||||
{
|
{
|
||||||
auto triggerIndex = GetTriggerIndex(item);
|
auto triggerIndex = GetTriggerIndex(item);
|
||||||
|
|
||||||
|
@ -95,14 +97,14 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
trigger += 2;
|
trigger += 2;
|
||||||
short* current = itemNos;
|
short* currentPtr = itemNumbersPtr;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (TRIG_BITS(*trigger) == TO_OBJECT && item != &g_Level.Items[*trigger & VALUE_BITS])
|
if (TRIG_BITS(*trigger) == TO_OBJECT && item != &g_Level.Items[*trigger & VALUE_BITS])
|
||||||
{
|
{
|
||||||
current[k] = *trigger & VALUE_BITS;
|
currentPtr[k] = *trigger & VALUE_BITS;
|
||||||
++k;
|
++k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +123,67 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
||||||
int SwitchTrigger(short itemNumber, short timer)
|
int SwitchTrigger(short itemNumber, short timer)
|
||||||
{
|
{
|
||||||
auto& item = g_Level.Items[itemNumber];
|
auto& item = g_Level.Items[itemNumber];
|
||||||
|
const auto& player = Lara;
|
||||||
|
|
||||||
|
// Handle reusable receptacles.
|
||||||
|
if (item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16 &&
|
||||||
|
item.ItemFlags[1] != 0)
|
||||||
|
{
|
||||||
|
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||||
|
item.Status = ITEM_ACTIVE;
|
||||||
|
item.ItemFlags[1] = false;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16 &&
|
||||||
|
item.ItemFlags[1] != 0)
|
||||||
|
{
|
||||||
|
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||||
|
item.Status = ITEM_DEACTIVATED;
|
||||||
|
item.ItemFlags[1] = false;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) ||
|
||||||
|
(item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle reusable receptacles.
|
||||||
|
if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 &&
|
||||||
|
item.ItemFlags[1] != 0 &&
|
||||||
|
(item.ItemFlags[5] == (int)ReusableReceptacleState::Empty || item.ItemFlags[5] == (int)ReusableReceptacleState::None) &&
|
||||||
|
player.Control.HandStatus != HandStatus::Busy)
|
||||||
|
{
|
||||||
|
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||||
|
item.Status = ITEM_ACTIVE;
|
||||||
|
item.ItemFlags[5] = (int)ReusableReceptacleState::Done;
|
||||||
|
item.ItemFlags[1] = false;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 &&
|
||||||
|
item.ItemFlags[1] != 0 && item.ItemFlags[5] == (int)ReusableReceptacleState::Done &&
|
||||||
|
player.Control.HandStatus != HandStatus::Busy)
|
||||||
|
{
|
||||||
|
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||||
|
item.Status = ITEM_DEACTIVATED;
|
||||||
|
item.ItemFlags[5] = (int)ReusableReceptacleState::Empty;
|
||||||
|
item.ItemFlags[1] = false;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Handle switches.
|
||||||
if (item.Status == ITEM_DEACTIVATED)
|
if (item.Status == ITEM_DEACTIVATED)
|
||||||
{
|
{
|
||||||
if ((!item.Animation.ActiveState && item.ObjectNumber != ID_JUMP_SWITCH || item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH) &&
|
if (((item.Animation.ActiveState == 0 && item.ObjectNumber != ID_JUMP_SWITCH) ||
|
||||||
|
(item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH)) &&
|
||||||
timer > 0)
|
timer > 0)
|
||||||
{
|
{
|
||||||
item.Timer = timer;
|
item.Timer = timer;
|
||||||
|
@ -135,14 +194,15 @@ int SwitchTrigger(short itemNumber, short timer)
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.TriggerFlags >= 0 || item.Animation.ActiveState)
|
if (item.TriggerFlags >= 0 || item.Animation.ActiveState != 0)
|
||||||
{
|
{
|
||||||
RemoveActiveItem(itemNumber);
|
RemoveActiveItem(itemNumber);
|
||||||
|
|
||||||
item.Status = ITEM_NOT_ACTIVE;
|
item.Status = ITEM_NOT_ACTIVE;
|
||||||
if (!item.ItemFlags[0] == 0)
|
if (!item.ItemFlags[0] == 0)
|
||||||
item.Flags |= ONESHOT;
|
item.Flags |= ONESHOT;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -151,11 +211,11 @@ int SwitchTrigger(short itemNumber, short timer)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item.Status)
|
else if (item.Status != 0)
|
||||||
{
|
{
|
||||||
if (item.ObjectNumber == ID_AIRLOCK_SWITCH &&
|
if (item.ObjectNumber == ID_AIRLOCK_SWITCH &&
|
||||||
item.Animation.AnimNumber == GetAnimNumber(item, 2) &&
|
item.Animation.AnimNumber == GetAnimIndex(item, 2) &&
|
||||||
item.Animation.FrameNumber == GetFrameNumber(&item, 0))
|
item.Animation.FrameNumber == GetFrameIndex(&item, 0))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -170,15 +230,18 @@ int SwitchTrigger(short itemNumber, short timer)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int KeyTrigger(short itemNum)
|
int KeyTrigger(short itemNumber)
|
||||||
{
|
{
|
||||||
ItemInfo* item = &g_Level.Items[itemNum];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
int oldkey;
|
const auto& player = Lara;
|
||||||
|
|
||||||
if ((item->Status != ITEM_ACTIVE || Lara.Control.HandStatus == HandStatus::Busy) && (!KeyTriggerActive || Lara.Control.HandStatus != HandStatus::Busy))
|
if ((item->Status != ITEM_ACTIVE || player.Control.HandStatus == HandStatus::Busy) &&
|
||||||
|
(!KeyTriggerActive || player.Control.HandStatus != HandStatus::Busy))
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
oldkey = KeyTriggerActive;
|
int oldkey = KeyTriggerActive;
|
||||||
|
|
||||||
if (!oldkey)
|
if (!oldkey)
|
||||||
item->Status = ITEM_DEACTIVATED;
|
item->Status = ITEM_DEACTIVATED;
|
||||||
|
@ -188,9 +251,9 @@ int KeyTrigger(short itemNum)
|
||||||
return oldkey;
|
return oldkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PickupTrigger(short itemNum)
|
bool PickupTrigger(short itemNumber)
|
||||||
{
|
{
|
||||||
ItemInfo* item = &g_Level.Items[itemNum];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
|
|
||||||
if (((item->Flags & IFLAG_CLEAR_BODY) && (item->Flags & IFLAG_KILLED)) ||
|
if (((item->Flags & IFLAG_CLEAR_BODY) && (item->Flags & IFLAG_KILLED)) ||
|
||||||
item->Status != ITEM_INVISIBLE ||
|
item->Status != ITEM_INVISIBLE ||
|
||||||
|
@ -200,7 +263,7 @@ bool PickupTrigger(short itemNum)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KillItem(itemNum);
|
KillItem(itemNumber);
|
||||||
item->Flags |= IFLAG_CLEAR_BODY;
|
item->Flags |= IFLAG_CLEAR_BODY;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -237,6 +300,7 @@ void RefreshCamera(short type, short* data)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
targetOk = 0;
|
targetOk = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_TARGET:
|
case TO_TARGET:
|
||||||
|
@ -250,7 +314,7 @@ void RefreshCamera(short type, short* data)
|
||||||
|
|
||||||
if (Camera.item)
|
if (Camera.item)
|
||||||
if (!targetOk || (targetOk == 2 && Camera.item->LookedAt && Camera.item != Camera.lastItem))
|
if (!targetOk || (targetOk == 2 && Camera.item->LookedAt && Camera.item != Camera.lastItem))
|
||||||
Camera.item = NULL;
|
Camera.item = nullptr;
|
||||||
|
|
||||||
if (Camera.number == -1 && Camera.timer > 0)
|
if (Camera.number == -1 && Camera.timer > 0)
|
||||||
Camera.timer = -1;
|
Camera.timer = -1;
|
||||||
|
@ -498,8 +562,8 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
||||||
short targetType = 0;
|
short targetType = 0;
|
||||||
short trigger = 0;
|
short trigger = 0;
|
||||||
|
|
||||||
ItemInfo* item = NULL;
|
ItemInfo* item = nullptr;
|
||||||
ItemInfo* cameraItem = NULL;
|
ItemInfo* cameraItem = nullptr;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -642,7 +706,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
||||||
UseSpotCam = true;
|
UseSpotCam = true;
|
||||||
if (LastSpotCamSequence != value)
|
if (LastSpotCamSequence != value)
|
||||||
TrackCameraInit = false;
|
TrackCameraInit = false;
|
||||||
InitialiseSpotCam(value);
|
InitializeSpotCam(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,7 +717,7 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_SINK:
|
case TO_SINK:
|
||||||
Lara.WaterCurrentActive = value + 1;
|
Lara.Context.WaterCurrentActive = value + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TO_FLIPMAP:
|
case TO_FLIPMAP:
|
||||||
|
@ -761,12 +825,12 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
||||||
FlipEffect = newEffect;
|
FlipEffect = newEffect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags)
|
void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags)
|
||||||
{
|
{
|
||||||
auto roomNum = item->RoomNumber;
|
auto roomNumber = item->RoomNumber;
|
||||||
auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNum);
|
auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber);
|
||||||
|
|
||||||
TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, heavy, heavyFlags);
|
TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, isHeavy, heavyFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags)
|
void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags)
|
||||||
|
|
|
@ -67,16 +67,16 @@ extern int TriggerTimer;
|
||||||
extern int KeyTriggerActive;
|
extern int KeyTriggerActive;
|
||||||
|
|
||||||
bool GetKeyTrigger(ItemInfo* item);
|
bool GetKeyTrigger(ItemInfo* item);
|
||||||
int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch);
|
int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch);
|
||||||
int SwitchTrigger(short itemNumber, short timer);
|
int SwitchTrigger(short itemNumber, short timer);
|
||||||
int KeyTrigger(short itemNum);
|
int KeyTrigger(short itemNumber);
|
||||||
bool PickupTrigger(short itemNum);
|
bool PickupTrigger(short itemNumber);
|
||||||
void RefreshCamera(short type, short* data);
|
void RefreshCamera(short type, short* data);
|
||||||
int TriggerActive(ItemInfo* item);
|
int TriggerActive(ItemInfo* item);
|
||||||
short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z);
|
short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z);
|
||||||
short* GetTriggerIndex(ItemInfo* item);
|
short* GetTriggerIndex(ItemInfo* item);
|
||||||
void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags = 0);
|
void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags = 0);
|
||||||
void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags = 0);
|
void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags = 0);
|
||||||
void ProcessSectorFlags(ItemInfo* item);
|
void ProcessSectorFlags(ItemInfo* item);
|
||||||
|
|
||||||
void Antitrigger(short const value, short const flags = 0);
|
void Antitrigger(short const value, short const flags = 0);
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Renderer/Renderer11Enums.h"
|
#include "Renderer/Renderer11Enums.h"
|
||||||
#include "Scripting/Include/ScriptInterfaceGame.h"
|
#include "Scripting/Include/ScriptInterfaceGame.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using TEN::Renderer::g_Renderer;
|
using TEN::Renderer::g_Renderer;
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ namespace TEN::Control::Volumes
|
||||||
|
|
||||||
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), RENDERER_DEBUG_PAGE::LARA_STATS);
|
||||||
|
|
||||||
if (item.IsLara() || item.Index == Lara.Vehicle)
|
if (item.IsLara() || item.Index == Lara.Context.Vehicle)
|
||||||
{
|
{
|
||||||
TestVolumes(item.RoomNumber, box, VolumeActivatorFlags::Player, itemNumber);
|
TestVolumes(item.RoomNumber, box, VolumeActivatorFlags::Player, itemNumber);
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ namespace TEN::Control::Volumes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseNodeScripts()
|
void InitializeNodeScripts()
|
||||||
{
|
{
|
||||||
static const std::string nodeScriptPath = "Scripts/Engine/NodeCatalogs/";
|
static const std::string nodeScriptPath = "Scripts/Engine/NodeCatalogs/";
|
||||||
|
|
||||||
|
@ -207,10 +207,18 @@ namespace TEN::Control::Volumes
|
||||||
TENLog("Loading node scripts...", LogLevel::Info);
|
TENLog("Loading node scripts...", LogLevel::Info);
|
||||||
|
|
||||||
std::sort(nodeCatalogs.rbegin(), nodeCatalogs.rend());
|
std::sort(nodeCatalogs.rbegin(), nodeCatalogs.rend());
|
||||||
for (const auto& file : nodeCatalogs)
|
|
||||||
g_GameScript->ExecuteScriptFile(nodeScriptPath + file);
|
|
||||||
|
|
||||||
TENLog(std::to_string(nodeCatalogs.size()) + " node catalogs were found and loaded.", LogLevel::Info);
|
if (!nodeCatalogs.empty())
|
||||||
|
{
|
||||||
|
for (const auto& file : nodeCatalogs)
|
||||||
|
g_GameScript->ExecuteScriptFile(nodeScriptPath + file);
|
||||||
|
|
||||||
|
TENLog(std::to_string(nodeCatalogs.size()) + " node catalogs were found and loaded.", LogLevel::Info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TENLog("No node catalogs were found.", LogLevel::Warning);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int nodeCount = 0;
|
unsigned int nodeCount = 0;
|
||||||
for (const auto& set : g_Level.EventSets)
|
for (const auto& set : g_Level.EventSets)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Game/control/volumeactivator.h"
|
#include "Game/control/volumeactivator.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
struct CollisionSetup;
|
struct CollisionSetup;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ namespace TEN::Control::Volumes
|
||||||
void TestVolumes(CAMERA_INFO* camera);
|
void TestVolumes(CAMERA_INFO* camera);
|
||||||
|
|
||||||
void HandleEvent(VolumeEvent& event, VolumeActivator& activator);
|
void HandleEvent(VolumeEvent& event, VolumeActivator& activator);
|
||||||
void InitialiseNodeScripts();
|
void InitializeNodeScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move into namespace and deal with errors.
|
// TODO: Move into namespace and deal with errors.
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace TEN::Control::Volumes
|
||||||
|
|
||||||
struct VolumeEventSet
|
struct VolumeEventSet
|
||||||
{
|
{
|
||||||
std::string Name = {};
|
std::string Name = {};
|
||||||
VolumeActivatorFlags Activators = VolumeActivatorFlags::None;
|
VolumeActivatorFlags Activators = VolumeActivatorFlags::None;
|
||||||
|
|
||||||
VolumeEvent OnEnter = {};
|
VolumeEvent OnEnter = {};
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
#include "Game/collision/collide_room.h"
|
#include "Game/collision/collide_room.h"
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
|
#include "Objects/Utils/object_helper.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
@ -17,6 +18,9 @@ namespace TEN::Effects::Blood
|
||||||
|
|
||||||
void SpawnUnderwaterBlood(const Vector3& pos, int roomNumber, float size)
|
void SpawnUnderwaterBlood(const Vector3& pos, int roomNumber, float size)
|
||||||
{
|
{
|
||||||
|
if (!CheckIfSlotExists(ID_DEFAULT_SPRITES, "Blood rendering"))
|
||||||
|
return;
|
||||||
|
|
||||||
constexpr auto LIFE_MAX = 8.5f;
|
constexpr auto LIFE_MAX = 8.5f;
|
||||||
constexpr auto LIFE_MIN = 8.0f;
|
constexpr auto LIFE_MIN = 8.0f;
|
||||||
constexpr auto SPAWN_RADIUS = BLOCK(0.25f);
|
constexpr auto SPAWN_RADIUS = BLOCK(0.25f);
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/people.h"
|
#include "Game/people.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#include "Game/effects/Ripple.h"
|
#include "Game/effects/Ripple.h"
|
||||||
|
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/objectslist.h"
|
#include "Objects/objectslist.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ namespace TEN::Effects::Streamer
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Members
|
// Members
|
||||||
std::map<int, std::vector<Streamer>> Pools = {}; // Key = tag.
|
std::unordered_map<int, std::vector<Streamer>> Pools = {}; // Key = tag.
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
void AddStreamer(int tag, const Vector3& pos, const Vector3& direction, short orient2D, const Vector4& color,
|
void AddStreamer(int tag, const Vector3& pos, const Vector3& direction, short orient2D, const Vector4& color,
|
||||||
|
@ -92,7 +92,7 @@ namespace TEN::Effects::Streamer
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Members
|
// Members
|
||||||
std::map<int, StreamerModule> Modules = {}; // Key = entity number.
|
std::unordered_map<int, StreamerModule> Modules = {}; // Key = entity number.
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
void Spawn(int entityID, int tag, const Vector3& pos, const Vector3& direction, short orient2D, const Vector4& color,
|
void Spawn(int entityID, int tag, const Vector3& pos, const Vector3& direction, short orient2D, const Vector4& color,
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
#include "Game/control/control.h"
|
#include "Game/control/control.h"
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/effects/Ripple.h"
|
#include "Game/effects/Ripple.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Objects/objectslist.h"
|
#include "Objects/objectslist.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Ripple;
|
using namespace TEN::Effects::Ripple;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
namespace TEN::Effects::Bubble
|
namespace TEN::Effects::Bubble
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
#include "Game/effects/tomb4fx.h"
|
#include "Game/effects/tomb4fx.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Renderer/Renderer11Enums.h"
|
#include "Renderer/Renderer11Enums.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
#include "Game/effects/debris.h"
|
#include "Game/effects/debris.h"
|
||||||
|
|
||||||
#include "Game/collision/collide_room.h"
|
#include "Game/collision/collide_room.h"
|
||||||
|
#include "Game/effects/tomb4fx.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Math/Random.h"
|
#include "Math/Random.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include <Game/effects/tomb4fx.h>
|
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
#include "Game/effects/Ripple.h"
|
#include "Game/effects/Ripple.h"
|
||||||
#include "Game/effects/weather.h"
|
#include "Game/effects/weather.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Environment;
|
using namespace TEN::Effects::Environment;
|
||||||
using namespace TEN::Effects::Ripple;
|
using namespace TEN::Effects::Ripple;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
namespace TEN::Effects::Drip
|
namespace TEN::Effects::Drip
|
||||||
|
|
|
@ -17,13 +17,13 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/objectslist.h"
|
#include "Objects/objectslist.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Blood;
|
using namespace TEN::Effects::Blood;
|
||||||
using namespace TEN::Effects::Bubble;
|
using namespace TEN::Effects::Bubble;
|
||||||
|
@ -52,7 +52,7 @@ int SplashCount = 0;
|
||||||
Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax];
|
Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax];
|
||||||
NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] =
|
NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] =
|
||||||
{
|
{
|
||||||
{ -16, 40, 160, -LM_LHAND, false }, // TR5 offset 0, TODO: This mesh is invalid as it can't be negative. -- TokyoSU 23.02.20
|
{ -16, 40, 160, 13, false }, // TR5 offset 0
|
||||||
{ -16, -8, 160, 0, false }, // TR5 offset 1
|
{ -16, -8, 160, 0, false }, // TR5 offset 1
|
||||||
{ 0, 0, 256, 8, false }, // TR5 offset 2
|
{ 0, 0, 256, 8, false }, // TR5 offset 2
|
||||||
{ 0, 0, 256, 17, false }, // TR5 offset 3
|
{ 0, 0, 256, 17, false }, // TR5 offset 3
|
||||||
|
@ -741,7 +741,7 @@ void TriggerExplosionBubbles(int x, int y, int z, short roomNumber)
|
||||||
spark->zVel = 0;
|
spark->zVel = 0;
|
||||||
spark->friction = 0;
|
spark->friction = 0;
|
||||||
spark->flags = SP_UNDERWEXP | SP_DEF | SP_SCALE;
|
spark->flags = SP_UNDERWEXP | SP_DEF | SP_SCALE;
|
||||||
spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + 13;
|
spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_BUBBLES;
|
||||||
spark->scalar = 3;
|
spark->scalar = 3;
|
||||||
spark->gravity = 0;
|
spark->gravity = 0;
|
||||||
spark->maxYvel = 0;
|
spark->maxYvel = 0;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/effects/spark.h"
|
#include "Game/effects/spark.h"
|
||||||
#include "Game/effects/tomb4fx.h"
|
#include "Game/effects/tomb4fx.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
|
|
@ -1,264 +1,222 @@
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
#include "Game/effects/footprint.h"
|
#include "Game/effects/Footprint.h"
|
||||||
|
|
||||||
#include "Game/animation.h"
|
#include "Game/animation.h"
|
||||||
#include "Game/collision/collide_room.h"
|
#include "Game/collision/collide_room.h"
|
||||||
|
#include "Game/collision/floordata.h"
|
||||||
#include "Game/control/control.h"
|
#include "Game/control/control.h"
|
||||||
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
|
#include "Objects/Utils/object_helper.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
|
|
||||||
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
namespace TEN::Effects::Footprints
|
namespace TEN::Effects::Footprint
|
||||||
{
|
{
|
||||||
std::deque<FOOTPRINT_STRUCT> footprints = std::deque<FOOTPRINT_STRUCT>();
|
const auto FootprintMaterials = std::vector<MaterialType>
|
||||||
|
|
||||||
bool CheckFootOnFloor(const ItemInfo& item, int mesh, Vector3& outFootprintPosition)
|
|
||||||
{
|
{
|
||||||
int x = item.Pose.Position.x;
|
MaterialType::Mud,
|
||||||
int y = item.Pose.Position.y;
|
MaterialType::Snow,
|
||||||
int z = item.Pose.Position.z;
|
MaterialType::Sand,
|
||||||
short roomNumber = item.RoomNumber;
|
MaterialType::Gravel,
|
||||||
|
MaterialType::Custom1,
|
||||||
|
MaterialType::Custom2,
|
||||||
|
MaterialType::Custom3,
|
||||||
|
MaterialType::Custom4
|
||||||
|
};
|
||||||
|
|
||||||
auto floor = GetFloor(x, y, z, &roomNumber);
|
struct FootprintPositionData
|
||||||
auto pos = GetJointPosition(LaraItem, mesh, Vector3i(0, FOOT_HEIGHT_OFFSET, 0));
|
{
|
||||||
int height = GetFloorHeight(floor, pos.x, pos.y - CLICK(1), pos.z);
|
bool CanSpawn = false;
|
||||||
|
Vector3 Position = Vector3::Zero;
|
||||||
|
};
|
||||||
|
|
||||||
outFootprintPosition.x = pos.x;
|
std::vector<Footprint> Footprints = {};
|
||||||
outFootprintPosition.y = height - 8;
|
|
||||||
outFootprintPosition.z = pos.z;
|
|
||||||
|
|
||||||
return abs(pos.y - height) < 64;
|
static SOUND_EFFECTS GetFootprintSfx(MaterialType material)
|
||||||
|
{
|
||||||
|
static const auto SOUND_MAP = std::unordered_map<MaterialType, SOUND_EFFECTS>
|
||||||
|
{
|
||||||
|
{ MaterialType::Mud, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_MUD },
|
||||||
|
{ MaterialType::Snow, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_SNOW },
|
||||||
|
{ MaterialType::Sand, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_SAND },
|
||||||
|
{ MaterialType::Gravel, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_GRAVEL },
|
||||||
|
{ MaterialType::Ice, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_ICE },
|
||||||
|
{ MaterialType::Water, SOUND_EFFECTS::SFX_TR4_LARA_WET_FEET },
|
||||||
|
{ MaterialType::Stone, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS },
|
||||||
|
{ MaterialType::Wood, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_WOOD },
|
||||||
|
{ MaterialType::Metal, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL },
|
||||||
|
{ MaterialType::Marble, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_MARBLE },
|
||||||
|
{ MaterialType::Grass, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_GRASS },
|
||||||
|
{ MaterialType::Concrete, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS },
|
||||||
|
{ MaterialType::OldWood, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_WOOD },
|
||||||
|
{ MaterialType::OldMetal, SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL },
|
||||||
|
{ MaterialType::Custom1, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_1 },
|
||||||
|
{ MaterialType::Custom2, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_2 },
|
||||||
|
{ MaterialType::Custom3, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_3 },
|
||||||
|
{ MaterialType::Custom4, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_4 },
|
||||||
|
{ MaterialType::Custom5, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_5 },
|
||||||
|
{ MaterialType::Custom6, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_6 },
|
||||||
|
{ MaterialType::Custom7, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_7 },
|
||||||
|
{ MaterialType::Custom8, SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_8 }
|
||||||
|
};
|
||||||
|
|
||||||
|
auto it = SOUND_MAP.find(material);
|
||||||
|
return ((it != SOUND_MAP.end()) ? it->second : SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFootprint(ItemInfo* item, bool rightFoot)
|
static std::array<Vector3, Footprint::VERTEX_COUNT> GetFootprintVertexPoints(const ItemInfo& item, const Vector3& pos, const Vector3& normal)
|
||||||
{
|
{
|
||||||
if (item != LaraItem)
|
constexpr auto SCALE = BLOCK(1 / 16.0f);
|
||||||
return;
|
constexpr auto POINT_0 = Vector3( SCALE, 0.0f, SCALE);
|
||||||
|
constexpr auto POINT_1 = Vector3(-SCALE, 0.0f, SCALE);
|
||||||
|
constexpr auto POINT_2 = Vector3(-SCALE, 0.0f, -SCALE);
|
||||||
|
constexpr auto POINT_3 = Vector3( SCALE, 0.0f, -SCALE);
|
||||||
|
|
||||||
auto foot = rightFoot ? LM_RFOOT : LM_LFOOT;
|
// Determine rotation matrix.
|
||||||
|
auto rotMatrix = Geometry::GetRelOrientToNormal(item.Pose.Orientation.y, normal).ToRotationMatrix();
|
||||||
|
|
||||||
// Don't process actual footprint placement if foot isn't on floor.
|
return std::array<Vector3, Footprint::VERTEX_COUNT>
|
||||||
auto footPos = Vector3();
|
|
||||||
if (!CheckFootOnFloor(*item, foot, footPos))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Slightly randomize foot position to avoid patterns.
|
|
||||||
footPos.x += (GetRandomControl() & 10) - 5;
|
|
||||||
footPos.z += (GetRandomControl() & 10) - 5;
|
|
||||||
|
|
||||||
auto result = GetCollision(footPos.x, footPos.y - STEP_SIZE, footPos.z, item->RoomNumber);
|
|
||||||
auto floor = result.BottomBlock;
|
|
||||||
|
|
||||||
// Don't process material if foot has hit bridge object.
|
|
||||||
if (result.Position.Bridge >= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS;
|
|
||||||
// Choose material for footstep sound
|
|
||||||
switch (floor->Material)
|
|
||||||
{
|
{
|
||||||
case MaterialType::Concrete:
|
pos + Vector3::Transform(POINT_0, rotMatrix),
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS;
|
pos + Vector3::Transform(POINT_1, rotMatrix),
|
||||||
break;
|
pos + Vector3::Transform(POINT_2, rotMatrix),
|
||||||
|
pos + Vector3::Transform(POINT_3, rotMatrix)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case MaterialType::Grass:
|
static FootprintPositionData GetFootprintPositionData(const ItemInfo& item, int jointIndex)
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_GRASS;
|
{
|
||||||
break;
|
constexpr auto SURFACE_OFFSET = 4;
|
||||||
|
constexpr auto ABS_FLOOR_BOUND = CLICK(0.25f);
|
||||||
|
constexpr auto HEIGHT_OFFSET = CLICK(0.25f);
|
||||||
|
constexpr auto FOOT_OFFSET = Vector3i(0, HEIGHT_OFFSET, 0);
|
||||||
|
|
||||||
case MaterialType::Gravel:
|
auto footPos = GetJointPosition(item, jointIndex, FOOT_OFFSET);
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_GRAVEL;
|
int floorHeight = GetCollision(footPos.x, footPos.y - CLICK(1), footPos.z, item.RoomNumber).Position.Floor;
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Ice:
|
bool canSpawn = (abs(footPos.y - floorHeight) < ABS_FLOOR_BOUND);
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_ICE;
|
auto pos = Vector3(footPos.x, floorHeight - SURFACE_OFFSET, footPos.z);
|
||||||
break;
|
return FootprintPositionData{ canSpawn, pos };
|
||||||
|
}
|
||||||
|
|
||||||
case MaterialType::Marble:
|
static bool TestFootprintFloor(const ItemInfo& item, const Vector3& pos, const std::array<Vector3, Footprint::VERTEX_COUNT>& vertexPoints)
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_MARBLE;
|
{
|
||||||
break;
|
constexpr auto ABS_FLOOR_BOUND = CLICK(0.5f);
|
||||||
|
|
||||||
case MaterialType::Metal:
|
// Get point collision at every vertex point.
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL;
|
auto pointColl0 = GetCollision(vertexPoints[0].x, pos.y - CLICK(1), vertexPoints[0].z, item.RoomNumber);
|
||||||
break;
|
auto pointColl1 = GetCollision(vertexPoints[1].x, pos.y - CLICK(1), vertexPoints[1].z, item.RoomNumber);
|
||||||
|
auto pointColl2 = GetCollision(vertexPoints[2].x, pos.y - CLICK(1), vertexPoints[2].z, item.RoomNumber);
|
||||||
|
auto pointColl3 = GetCollision(vertexPoints[3].x, pos.y - CLICK(1), vertexPoints[3].z, item.RoomNumber);
|
||||||
|
|
||||||
case MaterialType::Mud:
|
// Don't spawn footprint if floor heights at vertex points are outside upper/lower floor height bound.
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_MUD;
|
if ((abs(pointColl0.Position.Floor - pointColl1.Position.Floor) > ABS_FLOOR_BOUND) ||
|
||||||
break;
|
(abs(pointColl1.Position.Floor - pointColl2.Position.Floor) > ABS_FLOOR_BOUND) ||
|
||||||
|
(abs(pointColl2.Position.Floor - pointColl3.Position.Floor) > ABS_FLOOR_BOUND) ||
|
||||||
case MaterialType::OldMetal:
|
(abs(pointColl3.Position.Floor - pointColl0.Position.Floor) > ABS_FLOOR_BOUND))
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_METAL;
|
{
|
||||||
break;
|
return false;
|
||||||
|
|
||||||
case MaterialType::OldWood:
|
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_WOOD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Sand:
|
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_SAND;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Snow:
|
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_SNOW;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Stone:
|
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Water:
|
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_WET_FEET;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Wood:
|
|
||||||
fx = SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS_WOOD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom1:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom2:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom3:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_3;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom4:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom5:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_5;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom6:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_6;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom7:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_7;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MaterialType::Custom8:
|
|
||||||
fx = SOUND_EFFECTS::SFX_CUSTOM_FOOTSTEP_8;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Must be here until reference WAD2 is revised.
|
return true;
|
||||||
if (fx != SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS)
|
}
|
||||||
SoundEffect(fx, &item->Pose);
|
|
||||||
|
|
||||||
if (floor->Material != MaterialType::Sand &&
|
void SpawnFootprint(bool isRight, const std::array<Vector3, Footprint::VERTEX_COUNT>& vertexPoints)
|
||||||
floor->Material != MaterialType::Snow &&
|
{
|
||||||
floor->Material != MaterialType::Gravel &&
|
if (!CheckIfSlotExists(ID_MISC_SPRITES, "Footprint rendering"))
|
||||||
floor->Material != MaterialType::Mud &&
|
|
||||||
floor->Material != MaterialType::Custom2 &&
|
|
||||||
floor->Material != MaterialType::Custom1 &&
|
|
||||||
floor->Material != MaterialType::Custom3 &&
|
|
||||||
floor->Material != MaterialType::Custom4)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
constexpr auto LIFE_MAX = 20.0f;
|
||||||
|
constexpr auto LIFE_START_FADING = 10.0f;
|
||||||
|
constexpr auto OPACITY_MAX = 0.5f;
|
||||||
|
|
||||||
|
auto& footprint = GetNewEffect(Footprints, Footprint::COUNT_MAX);
|
||||||
|
|
||||||
|
footprint.SpriteIndex = Objects[ID_MISC_SPRITES].meshIndex + (1 + (int)isRight);
|
||||||
|
footprint.IsRight = isRight;
|
||||||
|
footprint.VertexPoints = vertexPoints;
|
||||||
|
footprint.Life = std::round(LIFE_MAX * FPS);
|
||||||
|
footprint.LifeStartFading = std::round(LIFE_START_FADING * FPS);
|
||||||
|
footprint.Opacity =
|
||||||
|
footprint.OpacityStart = OPACITY_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpawnFootprint(const ItemInfo& item, bool isRight)
|
||||||
|
{
|
||||||
|
if (!item.IsLara())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Don't spawn footprint if foot isn't on floor.
|
||||||
|
int jointIndex = isRight ? LM_RFOOT : LM_LFOOT;
|
||||||
|
auto posData = GetFootprintPositionData(item, jointIndex);
|
||||||
|
if (!posData.CanSpawn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Slightly randomize 2D position.
|
||||||
|
posData.Position += Vector3(Random::GenerateFloat(-5.0f, 5.0f), 0.0f, Random::GenerateFloat(-5.0f, 5.0f));
|
||||||
|
|
||||||
|
auto pointColl = GetCollision(posData.Position.x, posData.Position.y - CLICK(1), posData.Position.z, item.RoomNumber);
|
||||||
|
|
||||||
|
// Don't process material if foot hit bridge object.
|
||||||
|
// TODO: Handle bridges once bridge collision is less stupid.
|
||||||
|
if (pointColl.Position.Bridge >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get and emit footstep sound for floor material.
|
||||||
|
auto sfx = GetFootprintSfx(pointColl.BottomBlock->Material);
|
||||||
|
if (sfx != SOUND_EFFECTS::SFX_TR4_LARA_FOOTSTEPS) // HACK: Must be here until reference WAD2 is revised.
|
||||||
|
{
|
||||||
|
auto pose = item.Pose;
|
||||||
|
SoundEffect(sfx, &pose);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate footprint tilts.
|
// Check floor material.
|
||||||
auto plane = floor->FloorCollision.Planes[floor->GetSurfacePlaneIndex(footPos.x, footPos.z, true)];
|
if (!TestMaterial(pointColl.BottomBlock->Material, FootprintMaterials))
|
||||||
auto c = phd_cos(item->Pose.Orientation.y + ANGLE(180.0f));
|
|
||||||
auto s = phd_sin(item->Pose.Orientation.y + ANGLE(180.0f));
|
|
||||||
auto yRot = TO_RAD(item->Pose.Orientation.y);
|
|
||||||
auto xRot = plane.x * s + plane.y * c;
|
|
||||||
auto zRot = plane.y * s - plane.x * c;
|
|
||||||
|
|
||||||
// Calculate footprint positions.
|
|
||||||
auto p0 = Vector3( FOOTPRINT_SIZE, 0, FOOTPRINT_SIZE);
|
|
||||||
auto p1 = Vector3(-FOOTPRINT_SIZE, 0, FOOTPRINT_SIZE);
|
|
||||||
auto p2 = Vector3(-FOOTPRINT_SIZE, 0, -FOOTPRINT_SIZE);
|
|
||||||
auto p3 = Vector3( FOOTPRINT_SIZE, 0, -FOOTPRINT_SIZE);
|
|
||||||
auto rot = Matrix::CreateFromYawPitchRoll(yRot, xRot, zRot);
|
|
||||||
p0 = XMVector3Transform(p0, rot);
|
|
||||||
p1 = XMVector3Transform(p1, rot);
|
|
||||||
p2 = XMVector3Transform(p2, rot);
|
|
||||||
p3 = XMVector3Transform(p3, rot);
|
|
||||||
p0 += Vector3(footPos.x, footPos.y, footPos.z);
|
|
||||||
p1 += Vector3(footPos.x, footPos.y, footPos.z);
|
|
||||||
p2 += Vector3(footPos.x, footPos.y, footPos.z);
|
|
||||||
p3 += Vector3(footPos.x, footPos.y, footPos.z);
|
|
||||||
|
|
||||||
// Get blocks for every footprint corner
|
|
||||||
auto c0 = GetCollision(p0.x, footPos.y - STEP_SIZE, p0.z, item->RoomNumber);
|
|
||||||
auto c1 = GetCollision(p1.x, footPos.y - STEP_SIZE, p1.z, item->RoomNumber);
|
|
||||||
auto c2 = GetCollision(p2.x, footPos.y - STEP_SIZE, p2.z, item->RoomNumber);
|
|
||||||
auto c3 = GetCollision(p3.x, footPos.y - STEP_SIZE, p3.z, item->RoomNumber);
|
|
||||||
|
|
||||||
// Don't process footprint placement if all foot corners aren't on the same tilt level
|
|
||||||
if ((c0.FloorTilt.x != c1.FloorTilt.x) || (c1.FloorTilt.x != c2.FloorTilt.x) || (c2.FloorTilt.x != c3.FloorTilt.x))
|
|
||||||
return;
|
|
||||||
if ((c0.FloorTilt.y != c1.FloorTilt.y) || (c1.FloorTilt.y != c2.FloorTilt.y) || (c2.FloorTilt.y != c3.FloorTilt.y))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Don't process footprint placement if all foot corners aren't on the same height
|
auto vertexPoints = GetFootprintVertexPoints(item, posData.Position, GetSurfaceNormal(pointColl.FloorTilt, true));
|
||||||
if ((abs(c0.Position.Floor - c1.Position.Floor) > STEP_SIZE / 2) ||
|
|
||||||
(abs(c1.Position.Floor - c2.Position.Floor) > STEP_SIZE / 2) ||
|
// Test floor continuity.
|
||||||
(abs(c2.Position.Floor - c3.Position.Floor) > STEP_SIZE / 2) ||
|
if (!TestFootprintFloor(item, posData.Position, vertexPoints))
|
||||||
(abs(c3.Position.Floor - c0.Position.Floor) > STEP_SIZE / 2))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Construct footprint
|
SpawnFootprint(isRight, vertexPoints);
|
||||||
FOOTPRINT_STRUCT footprint = {};
|
|
||||||
footprint.Position[0] = p0;
|
|
||||||
footprint.Position[1] = p1;
|
|
||||||
footprint.Position[2] = p2;
|
|
||||||
footprint.Position[3] = p3;
|
|
||||||
footprint.StartOpacity = 0.5f;
|
|
||||||
footprint.LifeStartFading = FPS * 10;
|
|
||||||
footprint.Life = FPS * 20;
|
|
||||||
footprint.Active = true;
|
|
||||||
footprint.RightFoot = rightFoot;
|
|
||||||
|
|
||||||
// Add footprint
|
|
||||||
if (footprints.size() >= MAX_FOOTPRINTS)
|
|
||||||
footprints.pop_back();
|
|
||||||
footprints.push_front(footprint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateFootprints()
|
void UpdateFootprints()
|
||||||
{
|
{
|
||||||
if (footprints.size() == 0)
|
if (Footprints.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int numInvalidFootprints = 0;
|
for (auto& footprint: Footprints)
|
||||||
|
|
||||||
for (auto i = footprints.begin(); i != footprints.end(); i++)
|
|
||||||
{
|
{
|
||||||
FOOTPRINT_STRUCT& footprint = *i;
|
if (footprint.Life <= 0.0f)
|
||||||
footprint.Life--;
|
|
||||||
|
|
||||||
if (footprint.Life <= 0)
|
|
||||||
{
|
|
||||||
numInvalidFootprints++;
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Update opacity.
|
||||||
|
if (footprint.Life <= footprint.LifeStartFading)
|
||||||
|
{
|
||||||
|
float alpha = 1.0f - (footprint.Life / footprint.LifeStartFading);
|
||||||
|
footprint.Opacity = Lerp(footprint.OpacityStart, 0.0f, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (footprint.Life > footprint.LifeStartFading)
|
// Update life.
|
||||||
{
|
footprint.Life -= 1.0f;
|
||||||
footprint.Opacity = footprint.StartOpacity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float opacity = Lerp(0.0f, footprint.StartOpacity, fmax(0, fmin(1, footprint.Life / (float)footprint.LifeStartFading)));
|
|
||||||
footprint.Opacity = opacity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < numInvalidFootprints; i++)
|
ClearInactiveEffects(Footprints);
|
||||||
{
|
}
|
||||||
footprints.pop_back();
|
|
||||||
}
|
void ClearFootprints()
|
||||||
|
{
|
||||||
|
Footprints.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <deque>
|
|
||||||
#include "Math/Math.h"
|
|
||||||
|
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
|
||||||
namespace TEN::Effects::Footprints
|
namespace TEN::Effects::Footprint
|
||||||
{
|
{
|
||||||
constexpr size_t MAX_FOOTPRINTS = 20;
|
struct Footprint
|
||||||
constexpr auto FOOTPRINT_SIZE = 64.0f;
|
|
||||||
constexpr int FOOT_HEIGHT_OFFSET = 64;
|
|
||||||
|
|
||||||
struct FOOTPRINT_STRUCT
|
|
||||||
{
|
{
|
||||||
Vector3 Position[4];
|
static constexpr auto COUNT_MAX = 64;
|
||||||
bool RightFoot;
|
static constexpr auto VERTEX_COUNT = 4;
|
||||||
int Life;
|
|
||||||
int LifeStartFading;
|
unsigned int SpriteIndex = 0;
|
||||||
float StartOpacity;
|
bool IsRight = false;
|
||||||
float Opacity;
|
|
||||||
bool Active;
|
float Life = 0.0f;
|
||||||
};
|
float LifeStartFading = 0.0f;
|
||||||
extern std::deque<FOOTPRINT_STRUCT> footprints;
|
float Opacity = 0.0f;
|
||||||
|
float OpacityStart = 0.0f;
|
||||||
|
|
||||||
|
std::array<Vector3, VERTEX_COUNT> VertexPoints = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::vector<Footprint> Footprints;
|
||||||
|
|
||||||
|
void SpawnFootprint(bool isRight, const std::array<Vector3, Footprint::VERTEX_COUNT>& vertexPoints);
|
||||||
|
void SpawnFootprint(const ItemInfo& item, bool isRight);
|
||||||
|
|
||||||
bool CheckFootOnFloor(const ItemInfo& item, int mesh, Vector3& outFootprintPosition);
|
|
||||||
void AddFootprint(ItemInfo* item, bool rightFoot);
|
|
||||||
void UpdateFootprints();
|
void UpdateFootprints();
|
||||||
|
void ClearFootprints();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Environment;
|
using namespace TEN::Effects::Environment;
|
||||||
using TEN::Renderer::g_Renderer;
|
using TEN::Renderer::g_Renderer;
|
||||||
|
@ -81,7 +81,7 @@ namespace TEN::Effects::Hair
|
||||||
// TR3 UPV uses a hack which forces player water status to dry.
|
// TR3 UPV uses a hack which forces player water status to dry.
|
||||||
// Therefore, cannot directly use water status value to determine enrironment.
|
// Therefore, cannot directly use water status value to determine enrironment.
|
||||||
bool isOnLand = (player.Control.WaterStatus == WaterStatus::Dry &&
|
bool isOnLand = (player.Control.WaterStatus == WaterStatus::Dry &&
|
||||||
(player.Vehicle == -1 || g_Level.Items[player.Vehicle].ObjectNumber != ID_UPV));
|
(player.Context.Vehicle == -1 || g_Level.Items[player.Context.Vehicle].ObjectNumber != ID_UPV));
|
||||||
|
|
||||||
// Handle segment room collision.
|
// Handle segment room collision.
|
||||||
CollideSegmentWithRoom(segment, waterHeight, roomNumber, isOnLand);
|
CollideSegmentWithRoom(segment, waterHeight, roomNumber, isOnLand);
|
||||||
|
@ -161,7 +161,7 @@ namespace TEN::Effects::Hair
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int frameBaseIndex = GetAnimData(animNumber).FramePtr;
|
int frameBaseIndex = GetAnimData(item.ObjectNumber, animNumber).FramePtr;
|
||||||
const auto& frame = g_Level.Frames[frameBaseIndex + player.HitFrame];
|
const auto& frame = g_Level.Frames[frameBaseIndex + player.HitFrame];
|
||||||
return frame.BoundingBox.GetCenter();
|
return frame.BoundingBox.GetCenter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,17 +95,17 @@ namespace TEN::Effects::Items
|
||||||
switch (item->Animation.AnimNumber)
|
switch (item->Animation.AnimNumber)
|
||||||
{
|
{
|
||||||
case LA_STAND_IDLE:
|
case LA_STAND_IDLE:
|
||||||
if (item->Animation.FrameNumber < GetFrameNumber(ID_LARA, LA_STAND_IDLE, 30))
|
if (item->Animation.FrameNumber < GetFrameIndex(ID_LARA, LA_STAND_IDLE, 30))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_CROUCH_IDLE:
|
case LA_CROUCH_IDLE:
|
||||||
if (item->Animation.FrameNumber < GetFrameNumber(ID_LARA, LA_CROUCH_IDLE, 30))
|
if (item->Animation.FrameNumber < GetFrameIndex(ID_LARA, LA_CROUCH_IDLE, 30))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LA_CRAWL_IDLE:
|
case LA_CRAWL_IDLE:
|
||||||
if (item->Animation.FrameNumber < GetFrameNumber(ID_LARA, LA_CRAWL_IDLE, 30))
|
if (item->Animation.FrameNumber < GetFrameIndex(ID_LARA, LA_CRAWL_IDLE, 30))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#include "Game/effects/simple_particle.h"
|
#include "Game/effects/simple_particle.h"
|
||||||
|
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Environment;
|
using namespace TEN::Effects::Environment;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
@ -113,19 +113,24 @@ namespace TEN::Effects::Smoke
|
||||||
//TODO: add additional "Weapon Special" param or something. Currently initial == 2 means Rocket Launcher backwards smoke.
|
//TODO: add additional "Weapon Special" param or something. Currently initial == 2 means Rocket Launcher backwards smoke.
|
||||||
//TODO: Refactor different weapon types out of it
|
//TODO: Refactor different weapon types out of it
|
||||||
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count)
|
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count)
|
||||||
|
{
|
||||||
|
SpawnGunSmokeParticles(Vector3(x, y, z), Vector3(xv, yv, zv), LaraItem->RoomNumber, initial, weaponType, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpawnGunSmokeParticles(const Vector3& pos, const Vector3& direction, int roomNumber, byte initial, LaraWeaponType weaponType, int count)
|
||||||
{
|
{
|
||||||
auto& s = GetFreeSmokeParticle();
|
auto& s = GetFreeSmokeParticle();
|
||||||
s = {};
|
s = {};
|
||||||
s.active = true;
|
s.active = true;
|
||||||
s.position = Vector3(x, y, z);
|
s.position = pos;
|
||||||
|
|
||||||
Vector3 direction = Vector3(xv, yv, zv);
|
auto directionNorm = direction;
|
||||||
direction.Normalize();
|
directionNorm.Normalize();
|
||||||
|
|
||||||
s.velocity = direction;
|
s.velocity = directionNorm;
|
||||||
s.gravity = -.1f;
|
s.gravity = -.1f;
|
||||||
s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, LaraItem);
|
s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, pos.x, pos.y, pos.z, roomNumber);
|
||||||
s.sourceColor = Vector4(.4f, .4f, .4f, 1);
|
s.sourceColor = Vector4(0.4f, 0.4f, 0.4f, 1);
|
||||||
s.destinationColor = Vector4(0, 0, 0, 0);
|
s.destinationColor = Vector4(0, 0, 0, 0);
|
||||||
|
|
||||||
if (initial)
|
if (initial)
|
||||||
|
@ -135,7 +140,7 @@ namespace TEN::Effects::Smoke
|
||||||
float size = Random::GenerateFloat(48, 80);
|
float size = Random::GenerateFloat(48, 80);
|
||||||
s.sourceSize = size * 2;
|
s.sourceSize = size * 2;
|
||||||
s.destinationSize = size * 8;
|
s.destinationSize = size * 8;
|
||||||
s.sourceColor = {0.75,0.75,1,1};
|
s.sourceColor = { 0.75, 0.75, 1, 1 };
|
||||||
s.terminalVelocity = 0;
|
s.terminalVelocity = 0;
|
||||||
s.friction = 0.82f;
|
s.friction = 0.82f;
|
||||||
s.life = Random::GenerateFloat(60, 90);
|
s.life = Random::GenerateFloat(60, 90);
|
||||||
|
@ -145,7 +150,7 @@ namespace TEN::Effects::Smoke
|
||||||
float size = Random::GenerateFloat(48, 80);
|
float size = Random::GenerateFloat(48, 80);
|
||||||
s.sourceSize = size * 2;
|
s.sourceSize = size * 2;
|
||||||
s.destinationSize = size * 16;
|
s.destinationSize = size * 16;
|
||||||
s.velocity = Random::GenerateDirectionInCone(direction, 25);
|
s.velocity = Random::GenerateDirectionInCone(directionNorm, 25);
|
||||||
s.velocity *= Random::GenerateFloat(0, 32);
|
s.velocity *= Random::GenerateFloat(0, 32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -153,7 +158,7 @@ namespace TEN::Effects::Smoke
|
||||||
float size = Random::GenerateFloat(48, 80);
|
float size = Random::GenerateFloat(48, 80);
|
||||||
s.sourceSize = size;
|
s.sourceSize = size;
|
||||||
s.destinationSize = size * 8;
|
s.destinationSize = size * 8;
|
||||||
s.velocity = Random::GenerateDirectionInCone(direction, 3);
|
s.velocity = Random::GenerateDirectionInCone(directionNorm, 3);
|
||||||
s.velocity *= Random::GenerateFloat(0, 16);
|
s.velocity *= Random::GenerateFloat(0, 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +170,7 @@ namespace TEN::Effects::Smoke
|
||||||
s.terminalVelocity = 0;
|
s.terminalVelocity = 0;
|
||||||
s.friction = 0.88f;
|
s.friction = 0.88f;
|
||||||
s.life = Random::GenerateFloat(60, 90);
|
s.life = Random::GenerateFloat(60, 90);
|
||||||
s.velocity = Random::GenerateDirectionInCone(direction, 10);
|
s.velocity = Random::GenerateDirectionInCone(directionNorm, 10);
|
||||||
s.velocity *= Random::GenerateFloat(16, 30);
|
s.velocity *= Random::GenerateFloat(16, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,11 +189,11 @@ namespace TEN::Effects::Smoke
|
||||||
s.velocity *= Random::GenerateFloat(16, 40);
|
s.velocity *= Random::GenerateFloat(16, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
s.position = Vector3(x, y, z);
|
s.position = pos;
|
||||||
s.position += Vector3(Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8));
|
s.position += Vector3(Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8));
|
||||||
s.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4);
|
s.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4);
|
||||||
s.angularDrag = 0.95f;
|
s.angularDrag = 0.95f;
|
||||||
s.room = LaraItem->RoomNumber;
|
s.room = roomNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving)
|
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving)
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace TEN::Effects::Smoke
|
||||||
void DisableSmokeParticles();
|
void DisableSmokeParticles();
|
||||||
void TriggerFlareSmoke(const Vector3& pos, const Vector3& direction, int life, int room);
|
void TriggerFlareSmoke(const Vector3& pos, const Vector3& direction, int life, int room);
|
||||||
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count);
|
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count);
|
||||||
|
void SpawnGunSmokeParticles(const Vector3& pos, const Vector3& direction, int roomNumber, byte initial, LaraWeaponType weaponType, int count);
|
||||||
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving);
|
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving);
|
||||||
void TriggerRocketSmoke(int x, int y, int z);
|
void TriggerRocketSmoke(int x, int y, int z);
|
||||||
void TriggerBreathSmoke(long x, long y, long z, short angle);
|
void TriggerBreathSmoke(long x, long y, long z, short angle);
|
||||||
|
|
|
@ -15,18 +15,18 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Bubble;
|
using namespace TEN::Effects::Bubble;
|
||||||
using namespace TEN::Effects::Drip;
|
using namespace TEN::Effects::Drip;
|
||||||
using namespace TEN::Effects::Environment;
|
using namespace TEN::Effects::Environment;
|
||||||
using namespace TEN::Effects::Ripple;
|
using namespace TEN::Effects::Ripple;
|
||||||
using namespace TEN::Effects::Smoke;
|
using namespace TEN::Effects::Smoke;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
using TEN::Renderer::g_Renderer;
|
using TEN::Renderer::g_Renderer;
|
||||||
|
|
||||||
|
@ -203,14 +203,17 @@ void TriggerGlobalFireFlame()
|
||||||
spark->dSize = spark->size;
|
spark->dSize = spark->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriggerPilotFlame(int itemNum, int nodeIndex)
|
void TriggerPilotFlame(int itemNumber, int nodeIndex)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNum];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
|
|
||||||
int dx = Camera.pos.x - item->Pose.Position.x;
|
int dx = Camera.pos.x - item->Pose.Position.x;
|
||||||
int dz = Camera.pos.z - item->Pose.Position.z;
|
int dz = Camera.pos.z - item->Pose.Position.z;
|
||||||
if (dx < -SECTOR(16) || dx > SECTOR(16) || dz < -SECTOR(16) || dz > SECTOR(16))
|
if (dx < -BLOCK(16) || dx > BLOCK(16) ||
|
||||||
|
dz < -BLOCK(16) || dz > BLOCK(16))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto* spark = GetFreeParticle();
|
auto* spark = GetFreeParticle();
|
||||||
|
|
||||||
|
@ -229,7 +232,7 @@ void TriggerPilotFlame(int itemNum, int nodeIndex)
|
||||||
spark->blendMode = BLEND_MODES::BLENDMODE_ADDITIVE;
|
spark->blendMode = BLEND_MODES::BLENDMODE_ADDITIVE;
|
||||||
spark->extras = 0;
|
spark->extras = 0;
|
||||||
spark->dynamic = -1;
|
spark->dynamic = -1;
|
||||||
spark->fxObj = itemNum;
|
spark->fxObj = itemNumber;
|
||||||
|
|
||||||
spark->x = (GetRandomControl() & 31) - 16;
|
spark->x = (GetRandomControl() & 31) - 16;
|
||||||
spark->y = (GetRandomControl() & 31) - 16;
|
spark->y = (GetRandomControl() & 31) - 16;
|
||||||
|
@ -291,7 +294,7 @@ Particle* SetupFireSpark()
|
||||||
return spark;
|
return spark;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector3i offset, Vector3i speed)
|
void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector3i offset, Vector3i vel)
|
||||||
{
|
{
|
||||||
auto pos1 = GetJointPosition(item, meshIndex, Vector3i(-4, -30, -4) + offset);
|
auto pos1 = GetJointPosition(item, meshIndex, Vector3i(-4, -30, -4) + offset);
|
||||||
|
|
||||||
|
@ -299,7 +302,7 @@ void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector
|
||||||
spark->y = (GetRandomControl() & 0x1F) + pos1.y - 16;
|
spark->y = (GetRandomControl() & 0x1F) + pos1.y - 16;
|
||||||
spark->z = (GetRandomControl() & 0x1F) + pos1.z - 16;
|
spark->z = (GetRandomControl() & 0x1F) + pos1.z - 16;
|
||||||
|
|
||||||
auto pos2 = GetJointPosition(item, meshIndex, Vector3i(-4, -30, -4) + offset + speed);
|
auto pos2 = GetJointPosition(item, meshIndex, Vector3i(-4, -30, -4) + offset + vel);
|
||||||
|
|
||||||
int v = (GetRandomControl() & 0x3F) + 192;
|
int v = (GetRandomControl() & 0x3F) + 192;
|
||||||
|
|
||||||
|
@ -322,32 +325,41 @@ void AttachAndCreateSpark(Particle* spark, ItemInfo* item, int meshIndex, Vector
|
||||||
spark->on = 1;
|
spark->on = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed)
|
void ThrowFire(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNum];
|
auto& item = g_Level.Items[itemNumber];
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
auto* spark = SetupFireSpark();
|
auto& spark = *SetupFireSpark();
|
||||||
AttachAndCreateSpark(spark, item, meshIndex, offset, speed);
|
AttachAndCreateSpark(&spark, &item, meshIndex, offset, vel);
|
||||||
|
|
||||||
spark->flags = SP_FIRE | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
|
spark.flags = SP_FIRE | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color)
|
void ThrowFire(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNum];
|
ThrowFire(itemNumber, bite.BoneID, bite.Position, vel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThrowPoison(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel, const Vector3& color)
|
||||||
|
{
|
||||||
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
auto* spark = SetupPoisonSpark(color);
|
auto* spark = SetupPoisonSpark(color);
|
||||||
AttachAndCreateSpark(spark, item, meshIndex, offset, speed);
|
AttachAndCreateSpark(spark, item, meshIndex, offset, vel);
|
||||||
|
|
||||||
spark->flags = SP_POISON | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
|
spark->flags = SP_POISON | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ThrowPoison(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, const Vector3& color)
|
||||||
|
{
|
||||||
|
ThrowPoison(itemNumber, bite.BoneID, bite.Position, vel, color);
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateFireProgress()
|
void UpdateFireProgress()
|
||||||
{
|
{
|
||||||
TriggerGlobalStaticFlame();
|
TriggerGlobalStaticFlame();
|
||||||
|
@ -1072,7 +1084,7 @@ void SomeSparkEffect(int x, int y, int z, int count)
|
||||||
{
|
{
|
||||||
auto* spark = GetFreeParticle();
|
auto* spark = GetFreeParticle();
|
||||||
|
|
||||||
spark->on = 1;
|
spark->on = true;
|
||||||
spark->sR = 112;
|
spark->sR = 112;
|
||||||
spark->sG = (GetRandomControl() & 0x1F) + -128;
|
spark->sG = (GetRandomControl() & 0x1F) + -128;
|
||||||
spark->sB = (GetRandomControl() & 0x1F) + -128;
|
spark->sB = (GetRandomControl() & 0x1F) + -128;
|
||||||
|
@ -1109,9 +1121,9 @@ void TriggerUnderwaterExplosion(ItemInfo* item, int flag)
|
||||||
TriggerExplosionBubbles(x, y, z, item->RoomNumber);
|
TriggerExplosionBubbles(x, y, z, item->RoomNumber);
|
||||||
TriggerExplosionSparks(x, y, z, 2, -1, 1, item->RoomNumber);
|
TriggerExplosionSparks(x, y, z, 2, -1, 1, item->RoomNumber);
|
||||||
|
|
||||||
int wh = GetWaterHeight(x, y, z, item->RoomNumber);
|
int waterHeight = GetWaterHeight(x, y, z, item->RoomNumber);
|
||||||
if (wh != NO_HEIGHT)
|
if (waterHeight != NO_HEIGHT)
|
||||||
SomeSparkEffect(x, wh, z, 8);
|
SomeSparkEffect(x, waterHeight, z, 8);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1156,8 +1168,8 @@ void ExplodeVehicle(ItemInfo* laraItem, ItemInfo* vehicle)
|
||||||
|
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
auto* lara = GetLaraInfo(laraItem);
|
||||||
|
|
||||||
ExplodingDeath(lara->Vehicle, BODY_EXPLODE | BODY_STONE_SOUND);
|
ExplodingDeath(lara->Context.Vehicle, BODY_EXPLODE | BODY_STONE_SOUND);
|
||||||
KillItem(lara->Vehicle);
|
KillItem(lara->Context.Vehicle);
|
||||||
vehicle->Status = ITEM_DEACTIVATED;
|
vehicle->Status = ITEM_DEACTIVATED;
|
||||||
SoundEffect(SFX_TR4_EXPLOSION1, &laraItem->Pose);
|
SoundEffect(SFX_TR4_EXPLOSION1, &laraItem->Pose);
|
||||||
SoundEffect(SFX_TR4_EXPLOSION2, &laraItem->Pose);
|
SoundEffect(SFX_TR4_EXPLOSION2, &laraItem->Pose);
|
||||||
|
@ -1424,7 +1436,7 @@ void TriggerExplosionBubble(int x, int y, int z, short roomNumber)
|
||||||
spark->flags = 2058;
|
spark->flags = 2058;
|
||||||
spark->scalar = 3;
|
spark->scalar = 3;
|
||||||
spark->gravity = 0;
|
spark->gravity = 0;
|
||||||
spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + 13;
|
spark->spriteIndex = Objects[ID_DEFAULT_SPRITES].meshIndex + SPR_BUBBLES;
|
||||||
spark->maxYvel = 0;
|
spark->maxYvel = 0;
|
||||||
int size = (GetRandomControl() & 7) + 63;
|
int size = (GetRandomControl() & 7) + 63;
|
||||||
spark->sSize = size >> 1;
|
spark->sSize = size >> 1;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Renderer/Renderer11Enums.h"
|
#include "Renderer/Renderer11Enums.h"
|
||||||
|
|
||||||
enum class LaraWeaponType;
|
enum class LaraWeaponType;
|
||||||
|
struct CreatureBiteInfo;
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
|
||||||
enum BodyPartFlags
|
enum BodyPartFlags
|
||||||
|
@ -232,9 +233,11 @@ int GetFreeFireSpark();
|
||||||
void TriggerGlobalStaticFlame();
|
void TriggerGlobalStaticFlame();
|
||||||
void TriggerGlobalFireSmoke();
|
void TriggerGlobalFireSmoke();
|
||||||
void TriggerGlobalFireFlame();
|
void TriggerGlobalFireFlame();
|
||||||
void TriggerPilotFlame(int itemNum, int nodeIndex);
|
void TriggerPilotFlame(int itemNumber, int nodeIndex);
|
||||||
void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed);
|
void ThrowFire(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel);
|
||||||
void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color);
|
void ThrowFire(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel);
|
||||||
|
void ThrowPoison(int itemNumber, int meshIndex, const Vector3i& offset, const Vector3i& vel, const Vector3& color);
|
||||||
|
void ThrowPoison(int itemNumber, const CreatureBiteInfo& bite, const Vector3i& vel, const Vector3& color);
|
||||||
void UpdateFireProgress();
|
void UpdateFireProgress();
|
||||||
void ClearFires();
|
void ClearFires();
|
||||||
void AddFire(int x, int y, int z, short roomNum, float size, short fade);
|
void AddFire(int x, int y, int z, short roomNum, float size, short fade);
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
#include "Game/effects/Ripple.h"
|
#include "Game/effects/Ripple.h"
|
||||||
#include "Game/effects/tomb4fx.h"
|
#include "Game/effects/tomb4fx.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Random.h"
|
#include "Math/Random.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "ScriptInterfaceLevel.h"
|
#include "ScriptInterfaceLevel.h"
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace TEN::Gui
|
||||||
constexpr int LINE_HEIGHT = 25;
|
constexpr int LINE_HEIGHT = 25;
|
||||||
constexpr int PHD_CENTER_X = SCREEN_SPACE_RES.x / 2;
|
constexpr int PHD_CENTER_X = SCREEN_SPACE_RES.x / 2;
|
||||||
constexpr int PHD_CENTER_Y = SCREEN_SPACE_RES.y / 2;
|
constexpr int PHD_CENTER_Y = SCREEN_SPACE_RES.y / 2;
|
||||||
|
constexpr int OBJLIST_SPACING = PHD_CENTER_X / 2;
|
||||||
|
|
||||||
constexpr int VOLUME_MAX = 100;
|
constexpr int VOLUME_MAX = 100;
|
||||||
|
|
||||||
|
@ -86,6 +87,9 @@ namespace TEN::Gui
|
||||||
|
|
||||||
bool GuiController::GuiIsPulsed(ActionID actionID) const
|
bool GuiController::GuiIsPulsed(ActionID actionID) const
|
||||||
{
|
{
|
||||||
|
constexpr auto DELAY = 0.1f;
|
||||||
|
constexpr auto INITIAL_DELAY = 0.4f;
|
||||||
|
|
||||||
auto oppositeAction = In::None;
|
auto oppositeAction = In::None;
|
||||||
switch (actionID)
|
switch (actionID)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +111,7 @@ namespace TEN::Gui
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isActionLocked = (oppositeAction == In::None) ? false : IsHeld(oppositeAction);
|
bool isActionLocked = (oppositeAction == In::None) ? false : IsHeld(oppositeAction);
|
||||||
return (IsPulsed(actionID, 0.1f, 0.4f) && !isActionLocked);
|
return (IsPulsed(actionID, DELAY, INITIAL_DELAY) && !isActionLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GuiController::GuiIsSelected() const
|
bool GuiController::GuiIsSelected() const
|
||||||
|
@ -122,16 +126,13 @@ namespace TEN::Gui
|
||||||
|
|
||||||
bool GuiController::CanSelect() const
|
bool GuiController::CanSelect() const
|
||||||
{
|
{
|
||||||
|
// Holding Deselect safely cancels input.
|
||||||
if (IsHeld(In::Deselect))
|
if (IsHeld(In::Deselect))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Deselect) &&
|
// Avoid Action release interference when entering inventory.
|
||||||
GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Save) &&
|
if (GetActionTimeActive(In::Action) < TimeInMenu)
|
||||||
GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Load) &&
|
|
||||||
GetActionTimeActive(In::Action) <= GetActionTimeInactive(In::Pause))
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +179,11 @@ namespace TEN::Gui
|
||||||
|
|
||||||
void GuiController::SetInventoryMode(InventoryMode mode)
|
void GuiController::SetInventoryMode(InventoryMode mode)
|
||||||
{
|
{
|
||||||
InvMode = mode;
|
if (mode != InvMode)
|
||||||
|
{
|
||||||
|
TimeInMenu = 0.0f;
|
||||||
|
InvMode = mode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiController::SetInventoryItemChosen(int number)
|
void GuiController::SetInventoryItemChosen(int number)
|
||||||
|
@ -228,6 +233,8 @@ namespace TEN::Gui
|
||||||
static int selectedOptionBackup;
|
static int selectedOptionBackup;
|
||||||
auto inventoryResult = InventoryResult::None;
|
auto inventoryResult = InventoryResult::None;
|
||||||
|
|
||||||
|
TimeInMenu++;
|
||||||
|
|
||||||
// Stuff for credits goes here!
|
// Stuff for credits goes here!
|
||||||
|
|
||||||
switch (MenuToDisplay)
|
switch (MenuToDisplay)
|
||||||
|
@ -281,8 +288,8 @@ namespace TEN::Gui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (MenuToDisplay == Menu::Title ||
|
else if (MenuToDisplay == Menu::Title ||
|
||||||
MenuToDisplay == Menu::SelectLevel ||
|
MenuToDisplay == Menu::SelectLevel ||
|
||||||
MenuToDisplay == Menu::Options)
|
MenuToDisplay == Menu::Options)
|
||||||
{
|
{
|
||||||
if (GuiIsPulsed(In::Forward))
|
if (GuiIsPulsed(In::Forward))
|
||||||
{
|
{
|
||||||
|
@ -540,7 +547,7 @@ namespace TEN::Gui
|
||||||
|
|
||||||
void GuiController::HandleControlSettingsInput(ItemInfo* item, bool fromPauseMenu)
|
void GuiController::HandleControlSettingsInput(ItemInfo* item, bool fromPauseMenu)
|
||||||
{
|
{
|
||||||
static const int numControlSettingsOptions = KEY_COUNT + 1;
|
static const int numControlSettingsOptions = KEY_COUNT + 2;
|
||||||
|
|
||||||
OptionCount = numControlSettingsOptions;
|
OptionCount = numControlSettingsOptions;
|
||||||
CurrentSettings.WaitingForKey = false;
|
CurrentSettings.WaitingForKey = false;
|
||||||
|
@ -554,7 +561,7 @@ namespace TEN::Gui
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GuiIsSelected() &&
|
if (GuiIsSelected() &&
|
||||||
SelectedOption <= (numControlSettingsOptions - 2))
|
SelectedOption <= (numControlSettingsOptions - 3))
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||||
CurrentSettings.WaitingForKey = true;
|
CurrentSettings.WaitingForKey = true;
|
||||||
|
@ -635,6 +642,14 @@ namespace TEN::Gui
|
||||||
|
|
||||||
if (GuiIsSelected())
|
if (GuiIsSelected())
|
||||||
{
|
{
|
||||||
|
// Defaults.
|
||||||
|
if (SelectedOption == (OptionCount - 2))
|
||||||
|
{
|
||||||
|
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||||
|
ApplyDefaultBindings();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply.
|
// Apply.
|
||||||
if (SelectedOption == (OptionCount - 1))
|
if (SelectedOption == (OptionCount - 1))
|
||||||
{
|
{
|
||||||
|
@ -888,6 +903,7 @@ namespace TEN::Gui
|
||||||
static const int numStatisticsOptions = 0;
|
static const int numStatisticsOptions = 0;
|
||||||
static const int numOptionsOptions = 2;
|
static const int numOptionsOptions = 2;
|
||||||
|
|
||||||
|
TimeInMenu++;
|
||||||
UpdateInputActions(item);
|
UpdateInputActions(item);
|
||||||
|
|
||||||
switch (MenuToDisplay)
|
switch (MenuToDisplay)
|
||||||
|
@ -946,7 +962,7 @@ namespace TEN::Gui
|
||||||
{
|
{
|
||||||
if (MenuToDisplay == Menu::Pause)
|
if (MenuToDisplay == Menu::Pause)
|
||||||
{
|
{
|
||||||
InvMode = InventoryMode::None;
|
SetInventoryMode(InventoryMode::None);
|
||||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||||
return InventoryResult::None;
|
return InventoryResult::None;
|
||||||
}
|
}
|
||||||
|
@ -979,7 +995,7 @@ namespace TEN::Gui
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PauseMenuOption::ExitToTitle:
|
case PauseMenuOption::ExitToTitle:
|
||||||
InvMode = InventoryMode::None;
|
SetInventoryMode(InventoryMode::None);
|
||||||
return InventoryResult::ExitToTitle;
|
return InventoryResult::ExitToTitle;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1593,7 +1609,7 @@ namespace TEN::Gui
|
||||||
Rings[(int)RingTypes::Ammo]->RingActive = false;
|
Rings[(int)RingTypes::Ammo]->RingActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiController::InitialiseInventory(ItemInfo* item)
|
void GuiController::InitializeInventory(ItemInfo* item)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
|
@ -1603,14 +1619,22 @@ namespace TEN::Gui
|
||||||
UseItem = false;
|
UseItem = false;
|
||||||
|
|
||||||
if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite())
|
if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].HasInfinite())
|
||||||
|
{
|
||||||
Ammo.AmountShotGunAmmo1 = -1;
|
Ammo.AmountShotGunAmmo1 = -1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].GetCount() / 6;
|
Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[0].GetCount() / 6;
|
||||||
|
}
|
||||||
|
|
||||||
if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].HasInfinite())
|
if (lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].HasInfinite())
|
||||||
|
{
|
||||||
Ammo.AmountShotGunAmmo2 = -1;
|
Ammo.AmountShotGunAmmo2 = -1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].GetCount() / 6;
|
Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[1].GetCount() / 6;
|
||||||
|
}
|
||||||
|
|
||||||
Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount();
|
Ammo.AmountShotGunAmmo1 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo1].GetCount();
|
||||||
Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].GetCount();
|
Ammo.AmountShotGunAmmo2 = lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].HasInfinite() ? -1 : lara->Weapons[(int)LaraWeaponType::Shotgun].Ammo[(int)WeaponAmmoType::Ammo2].GetCount();
|
||||||
|
@ -1633,7 +1657,9 @@ namespace TEN::Gui
|
||||||
if (LastInvItem != NO_ITEM)
|
if (LastInvItem != NO_ITEM)
|
||||||
{
|
{
|
||||||
if (IsItemInInventory(LastInvItem))
|
if (IsItemInInventory(LastInvItem))
|
||||||
|
{
|
||||||
SetupObjectListStartPosition(LastInvItem);
|
SetupObjectListStartPosition(LastInvItem);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (LastInvItem >= INV_OBJECT_SMALL_WATERSKIN_EMPTY && LastInvItem <= INV_OBJECT_SMALL_WATERSKIN_3L)
|
if (LastInvItem >= INV_OBJECT_SMALL_WATERSKIN_EMPTY && LastInvItem <= INV_OBJECT_SMALL_WATERSKIN_3L)
|
||||||
|
@ -1820,7 +1846,7 @@ namespace TEN::Gui
|
||||||
ClearAllActions();
|
ClearAllActions();
|
||||||
ActionMap[(int)In::Flare].Update(1.0f);
|
ActionMap[(int)In::Flare].Update(1.0f);
|
||||||
|
|
||||||
HandleWeapon(item);
|
HandleWeapon(*item);
|
||||||
ClearAllActions();
|
ClearAllActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2310,20 +2336,20 @@ namespace TEN::Gui
|
||||||
|
|
||||||
case MenuType::Load:
|
case MenuType::Load:
|
||||||
// fill_up_savegames_array // Maybe not?
|
// fill_up_savegames_array // Maybe not?
|
||||||
InvMode = InventoryMode::Load;
|
SetInventoryMode(InventoryMode::Load);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuType::Save:
|
case MenuType::Save:
|
||||||
// fill_up_savegames_array
|
// fill_up_savegames_array
|
||||||
InvMode = InventoryMode::Save;
|
SetInventoryMode(InventoryMode::Save);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuType::Examine:
|
case MenuType::Examine:
|
||||||
InvMode = InventoryMode::Examine;
|
SetInventoryMode(InventoryMode::Examine);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuType::Statistics:
|
case MenuType::Statistics:
|
||||||
InvMode = InventoryMode::Statistics;
|
SetInventoryMode(InventoryMode::Statistics);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuType::Ammo1:
|
case MenuType::Ammo1:
|
||||||
|
@ -2355,7 +2381,7 @@ namespace TEN::Gui
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MenuType::Diary:
|
case MenuType::Diary:
|
||||||
InvMode = InventoryMode::Diary;
|
SetInventoryMode(InventoryMode::Diary);
|
||||||
lara->Inventory.Diary.CurrentPage = 1;
|
lara->Inventory.Diary.CurrentPage = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2918,9 +2944,9 @@ namespace TEN::Gui
|
||||||
g_Renderer.DumpGameScene();
|
g_Renderer.DumpGameScene();
|
||||||
|
|
||||||
if (resetMode)
|
if (resetMode)
|
||||||
InvMode = InventoryMode::InGame;
|
SetInventoryMode(InventoryMode::InGame);
|
||||||
|
|
||||||
InitialiseInventory(item);
|
InitializeInventory(item);
|
||||||
Camera.numberFrames = 2;
|
Camera.numberFrames = 2;
|
||||||
|
|
||||||
bool exitLoop = false;
|
bool exitLoop = false;
|
||||||
|
@ -2929,10 +2955,10 @@ namespace TEN::Gui
|
||||||
if (ThreadEnded)
|
if (ThreadEnded)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
OBJLIST_SPACING = PHD_CENTER_X / 2;
|
TimeInMenu++;
|
||||||
|
GameTimer++;
|
||||||
|
|
||||||
UpdateInputActions(item);
|
UpdateInputActions(item);
|
||||||
GameTimer++;
|
|
||||||
|
|
||||||
if (IsClicked(In::Option))
|
if (IsClicked(In::Option))
|
||||||
{
|
{
|
||||||
|
@ -2973,7 +2999,7 @@ namespace TEN::Gui
|
||||||
exitLoop = !resetMode;
|
exitLoop = !resetMode;
|
||||||
|
|
||||||
if (resetMode)
|
if (resetMode)
|
||||||
InvMode = InventoryMode::InGame;
|
SetInventoryMode(InventoryMode::InGame);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2988,7 +3014,7 @@ namespace TEN::Gui
|
||||||
{
|
{
|
||||||
exitLoop = !resetMode;
|
exitLoop = !resetMode;
|
||||||
if (resetMode)
|
if (resetMode)
|
||||||
InvMode = InventoryMode::InGame;
|
SetInventoryMode(InventoryMode::InGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -3011,30 +3037,30 @@ namespace TEN::Gui
|
||||||
AlterFOV(LastFOV);
|
AlterFOV(LastFOV);
|
||||||
|
|
||||||
lara->Inventory.IsBusy = lara->Inventory.OldBusy;
|
lara->Inventory.IsBusy = lara->Inventory.OldBusy;
|
||||||
InvMode = InventoryMode::None;
|
SetInventoryMode(InventoryMode::None);
|
||||||
|
|
||||||
return doLoad;
|
return doLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiController::DoStatisticsMode()
|
void GuiController::DoStatisticsMode()
|
||||||
{
|
{
|
||||||
InvMode = InventoryMode::Statistics;
|
SetInventoryMode(InventoryMode::Statistics);
|
||||||
|
|
||||||
if (GuiIsDeselected())
|
if (GuiIsDeselected())
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||||
InvMode = InventoryMode::InGame;
|
SetInventoryMode(InventoryMode::InGame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GuiController::DoExamineMode()
|
void GuiController::DoExamineMode()
|
||||||
{
|
{
|
||||||
this->InvMode = InventoryMode::Examine;
|
SetInventoryMode(InventoryMode::Examine);
|
||||||
|
|
||||||
if (GuiIsDeselected())
|
if (GuiIsDeselected())
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||||
this->InvMode = InventoryMode::None;
|
SetInventoryMode(InventoryMode::None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3056,7 +3082,7 @@ namespace TEN::Gui
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(item);
|
auto* lara = GetLaraInfo(item);
|
||||||
|
|
||||||
this->InvMode = InventoryMode::Diary;
|
SetInventoryMode(InventoryMode::Diary);
|
||||||
|
|
||||||
if (GuiIsPulsed(In::Right) &&
|
if (GuiIsPulsed(In::Right) &&
|
||||||
lara->Inventory.Diary.CurrentPage < lara->Inventory.Diary.NumPages)
|
lara->Inventory.Diary.CurrentPage < lara->Inventory.Diary.NumPages)
|
||||||
|
@ -3075,7 +3101,7 @@ namespace TEN::Gui
|
||||||
if (GuiIsDeselected())
|
if (GuiIsDeselected())
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
SoundEffect(SFX_TR4_MENU_SELECT, nullptr, SoundEnvironment::Always);
|
||||||
InvMode = InventoryMode::None;
|
SetInventoryMode(InventoryMode::None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ namespace TEN::Gui
|
||||||
int OptionCount;
|
int OptionCount;
|
||||||
int SelectedSaveSlot;
|
int SelectedSaveSlot;
|
||||||
|
|
||||||
|
float TimeInMenu = 0.0f;
|
||||||
SettingsData CurrentSettings;
|
SettingsData CurrentSettings;
|
||||||
|
|
||||||
// Inventory variables
|
// Inventory variables
|
||||||
|
@ -150,7 +151,6 @@ namespace TEN::Gui
|
||||||
short NormalRingFadeVal;
|
short NormalRingFadeVal;
|
||||||
short NormalRingFadeDir;
|
short NormalRingFadeDir;
|
||||||
unsigned char AmmoActive;
|
unsigned char AmmoActive;
|
||||||
int OBJLIST_SPACING;
|
|
||||||
MenuOption CurrentOptions[3];
|
MenuOption CurrentOptions[3];
|
||||||
InventoryMode InvMode;
|
InventoryMode InvMode;
|
||||||
int InventoryItemChosen;
|
int InventoryItemChosen;
|
||||||
|
@ -199,7 +199,7 @@ namespace TEN::Gui
|
||||||
void HandleOptionsInput();
|
void HandleOptionsInput();
|
||||||
void BackupOptions();
|
void BackupOptions();
|
||||||
bool DoObjectsCombine(int objectNumber1, int objectNumber2);
|
bool DoObjectsCombine(int objectNumber1, int objectNumber2);
|
||||||
void InitialiseInventory(ItemInfo* item);
|
void InitializeInventory(ItemInfo* item);
|
||||||
void FillDisplayOptions();
|
void FillDisplayOptions();
|
||||||
bool IsItemCurrentlyCombinable(int objectNumber);
|
bool IsItemCurrentlyCombinable(int objectNumber);
|
||||||
bool IsItemInInventory(int objectNumber);
|
bool IsItemInInventory(int objectNumber);
|
||||||
|
|
9
TombEngine/Game/itemdata/creature_info.cpp
Normal file
9
TombEngine/Game/itemdata/creature_info.cpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "framework.h"
|
||||||
|
#include "Game/itemdata/creature_info.h"
|
||||||
|
|
||||||
|
#include "Game/items.h"
|
||||||
|
|
||||||
|
bool CreatureInfo::IsTargetAlive()
|
||||||
|
{
|
||||||
|
return ((Enemy != nullptr) && (Enemy->HitPoints > 0));
|
||||||
|
}
|
|
@ -45,7 +45,7 @@ struct BoxNode
|
||||||
|
|
||||||
struct LOTInfo
|
struct LOTInfo
|
||||||
{
|
{
|
||||||
bool Initialised = false;
|
bool Initialized = false;
|
||||||
|
|
||||||
std::vector<BoxNode> Node = {};
|
std::vector<BoxNode> Node = {};
|
||||||
int Head = 0;
|
int Head = 0;
|
||||||
|
@ -71,6 +71,62 @@ struct LOTInfo
|
||||||
bool CanMonkey = false;
|
bool CanMonkey = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CreatureBiteInfo
|
||||||
|
{
|
||||||
|
Vector3i Position = Vector3i::Zero; // TODO: Change back to Vector3.
|
||||||
|
int BoneID = -1;
|
||||||
|
|
||||||
|
CreatureBiteInfo() {}
|
||||||
|
|
||||||
|
CreatureBiteInfo(const Vector3i& pos, int boneID)
|
||||||
|
{
|
||||||
|
Position = pos;
|
||||||
|
BoneID = boneID;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureBiteInfo(int x, int y, int z, int boneID)
|
||||||
|
{
|
||||||
|
Position = Vector3i(x, y, z);
|
||||||
|
BoneID = boneID;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CreatureMuzzleFlashInfo
|
||||||
|
{
|
||||||
|
CreatureBiteInfo Bite = {};
|
||||||
|
|
||||||
|
int Delay = 0;
|
||||||
|
bool SwitchToMuzzle2 = false; // Changes muzzle object to ID_GUNFLASH2.
|
||||||
|
bool ApplyXRotation = true; // Applies X axis rotation for muzzleflash (required for creatures).
|
||||||
|
bool ApplyZRotation = true; // Applies Y axis rotation for muzzleflash (required for creatures).
|
||||||
|
bool UseSmoke = true; // Determines if CreatureAnimation calls TriggerGunSmokeParticles().
|
||||||
|
|
||||||
|
CreatureMuzzleFlashInfo() {}
|
||||||
|
|
||||||
|
CreatureMuzzleFlashInfo(const Vector3i& pos, int boneID, int delay, bool changeToMuzzle2 = false)
|
||||||
|
{
|
||||||
|
Bite = CreatureBiteInfo(pos, boneID);
|
||||||
|
Delay = delay;
|
||||||
|
SwitchToMuzzle2 = changeToMuzzle2;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureMuzzleFlashInfo(const CreatureBiteInfo& bite, int delay, bool changeToMuzzle2 = false)
|
||||||
|
{
|
||||||
|
Bite = bite;
|
||||||
|
Delay = delay;
|
||||||
|
SwitchToMuzzle2 = changeToMuzzle2;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreatureMuzzleFlashInfo(const CreatureBiteInfo& bite, int delay, bool changeToMuzzle2 = false, bool applyXRot = true, bool applyZRot = true)
|
||||||
|
{
|
||||||
|
Bite = bite;
|
||||||
|
Delay = delay;
|
||||||
|
SwitchToMuzzle2 = changeToMuzzle2;
|
||||||
|
ApplyXRotation = applyXRot;
|
||||||
|
ApplyZRotation = applyZRot;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct CreatureInfo
|
struct CreatureInfo
|
||||||
{
|
{
|
||||||
int ItemNumber = -1;
|
int ItemNumber = -1;
|
||||||
|
@ -96,11 +152,13 @@ struct CreatureInfo
|
||||||
bool MonkeySwingAhead = false;
|
bool MonkeySwingAhead = false;
|
||||||
bool ReachedGoal = false;
|
bool ReachedGoal = false;
|
||||||
|
|
||||||
short FiredWeapon = 0;
|
CreatureMuzzleFlashInfo MuzzleFlash[2];
|
||||||
short Tosspad = 0;
|
short Tosspad = 0;
|
||||||
short LocationAI = 0;
|
short LocationAI = 0;
|
||||||
short Flags = 0;
|
short Flags = 0;
|
||||||
|
|
||||||
|
bool IsTargetAlive();
|
||||||
|
|
||||||
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
||||||
CreatureAIPriority Priority = CreatureAIPriority::None;
|
CreatureAIPriority Priority = CreatureAIPriority::None;
|
||||||
size_t FramesSinceLOTUpdate = 0;
|
size_t FramesSinceLOTUpdate = 0;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
#include "Game/itemdata/itemdata.h"
|
#include "Game/itemdata/itemdata.h"
|
||||||
|
|
||||||
ITEM_DATA::ITEM_DATA() : data(nullptr) {}
|
ItemData::ItemData() : data(nullptr) {}
|
||||||
|
|
|
@ -20,19 +20,20 @@
|
||||||
#include "Objects/TR4/Vehicles/jeep_info.h"
|
#include "Objects/TR4/Vehicles/jeep_info.h"
|
||||||
#include "Objects/TR4/Vehicles/motorbike_info.h"
|
#include "Objects/TR4/Vehicles/motorbike_info.h"
|
||||||
#include "Objects/TR5/Entity/tr5_laserhead_info.h"
|
#include "Objects/TR5/Entity/tr5_laserhead_info.h"
|
||||||
|
#include "Objects/TR5/Light/tr5_light_info.h"
|
||||||
#include "Objects/TR5/Object/tr5_pushableblock_info.h"
|
#include "Objects/TR5/Object/tr5_pushableblock_info.h"
|
||||||
|
|
||||||
template<class... Ts> struct visitor : Ts... { using Ts::operator()...; };
|
template<class... Ts> struct visitor : Ts... { using Ts::operator()...; };
|
||||||
template<class... Ts> visitor(Ts...)->visitor<Ts...>; // line not needed in C++20...
|
template<class... Ts> visitor(Ts...)->visitor<Ts...>; // TODO: Line not needed in C++20.
|
||||||
|
|
||||||
using namespace TEN::Entities::TR4;
|
|
||||||
using namespace TEN::Entities::Creatures::TR5;
|
using namespace TEN::Entities::Creatures::TR5;
|
||||||
using namespace TEN::Entities::Generic;
|
using namespace TEN::Entities::Generic;
|
||||||
|
using namespace TEN::Entities::TR4;
|
||||||
using namespace TEN::Entities::Vehicles;
|
using namespace TEN::Entities::Vehicles;
|
||||||
|
|
||||||
struct ItemInfo;
|
struct ItemInfo;
|
||||||
|
|
||||||
class ITEM_DATA
|
class ItemData
|
||||||
{
|
{
|
||||||
std::variant<
|
std::variant<
|
||||||
std::nullptr_t,
|
std::nullptr_t,
|
||||||
|
@ -67,16 +68,17 @@ class ITEM_DATA
|
||||||
UPVInfo,
|
UPVInfo,
|
||||||
SpeedboatInfo,
|
SpeedboatInfo,
|
||||||
RubberBoatInfo,
|
RubberBoatInfo,
|
||||||
MinecartInfo
|
MinecartInfo,
|
||||||
|
ElectricalLightInfo
|
||||||
> data;
|
> data;
|
||||||
public:
|
public:
|
||||||
ITEM_DATA();
|
ItemData();
|
||||||
|
|
||||||
template<typename D>
|
template<typename D>
|
||||||
ITEM_DATA(D&& type) : data(std::move(type)) {}
|
ItemData(D&& type) : data(std::move(type)) {}
|
||||||
|
|
||||||
// conversion operators to keep original syntax!
|
// Conversion operators to keep original syntax.
|
||||||
// TODO: should be removed later and
|
// TODO: Should be removed later and use polymorphism instead.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
operator T* ()
|
operator T* ()
|
||||||
{
|
{
|
||||||
|
@ -86,7 +88,7 @@ class ITEM_DATA
|
||||||
return &ref;
|
return &ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("ITEM_DATA does not hold the requested type!\n The code set the ITEM_DATA to a different type than the type that was attempted to read");
|
throw std::runtime_error("Attempted to read ItemData as wrong type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -98,33 +100,33 @@ class ITEM_DATA
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("ITEM_DATA does not hold the requested type!\n The code set the ITEM_DATA to a different type than the type that was attempted to read");
|
throw std::runtime_error("Attempted to read ItemData as wrong type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Uncommented, we want to store pointers to global data, too (LaraInfo for example)
|
/* Uncommented, we want to store pointers to global data too (LaraInfo for example).
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ITEM_DATA& operator=(T* newData)
|
ItemData& operator =(T* newData)
|
||||||
{
|
{
|
||||||
data = *newData;
|
data = *newData;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ITEM_DATA& operator=(std::nullptr_t null)
|
ItemData& operator =(std::nullptr_t null)
|
||||||
{
|
{
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ITEM_DATA& operator=(T& newData)
|
ItemData& operator =(T& newData)
|
||||||
{
|
{
|
||||||
data = newData;
|
data = newData;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ITEM_DATA& operator=(T&& newData)
|
ItemData& operator =(T&& newData)
|
||||||
{
|
{
|
||||||
data = std::move(newData);
|
data = std::move(newData);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -139,12 +141,12 @@ class ITEM_DATA
|
||||||
void apply(Funcs&&... funcs)
|
void apply(Funcs&&... funcs)
|
||||||
{
|
{
|
||||||
std::visit(
|
std::visit(
|
||||||
visitor
|
visitor
|
||||||
{
|
{
|
||||||
[](auto const&) {},
|
[](auto const&) {},
|
||||||
std::forward<Funcs>(funcs)...
|
std::forward<Funcs>(funcs)...
|
||||||
},
|
},
|
||||||
data);
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Lara/lara_helpers.h"
|
#include "Game/Lara/lara_helpers.h"
|
||||||
#include "Game/savegame.h"
|
#include "Game/savegame.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
||||||
#include "Scripting/Include/ScriptInterfaceGame.h"
|
#include "Scripting/Include/ScriptInterfaceGame.h"
|
||||||
|
@ -17,12 +18,11 @@
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Scripting/Internal/TEN/Objects/ObjectIDs.h"
|
#include "Scripting/Internal/TEN/Objects/ObjectIDs.h"
|
||||||
|
|
||||||
using namespace TEN::Control::Volumes;
|
using namespace TEN::Control::Volumes;
|
||||||
using namespace TEN::Effects::Items;
|
using namespace TEN::Effects::Items;
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Input;
|
using namespace TEN::Input;
|
||||||
using namespace TEN::Math;
|
using namespace TEN::Math;
|
||||||
|
|
||||||
|
@ -144,10 +144,10 @@ bool ItemInfo::IsCreature() const
|
||||||
|
|
||||||
void ItemInfo::ResetModelToDefault()
|
void ItemInfo::ResetModelToDefault()
|
||||||
{
|
{
|
||||||
this->Model.BaseMesh = Objects[this->ObjectNumber].meshIndex;
|
Model.BaseMesh = Objects[ObjectNumber].meshIndex;
|
||||||
|
|
||||||
for (int i = 0; i < this->Model.MeshIndex.size(); i++)
|
for (int i = 0; i < Model.MeshIndex.size(); i++)
|
||||||
this->Model.MeshIndex[i] = this->Model.BaseMesh + i;
|
Model.MeshIndex[i] = Model.BaseMesh + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestState(int refState, const vector<int>& stateList)
|
bool TestState(int refState, const vector<int>& stateList)
|
||||||
|
@ -196,7 +196,9 @@ void KillItem(short const itemNumber)
|
||||||
item->Active = false;
|
item->Active = false;
|
||||||
|
|
||||||
if (NextItemActive == itemNumber)
|
if (NextItemActive == itemNumber)
|
||||||
|
{
|
||||||
NextItemActive = item->NextActive;
|
NextItemActive = item->NextActive;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
short linkNumber;
|
short linkNumber;
|
||||||
|
@ -213,7 +215,9 @@ void KillItem(short const itemNumber)
|
||||||
if (item->RoomNumber != NO_ROOM)
|
if (item->RoomNumber != NO_ROOM)
|
||||||
{
|
{
|
||||||
if (g_Level.Rooms[item->RoomNumber].itemNumber == itemNumber)
|
if (g_Level.Rooms[item->RoomNumber].itemNumber == itemNumber)
|
||||||
|
{
|
||||||
g_Level.Rooms[item->RoomNumber].itemNumber = item->NextItem;
|
g_Level.Rooms[item->RoomNumber].itemNumber = item->NextItem;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
short linkNumber;
|
short linkNumber;
|
||||||
|
@ -229,7 +233,7 @@ void KillItem(short const itemNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item == Lara.TargetEntity)
|
if (item == Lara.TargetEntity)
|
||||||
Lara.TargetEntity = NULL;
|
Lara.TargetEntity = nullptr;
|
||||||
|
|
||||||
if (Objects[item->ObjectNumber].floor != nullptr)
|
if (Objects[item->ObjectNumber].floor != nullptr)
|
||||||
UpdateBridgeItem(itemNumber, true);
|
UpdateBridgeItem(itemNumber, true);
|
||||||
|
@ -242,7 +246,9 @@ void KillItem(short const itemNumber)
|
||||||
NextItemFree = itemNumber;
|
NextItemFree = itemNumber;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
item->Flags |= IFLAG_KILLED;
|
item->Flags |= IFLAG_KILLED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +428,7 @@ short CreateNewEffect(short roomNumber)
|
||||||
return fxNumber;
|
return fxNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseFXArray(int allocateMemory)
|
void InitializeFXArray(int allocateMemory)
|
||||||
{
|
{
|
||||||
NextFxActive = NO_ITEM;
|
NextFxActive = NO_ITEM;
|
||||||
NextFxFree = 0;
|
NextFxFree = 0;
|
||||||
|
@ -482,19 +488,13 @@ void RemoveActiveItem(short itemNumber, bool killed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseItem(short itemNumber)
|
void InitializeItem(short itemNumber)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
|
|
||||||
item->Animation.AnimNumber = Objects[item->ObjectNumber].animIndex;
|
SetAnimation(item, 0);
|
||||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
|
||||||
|
|
||||||
item->Animation.RequiredState = NO_STATE;
|
item->Animation.RequiredState = NO_STATE;
|
||||||
item->Animation.TargetState = g_Level.Anims[item->Animation.AnimNumber].ActiveState;
|
item->Animation.Velocity = Vector3::Zero;
|
||||||
item->Animation.ActiveState = g_Level.Anims[item->Animation.AnimNumber].ActiveState;
|
|
||||||
|
|
||||||
item->Animation.Velocity.y = 0;
|
|
||||||
item->Animation.Velocity.z = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_ITEM_FLAGS; i++)
|
for (int i = 0; i < NUM_ITEM_FLAGS; i++)
|
||||||
item->ItemFlags[i] = 0;
|
item->ItemFlags[i] = 0;
|
||||||
|
@ -516,7 +516,9 @@ void InitialiseItem(short itemNumber)
|
||||||
item->MeshBits = 1;
|
item->MeshBits = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
item->MeshBits = ALL_JOINT_BITS;
|
item->MeshBits = ALL_JOINT_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
item->TouchBits = NO_JOINT_BITS;
|
item->TouchBits = NO_JOINT_BITS;
|
||||||
item->AfterDeath = 0;
|
item->AfterDeath = 0;
|
||||||
|
@ -527,7 +529,9 @@ void InitialiseItem(short itemNumber)
|
||||||
item->Status = ITEM_INVISIBLE;
|
item->Status = ITEM_INVISIBLE;
|
||||||
}
|
}
|
||||||
else if (Objects[item->ObjectNumber].intelligent)
|
else if (Objects[item->ObjectNumber].intelligent)
|
||||||
|
{
|
||||||
item->Status = ITEM_INVISIBLE;
|
item->Status = ITEM_INVISIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
if ((item->Flags & IFLAG_ACTIVATION_MASK) == IFLAG_ACTIVATION_MASK)
|
if ((item->Flags & IFLAG_ACTIVATION_MASK) == IFLAG_ACTIVATION_MASK)
|
||||||
{
|
{
|
||||||
|
@ -560,8 +564,8 @@ void InitialiseItem(short itemNumber)
|
||||||
item->Model.MeshIndex.clear();
|
item->Model.MeshIndex.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Objects[item->ObjectNumber].initialise != nullptr)
|
if (Objects[item->ObjectNumber].Initialize != nullptr)
|
||||||
Objects[item->ObjectNumber].initialise(itemNumber);
|
Objects[item->ObjectNumber].Initialize(itemNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
short CreateItem()
|
short CreateItem()
|
||||||
|
@ -576,7 +580,7 @@ short CreateItem()
|
||||||
return itemNumber;
|
return itemNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseItemArray(int totalItem)
|
void InitializeItemArray(int totalItem)
|
||||||
{
|
{
|
||||||
g_Level.Items.clear();
|
g_Level.Items.clear();
|
||||||
g_Level.Items.resize(totalItem);
|
g_Level.Items.resize(totalItem);
|
||||||
|
@ -612,7 +616,7 @@ short SpawnItem(ItemInfo* item, GAME_OBJECT_ID objectNumber)
|
||||||
spawn->RoomNumber = item->RoomNumber;
|
spawn->RoomNumber = item->RoomNumber;
|
||||||
memcpy(&spawn->Pose, &item->Pose, sizeof(Pose));
|
memcpy(&spawn->Pose, &item->Pose, sizeof(Pose));
|
||||||
|
|
||||||
InitialiseItem(itemNumber);
|
InitializeItem(itemNumber);
|
||||||
|
|
||||||
spawn->Status = ITEM_NOT_ACTIVE;
|
spawn->Status = ITEM_NOT_ACTIVE;
|
||||||
spawn->Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
|
spawn->Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
|
|
|
@ -5,14 +5,13 @@
|
||||||
|
|
||||||
#include "Game/animation.h"
|
#include "Game/animation.h"
|
||||||
#include "Game/itemdata/itemdata.h"
|
#include "Game/itemdata/itemdata.h"
|
||||||
|
#include "Objects/game_object_ids.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Specific/newtypes.h"
|
#include "Specific/newtypes.h"
|
||||||
#include "Specific/BitField.h"
|
#include "Specific/BitField.h"
|
||||||
|
|
||||||
using namespace TEN::Utils;
|
using namespace TEN::Utils;
|
||||||
|
|
||||||
enum GAME_OBJECT_ID : short;
|
|
||||||
|
|
||||||
constexpr auto NO_ITEM = -1;
|
constexpr auto NO_ITEM = -1;
|
||||||
constexpr auto NOT_TARGETABLE = -16384;
|
constexpr auto NOT_TARGETABLE = -16384;
|
||||||
|
|
||||||
|
@ -66,6 +65,8 @@ enum class EffectType
|
||||||
|
|
||||||
struct EntityAnimationData
|
struct EntityAnimationData
|
||||||
{
|
{
|
||||||
|
GAME_OBJECT_ID AnimObjectID = ID_NO_OBJECT;
|
||||||
|
|
||||||
int AnimNumber = 0; // g_Level.Anims index.
|
int AnimNumber = 0; // g_Level.Anims index.
|
||||||
int FrameNumber = 0; // g_Level.Frames index.
|
int FrameNumber = 0; // g_Level.Frames index.
|
||||||
int ActiveState = 0;
|
int ActiveState = 0;
|
||||||
|
@ -106,8 +107,8 @@ struct EntityEffectData
|
||||||
// TODO: We need to find good "default states" for a lot of these. -- squidshire 25/05/2022
|
// TODO: We need to find good "default states" for a lot of these. -- squidshire 25/05/2022
|
||||||
struct ItemInfo
|
struct ItemInfo
|
||||||
{
|
{
|
||||||
GAME_OBJECT_ID ObjectNumber;
|
GAME_OBJECT_ID ObjectNumber = ID_NO_OBJECT; // ObjectID
|
||||||
std::string Name;
|
std::string Name = {};
|
||||||
|
|
||||||
int Status; // ItemStatus enum.
|
int Status; // ItemStatus enum.
|
||||||
bool Active;
|
bool Active;
|
||||||
|
@ -116,7 +117,7 @@ struct ItemInfo
|
||||||
short NextItem;
|
short NextItem;
|
||||||
short NextActive;
|
short NextActive;
|
||||||
|
|
||||||
ITEM_DATA Data;
|
ItemData Data;
|
||||||
EntityAnimationData Animation;
|
EntityAnimationData Animation;
|
||||||
EntityCallbackData Callbacks;
|
EntityCallbackData Callbacks;
|
||||||
EntityModelData Model;
|
EntityModelData Model;
|
||||||
|
@ -178,11 +179,11 @@ short CreateItem();
|
||||||
void RemoveAllItemsInRoom(short roomNumber, short objectNumber);
|
void RemoveAllItemsInRoom(short roomNumber, short objectNumber);
|
||||||
void RemoveActiveItem(short itemNumber, bool killed = true);
|
void RemoveActiveItem(short itemNumber, bool killed = true);
|
||||||
void RemoveDrawnItem(short itemNumber);
|
void RemoveDrawnItem(short itemNumber);
|
||||||
void InitialiseFXArray(int allocateMemory);
|
void InitializeFXArray(int allocateMemory);
|
||||||
short CreateNewEffect(short roomNumber);
|
short CreateNewEffect(short roomNumber);
|
||||||
void KillEffect(short fxNumber);
|
void KillEffect(short fxNumber);
|
||||||
void InitialiseItem(short itemNumber);
|
void InitializeItem(short itemNumber);
|
||||||
void InitialiseItemArray(int totalItems);
|
void InitializeItemArray(int totalItems);
|
||||||
void KillItem(short itemNumber);
|
void KillItem(short itemNumber);
|
||||||
bool UpdateItemRoom(short itemNumber);
|
bool UpdateItemRoom(short itemNumber);
|
||||||
void UpdateAllItems();
|
void UpdateAllItems();
|
||||||
|
@ -195,3 +196,4 @@ int FindItem(ItemInfo* item);
|
||||||
void DoDamage(ItemInfo* item, int damage);
|
void DoDamage(ItemInfo* item, int damage);
|
||||||
void DoItemHit(ItemInfo* target, int damage, bool isExplosive, bool allowBurn = true);
|
void DoItemHit(ItemInfo* target, int damage, bool isExplosive, bool allowBurn = true);
|
||||||
void DefaultItemHit(ItemInfo& target, ItemInfo& source, std::optional<GameVector> pos, int damage, bool isExplosive, int jointIndex);
|
void DefaultItemHit(ItemInfo& target, ItemInfo& source, std::optional<GameVector> pos, int damage, bool isExplosive, int jointIndex);
|
||||||
|
short SpawnItem(ItemInfo* item, GAME_OBJECT_ID objectNumber);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/itemdata/creature_info.h"
|
#include "Game/itemdata/creature_info.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Specific/setup.h"
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
#include "Game/effects/Bubble.h"
|
#include "Game/effects/Bubble.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
|
|
||||||
using namespace TEN::Effects::Bubble;
|
using namespace TEN::Effects::Bubble;
|
||||||
using namespace TEN::Effects::Explosion;
|
using namespace TEN::Effects::Explosion;
|
||||||
|
@ -115,7 +115,7 @@ void ControlMissile(short fxNumber)
|
||||||
EffectNewRoom(fxNumber, pointColl.RoomNumber);
|
EffectNewRoom(fxNumber, pointColl.RoomNumber);
|
||||||
|
|
||||||
if (fx.objectNumber == ID_KNIFETHROWER_KNIFE)
|
if (fx.objectNumber == ID_KNIFETHROWER_KNIFE)
|
||||||
fx.pos.Orientation.z += ANGLE(3.0f); // Update knife rotation over time.
|
fx.pos.Orientation.z += ANGLE(30.0f); // Update knife rotation over time.
|
||||||
|
|
||||||
switch (fx.objectNumber)
|
switch (fx.objectNumber)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "Game/misc.h"
|
#include "Game/misc.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
|
|
||||||
bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, int damage)
|
bool ShotLara(ItemInfo* item, AI_INFO* AI, const CreatureBiteInfo& gun, short extraRotation, int damage)
|
||||||
{
|
{
|
||||||
auto* creature = GetCreatureInfo(item);
|
auto* creature = GetCreatureInfo(item);
|
||||||
auto* enemy = creature->Enemy;
|
auto* enemy = creature->Enemy;
|
||||||
|
@ -79,13 +79,14 @@ bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, in
|
||||||
|
|
||||||
short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber)
|
short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber)
|
||||||
{
|
{
|
||||||
|
// TODO: Remove -128 and fix ricochet effect going on floor. -- TokyoSU 2023.04.28
|
||||||
auto pos = GameVector(
|
auto pos = GameVector(
|
||||||
LaraItem->Pose.Position.x + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
LaraItem->Pose.Position.x + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
||||||
LaraItem->Floor,
|
LaraItem->Floor - 128,
|
||||||
LaraItem->Pose.Position.z + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
LaraItem->Pose.Position.z + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
||||||
LaraItem->RoomNumber);
|
LaraItem->RoomNumber);
|
||||||
|
|
||||||
Ricochet(Pose(pos.x, pos.y, pos.z));
|
Ricochet(Pose(pos.ToVector3i()));
|
||||||
return GunShot(x, y, z, velocity, yRot, roomNumber);
|
return GunShot(x, y, z, velocity, yRot, roomNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,11 +102,11 @@ short GunShot(int x, int y, int z, short velocity, short yRot, short roomNumber)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Targetable(ItemInfo* item, AI_INFO* AI)
|
bool Targetable(ItemInfo* item, AI_INFO* ai)
|
||||||
{
|
{
|
||||||
// Discard it entity is not a creature (only creatures can use Targetable())
|
// Discard it entity is not a creature (only creatures can use Targetable())
|
||||||
// or if the target is not visible.
|
// or if the target is not visible.
|
||||||
if (!item->IsCreature() || !AI->ahead || AI->distance >= SQUARE(MAX_VISIBILITY_DISTANCE))
|
if (!item->IsCreature() || !ai->ahead || ai->distance >= SQUARE(MAX_VISIBILITY_DISTANCE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto* creature = GetCreatureInfo(item);
|
auto* creature = GetCreatureInfo(item);
|
||||||
|
@ -134,9 +135,9 @@ bool Targetable(ItemInfo* item, AI_INFO* AI)
|
||||||
return LOS(&origin, &target);
|
return LOS(&origin, &target);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TargetVisible(ItemInfo* item, AI_INFO* AI, float maxAngleInDegrees)
|
bool TargetVisible(ItemInfo* item, AI_INFO* ai, float maxAngleInDegrees)
|
||||||
{
|
{
|
||||||
if (!item->IsCreature() || AI->distance >= SQUARE(MAX_VISIBILITY_DISTANCE))
|
if (!item->IsCreature() || ai->distance >= SQUARE(MAX_VISIBILITY_DISTANCE))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check just in case.
|
// Check just in case.
|
||||||
|
@ -148,7 +149,7 @@ bool TargetVisible(ItemInfo* item, AI_INFO* AI, float maxAngleInDegrees)
|
||||||
if (enemy == nullptr || enemy->HitPoints == 0)
|
if (enemy == nullptr || enemy->HitPoints == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
short angle = AI->angle - creature->JointRotation[2];
|
short angle = ai->angle - creature->JointRotation[2];
|
||||||
if (angle > ANGLE(-maxAngleInDegrees) && angle < ANGLE(maxAngleInDegrees))
|
if (angle > ANGLE(-maxAngleInDegrees) && angle < ANGLE(maxAngleInDegrees))
|
||||||
{
|
{
|
||||||
const auto& bounds = GetBestFrame(*enemy).BoundingBox;
|
const auto& bounds = GetBestFrame(*enemy).BoundingBox;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Game/control/box.h"
|
#include "Game/control/box.h"
|
||||||
|
|
||||||
constexpr auto MAX_VISIBILITY_DISTANCE = SECTOR(8);
|
struct CreatureBiteInfo;
|
||||||
|
|
||||||
bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, int damage);
|
constexpr auto MAX_VISIBILITY_DISTANCE = BLOCK(8);
|
||||||
|
|
||||||
|
bool ShotLara(ItemInfo* item, AI_INFO* AI, const CreatureBiteInfo& gun, short extraRotation, int damage);
|
||||||
short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
||||||
short GunHit(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
short GunHit(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
||||||
short GunShot(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
short GunShot(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
||||||
bool Targetable(ItemInfo* item, AI_INFO* AI);
|
bool Targetable(ItemInfo* item, AI_INFO* ai);
|
||||||
bool TargetVisible(ItemInfo* item, AI_INFO* AI, float maxAngleInDegrees = 45.0f);
|
bool TargetVisible(ItemInfo* item, AI_INFO* ai, float maxAngleInDegrees = 45.0f);
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
#include "Game/pickup/pickup_misc_items.h"
|
#include "Game/pickup/pickup_misc_items.h"
|
||||||
#include "Game/pickup/pickup_weapon.h"
|
#include "Game/pickup/pickup_weapon.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
|
#include "Math/Math.h"
|
||||||
#include "Objects/Generic/Object/burning_torch.h"
|
#include "Objects/Generic/Object/burning_torch.h"
|
||||||
#include "Objects/TR4/Object/tr4_clockwork_beetle.h"
|
#include "Objects/TR4/Object/tr4_clockwork_beetle.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/Input/Input.h"
|
#include "Specific/Input/Input.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Math/Math.h"
|
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||||
|
|
||||||
using namespace TEN::Entities::Generic;
|
using namespace TEN::Entities::Generic;
|
||||||
|
@ -273,10 +273,10 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
auto* lara = GetLaraInfo(laraItem);
|
auto* lara = GetLaraInfo(laraItem);
|
||||||
|
|
||||||
if (lara->InteractedItem == NO_ITEM)
|
if (lara->Context.InteractedItem == NO_ITEM)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
short pickupItemNumber = lara->InteractedItem;
|
short pickupItemNumber = lara->Context.InteractedItem;
|
||||||
auto* pickupItem = &g_Level.Items[pickupItemNumber];
|
auto* pickupItem = &g_Level.Items[pickupItemNumber];
|
||||||
|
|
||||||
if (!Objects[pickupItem->ObjectNumber].isPickup)
|
if (!Objects[pickupItem->ObjectNumber].isPickup)
|
||||||
|
@ -292,7 +292,7 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
|
|
||||||
KillItem(pickupItemNumber);
|
KillItem(pickupItemNumber);
|
||||||
pickupItem->Pose.Orientation = prevOrient;
|
pickupItem->Pose.Orientation = prevOrient;
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (pickupItem->ObjectNumber == ID_FLARE_ITEM)
|
else if (pickupItem->ObjectNumber == ID_FLARE_ITEM)
|
||||||
|
@ -301,25 +301,25 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
lara->Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
lara->Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||||
lara->Control.Weapon.GunType = LaraWeaponType::Flare;
|
lara->Control.Weapon.GunType = LaraWeaponType::Flare;
|
||||||
InitialiseNewWeapon(laraItem);
|
InitializeNewWeapon(*laraItem);
|
||||||
lara->Control.HandStatus = HandStatus::Special;
|
lara->Control.HandStatus = HandStatus::Special;
|
||||||
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
|
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
|
||||||
DrawFlareMeshes(laraItem);
|
DrawFlareMeshes(*laraItem);
|
||||||
KillItem(pickupItemNumber);
|
KillItem(pickupItemNumber);
|
||||||
|
|
||||||
pickupItem->Pose.Orientation = prevOrient;
|
pickupItem->Pose.Orientation = prevOrient;
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (laraItem->Animation.ActiveState == LS_PICKUP_FLARE)
|
else if (laraItem->Animation.ActiveState == LS_PICKUP_FLARE)
|
||||||
{
|
{
|
||||||
lara->Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
lara->Control.Weapon.RequestGunType = LaraWeaponType::Flare;
|
||||||
lara->Control.Weapon.GunType = LaraWeaponType::Flare;
|
lara->Control.Weapon.GunType = LaraWeaponType::Flare;
|
||||||
InitialiseNewWeapon(laraItem);
|
InitializeNewWeapon(*laraItem);
|
||||||
lara->Control.HandStatus = HandStatus::Special;
|
lara->Control.HandStatus = HandStatus::Special;
|
||||||
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
|
lara->Flare.Life = int(pickupItem->Data) & 0x7FFF;
|
||||||
KillItem(pickupItemNumber);
|
KillItem(pickupItemNumber);
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,8 +330,8 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
if (g_GameFlow->IsMassPickupEnabled())
|
if (g_GameFlow->IsMassPickupEnabled())
|
||||||
{
|
{
|
||||||
CollectMultiplePickups(lara->InteractedItem);
|
CollectMultiplePickups(lara->Context.InteractedItem);
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
pickupItem->Pose.Orientation = prevOrient;
|
pickupItem->Pose.Orientation = prevOrient;
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -365,8 +365,8 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
{
|
{
|
||||||
if (g_GameFlow->IsMassPickupEnabled())
|
if (g_GameFlow->IsMassPickupEnabled())
|
||||||
{
|
{
|
||||||
CollectMultiplePickups(lara->InteractedItem);
|
CollectMultiplePickups(lara->Context.InteractedItem);
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,13 +389,13 @@ void DoPickup(ItemInfo* laraItem)
|
||||||
|
|
||||||
pickupItem->Pose.Orientation = prevOrient;
|
pickupItem->Pose.Orientation = prevOrient;
|
||||||
KillItem(pickupItemNumber);
|
KillItem(pickupItemNumber);
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = NO_ITEM;
|
lara->Context.InteractedItem = NO_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
|
@ -430,7 +430,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
item->ObjectNumber != ID_BURNING_TORCH_ITEM &&
|
item->ObjectNumber != ID_BURNING_TORCH_ITEM &&
|
||||||
laraItem->Animation.ActiveState == LS_UNDERWATER_IDLE &&
|
laraItem->Animation.ActiveState == LS_UNDERWATER_IDLE &&
|
||||||
lara->Control.HandStatus == HandStatus::Free &&
|
lara->Control.HandStatus == HandStatus::Free &&
|
||||||
TestLaraPosition(PickUpBoundsUW, item, laraItem) || lara->Control.IsMoving && lara->InteractedItem == itemNumber)
|
TestLaraPosition(PickUpBoundsUW, item, laraItem) || lara->Control.IsMoving && lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
if (TestLaraPosition(PickUpBoundsUW, item, laraItem))
|
if (TestLaraPosition(PickUpBoundsUW, item, laraItem))
|
||||||
{
|
{
|
||||||
|
@ -454,13 +454,13 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
lara->Control.HandStatus = HandStatus::Busy;
|
lara->Control.HandStatus = HandStatus::Busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lara->Control.IsMoving)
|
if (lara->Control.IsMoving)
|
||||||
{
|
{
|
||||||
if (lara->InteractedItem == itemNumber)
|
if (lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
@ -486,7 +486,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
if (!lara->Control.IsMoving)
|
if (!lara->Control.IsMoving)
|
||||||
{
|
{
|
||||||
if (lara->InteractedItem == itemNumber)
|
if (lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
if (laraItem->Animation.ActiveState != LS_PICKUP && laraItem->Animation.ActiveState != LS_HOLE)
|
if (laraItem->Animation.ActiveState != LS_PICKUP && laraItem->Animation.ActiveState != LS_HOLE)
|
||||||
{
|
{
|
||||||
|
@ -501,7 +501,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->InteractedItem != itemNumber)
|
if (lara->Context.InteractedItem != itemNumber)
|
||||||
{
|
{
|
||||||
item->Pose.Orientation = prevOrient;
|
item->Pose.Orientation = prevOrient;
|
||||||
return;
|
return;
|
||||||
|
@ -519,7 +519,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
if (lara->Control.IsMoving)
|
if (lara->Control.IsMoving)
|
||||||
{
|
{
|
||||||
if (lara->InteractedItem == itemNumber)
|
if (lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
@ -536,7 +536,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Pick up with crowbar.
|
// Pick up with crowbar.
|
||||||
|
@ -551,7 +551,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->InteractedItem == itemNumber)
|
if (lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
@ -590,7 +590,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Pick up from plinth.
|
// Pick up from plinth.
|
||||||
|
@ -642,7 +642,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,7 +652,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->InteractedItem == itemNumber)
|
if (lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
@ -679,7 +679,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Pick up from ground.
|
// Pick up from ground.
|
||||||
|
@ -692,7 +692,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lara->InteractedItem == itemNumber)
|
if (lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
@ -716,7 +716,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
laraItem->Animation.AnimNumber = LA_CROUCH_PICKUP_FLARE;
|
laraItem->Animation.AnimNumber = LA_CROUCH_PICKUP_FLARE;
|
||||||
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
|
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
flag = true;
|
flag = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -741,14 +741,14 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
laraItem->Animation.TargetState = LS_PICKUP;
|
laraItem->Animation.TargetState = LS_PICKUP;
|
||||||
}
|
}
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!MoveLaraPosition(PickUpPosition, item, laraItem))
|
if (!MoveLaraPosition(PickUpPosition, item, laraItem))
|
||||||
{
|
{
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +756,7 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
{
|
{
|
||||||
laraItem->Animation.AnimNumber = LA_PICKUP;
|
laraItem->Animation.AnimNumber = LA_PICKUP;
|
||||||
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
|
laraItem->Animation.ActiveState = LS_PICKUP_FLARE;
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
flag = true;
|
flag = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -769,14 +769,14 @@ void PickupCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||||
ResetLaraFlex(laraItem);
|
ResetPlayerFlex(laraItem);
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Busy;
|
lara->Control.HandStatus = HandStatus::Busy;
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1071,7 @@ GameBoundingBox* FindPlinth(ItemInfo* item)
|
||||||
return &GetBestFrame(g_Level.Items[itemNumber]).BoundingBox;
|
return &GetBestFrame(g_Level.Items[itemNumber]).BoundingBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialisePickup(short itemNumber)
|
void InitializePickup(short itemNumber)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
|
|
||||||
|
@ -1130,7 +1130,7 @@ void InitialisePickup(short itemNumber)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseSearchObject(short itemNumber)
|
void InitializeSearchObject(short itemNumber)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNumber];
|
auto* item = &g_Level.Items[itemNumber];
|
||||||
if (item->ObjectNumber == ID_SEARCH_OBJECT1)
|
if (item->ObjectNumber == ID_SEARCH_OBJECT1)
|
||||||
|
@ -1183,7 +1183,7 @@ void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo*
|
||||||
laraItem->Animation.AnimNumber == LA_STAND_IDLE &&
|
laraItem->Animation.AnimNumber == LA_STAND_IDLE &&
|
||||||
lara->Control.HandStatus == HandStatus::Free &&
|
lara->Control.HandStatus == HandStatus::Free &&
|
||||||
((item->Status == ITEM_NOT_ACTIVE && item->ObjectNumber != ID_SEARCH_OBJECT4) || !item->ItemFlags[0])) ||
|
((item->Status == ITEM_NOT_ACTIVE && item->ObjectNumber != ID_SEARCH_OBJECT4) || !item->ItemFlags[0])) ||
|
||||||
(lara->Control.IsMoving && lara->InteractedItem == itemNumber))
|
(lara->Control.IsMoving && lara->Context.InteractedItem == itemNumber))
|
||||||
{
|
{
|
||||||
auto bounds = GameBoundingBox(item);
|
auto bounds = GameBoundingBox(item);
|
||||||
if (item->ObjectNumber != ID_SEARCH_OBJECT1)
|
if (item->ObjectNumber != ID_SEARCH_OBJECT1)
|
||||||
|
@ -1205,7 +1205,7 @@ void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo*
|
||||||
{
|
{
|
||||||
if (MoveLaraPosition(SOPos, item, laraItem))
|
if (MoveLaraPosition(SOPos, item, laraItem))
|
||||||
{
|
{
|
||||||
ResetLaraFlex(laraItem);
|
ResetPlayerFlex(laraItem);
|
||||||
laraItem->Animation.AnimNumber = SearchAnims[objectNumber];
|
laraItem->Animation.AnimNumber = SearchAnims[objectNumber];
|
||||||
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||||
laraItem->Animation.ActiveState = LS_MISC_CONTROL;
|
laraItem->Animation.ActiveState = LS_MISC_CONTROL;
|
||||||
|
@ -1225,9 +1225,9 @@ void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo*
|
||||||
AnimateItem(item);
|
AnimateItem(item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lara->InteractedItem = itemNumber;
|
lara->Context.InteractedItem = itemNumber;
|
||||||
}
|
}
|
||||||
else if (lara->Control.IsMoving && lara->InteractedItem == itemNumber)
|
else if (lara->Control.IsMoving && lara->Context.InteractedItem == itemNumber)
|
||||||
{
|
{
|
||||||
lara->Control.IsMoving = false;
|
lara->Control.IsMoving = false;
|
||||||
lara->Control.HandStatus = HandStatus::Free;
|
lara->Control.HandStatus = HandStatus::Free;
|
||||||
|
@ -1363,7 +1363,7 @@ bool UseSpecialItem(ItemInfo* laraItem)
|
||||||
|
|
||||||
if (flag == 1)
|
if (flag == 1)
|
||||||
{
|
{
|
||||||
if (itemIDToUse != ID_WATERSKIN1_3 && itemIDToUse != ID_WATERSKIN2_5 && (lara->WaterSurfaceDist < -SHALLOW_WATER_DEPTH))
|
if (itemIDToUse != ID_WATERSKIN1_3 && itemIDToUse != ID_WATERSKIN2_5 && (lara->Context.WaterSurfaceDist < -SHALLOW_WATER_DEPTH))
|
||||||
{
|
{
|
||||||
if (itemIDToUse < ID_WATERSKIN1_3)
|
if (itemIDToUse < ID_WATERSKIN1_3)
|
||||||
lara->Inventory.SmallWaterskin = 4;
|
lara->Inventory.SmallWaterskin = 4;
|
||||||
|
|
|
@ -10,7 +10,7 @@ extern int NumRPickups;
|
||||||
extern short RPickups[16];
|
extern short RPickups[16];
|
||||||
extern Vector3i OldPickupPos;
|
extern Vector3i OldPickupPos;
|
||||||
|
|
||||||
void InitialisePickup(short itemNumber);
|
void InitializePickup(short itemNumber);
|
||||||
bool SetInventoryCount(GAME_OBJECT_ID objectID, int count);
|
bool SetInventoryCount(GAME_OBJECT_ID objectID, int count);
|
||||||
void PickedUpObject(GAME_OBJECT_ID objectID, std::optional<int> count = std::nullopt);
|
void PickedUpObject(GAME_OBJECT_ID objectID, std::optional<int> count = std::nullopt);
|
||||||
void RemoveObjectFromInventory(GAME_OBJECT_ID objectID, std::optional<int> count = std::nullopt);
|
void RemoveObjectFromInventory(GAME_OBJECT_ID objectID, std::optional<int> count = std::nullopt);
|
||||||
|
@ -24,7 +24,7 @@ GameBoundingBox* FindPlinth(ItemInfo* item);
|
||||||
|
|
||||||
void PickupControl(short itemNumber);
|
void PickupControl(short itemNumber);
|
||||||
|
|
||||||
void InitialiseSearchObject(short itemNumber);
|
void InitializeSearchObject(short itemNumber);
|
||||||
void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
|
void SearchObjectCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
|
||||||
void SearchObjectControl(short itemNumber);
|
void SearchObjectControl(short itemNumber);
|
||||||
void DoPickup(ItemInfo* laraItem);
|
void DoPickup(ItemInfo* laraItem);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Renderer/Renderer11.h"
|
#include "Renderer/Renderer11.h"
|
||||||
|
|
||||||
using namespace TEN::Floordata;
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Renderer;
|
using namespace TEN::Renderer;
|
||||||
|
|
||||||
byte FlipStatus = 0;
|
byte FlipStatus = 0;
|
||||||
|
|
|
@ -1,11 +1,43 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "framework.h"
|
#include "framework.h"
|
||||||
#include "Game/collision/floordata.h"
|
#include "Game/collision/floordata.h"
|
||||||
#include "Specific/newtypes.h"
|
|
||||||
#include "Math/Math.h"
|
#include "Math/Math.h"
|
||||||
|
#include "Specific/newtypes.h"
|
||||||
|
|
||||||
struct TriggerVolume;
|
|
||||||
enum class ReverbType;
|
enum class ReverbType;
|
||||||
|
struct TriggerVolume;
|
||||||
|
|
||||||
|
constexpr auto MAX_FLIPMAP = 256;
|
||||||
|
constexpr auto NUM_ROOMS = 1024;
|
||||||
|
constexpr auto NO_ROOM = -1;
|
||||||
|
constexpr auto OUTSIDE_Z = 64;
|
||||||
|
constexpr auto OUTSIDE_SIZE = 1024;
|
||||||
|
|
||||||
|
extern byte FlipStatus;
|
||||||
|
extern int FlipStats[MAX_FLIPMAP];
|
||||||
|
extern int FlipMap[MAX_FLIPMAP];
|
||||||
|
|
||||||
|
enum RoomEnvFlags
|
||||||
|
{
|
||||||
|
ENV_FLAG_WATER = (1 << 0),
|
||||||
|
ENV_FLAG_SWAMP = (1 << 2),
|
||||||
|
ENV_FLAG_OUTSIDE = (1 << 3),
|
||||||
|
ENV_FLAG_DYNAMIC_LIT = (1 << 4),
|
||||||
|
ENV_FLAG_WIND = (1 << 5),
|
||||||
|
ENV_FLAG_NOT_NEAR_OUTSIDE = (1 << 6),
|
||||||
|
ENV_FLAG_NO_LENSFLARE = (1 << 7),
|
||||||
|
ENV_FLAG_MIST = (1 << 8),
|
||||||
|
ENV_FLAG_CAUSTICS = (1 << 9),
|
||||||
|
ENV_FLAG_UNKNOWN3 = (1 << 10),
|
||||||
|
ENV_FLAG_DAMAGE = (1 << 11),
|
||||||
|
ENV_FLAG_COLD = (1 << 12)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StaticMeshFlags : short
|
||||||
|
{
|
||||||
|
SM_VISIBLE = 1,
|
||||||
|
SM_SOLID = 2
|
||||||
|
};
|
||||||
|
|
||||||
struct ROOM_VERTEX
|
struct ROOM_VERTEX
|
||||||
{
|
{
|
||||||
|
@ -13,8 +45,8 @@ struct ROOM_VERTEX
|
||||||
Vector3 normal;
|
Vector3 normal;
|
||||||
Vector2 textureCoordinates;
|
Vector2 textureCoordinates;
|
||||||
Vector3 color;
|
Vector3 color;
|
||||||
int effects;
|
int effects;
|
||||||
int index;
|
int index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ROOM_DOOR
|
struct ROOM_DOOR
|
||||||
|
@ -53,44 +85,22 @@ struct MESH_INFO
|
||||||
|
|
||||||
struct LIGHTINFO
|
struct LIGHTINFO
|
||||||
{
|
{
|
||||||
int x; // size=0, offset=0
|
int x;
|
||||||
int y; // size=0, offset=4
|
int y;
|
||||||
int z; // size=0, offset=8
|
int z;
|
||||||
unsigned char Type; // size=0, offset=12
|
unsigned char Type;
|
||||||
unsigned char r; // size=0, offset=13
|
unsigned char r;
|
||||||
unsigned char g; // size=0, offset=14
|
unsigned char g;
|
||||||
unsigned char b; // size=0, offset=15
|
unsigned char b;
|
||||||
short nx; // size=0, offset=16
|
short nx;
|
||||||
short ny; // size=0, offset=18
|
short ny;
|
||||||
short nz; // size=0, offset=20
|
short nz;
|
||||||
short Intensity; // size=0, offset=22
|
short Intensity;
|
||||||
unsigned char Inner; // size=0, offset=24
|
unsigned char Inner;
|
||||||
unsigned char Outer; // size=0, offset=25
|
unsigned char Outer;
|
||||||
short FalloffScale; // size=0, offset=26
|
short FalloffScale;
|
||||||
short Length; // size=0, offset=28
|
short Length;
|
||||||
short Cutoff; // size=0, offset=30
|
short Cutoff;
|
||||||
};
|
|
||||||
|
|
||||||
enum RoomEnvFlags
|
|
||||||
{
|
|
||||||
ENV_FLAG_WATER = (1 << 0),
|
|
||||||
ENV_FLAG_SWAMP = (1 << 2),
|
|
||||||
ENV_FLAG_OUTSIDE = (1 << 3),
|
|
||||||
ENV_FLAG_DYNAMIC_LIT = (1 << 4),
|
|
||||||
ENV_FLAG_WIND = (1 << 5),
|
|
||||||
ENV_FLAG_NOT_NEAR_OUTSIDE = (1 << 6),
|
|
||||||
ENV_FLAG_NO_LENSFLARE = (1 << 7),
|
|
||||||
ENV_FLAG_MIST = (1 << 8),
|
|
||||||
ENV_FLAG_CAUSTICS = (1 << 9),
|
|
||||||
ENV_FLAG_UNKNOWN3 = (1 << 10),
|
|
||||||
ENV_FLAG_DAMAGE = (1 << 11),
|
|
||||||
ENV_FLAG_COLD = (1 << 12)
|
|
||||||
};
|
|
||||||
|
|
||||||
enum StaticMeshFlags : short
|
|
||||||
{
|
|
||||||
SM_VISIBLE = 1,
|
|
||||||
SM_SOLID = 2
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ROOM_INFO
|
struct ROOM_INFO
|
||||||
|
@ -113,36 +123,26 @@ struct ROOM_INFO
|
||||||
short fxNumber;
|
short fxNumber;
|
||||||
bool boundActive;
|
bool boundActive;
|
||||||
|
|
||||||
std::string name;
|
std::string name = {};
|
||||||
std::vector<std::string> tags;
|
std::vector<std::string> tags = {};
|
||||||
|
|
||||||
std::vector<FloorInfo> floor;
|
std::vector<FloorInfo> floor = {};
|
||||||
std::vector<ROOM_LIGHT> lights;
|
std::vector<ROOM_LIGHT> lights = {};
|
||||||
std::vector<MESH_INFO> mesh;
|
std::vector<MESH_INFO> mesh = {};
|
||||||
std::vector<TriggerVolume> triggerVolumes;
|
std::vector<TriggerVolume> triggerVolumes = {};
|
||||||
|
|
||||||
std::vector<Vector3> positions;
|
std::vector<Vector3> positions = {};
|
||||||
std::vector<Vector3> normals;
|
std::vector<Vector3> normals = {};
|
||||||
std::vector<Vector3> colors;
|
std::vector<Vector3> colors = {};
|
||||||
std::vector<Vector3> effects;
|
std::vector<Vector3> effects = {};
|
||||||
std::vector<BUCKET> buckets;
|
std::vector<BUCKET> buckets = {};
|
||||||
std::vector<ROOM_DOOR> doors;
|
std::vector<ROOM_DOOR> doors = {};
|
||||||
|
|
||||||
std::vector<int> neighbors; // TODO: Move to level struct
|
std::vector<int> neighbors = {};
|
||||||
|
|
||||||
bool Active();
|
bool Active();
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto MAX_FLIPMAP = 256;
|
|
||||||
constexpr auto NUM_ROOMS = 1024;
|
|
||||||
constexpr auto NO_ROOM = -1;
|
|
||||||
constexpr auto OUTSIDE_Z = 64;
|
|
||||||
constexpr auto OUTSIDE_SIZE = 1024;
|
|
||||||
|
|
||||||
extern byte FlipStatus;
|
|
||||||
extern int FlipStats[MAX_FLIPMAP];
|
|
||||||
extern int FlipMap[MAX_FLIPMAP];
|
|
||||||
|
|
||||||
void DoFlipMap(short group);
|
void DoFlipMap(short group);
|
||||||
void AddRoomFlipItems(ROOM_INFO* room);
|
void AddRoomFlipItems(ROOM_INFO* room);
|
||||||
void RemoveRoomFlipItems(ROOM_INFO* room);
|
void RemoveRoomFlipItems(ROOM_INFO* room);
|
||||||
|
|
|
@ -18,31 +18,30 @@
|
||||||
#include "Game/misc.h"
|
#include "Game/misc.h"
|
||||||
#include "Game/spotcam.h"
|
#include "Game/spotcam.h"
|
||||||
#include "Game/room.h"
|
#include "Game/room.h"
|
||||||
|
#include "Game/Setup.h"
|
||||||
#include "Objects/Generic/Object/rope.h"
|
#include "Objects/Generic/Object/rope.h"
|
||||||
#include "Objects/Generic/Switches/fullblock_switch.h"
|
#include "Objects/Generic/Switches/fullblock_switch.h"
|
||||||
#include "Objects/Generic/Traps/traps.h"
|
|
||||||
#include "Objects/Generic/puzzles_keys.h"
|
#include "Objects/Generic/puzzles_keys.h"
|
||||||
#include "Objects/Sink.h"
|
#include "Objects/Sink.h"
|
||||||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||||
#include "Objects/TR5/Emitter/tr5_rats_emitter.h"
|
#include "Objects/TR5/Emitter/tr5_rats_emitter.h"
|
||||||
#include "Objects/TR5/Emitter/tr5_bats_emitter.h"
|
#include "Objects/TR5/Emitter/tr5_bats_emitter.h"
|
||||||
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
|
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
|
||||||
|
#include "Scripting/Include/ScriptInterfaceGame.h"
|
||||||
|
#include "Scripting/Include/ScriptInterfaceLevel.h"
|
||||||
|
#include "Scripting/Include/Objects/ScriptInterfaceObjectsHandler.h"
|
||||||
#include "Sound/sound.h"
|
#include "Sound/sound.h"
|
||||||
#include "Specific/clock.h"
|
#include "Specific/clock.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/setup.h"
|
|
||||||
#include "Specific/savegame/flatbuffers/ten_savegame_generated.h"
|
#include "Specific/savegame/flatbuffers/ten_savegame_generated.h"
|
||||||
#include "ScriptInterfaceLevel.h"
|
|
||||||
#include "ScriptInterfaceGame.h"
|
|
||||||
#include "Objects/ScriptInterfaceObjectsHandler.h"
|
|
||||||
|
|
||||||
|
using namespace flatbuffers;
|
||||||
|
using namespace TEN::Collision::Floordata;
|
||||||
using namespace TEN::Control::Volumes;
|
using namespace TEN::Control::Volumes;
|
||||||
|
using namespace TEN::Entities::Generic;
|
||||||
using namespace TEN::Effects::Items;
|
using namespace TEN::Effects::Items;
|
||||||
using namespace TEN::Entities::Switches;
|
using namespace TEN::Entities::Switches;
|
||||||
using namespace TEN::Entities::TR4;
|
using namespace TEN::Entities::TR4;
|
||||||
using namespace TEN::Entities::Generic;
|
|
||||||
using namespace TEN::Floordata;
|
|
||||||
using namespace flatbuffers;
|
|
||||||
|
|
||||||
namespace Save = TEN::Save;
|
namespace Save = TEN::Save;
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ void LoadSavegameInfos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pose ToPHD(Save::Position const* src)
|
Pose ToPHD(const Save::Position* src)
|
||||||
{
|
{
|
||||||
Pose dest;
|
Pose dest;
|
||||||
dest.Position.x = src->x_pos();
|
dest.Position.x = src->x_pos();
|
||||||
|
@ -92,9 +91,10 @@ Pose ToPHD(Save::Position const* src)
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
Save::Position FromPHD(Pose const& src)
|
Save::Position FromPHD(const Pose& src)
|
||||||
{
|
{
|
||||||
return Save::Position{
|
return Save::Position
|
||||||
|
{
|
||||||
src.Position.x,
|
src.Position.x,
|
||||||
src.Position.y,
|
src.Position.y,
|
||||||
src.Position.z,
|
src.Position.z,
|
||||||
|
@ -104,6 +104,11 @@ Save::Position FromPHD(Pose const& src)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Save::Vector2 FromVector2(Vector2i vec)
|
||||||
|
{
|
||||||
|
return Save::Vector2(vec.x, vec.y);
|
||||||
|
}
|
||||||
|
|
||||||
Save::Vector3 FromVector3(Vector3 vec)
|
Save::Vector3 FromVector3(Vector3 vec)
|
||||||
{
|
{
|
||||||
return Save::Vector3(vec.x, vec.y, vec.z);
|
return Save::Vector3(vec.x, vec.y, vec.z);
|
||||||
|
@ -126,12 +131,17 @@ Save::Vector4 FromVector4(Vector4 vec)
|
||||||
|
|
||||||
EulerAngles ToEulerAngles(const Save::Vector3* vec)
|
EulerAngles ToEulerAngles(const Save::Vector3* vec)
|
||||||
{
|
{
|
||||||
return EulerAngles(short(vec->x()), short(vec->y()), short(vec->z()));
|
return EulerAngles((short)vec->x(), (short)vec->y(), (short)vec->z());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2i ToVector2i(const Save::Vector2* vec)
|
||||||
|
{
|
||||||
|
return Vector2i((int)vec->x(), (int)vec->y());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3i ToVector3i(const Save::Vector3* vec)
|
Vector3i ToVector3i(const Save::Vector3* vec)
|
||||||
{
|
{
|
||||||
return Vector3i(int(vec->x()), int(vec->y()), int(vec->z()));
|
return Vector3i((int)vec->x(), (int)vec->y(), (int)vec->z());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 ToVector3(const Save::Vector3* vec)
|
Vector3 ToVector3(const Save::Vector3* vec)
|
||||||
|
@ -149,10 +159,10 @@ Vector4 ToVector4(const Save::Vector4* vec)
|
||||||
return Vector4(vec->x(), vec->y(), vec->z(), vec->w());
|
return Vector4(vec->x(), vec->y(), vec->z(), vec->w());
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SaveVec(Type, Data, TableBuilder, UnionType) \
|
#define SaveVec(Type, Data, TableBuilder, UnionType, SaveType, ConversionFunc) \
|
||||||
auto data = std::get<(int)Type>(Data); \
|
auto data = std::get<(int)Type>(Data); \
|
||||||
TableBuilder vtb{ fbb }; \
|
TableBuilder vtb{ fbb }; \
|
||||||
Save::Vector3 saveVec = FromVector3(data); \
|
SaveType saveVec = ConversionFunc(data); \
|
||||||
vtb.add_vec(&saveVec); \
|
vtb.add_vec(&saveVec); \
|
||||||
auto vecOffset = vtb.Finish(); \
|
auto vecOffset = vtb.Finish(); \
|
||||||
putDataInVec(UnionType, vecOffset);
|
putDataInVec(UnionType, vecOffset);
|
||||||
|
@ -389,7 +399,7 @@ bool SaveGame::Save(int slot)
|
||||||
Save::LaraControlDataBuilder control{ fbb };
|
Save::LaraControlDataBuilder control{ fbb };
|
||||||
control.add_move_angle(Lara.Control.MoveAngle);
|
control.add_move_angle(Lara.Control.MoveAngle);
|
||||||
control.add_turn_rate(Lara.Control.TurnRate);
|
control.add_turn_rate(Lara.Control.TurnRate);
|
||||||
control.add_calculated_jump_velocity(Lara.Control.CalculatedJumpVelocity);
|
control.add_calculated_jump_velocity(Lara.Context.CalcJumpVelocity);
|
||||||
control.add_jump_direction((int)Lara.Control.JumpDirection);
|
control.add_jump_direction((int)Lara.Control.JumpDirection);
|
||||||
control.add_hand_status((int)Lara.Control.HandStatus);
|
control.add_hand_status((int)Lara.Control.HandStatus);
|
||||||
control.add_is_moving(Lara.Control.IsMoving);
|
control.add_is_moving(Lara.Control.IsMoving);
|
||||||
|
@ -452,7 +462,7 @@ bool SaveGame::Save(int slot)
|
||||||
|
|
||||||
Save::LaraBuilder lara{ fbb };
|
Save::LaraBuilder lara{ fbb };
|
||||||
lara.add_control(controlOffset);
|
lara.add_control(controlOffset);
|
||||||
lara.add_next_corner_pose(&FromPHD(Lara.NextCornerPos));
|
lara.add_next_corner_pose(&FromPHD(Lara.Context.NextCornerPos));
|
||||||
lara.add_effect(effectOffset);
|
lara.add_effect(effectOffset);
|
||||||
lara.add_extra_anim(Lara.ExtraAnim);
|
lara.add_extra_anim(Lara.ExtraAnim);
|
||||||
lara.add_extra_head_rot(&FromVector3(Lara.ExtraHeadRot));
|
lara.add_extra_head_rot(&FromVector3(Lara.ExtraHeadRot));
|
||||||
|
@ -461,23 +471,23 @@ bool SaveGame::Save(int slot)
|
||||||
lara.add_highest_location(Lara.HighestLocation);
|
lara.add_highest_location(Lara.HighestLocation);
|
||||||
lara.add_hit_direction(Lara.HitDirection);
|
lara.add_hit_direction(Lara.HitDirection);
|
||||||
lara.add_hit_frame(Lara.HitFrame);
|
lara.add_hit_frame(Lara.HitFrame);
|
||||||
lara.add_interacted_item(Lara.InteractedItem);
|
lara.add_interacted_item(Lara.Context.InteractedItem);
|
||||||
lara.add_inventory(inventoryOffset);
|
lara.add_inventory(inventoryOffset);
|
||||||
lara.add_item_number(Lara.ItemNumber);
|
lara.add_item_number(Lara.ItemNumber);
|
||||||
lara.add_left_arm(leftArmOffset);
|
lara.add_left_arm(leftArmOffset);
|
||||||
lara.add_location(Lara.Location);
|
lara.add_location(Lara.Location);
|
||||||
lara.add_location_pad(Lara.LocationPad);
|
lara.add_location_pad(Lara.LocationPad);
|
||||||
lara.add_projected_floor_height(Lara.ProjectedFloorHeight);
|
lara.add_projected_floor_height(Lara.Context.ProjectedFloorHeight);
|
||||||
lara.add_right_arm(rightArmOffset);
|
lara.add_right_arm(rightArmOffset);
|
||||||
lara.add_status(statusOffset);
|
lara.add_status(statusOffset);
|
||||||
lara.add_target_facing_angle(Lara.TargetOrientation.y);
|
lara.add_target_facing_angle(Lara.Context.TargetOrientation.y);
|
||||||
lara.add_target_arm_angles(laraTargetAnglesOffset);
|
lara.add_target_arm_angles(laraTargetAnglesOffset);
|
||||||
lara.add_target_entity_number(Lara.TargetEntity - g_Level.Items.data());
|
lara.add_target_entity_number(Lara.TargetEntity - g_Level.Items.data());
|
||||||
lara.add_torch(torchOffset);
|
lara.add_torch(torchOffset);
|
||||||
lara.add_vehicle(Lara.Vehicle);
|
lara.add_vehicle(Lara.Context.Vehicle);
|
||||||
lara.add_water_current_active(Lara.WaterCurrentActive);
|
lara.add_water_current_active(Lara.Context.WaterCurrentActive);
|
||||||
lara.add_water_current_pull(&FromVector3(Lara.WaterCurrentPull));
|
lara.add_water_current_pull(&FromVector3(Lara.Context.WaterCurrentPull));
|
||||||
lara.add_water_surface_dist(Lara.WaterSurfaceDist);
|
lara.add_water_surface_dist(Lara.Context.WaterSurfaceDist);
|
||||||
lara.add_weapons(carriedWeaponsOffset);
|
lara.add_weapons(carriedWeaponsOffset);
|
||||||
auto laraOffset = lara.Finish();
|
auto laraOffset = lara.Finish();
|
||||||
|
|
||||||
|
@ -527,8 +537,7 @@ bool SaveGame::Save(int slot)
|
||||||
flatbuffers::Offset<Save::Short> shortOffset;
|
flatbuffers::Offset<Save::Short> shortOffset;
|
||||||
flatbuffers::Offset<Save::Int> intOffset;
|
flatbuffers::Offset<Save::Int> intOffset;
|
||||||
|
|
||||||
if (Objects[itemToSerialize.ObjectNumber].intelligent
|
if (Objects[itemToSerialize.ObjectNumber].intelligent && itemToSerialize.IsCreature())
|
||||||
&& itemToSerialize.Data.is<CreatureInfo>())
|
|
||||||
{
|
{
|
||||||
auto creature = GetCreatureInfo(&itemToSerialize);
|
auto creature = GetCreatureInfo(&itemToSerialize);
|
||||||
|
|
||||||
|
@ -538,12 +547,10 @@ bool SaveGame::Save(int slot)
|
||||||
auto jointRotationsOffset = fbb.CreateVector(jointRotations);
|
auto jointRotationsOffset = fbb.CreateVector(jointRotations);
|
||||||
|
|
||||||
Save::CreatureBuilder creatureBuilder{ fbb };
|
Save::CreatureBuilder creatureBuilder{ fbb };
|
||||||
|
|
||||||
creatureBuilder.add_alerted(creature->Alerted);
|
creatureBuilder.add_alerted(creature->Alerted);
|
||||||
creatureBuilder.add_can_jump(creature->LOT.CanJump);
|
creatureBuilder.add_can_jump(creature->LOT.CanJump);
|
||||||
creatureBuilder.add_can_monkey(creature->LOT.CanMonkey);
|
creatureBuilder.add_can_monkey(creature->LOT.CanMonkey);
|
||||||
creatureBuilder.add_enemy(creature->Enemy - g_Level.Items.data());
|
creatureBuilder.add_enemy(creature->Enemy - g_Level.Items.data());
|
||||||
creatureBuilder.add_fired_weapon(creature->FiredWeapon);
|
|
||||||
creatureBuilder.add_flags(creature->Flags);
|
creatureBuilder.add_flags(creature->Flags);
|
||||||
creatureBuilder.add_friendly(creature->Friendly);
|
creatureBuilder.add_friendly(creature->Friendly);
|
||||||
creatureBuilder.add_head_left(creature->HeadLeft);
|
creatureBuilder.add_head_left(creature->HeadLeft);
|
||||||
|
@ -555,6 +562,8 @@ bool SaveGame::Save(int slot)
|
||||||
creatureBuilder.add_joint_rotation(jointRotationsOffset);
|
creatureBuilder.add_joint_rotation(jointRotationsOffset);
|
||||||
creatureBuilder.add_jump_ahead(creature->JumpAhead);
|
creatureBuilder.add_jump_ahead(creature->JumpAhead);
|
||||||
creatureBuilder.add_location_ai(creature->LocationAI);
|
creatureBuilder.add_location_ai(creature->LocationAI);
|
||||||
|
creatureBuilder.add_weapon_delay1(creature->MuzzleFlash[0].Delay);
|
||||||
|
creatureBuilder.add_weapon_delay2(creature->MuzzleFlash[1].Delay);
|
||||||
creatureBuilder.add_maximum_turn(creature->MaxTurn);
|
creatureBuilder.add_maximum_turn(creature->MaxTurn);
|
||||||
creatureBuilder.add_monkey_swing_ahead(creature->MonkeySwingAhead);
|
creatureBuilder.add_monkey_swing_ahead(creature->MonkeySwingAhead);
|
||||||
creatureBuilder.add_mood((int)creature->Mood);
|
creatureBuilder.add_mood((int)creature->Mood);
|
||||||
|
@ -1164,16 +1173,24 @@ bool SaveGame::Save(int slot)
|
||||||
{
|
{
|
||||||
switch (SavedVarType(s.index()))
|
switch (SavedVarType(s.index()))
|
||||||
{
|
{
|
||||||
|
case SavedVarType::Vec2:
|
||||||
|
{
|
||||||
|
SaveVec(SavedVarType::Vec2, s, Save::vec2TableBuilder, Save::VarUnion::vec2, Save::Vector2, FromVector2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case SavedVarType::Vec3:
|
case SavedVarType::Vec3:
|
||||||
{
|
{
|
||||||
SaveVec(SavedVarType::Vec3, s, Save::vec3TableBuilder, Save::VarUnion::vec3);
|
SaveVec(SavedVarType::Vec3, s, Save::vec3TableBuilder, Save::VarUnion::vec3, Save::Vector3, FromVector3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SavedVarType::Rotation:
|
case SavedVarType::Rotation:
|
||||||
{
|
{
|
||||||
SaveVec(SavedVarType::Rotation, s, Save::rotationTableBuilder, Save::VarUnion::rotation);
|
SaveVec(SavedVarType::Rotation, s, Save::rotationTableBuilder, Save::VarUnion::rotation, Save::Vector3, FromVector3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SavedVarType::Color:
|
case SavedVarType::Color:
|
||||||
{
|
{
|
||||||
Save::colorTableBuilder ctb{ fbb };
|
Save::colorTableBuilder ctb{ fbb };
|
||||||
|
@ -1183,18 +1200,51 @@ bool SaveGame::Save(int slot)
|
||||||
putDataInVec(Save::VarUnion::color, offset);
|
putDataInVec(Save::VarUnion::color, offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto unionVec = fbb.CreateVector(varsVec);
|
auto unionVec = fbb.CreateVector(varsVec);
|
||||||
Save::UnionVecBuilder uvb{ fbb };
|
Save::UnionVecBuilder uvb{ fbb };
|
||||||
uvb.add_members(unionVec);
|
uvb.add_members(unionVec);
|
||||||
auto unionVecOffset = uvb.Finish();
|
auto unionVecOffset = uvb.Finish();
|
||||||
|
|
||||||
|
std::vector<std::string> callbackVecPreStart;
|
||||||
|
std::vector<std::string> callbackVecPostStart;
|
||||||
|
|
||||||
|
std::vector<std::string> callbackVecPreEnd;
|
||||||
|
std::vector<std::string> callbackVecPostEnd;
|
||||||
|
|
||||||
|
std::vector<std::string> callbackVecPreSave;
|
||||||
|
std::vector<std::string> callbackVecPostSave;
|
||||||
|
|
||||||
|
std::vector<std::string> callbackVecPreLoad;
|
||||||
|
std::vector<std::string> callbackVecPostLoad;
|
||||||
|
|
||||||
std::vector<std::string> callbackVecPreControl;
|
std::vector<std::string> callbackVecPreControl;
|
||||||
std::vector<std::string> callbackVecPostControl;
|
std::vector<std::string> callbackVecPostControl;
|
||||||
g_GameScript->GetCallbackStrings(callbackVecPreControl, callbackVecPostControl);
|
|
||||||
|
|
||||||
|
g_GameScript->GetCallbackStrings(
|
||||||
|
callbackVecPreStart,
|
||||||
|
callbackVecPostStart,
|
||||||
|
callbackVecPreEnd,
|
||||||
|
callbackVecPostEnd,
|
||||||
|
callbackVecPreSave,
|
||||||
|
callbackVecPostSave,
|
||||||
|
callbackVecPreLoad,
|
||||||
|
callbackVecPostLoad,
|
||||||
|
callbackVecPreControl,
|
||||||
|
callbackVecPostControl);
|
||||||
|
|
||||||
|
auto stringsCallbackPreStart = fbb.CreateVectorOfStrings(callbackVecPreStart);
|
||||||
|
auto stringsCallbackPostStart = fbb.CreateVectorOfStrings(callbackVecPostStart);
|
||||||
|
auto stringsCallbackPreEnd = fbb.CreateVectorOfStrings(callbackVecPreEnd);
|
||||||
|
auto stringsCallbackPostEnd = fbb.CreateVectorOfStrings(callbackVecPostEnd);
|
||||||
|
auto stringsCallbackPreSave = fbb.CreateVectorOfStrings(callbackVecPreSave);
|
||||||
|
auto stringsCallbackPostSave = fbb.CreateVectorOfStrings(callbackVecPostSave);
|
||||||
|
auto stringsCallbackPreLoad = fbb.CreateVectorOfStrings(callbackVecPreLoad);
|
||||||
|
auto stringsCallbackPostLoad = fbb.CreateVectorOfStrings(callbackVecPostLoad);
|
||||||
auto stringsCallbackPreControl = fbb.CreateVectorOfStrings(callbackVecPreControl);
|
auto stringsCallbackPreControl = fbb.CreateVectorOfStrings(callbackVecPreControl);
|
||||||
auto stringsCallbackPostControl = fbb.CreateVectorOfStrings(callbackVecPostControl);
|
auto stringsCallbackPostControl = fbb.CreateVectorOfStrings(callbackVecPostControl);
|
||||||
|
|
||||||
|
@ -1243,6 +1293,19 @@ bool SaveGame::Save(int slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
sgb.add_script_vars(unionVecOffset);
|
sgb.add_script_vars(unionVecOffset);
|
||||||
|
|
||||||
|
sgb.add_callbacks_pre_start(stringsCallbackPreStart);
|
||||||
|
sgb.add_callbacks_post_start(stringsCallbackPostStart);
|
||||||
|
|
||||||
|
sgb.add_callbacks_pre_end(stringsCallbackPreEnd);
|
||||||
|
sgb.add_callbacks_post_end(stringsCallbackPostEnd);
|
||||||
|
|
||||||
|
sgb.add_callbacks_pre_save(stringsCallbackPreSave);
|
||||||
|
sgb.add_callbacks_post_save(stringsCallbackPostSave);
|
||||||
|
|
||||||
|
sgb.add_callbacks_pre_load(stringsCallbackPreLoad);
|
||||||
|
sgb.add_callbacks_post_load(stringsCallbackPostLoad);
|
||||||
|
|
||||||
sgb.add_callbacks_pre_control(stringsCallbackPreControl);
|
sgb.add_callbacks_pre_control(stringsCallbackPreControl);
|
||||||
sgb.add_callbacks_post_control(stringsCallbackPostControl);
|
sgb.add_callbacks_post_control(stringsCallbackPostControl);
|
||||||
|
|
||||||
|
@ -1543,20 +1606,25 @@ bool SaveGame::Load(int slot)
|
||||||
creature->Alerted = savedCreature->alerted();
|
creature->Alerted = savedCreature->alerted();
|
||||||
creature->LOT.CanJump = savedCreature->can_jump();
|
creature->LOT.CanJump = savedCreature->can_jump();
|
||||||
creature->LOT.CanMonkey = savedCreature->can_monkey();
|
creature->LOT.CanMonkey = savedCreature->can_monkey();
|
||||||
|
|
||||||
if (savedCreature->enemy() >= 0)
|
if (savedCreature->enemy() >= 0)
|
||||||
creature->Enemy = &g_Level.Items[savedCreature->enemy()];
|
creature->Enemy = &g_Level.Items[savedCreature->enemy()];
|
||||||
creature->FiredWeapon = savedCreature->fired_weapon();
|
|
||||||
creature->Flags = savedCreature->flags();
|
creature->Flags = savedCreature->flags();
|
||||||
creature->Friendly = savedCreature->friendly();
|
creature->Friendly = savedCreature->friendly();
|
||||||
creature->HeadLeft = savedCreature->head_left();
|
creature->HeadLeft = savedCreature->head_left();
|
||||||
creature->HeadRight = savedCreature->head_right();
|
creature->HeadRight = savedCreature->head_right();
|
||||||
creature->HurtByLara = savedCreature->hurt_by_lara();
|
creature->HurtByLara = savedCreature->hurt_by_lara();
|
||||||
creature->LocationAI = savedCreature->location_ai();
|
creature->LocationAI = savedCreature->location_ai();
|
||||||
|
creature->MuzzleFlash[0].Delay = savedCreature->weapon_delay1();
|
||||||
|
creature->MuzzleFlash[1].Delay = savedCreature->weapon_delay2();
|
||||||
creature->LOT.IsAmphibious = savedCreature->is_amphibious();
|
creature->LOT.IsAmphibious = savedCreature->is_amphibious();
|
||||||
creature->LOT.IsJumping = savedCreature->is_jumping();
|
creature->LOT.IsJumping = savedCreature->is_jumping();
|
||||||
creature->LOT.IsMonkeying = savedCreature->is_monkeying();
|
creature->LOT.IsMonkeying = savedCreature->is_monkeying();
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++)
|
for (int j = 0; j < 4; j++)
|
||||||
creature->JointRotation[j] = savedCreature->joint_rotation()->Get(j);
|
creature->JointRotation[j] = savedCreature->joint_rotation()->Get(j);
|
||||||
|
|
||||||
creature->JumpAhead = savedCreature->jump_ahead();
|
creature->JumpAhead = savedCreature->jump_ahead();
|
||||||
creature->MaxTurn = savedCreature->maximum_turn();
|
creature->MaxTurn = savedCreature->maximum_turn();
|
||||||
creature->MonkeySwingAhead = savedCreature->monkey_swing_ahead();
|
creature->MonkeySwingAhead = savedCreature->monkey_swing_ahead();
|
||||||
|
@ -1813,7 +1881,7 @@ bool SaveGame::Load(int slot)
|
||||||
for (int i = 0; i < Lara.Effect.DripNodes.size(); i++)
|
for (int i = 0; i < Lara.Effect.DripNodes.size(); i++)
|
||||||
Lara.Effect.DripNodes[i] = s->lara()->effect()->drip_nodes()->Get(i);
|
Lara.Effect.DripNodes[i] = s->lara()->effect()->drip_nodes()->Get(i);
|
||||||
|
|
||||||
Lara.Control.CalculatedJumpVelocity = s->lara()->control()->calculated_jump_velocity();
|
Lara.Context.CalcJumpVelocity = s->lara()->control()->calculated_jump_velocity();
|
||||||
Lara.Control.CanMonkeySwing = s->lara()->control()->can_monkey_swing();
|
Lara.Control.CanMonkeySwing = s->lara()->control()->can_monkey_swing();
|
||||||
Lara.Control.CanClimbLadder = s->lara()->control()->is_climbing_ladder();
|
Lara.Control.CanClimbLadder = s->lara()->control()->is_climbing_ladder();
|
||||||
Lara.Control.Count.Death = s->lara()->control()->count()->death();
|
Lara.Control.Count.Death = s->lara()->control()->count()->death();
|
||||||
|
@ -1853,17 +1921,17 @@ bool SaveGame::Load(int slot)
|
||||||
Lara.ExtraTorsoRot.z = s->lara()->extra_torso_rot()->x();
|
Lara.ExtraTorsoRot.z = s->lara()->extra_torso_rot()->x();
|
||||||
Lara.ExtraTorsoRot.y = s->lara()->extra_torso_rot()->y();
|
Lara.ExtraTorsoRot.y = s->lara()->extra_torso_rot()->y();
|
||||||
Lara.ExtraTorsoRot.z = s->lara()->extra_torso_rot()->z();
|
Lara.ExtraTorsoRot.z = s->lara()->extra_torso_rot()->z();
|
||||||
Lara.WaterCurrentActive = s->lara()->water_current_active();
|
Lara.Context.WaterCurrentActive = s->lara()->water_current_active();
|
||||||
Lara.WaterCurrentPull.x = s->lara()->water_current_pull()->x();
|
Lara.Context.WaterCurrentPull.x = s->lara()->water_current_pull()->x();
|
||||||
Lara.WaterCurrentPull.y = s->lara()->water_current_pull()->y();
|
Lara.Context.WaterCurrentPull.y = s->lara()->water_current_pull()->y();
|
||||||
Lara.WaterCurrentPull.z = s->lara()->water_current_pull()->z();
|
Lara.Context.WaterCurrentPull.z = s->lara()->water_current_pull()->z();
|
||||||
Lara.Flare.Life = s->lara()->flare()->life();
|
Lara.Flare.Life = s->lara()->flare()->life();
|
||||||
Lara.Flare.ControlLeft = s->lara()->flare()->control_left();
|
Lara.Flare.ControlLeft = s->lara()->flare()->control_left();
|
||||||
Lara.Flare.Frame = s->lara()->flare()->frame();
|
Lara.Flare.Frame = s->lara()->flare()->frame();
|
||||||
Lara.HighestLocation = s->lara()->highest_location();
|
Lara.HighestLocation = s->lara()->highest_location();
|
||||||
Lara.HitDirection = s->lara()->hit_direction();
|
Lara.HitDirection = s->lara()->hit_direction();
|
||||||
Lara.HitFrame = s->lara()->hit_frame();
|
Lara.HitFrame = s->lara()->hit_frame();
|
||||||
Lara.InteractedItem = s->lara()->interacted_item();
|
Lara.Context.InteractedItem = s->lara()->interacted_item();
|
||||||
Lara.Inventory.BeetleComponents = s->lara()->inventory()->beetle_components();
|
Lara.Inventory.BeetleComponents = s->lara()->inventory()->beetle_components();
|
||||||
Lara.Inventory.BeetleLife = s->lara()->inventory()->beetle_life();
|
Lara.Inventory.BeetleLife = s->lara()->inventory()->beetle_life();
|
||||||
Lara.Inventory.BigWaterskin = s->lara()->inventory()->big_waterskin();
|
Lara.Inventory.BigWaterskin = s->lara()->inventory()->big_waterskin();
|
||||||
|
@ -1888,8 +1956,8 @@ bool SaveGame::Load(int slot)
|
||||||
Lara.LeftArm.Orientation = ToEulerAngles(s->lara()->left_arm()->rotation());
|
Lara.LeftArm.Orientation = ToEulerAngles(s->lara()->left_arm()->rotation());
|
||||||
Lara.Location = s->lara()->location();
|
Lara.Location = s->lara()->location();
|
||||||
Lara.LocationPad = s->lara()->location_pad();
|
Lara.LocationPad = s->lara()->location_pad();
|
||||||
Lara.NextCornerPos = ToPHD(s->lara()->next_corner_pose());
|
Lara.Context.NextCornerPos = ToPHD(s->lara()->next_corner_pose());
|
||||||
Lara.ProjectedFloorHeight = s->lara()->projected_floor_height();
|
Lara.Context.ProjectedFloorHeight = s->lara()->projected_floor_height();
|
||||||
Lara.RightArm.AnimNumber = s->lara()->right_arm()->anim_number();
|
Lara.RightArm.AnimNumber = s->lara()->right_arm()->anim_number();
|
||||||
Lara.RightArm.GunFlash = s->lara()->right_arm()->gun_flash();
|
Lara.RightArm.GunFlash = s->lara()->right_arm()->gun_flash();
|
||||||
Lara.RightArm.GunSmoke = s->lara()->right_arm()->gun_smoke();
|
Lara.RightArm.GunSmoke = s->lara()->right_arm()->gun_smoke();
|
||||||
|
@ -1934,9 +2002,9 @@ bool SaveGame::Load(int slot)
|
||||||
Lara.TargetEntity = (s->lara()->target_entity_number() >= 0 ? &g_Level.Items[s->lara()->target_entity_number()] : nullptr);
|
Lara.TargetEntity = (s->lara()->target_entity_number() >= 0 ? &g_Level.Items[s->lara()->target_entity_number()] : nullptr);
|
||||||
Lara.TargetArmOrient.y = s->lara()->target_arm_angles()->Get(0);
|
Lara.TargetArmOrient.y = s->lara()->target_arm_angles()->Get(0);
|
||||||
Lara.TargetArmOrient.x = s->lara()->target_arm_angles()->Get(1);
|
Lara.TargetArmOrient.x = s->lara()->target_arm_angles()->Get(1);
|
||||||
Lara.TargetOrientation.y = s->lara()->target_facing_angle();
|
Lara.Context.TargetOrientation.y = s->lara()->target_facing_angle();
|
||||||
Lara.Vehicle = s->lara()->vehicle();
|
Lara.Context.Vehicle = s->lara()->vehicle();
|
||||||
Lara.WaterSurfaceDist = s->lara()->water_surface_dist();
|
Lara.Context.WaterSurfaceDist = s->lara()->water_surface_dist();
|
||||||
|
|
||||||
for (int i = 0; i < s->lara()->weapons()->size(); i++)
|
for (int i = 0; i < s->lara()->weapons()->size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -1988,10 +2056,10 @@ bool SaveGame::Load(int slot)
|
||||||
|
|
||||||
std::vector<SavedVar> loadedVars;
|
std::vector<SavedVar> loadedVars;
|
||||||
|
|
||||||
auto theVec = s->script_vars();
|
auto unionVec = s->script_vars();
|
||||||
if (theVec)
|
if (unionVec)
|
||||||
{
|
{
|
||||||
for (auto const& var : *(theVec->members()))
|
for (const auto& var : *(unionVec->members()))
|
||||||
{
|
{
|
||||||
if (var->u_type() == Save::VarUnion::num)
|
if (var->u_type() == Save::VarUnion::num)
|
||||||
{
|
{
|
||||||
|
@ -2010,24 +2078,29 @@ bool SaveGame::Load(int slot)
|
||||||
auto tab = var->u_as_tab()->keys_vals();
|
auto tab = var->u_as_tab()->keys_vals();
|
||||||
auto& loadedTab = loadedVars.emplace_back(IndexTable{});
|
auto& loadedTab = loadedVars.emplace_back(IndexTable{});
|
||||||
|
|
||||||
for (auto const& p : *tab)
|
for (const auto& pair : *tab)
|
||||||
{
|
std::get<IndexTable>(loadedTab).push_back(std::make_pair(pair->key(), pair->val()));
|
||||||
std::get<IndexTable>(loadedTab).push_back(std::make_pair(p->key(), p->val()));
|
}
|
||||||
}
|
else if (var->u_type() == Save::VarUnion::vec2)
|
||||||
|
{
|
||||||
|
auto stored = var->u_as_vec2()->vec();
|
||||||
|
SavedVar var;
|
||||||
|
var.emplace<(int)SavedVarType::Vec2>(ToVector2i(stored));
|
||||||
|
loadedVars.push_back(var);
|
||||||
}
|
}
|
||||||
else if (var->u_type() == Save::VarUnion::vec3)
|
else if (var->u_type() == Save::VarUnion::vec3)
|
||||||
{
|
{
|
||||||
auto stored = var->u_as_vec3()->vec();
|
auto stored = var->u_as_vec3()->vec();
|
||||||
SavedVar v;
|
SavedVar var;
|
||||||
v.emplace<(int)SavedVarType::Vec3>(ToVector3i(stored));
|
var.emplace<(int)SavedVarType::Vec3>(ToVector3i(stored));
|
||||||
loadedVars.push_back(v);
|
loadedVars.push_back(var);
|
||||||
}
|
}
|
||||||
else if (var->u_type() == Save::VarUnion::rotation)
|
else if (var->u_type() == Save::VarUnion::rotation)
|
||||||
{
|
{
|
||||||
auto stored = var->u_as_rotation()->vec();
|
auto stored = var->u_as_rotation()->vec();
|
||||||
SavedVar v;
|
SavedVar var;
|
||||||
v.emplace<(int)SavedVarType::Rotation>(ToVector3(stored));
|
var.emplace<(int)SavedVarType::Rotation>(ToVector3(stored));
|
||||||
loadedVars.push_back(v);
|
loadedVars.push_back(var);
|
||||||
}
|
}
|
||||||
else if (var->u_type() == Save::VarUnion::color)
|
else if (var->u_type() == Save::VarUnion::color)
|
||||||
{
|
{
|
||||||
|
@ -2037,23 +2110,48 @@ bool SaveGame::Load(int slot)
|
||||||
{
|
{
|
||||||
loadedVars.push_back(FuncName{var->u_as_funcName()->str()->str()});
|
loadedVars.push_back(FuncName{var->u_as_funcName()->str()->str()});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_GameScript->SetVariables(loadedVars);
|
g_GameScript->SetVariables(loadedVars);
|
||||||
|
|
||||||
std::vector<std::string> callbacksPreControlVec;
|
auto populateCallbackVecs = [&s](auto callbackFunc)
|
||||||
auto callbacksPreControlOffsetVec = s->callbacks_pre_control();
|
{
|
||||||
for (auto const& s : *callbacksPreControlOffsetVec)
|
auto callbacksVec = std::vector<std::string>{};
|
||||||
callbacksPreControlVec.push_back(s->str());
|
auto callbacksOffsetVec = std::invoke(callbackFunc, s);
|
||||||
|
|
||||||
std::vector<std::string> callbacksPostControlVec;
|
for (const auto& e : *callbacksOffsetVec)
|
||||||
auto callbacksPostControlOffsetVec = s->callbacks_post_control();
|
callbacksVec.push_back(e->str());
|
||||||
for (auto const& s : *callbacksPostControlOffsetVec)
|
|
||||||
callbacksPostControlVec.push_back(s->str());
|
|
||||||
|
|
||||||
g_GameScript->SetCallbackStrings(callbacksPreControlVec, callbacksPostControlVec);
|
return callbacksVec;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto callbacksPreStartVec = populateCallbackVecs(&Save::SaveGame::callbacks_pre_start);
|
||||||
|
auto callbacksPostStartVec = populateCallbackVecs(&Save::SaveGame::callbacks_post_start);
|
||||||
|
|
||||||
|
auto callbacksPreEndVec = populateCallbackVecs(&Save::SaveGame::callbacks_pre_end);
|
||||||
|
auto callbacksPostEndVec = populateCallbackVecs(&Save::SaveGame::callbacks_post_end);
|
||||||
|
|
||||||
|
auto callbacksPreSaveVec = populateCallbackVecs(&Save::SaveGame::callbacks_pre_save);
|
||||||
|
auto callbacksPostSaveVec = populateCallbackVecs(&Save::SaveGame::callbacks_post_save);
|
||||||
|
|
||||||
|
auto callbacksPreLoadVec = populateCallbackVecs(&Save::SaveGame::callbacks_pre_load);
|
||||||
|
auto callbacksPostLoadVec = populateCallbackVecs(&Save::SaveGame::callbacks_post_load);
|
||||||
|
|
||||||
|
auto callbacksPreControlVec = populateCallbackVecs(&Save::SaveGame::callbacks_pre_control);
|
||||||
|
auto callbacksPostControlVec = populateCallbackVecs(&Save::SaveGame::callbacks_post_control);
|
||||||
|
|
||||||
|
g_GameScript->SetCallbackStrings(
|
||||||
|
callbacksPreStartVec,
|
||||||
|
callbacksPostStartVec,
|
||||||
|
callbacksPreEndVec,
|
||||||
|
callbacksPostEndVec,
|
||||||
|
callbacksPreSaveVec,
|
||||||
|
callbacksPostSaveVec,
|
||||||
|
callbacksPreLoadVec,
|
||||||
|
callbacksPostLoadVec,
|
||||||
|
callbacksPreControlVec,
|
||||||
|
callbacksPostControlVec);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ void ClearSpotCamSequences()
|
||||||
SpotCam[i] = {};
|
SpotCam[i] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseSpotCamSequences(bool startFirstSequence)
|
void InitializeSpotCamSequences(bool startFirstSequence)
|
||||||
{
|
{
|
||||||
TrackCameraInit = false;
|
TrackCameraInit = false;
|
||||||
|
|
||||||
|
@ -105,12 +105,12 @@ void InitialiseSpotCamSequences(bool startFirstSequence)
|
||||||
|
|
||||||
if (startFirstSequence)
|
if (startFirstSequence)
|
||||||
{
|
{
|
||||||
InitialiseSpotCam(0);
|
InitializeSpotCam(0);
|
||||||
UseSpotCam = true;
|
UseSpotCam = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialiseSpotCam(short Sequence)
|
void InitializeSpotCam(short Sequence)
|
||||||
{
|
{
|
||||||
if (TrackCameraInit != 0 && LastSpotCamSequence == Sequence)
|
if (TrackCameraInit != 0 && LastSpotCamSequence == Sequence)
|
||||||
{
|
{
|
||||||
|
@ -125,7 +125,7 @@ void InitialiseSpotCam(short Sequence)
|
||||||
|
|
||||||
LaraItem->MeshBits = ALL_JOINT_BITS;
|
LaraItem->MeshBits = ALL_JOINT_BITS;
|
||||||
|
|
||||||
ResetLaraFlex(LaraItem);
|
ResetPlayerFlex(LaraItem);
|
||||||
|
|
||||||
Camera.bounce = 0;
|
Camera.bounce = 0;
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue